Home | History | Annotate | Download | only in ip
      1 /* $USAGI: $ */
      2 
      3 /*
      4  * Copyright (C)2004 USAGI/WIDE Project
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation; either version 2 of the License, or
      9  * (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program; if not, write to the Free Software
     18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     19  */
     20 /*
     21  * based on ip.c, iproute.c
     22  */
     23 /*
     24  * Authors:
     25  *	Masahide NAKAMURA @USAGI
     26  */
     27 
     28 #include <stdio.h>
     29 #include <stdlib.h>
     30 #include <string.h>
     31 #include <sys/types.h>
     32 #include <sys/socket.h>
     33 #include <time.h>
     34 #include <netdb.h>
     35 #include <linux/netlink.h>
     36 #include <linux/rtnetlink.h>
     37 #include <linux/xfrm.h>
     38 
     39 #include "utils.h"
     40 #include "xfrm.h"
     41 
     42 #define STRBUF_SIZE	(128)
     43 #define STRBUF_CAT(buf, str) \
     44 	do { \
     45 		int rest = sizeof(buf) - 1 - strlen(buf); \
     46 		if (rest > 0) { \
     47 			int len = strlen(str); \
     48 			if (len > rest) \
     49 				len = rest; \
     50 			strncat(buf, str, len); \
     51 			buf[sizeof(buf) - 1] = '\0'; \
     52 		} \
     53 	} while(0);
     54 
     55 struct xfrm_filter filter;
     56 
     57 static void usage(void) __attribute__((noreturn));
     58 
     59 static void usage(void)
     60 {
     61 	fprintf(stderr,
     62 		"Usage: ip xfrm XFRM_OBJECT { COMMAND | help }\n"
     63 		"where  XFRM_OBJECT := { state | policy | monitor }\n");
     64 	exit(-1);
     65 }
     66 
     67 /* This is based on utils.c(inet_addr_match) */
     68 int xfrm_addr_match(xfrm_address_t *x1, xfrm_address_t *x2, int bits)
     69 {
     70 	__u32 *a1 = (__u32 *)x1;
     71 	__u32 *a2 = (__u32 *)x2;
     72 	int words = bits >> 0x05;
     73 
     74 	bits &= 0x1f;
     75 
     76 	if (words)
     77 		if (memcmp(a1, a2, words << 2))
     78 			return -1;
     79 
     80 	if (bits) {
     81 		__u32 w1, w2;
     82 		__u32 mask;
     83 
     84 		w1 = a1[words];
     85 		w2 = a2[words];
     86 
     87 		mask = htonl((0xffffffff) << (0x20 - bits));
     88 
     89 		if ((w1 ^ w2) & mask)
     90 			return 1;
     91 	}
     92 
     93 	return 0;
     94 }
     95 
     96 int xfrm_xfrmproto_is_ipsec(__u8 proto)
     97 {
     98 	return (proto ==  IPPROTO_ESP ||
     99 		proto ==  IPPROTO_AH  ||
    100 		proto ==  IPPROTO_COMP);
    101 }
    102 
    103 int xfrm_xfrmproto_is_ro(__u8 proto)
    104 {
    105 	return (proto ==  IPPROTO_ROUTING ||
    106 		proto ==  IPPROTO_DSTOPTS);
    107 }
    108 
    109 struct typeent {
    110 	const char *t_name;
    111 	int t_type;
    112 };
    113 
    114 static const struct typeent xfrmproto_types[]= {
    115 	{ "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "comp", IPPROTO_COMP },
    116 	{ "route2", IPPROTO_ROUTING }, { "hao", IPPROTO_DSTOPTS },
    117 	{ "ipsec-any", IPSEC_PROTO_ANY },
    118 	{ NULL, -1 }
    119 };
    120 
    121 int xfrm_xfrmproto_getbyname(char *name)
    122 {
    123 	int i;
    124 
    125 	for (i = 0; ; i++) {
    126 		const struct typeent *t = &xfrmproto_types[i];
    127 		if (!t->t_name || t->t_type == -1)
    128 			break;
    129 
    130 		if (strcmp(t->t_name, name) == 0)
    131 			return t->t_type;
    132 	}
    133 
    134 	return -1;
    135 }
    136 
    137 const char *strxf_xfrmproto(__u8 proto)
    138 {
    139 	static char str[16];
    140 	int i;
    141 
    142 	for (i = 0; ; i++) {
    143 		const struct typeent *t = &xfrmproto_types[i];
    144 		if (!t->t_name || t->t_type == -1)
    145 			break;
    146 
    147 		if (t->t_type == proto)
    148 			return t->t_name;
    149 	}
    150 
    151 	sprintf(str, "%u", proto);
    152 	return str;
    153 }
    154 
    155 static const struct typeent algo_types[]= {
    156 	{ "enc", XFRMA_ALG_CRYPT }, { "auth", XFRMA_ALG_AUTH },
    157 	{ "comp", XFRMA_ALG_COMP }, { "aead", XFRMA_ALG_AEAD },
    158 	{ NULL, -1 }
    159 };
    160 
    161 int xfrm_algotype_getbyname(char *name)
    162 {
    163 	int i;
    164 
    165 	for (i = 0; ; i++) {
    166 		const struct typeent *t = &algo_types[i];
    167 		if (!t->t_name || t->t_type == -1)
    168 			break;
    169 
    170 		if (strcmp(t->t_name, name) == 0)
    171 			return t->t_type;
    172 	}
    173 
    174 	return -1;
    175 }
    176 
    177 const char *strxf_algotype(int type)
    178 {
    179 	static char str[32];
    180 	int i;
    181 
    182 	for (i = 0; ; i++) {
    183 		const struct typeent *t = &algo_types[i];
    184 		if (!t->t_name || t->t_type == -1)
    185 			break;
    186 
    187 		if (t->t_type == type)
    188 			return t->t_name;
    189 	}
    190 
    191 	sprintf(str, "%d", type);
    192 	return str;
    193 }
    194 
    195 const char *strxf_mask8(__u8 mask)
    196 {
    197 	static char str[16];
    198 	const int sn = sizeof(mask) * 8 - 1;
    199 	__u8 b;
    200 	int i = 0;
    201 
    202 	for (b = (1 << sn); b > 0; b >>= 1)
    203 		str[i++] = ((b & mask) ? '1' : '0');
    204 	str[i] = '\0';
    205 
    206 	return str;
    207 }
    208 
    209 const char *strxf_mask32(__u32 mask)
    210 {
    211 	static char str[16];
    212 
    213 	sprintf(str, "%.8x", mask);
    214 
    215 	return str;
    216 }
    217 
    218 const char *strxf_share(__u8 share)
    219 {
    220 	static char str[32];
    221 
    222 	switch (share) {
    223 	case XFRM_SHARE_ANY:
    224 		strcpy(str, "any");
    225 		break;
    226 	case XFRM_SHARE_SESSION:
    227 		strcpy(str, "session");
    228 		break;
    229 	case XFRM_SHARE_USER:
    230 		strcpy(str, "user");
    231 		break;
    232 	case XFRM_SHARE_UNIQUE:
    233 		strcpy(str, "unique");
    234 		break;
    235 	default:
    236 		sprintf(str, "%u", share);
    237 		break;
    238 	}
    239 
    240 	return str;
    241 }
    242 
    243 const char *strxf_proto(__u8 proto)
    244 {
    245 	static char buf[32];
    246 	struct protoent *pp;
    247 	const char *p;
    248 
    249 	pp = getprotobynumber(proto);
    250 	if (pp)
    251 		p = pp->p_name;
    252 	else {
    253 		sprintf(buf, "%u", proto);
    254 		p = buf;
    255 	}
    256 
    257 	return p;
    258 }
    259 
    260 const char *strxf_ptype(__u8 ptype)
    261 {
    262 	static char str[16];
    263 
    264 	switch (ptype) {
    265 	case XFRM_POLICY_TYPE_MAIN:
    266 		strcpy(str, "main");
    267 		break;
    268 	case XFRM_POLICY_TYPE_SUB:
    269 		strcpy(str, "sub");
    270 		break;
    271 	default:
    272 		sprintf(str, "%u", ptype);
    273 		break;
    274 	}
    275 
    276 	return str;
    277 }
    278 
    279 void xfrm_id_info_print(xfrm_address_t *saddr, struct xfrm_id *id,
    280 			__u8 mode, __u32 reqid, __u16 family, int force_spi,
    281 			FILE *fp, const char *prefix, const char *title)
    282 {
    283 	char abuf[256];
    284 
    285 	if (title)
    286 		fputs(title, fp);
    287 
    288 	memset(abuf, '\0', sizeof(abuf));
    289 	fprintf(fp, "src %s ", rt_addr_n2a(family, sizeof(*saddr),
    290 					   saddr, abuf, sizeof(abuf)));
    291 	memset(abuf, '\0', sizeof(abuf));
    292 	fprintf(fp, "dst %s", rt_addr_n2a(family, sizeof(id->daddr),
    293 					  &id->daddr, abuf, sizeof(abuf)));
    294 	fprintf(fp, "%s", _SL_);
    295 
    296 	if (prefix)
    297 		fputs(prefix, fp);
    298 	fprintf(fp, "\t");
    299 
    300 	fprintf(fp, "proto %s ", strxf_xfrmproto(id->proto));
    301 
    302 	if (show_stats > 0 || force_spi || id->spi) {
    303 		__u32 spi = ntohl(id->spi);
    304 		fprintf(fp, "spi 0x%08x", spi);
    305 		if (show_stats > 0)
    306 			fprintf(fp, "(%u)", spi);
    307 		fprintf(fp, " ");
    308 	}
    309 
    310 	fprintf(fp, "reqid %u", reqid);
    311 	if (show_stats > 0)
    312 		fprintf(fp, "(0x%08x)", reqid);
    313 	fprintf(fp, " ");
    314 
    315 	fprintf(fp, "mode ");
    316 	switch (mode) {
    317 	case XFRM_MODE_TRANSPORT:
    318 		fprintf(fp, "transport");
    319 		break;
    320 	case XFRM_MODE_TUNNEL:
    321 		fprintf(fp, "tunnel");
    322 		break;
    323 	case XFRM_MODE_ROUTEOPTIMIZATION:
    324 		fprintf(fp, "ro");
    325 		break;
    326 	case XFRM_MODE_IN_TRIGGER:
    327 		fprintf(fp, "in_trigger");
    328 		break;
    329 	case XFRM_MODE_BEET:
    330 		fprintf(fp, "beet");
    331 		break;
    332 	default:
    333 		fprintf(fp, "%u", mode);
    334 		break;
    335 	}
    336 	fprintf(fp, "%s", _SL_);
    337 }
    338 
    339 static const char *strxf_limit(__u64 limit)
    340 {
    341 	static char str[32];
    342 	if (limit == XFRM_INF)
    343 		strcpy(str, "(INF)");
    344 	else
    345 		sprintf(str, "%llu", (unsigned long long) limit);
    346 
    347 	return str;
    348 }
    349 
    350 void xfrm_stats_print(struct xfrm_stats *s, FILE *fp, const char *prefix)
    351 {
    352 	if (prefix)
    353 		fputs(prefix, fp);
    354 	fprintf(fp, "stats:%s", _SL_);
    355 
    356 	if (prefix)
    357 		fputs(prefix, fp);
    358 	fprintf(fp, "  replay-window %u replay %u failed %u%s",
    359 		s->replay_window, s->replay, s->integrity_failed, _SL_);
    360 }
    361 
    362 static const char *strxf_time(__u64 time)
    363 {
    364 	static char str[32];
    365 
    366 	if (time == 0)
    367 		strcpy(str, "-");
    368 	else {
    369 		time_t t;
    370 		struct tm *tp;
    371 
    372 		/* XXX: treat time in the same manner of kernel's
    373 		 * net/xfrm/xfrm_{user,state}.c
    374 		 */
    375 		t = (long)time;
    376 		tp = localtime(&t);
    377 
    378 		strftime(str, sizeof(str), "%Y-%m-%d %T", tp);
    379 	}
    380 
    381 	return str;
    382 }
    383 
    384 void xfrm_lifetime_print(struct xfrm_lifetime_cfg *cfg,
    385 			 struct xfrm_lifetime_cur *cur,
    386 			 FILE *fp, const char *prefix)
    387 {
    388 	if (cfg) {
    389 		if (prefix)
    390 			fputs(prefix, fp);
    391 		fprintf(fp, "lifetime config:%s",_SL_);
    392 
    393 		if (prefix)
    394 			fputs(prefix, fp);
    395 		fprintf(fp, "  limit: soft %s(bytes),",
    396 			strxf_limit(cfg->soft_byte_limit));
    397 		fprintf(fp, " hard %s(bytes)%s",
    398 			strxf_limit(cfg->hard_byte_limit), _SL_);
    399 
    400 		if (prefix)
    401 			fputs(prefix, fp);
    402 		fprintf(fp, "  limit: soft %s(packets),",
    403 			strxf_limit(cfg->soft_packet_limit));
    404 		fprintf(fp, " hard %s(packets)%s",
    405 			strxf_limit(cfg->hard_packet_limit), _SL_);
    406 
    407 		if (prefix)
    408 			fputs(prefix, fp);
    409 		fprintf(fp, "  expire add: soft %llu(sec), hard %llu(sec)%s",
    410 			(unsigned long long) cfg->soft_add_expires_seconds,
    411 			(unsigned long long) cfg->hard_add_expires_seconds,
    412 			_SL_);
    413 
    414 		if (prefix)
    415 			fputs(prefix, fp);
    416 		fprintf(fp, "  expire use: soft %llu(sec), hard %llu(sec)%s",
    417 			(unsigned long long) cfg->soft_use_expires_seconds,
    418 			(unsigned long long) cfg->hard_use_expires_seconds,
    419 			_SL_);
    420 	}
    421 	if (cur) {
    422 		if (prefix)
    423 			fputs(prefix, fp);
    424 		fprintf(fp, "lifetime current:%s", _SL_);
    425 
    426 		if (prefix)
    427 			fputs(prefix, fp);
    428 		fprintf(fp, "  %llu(bytes), %llu(packets)%s",
    429 			(unsigned long long) cur->bytes,
    430 			(unsigned long long) cur->packets,
    431 			 _SL_);
    432 
    433 		if (prefix)
    434 			fputs(prefix, fp);
    435 		fprintf(fp, "  add %s ", strxf_time(cur->add_time));
    436 		fprintf(fp, "use %s%s", strxf_time(cur->use_time), _SL_);
    437 	}
    438 }
    439 
    440 void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,
    441 			 FILE *fp, const char *prefix)
    442 {
    443 	char abuf[256];
    444 	__u16 f;
    445 
    446 	f = sel->family;
    447 	if (f == AF_UNSPEC)
    448 		f = family;
    449 	if (f == AF_UNSPEC)
    450 		f = preferred_family;
    451 
    452 	if (prefix)
    453 		fputs(prefix, fp);
    454 
    455 	memset(abuf, '\0', sizeof(abuf));
    456 	fprintf(fp, "src %s/%u ", rt_addr_n2a(f, sizeof(sel->saddr),
    457 					      &sel->saddr, abuf, sizeof(abuf)),
    458 		sel->prefixlen_s);
    459 
    460 	memset(abuf, '\0', sizeof(abuf));
    461 	fprintf(fp, "dst %s/%u ", rt_addr_n2a(f, sizeof(sel->daddr),
    462 					      &sel->daddr, abuf, sizeof(abuf)),
    463 		sel->prefixlen_d);
    464 
    465 	if (sel->proto)
    466 		fprintf(fp, "proto %s ", strxf_proto(sel->proto));
    467 	switch (sel->proto) {
    468 	case IPPROTO_TCP:
    469 	case IPPROTO_UDP:
    470 	case IPPROTO_SCTP:
    471 	case IPPROTO_DCCP:
    472 	default: /* XXX */
    473 		if (sel->sport_mask)
    474 			fprintf(fp, "sport %u ", ntohs(sel->sport));
    475 		if (sel->dport_mask)
    476 			fprintf(fp, "dport %u ", ntohs(sel->dport));
    477 		break;
    478 	case IPPROTO_ICMP:
    479 	case IPPROTO_ICMPV6:
    480 		/* type/code is stored at sport/dport in selector */
    481 		if (sel->sport_mask)
    482 			fprintf(fp, "type %u ", ntohs(sel->sport));
    483 		if (sel->dport_mask)
    484 			fprintf(fp, "code %u ", ntohs(sel->dport));
    485 		break;
    486 	case IPPROTO_MH:
    487 		if (sel->sport_mask)
    488 			fprintf(fp, "type %u ", ntohs(sel->sport));
    489 		if (sel->dport_mask) {
    490 			if (show_stats > 0)
    491 				fprintf(fp, "(dport) 0x%.4x ", sel->dport);
    492 		}
    493 		break;
    494 	}
    495 
    496 	if (sel->ifindex > 0)
    497 		fprintf(fp, "dev %s ", ll_index_to_name(sel->ifindex));
    498 
    499 	if (show_stats > 0)
    500 		fprintf(fp, "uid %u", sel->user);
    501 
    502 	fprintf(fp, "%s", _SL_);
    503 }
    504 
    505 static void __xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
    506 			      FILE *fp, const char *prefix, int newline)
    507 {
    508 	int keylen;
    509 	int i;
    510 
    511 	if (prefix)
    512 		fputs(prefix, fp);
    513 
    514 	fprintf(fp, "%s ", strxf_algotype(type));
    515 
    516 	if (len < sizeof(*algo)) {
    517 		fprintf(fp, "(ERROR truncated)");
    518 		goto fin;
    519 	}
    520 	len -= sizeof(*algo);
    521 
    522 	fprintf(fp, "%s ", algo->alg_name);
    523 
    524 	keylen = algo->alg_key_len / 8;
    525 	if (len < keylen) {
    526 		fprintf(fp, "(ERROR truncated)");
    527 		goto fin;
    528 	}
    529 
    530 	fprintf(fp, "0x");
    531 	for (i = 0; i < keylen; i ++)
    532 		fprintf(fp, "%.2x", (unsigned char)algo->alg_key[i]);
    533 
    534 	if (show_stats > 0)
    535 		fprintf(fp, " (%d bits)", algo->alg_key_len);
    536 
    537  fin:
    538 	if (newline)
    539 		fprintf(fp, "%s", _SL_);
    540 }
    541 
    542 static inline void xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
    543 				   FILE *fp, const char *prefix)
    544 {
    545 	return __xfrm_algo_print(algo, type, len, fp, prefix, 1);
    546 }
    547 
    548 static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len,
    549 			    FILE *fp, const char *prefix)
    550 {
    551 	struct {
    552 		struct xfrm_algo algo;
    553 		char key[algo->alg_key_len / 8];
    554 	} base;
    555 
    556 	memcpy(base.algo.alg_name, algo->alg_name, sizeof(base.algo.alg_name));
    557 	base.algo.alg_key_len = algo->alg_key_len;
    558 	memcpy(base.algo.alg_key, algo->alg_key, algo->alg_key_len / 8);
    559 
    560 	__xfrm_algo_print(&base.algo, XFRMA_ALG_AEAD, len, fp, prefix, 0);
    561 
    562 	fprintf(fp, " %d", algo->alg_icv_len);
    563 
    564 	fprintf(fp, "%s", _SL_);
    565 }
    566 
    567 static void xfrm_tmpl_print(struct xfrm_user_tmpl *tmpls, int len,
    568 			    __u16 family, FILE *fp, const char *prefix)
    569 {
    570 	int ntmpls = len / sizeof(struct xfrm_user_tmpl);
    571 	int i;
    572 
    573 	if (ntmpls <= 0) {
    574 		if (prefix)
    575 			fputs(prefix, fp);
    576 		fprintf(fp, "(ERROR \"tmpl\" truncated)");
    577 		fprintf(fp, "%s", _SL_);
    578 		return;
    579 	}
    580 
    581 	for (i = 0; i < ntmpls; i++) {
    582 		struct xfrm_user_tmpl *tmpl = &tmpls[i];
    583 
    584 		if (prefix)
    585 			fputs(prefix, fp);
    586 
    587 		xfrm_id_info_print(&tmpl->saddr, &tmpl->id, tmpl->mode,
    588 				   tmpl->reqid, tmpl->family, 0, fp, prefix, "tmpl ");
    589 
    590 		if (show_stats > 0 || tmpl->optional) {
    591 			if (prefix)
    592 				fputs(prefix, fp);
    593 			fprintf(fp, "\t");
    594 			switch (tmpl->optional) {
    595 			case 0:
    596 				if (show_stats > 0)
    597 					fprintf(fp, "level required ");
    598 				break;
    599 			case 1:
    600 				fprintf(fp, "level use ");
    601 				break;
    602 			default:
    603 				fprintf(fp, "level %u ", tmpl->optional);
    604 				break;
    605 			}
    606 
    607 			if (show_stats > 0)
    608 				fprintf(fp, "share %s ", strxf_share(tmpl->share));
    609 
    610 			fprintf(fp, "%s", _SL_);
    611 		}
    612 
    613 		if (show_stats > 0) {
    614 			if (prefix)
    615 				fputs(prefix, fp);
    616 			fprintf(fp, "\t");
    617 			fprintf(fp, "%s-mask %s ",
    618 				strxf_algotype(XFRMA_ALG_CRYPT),
    619 				strxf_mask32(tmpl->ealgos));
    620 			fprintf(fp, "%s-mask %s ",
    621 				strxf_algotype(XFRMA_ALG_AUTH),
    622 				strxf_mask32(tmpl->aalgos));
    623 			fprintf(fp, "%s-mask %s",
    624 				strxf_algotype(XFRMA_ALG_COMP),
    625 				strxf_mask32(tmpl->calgos));
    626 
    627 			fprintf(fp, "%s", _SL_);
    628 		}
    629 	}
    630 }
    631 
    632 void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
    633 		      FILE *fp, const char *prefix)
    634 {
    635 	if (tb[XFRMA_ALG_AUTH]) {
    636 		struct rtattr *rta = tb[XFRMA_ALG_AUTH];
    637 		xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
    638 				XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix);
    639 	}
    640 
    641 	if (tb[XFRMA_ALG_AEAD]) {
    642 		struct rtattr *rta = tb[XFRMA_ALG_AEAD];
    643 		xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta),
    644 				RTA_PAYLOAD(rta), fp, prefix);
    645 	}
    646 
    647 	if (tb[XFRMA_ALG_CRYPT]) {
    648 		struct rtattr *rta = tb[XFRMA_ALG_CRYPT];
    649 		xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
    650 				XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix);
    651 	}
    652 
    653 	if (tb[XFRMA_ALG_COMP]) {
    654 		struct rtattr *rta = tb[XFRMA_ALG_COMP];
    655 		xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
    656 				XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix);
    657 	}
    658 
    659 	if (tb[XFRMA_ENCAP]) {
    660 		struct xfrm_encap_tmpl *e;
    661 		char abuf[256];
    662 
    663 		if (prefix)
    664 			fputs(prefix, fp);
    665 		fprintf(fp, "encap ");
    666 
    667 		if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) {
    668 			fprintf(fp, "(ERROR truncated)");
    669 			fprintf(fp, "%s", _SL_);
    670 			return;
    671 		}
    672 		e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]);
    673 
    674 		fprintf(fp, "type ");
    675 		switch (e->encap_type) {
    676 		case 1:
    677 			fprintf(fp, "espinudp-nonike ");
    678 			break;
    679 		case 2:
    680 			fprintf(fp, "espinudp ");
    681 			break;
    682 		default:
    683 			fprintf(fp, "%u ", e->encap_type);
    684 			break;
    685 		}
    686 		fprintf(fp, "sport %u ", ntohs(e->encap_sport));
    687 		fprintf(fp, "dport %u ", ntohs(e->encap_dport));
    688 
    689 		memset(abuf, '\0', sizeof(abuf));
    690 		fprintf(fp, "addr %s",
    691 			rt_addr_n2a(family, sizeof(e->encap_oa),
    692 				    &e->encap_oa, abuf, sizeof(abuf)));
    693 		fprintf(fp, "%s", _SL_);
    694 	}
    695 
    696 	if (tb[XFRMA_TMPL]) {
    697 		struct rtattr *rta = tb[XFRMA_TMPL];
    698 		xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta),
    699 				RTA_PAYLOAD(rta), family, fp, prefix);
    700 	}
    701 
    702 	if (tb[XFRMA_COADDR]) {
    703 		char abuf[256];
    704 		xfrm_address_t *coa;
    705 
    706 		if (prefix)
    707 			fputs(prefix, fp);
    708 		fprintf(fp, "coa ");
    709 
    710 		coa = (xfrm_address_t *)RTA_DATA(tb[XFRMA_COADDR]);
    711 
    712 		if (RTA_PAYLOAD(tb[XFRMA_COADDR]) < sizeof(*coa)) {
    713 			fprintf(fp, "(ERROR truncated)");
    714 			fprintf(fp, "%s", _SL_);
    715 			return;
    716 		}
    717 
    718 		memset(abuf, '\0', sizeof(abuf));
    719 		fprintf(fp, "%s",
    720 			rt_addr_n2a(family, sizeof(*coa), coa,
    721 				    abuf, sizeof(abuf)));
    722 		fprintf(fp, "%s", _SL_);
    723 	}
    724 
    725 	if (tb[XFRMA_LASTUSED]) {
    726 		__u64 lastused;
    727 
    728 		if (prefix)
    729 			fputs(prefix, fp);
    730 		fprintf(fp, "lastused ");
    731 
    732 		if (RTA_PAYLOAD(tb[XFRMA_LASTUSED]) < sizeof(lastused)) {
    733 			fprintf(fp, "(ERROR truncated)");
    734 			fprintf(fp, "%s", _SL_);
    735 			return;
    736 		}
    737 
    738 		lastused = *(__u64 *)RTA_DATA(tb[XFRMA_LASTUSED]);
    739 
    740 		fprintf(fp, "%s", strxf_time(lastused));
    741 		fprintf(fp, "%s", _SL_);
    742 	}
    743 }
    744 
    745 static int xfrm_selector_iszero(struct xfrm_selector *s)
    746 {
    747 	struct xfrm_selector s0;
    748 
    749 	memset(&s0, 0, sizeof(s0));
    750 
    751 	return (memcmp(&s0, s, sizeof(s0)) == 0);
    752 }
    753 
    754 void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
    755 			    struct rtattr *tb[], FILE *fp, const char *prefix,
    756 			    const char *title)
    757 {
    758 	char buf[STRBUF_SIZE];
    759 	int force_spi = xfrm_xfrmproto_is_ipsec(xsinfo->id.proto);
    760 
    761 	memset(buf, '\0', sizeof(buf));
    762 
    763 	xfrm_id_info_print(&xsinfo->saddr, &xsinfo->id, xsinfo->mode,
    764 			   xsinfo->reqid, xsinfo->family, force_spi, fp,
    765 			   prefix, title);
    766 
    767 	if (prefix)
    768 		STRBUF_CAT(buf, prefix);
    769 	STRBUF_CAT(buf, "\t");
    770 
    771 	fputs(buf, fp);
    772 	fprintf(fp, "replay-window %u ", xsinfo->replay_window);
    773 	if (show_stats > 0)
    774 		fprintf(fp, "seq 0x%08u ", xsinfo->seq);
    775 	if (show_stats > 0 || xsinfo->flags) {
    776 		__u8 flags = xsinfo->flags;
    777 
    778 		fprintf(fp, "flag ");
    779 		XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_NOECN, "noecn");
    780 		XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_DECAP_DSCP, "decap-dscp");
    781 		XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_NOPMTUDISC, "nopmtudisc");
    782 		XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_WILDRECV, "wildrecv");
    783 		if (flags)
    784 			fprintf(fp, "%x", flags);
    785 	}
    786 	if (show_stats > 0)
    787 		fprintf(fp, " (0x%s)", strxf_mask8(xsinfo->flags));
    788 	fprintf(fp, "%s", _SL_);
    789 
    790 	xfrm_xfrma_print(tb, xsinfo->family, fp, buf);
    791 
    792 	if (!xfrm_selector_iszero(&xsinfo->sel)) {
    793 		char sbuf[STRBUF_SIZE];
    794 
    795 		memcpy(sbuf, buf, sizeof(sbuf));
    796 		STRBUF_CAT(sbuf, "sel ");
    797 
    798 		xfrm_selector_print(&xsinfo->sel, xsinfo->family, fp, sbuf);
    799 	}
    800 
    801 	if (show_stats > 0) {
    802 		xfrm_lifetime_print(&xsinfo->lft, &xsinfo->curlft, fp, buf);
    803 		xfrm_stats_print(&xsinfo->stats, fp, buf);
    804 	}
    805 }
    806 
    807 void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo,
    808 			    struct rtattr *tb[], FILE *fp, const char *prefix,
    809 			    const char *title)
    810 {
    811 	char buf[STRBUF_SIZE];
    812 
    813 	memset(buf, '\0', sizeof(buf));
    814 
    815 	xfrm_selector_print(&xpinfo->sel, preferred_family, fp, title);
    816 
    817 	if (prefix)
    818 		STRBUF_CAT(buf, prefix);
    819 	STRBUF_CAT(buf, "\t");
    820 
    821 	fputs(buf, fp);
    822 	fprintf(fp, "dir ");
    823 	switch (xpinfo->dir) {
    824 	case XFRM_POLICY_IN:
    825 		fprintf(fp, "in");
    826 		break;
    827 	case XFRM_POLICY_OUT:
    828 		fprintf(fp, "out");
    829 		break;
    830 	case XFRM_POLICY_FWD:
    831 		fprintf(fp, "fwd");
    832 		break;
    833 	default:
    834 		fprintf(fp, "%u", xpinfo->dir);
    835 		break;
    836 	}
    837 	fprintf(fp, " ");
    838 
    839 	switch (xpinfo->action) {
    840 	case XFRM_POLICY_ALLOW:
    841 		if (show_stats > 0)
    842 			fprintf(fp, "action allow ");
    843 		break;
    844 	case XFRM_POLICY_BLOCK:
    845 		fprintf(fp, "action block ");
    846 		break;
    847 	default:
    848 		fprintf(fp, "action %u ", xpinfo->action);
    849 		break;
    850 	}
    851 
    852 	if (show_stats)
    853 		fprintf(fp, "index %u ", xpinfo->index);
    854 	fprintf(fp, "priority %u ", xpinfo->priority);
    855 
    856 	if (tb[XFRMA_POLICY_TYPE]) {
    857 		struct xfrm_userpolicy_type *upt;
    858 
    859 		fprintf(fp, "ptype ");
    860 
    861 		if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt))
    862 			fprintf(fp, "(ERROR truncated)");
    863 
    864 		upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
    865 		fprintf(fp, "%s ", strxf_ptype(upt->type));
    866 	}
    867 
    868 	if (show_stats > 0)
    869 		fprintf(fp, "share %s ", strxf_share(xpinfo->share));
    870 
    871 	if (show_stats > 0 || xpinfo->flags) {
    872 		__u8 flags = xpinfo->flags;
    873 
    874 		fprintf(fp, "flag ");
    875 		XFRM_FLAG_PRINT(fp, flags, XFRM_POLICY_LOCALOK, "localok");
    876 		if (flags)
    877 			fprintf(fp, "%x", flags);
    878 	}
    879 	if (show_stats > 0)
    880 		fprintf(fp, " (0x%s)", strxf_mask8(xpinfo->flags));
    881 	fprintf(fp, "%s", _SL_);
    882 
    883 	if (show_stats > 0)
    884 		xfrm_lifetime_print(&xpinfo->lft, &xpinfo->curlft, fp, buf);
    885 
    886 	xfrm_xfrma_print(tb, xpinfo->sel.family, fp, buf);
    887 }
    888 
    889 int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family,
    890 		  int loose, int *argcp, char ***argvp)
    891 {
    892 	int argc = *argcp;
    893 	char **argv = *argvp;
    894 	inet_prefix dst;
    895 	inet_prefix src;
    896 
    897 	memset(&dst, 0, sizeof(dst));
    898 	memset(&src, 0, sizeof(src));
    899 
    900 	while (1) {
    901 		if (strcmp(*argv, "src") == 0) {
    902 			NEXT_ARG();
    903 
    904 			get_prefix(&src, *argv, preferred_family);
    905 			if (src.family == AF_UNSPEC)
    906 				invarg("\"src\" address family is AF_UNSPEC", *argv);
    907 			if (family)
    908 				*family = src.family;
    909 
    910 			memcpy(saddr, &src.data, sizeof(*saddr));
    911 
    912 			filter.id_src_mask = src.bitlen;
    913 
    914 		} else if (strcmp(*argv, "dst") == 0) {
    915 			NEXT_ARG();
    916 
    917 			get_prefix(&dst, *argv, preferred_family);
    918 			if (dst.family == AF_UNSPEC)
    919 				invarg("\"dst\" address family is AF_UNSPEC", *argv);
    920 			if (family)
    921 				*family = dst.family;
    922 
    923 			memcpy(&id->daddr, &dst.data, sizeof(id->daddr));
    924 
    925 			filter.id_dst_mask = dst.bitlen;
    926 
    927 		} else if (strcmp(*argv, "proto") == 0) {
    928 			int ret;
    929 
    930 			NEXT_ARG();
    931 
    932 			ret = xfrm_xfrmproto_getbyname(*argv);
    933 			if (ret < 0)
    934 				invarg("\"XFRM_PROTO\" is invalid", *argv);
    935 
    936 			id->proto = (__u8)ret;
    937 
    938 			filter.id_proto_mask = XFRM_FILTER_MASK_FULL;
    939 
    940 		} else if (strcmp(*argv, "spi") == 0) {
    941 			__u32 spi;
    942 
    943 			NEXT_ARG();
    944 			if (get_u32(&spi, *argv, 0))
    945 				invarg("\"SPI\" is invalid", *argv);
    946 
    947 			spi = htonl(spi);
    948 			id->spi = spi;
    949 
    950 			filter.id_spi_mask = XFRM_FILTER_MASK_FULL;
    951 
    952 		} else {
    953 			PREV_ARG(); /* back track */
    954 			break;
    955 		}
    956 
    957 		if (!NEXT_ARG_OK())
    958 			break;
    959 		NEXT_ARG();
    960 	}
    961 
    962 	if (src.family && dst.family && (src.family != dst.family))
    963 		invarg("the same address family is required between \"src\" and \"dst\"", *argv);
    964 
    965 	if (loose == 0 && id->proto == 0)
    966 		missarg("XFRM_PROTO");
    967 	if (argc == *argcp)
    968 		missarg("ID");
    969 
    970 	*argcp = argc;
    971 	*argvp = argv;
    972 
    973 	return 0;
    974 }
    975 
    976 int xfrm_mode_parse(__u8 *mode, int *argcp, char ***argvp)
    977 {
    978 	int argc = *argcp;
    979 	char **argv = *argvp;
    980 
    981 	if (matches(*argv, "transport") == 0)
    982 		*mode = XFRM_MODE_TRANSPORT;
    983 	else if (matches(*argv, "tunnel") == 0)
    984 		*mode = XFRM_MODE_TUNNEL;
    985 	else if (matches(*argv, "ro") == 0)
    986 		*mode = XFRM_MODE_ROUTEOPTIMIZATION;
    987 	else if (matches(*argv, "in_trigger") == 0)
    988 		*mode = XFRM_MODE_IN_TRIGGER;
    989 	else if (matches(*argv, "beet") == 0)
    990 		*mode = XFRM_MODE_BEET;
    991 	else
    992 		invarg("\"MODE\" is invalid", *argv);
    993 
    994 	*argcp = argc;
    995 	*argvp = argv;
    996 
    997 	return 0;
    998 }
    999 
   1000 int xfrm_encap_type_parse(__u16 *type, int *argcp, char ***argvp)
   1001 {
   1002 	int argc = *argcp;
   1003 	char **argv = *argvp;
   1004 
   1005 	if (strcmp(*argv, "espinudp-nonike") == 0)
   1006 		*type = 1;
   1007 	else if (strcmp(*argv, "espinudp") == 0)
   1008 		*type = 2;
   1009 	else
   1010 		invarg("\"ENCAP-TYPE\" is invalid", *argv);
   1011 
   1012 	*argcp = argc;
   1013 	*argvp = argv;
   1014 
   1015 	return 0;
   1016 }
   1017 
   1018 /* NOTE: reqid is used by host-byte order */
   1019 int xfrm_reqid_parse(__u32 *reqid, int *argcp, char ***argvp)
   1020 {
   1021 	int argc = *argcp;
   1022 	char **argv = *argvp;
   1023 
   1024 	if (get_u32(reqid, *argv, 0))
   1025 		invarg("\"REQID\" is invalid", *argv);
   1026 
   1027 	*argcp = argc;
   1028 	*argvp = argv;
   1029 
   1030 	return 0;
   1031 }
   1032 
   1033 static int xfrm_selector_upspec_parse(struct xfrm_selector *sel,
   1034 				      int *argcp, char ***argvp)
   1035 {
   1036 	int argc = *argcp;
   1037 	char **argv = *argvp;
   1038 	char *sportp = NULL;
   1039 	char *dportp = NULL;
   1040 	char *typep = NULL;
   1041 	char *codep = NULL;
   1042 
   1043 	while (1) {
   1044 		if (strcmp(*argv, "proto") == 0) {
   1045 			__u8 upspec;
   1046 
   1047 			NEXT_ARG();
   1048 
   1049 			if (strcmp(*argv, "any") == 0)
   1050 				upspec = 0;
   1051 			else {
   1052 				struct protoent *pp;
   1053 				pp = getprotobyname(*argv);
   1054 				if (pp)
   1055 					upspec = pp->p_proto;
   1056 				else {
   1057 					if (get_u8(&upspec, *argv, 0))
   1058 						invarg("\"PROTO\" is invalid", *argv);
   1059 				}
   1060 			}
   1061 			sel->proto = upspec;
   1062 
   1063 			filter.upspec_proto_mask = XFRM_FILTER_MASK_FULL;
   1064 
   1065 		} else if (strcmp(*argv, "sport") == 0) {
   1066 			sportp = *argv;
   1067 
   1068 			NEXT_ARG();
   1069 
   1070 			if (get_u16(&sel->sport, *argv, 0))
   1071 				invarg("\"PORT\" is invalid", *argv);
   1072 			sel->sport = htons(sel->sport);
   1073 			if (sel->sport)
   1074 				sel->sport_mask = ~((__u16)0);
   1075 
   1076 			filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL;
   1077 
   1078 		} else if (strcmp(*argv, "dport") == 0) {
   1079 			dportp = *argv;
   1080 
   1081 			NEXT_ARG();
   1082 
   1083 			if (get_u16(&sel->dport, *argv, 0))
   1084 				invarg("\"PORT\" is invalid", *argv);
   1085 			sel->dport = htons(sel->dport);
   1086 			if (sel->dport)
   1087 				sel->dport_mask = ~((__u16)0);
   1088 
   1089 			filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;
   1090 
   1091 		} else if (strcmp(*argv, "type") == 0) {
   1092 			typep = *argv;
   1093 
   1094 			NEXT_ARG();
   1095 
   1096 			if (get_u16(&sel->sport, *argv, 0) ||
   1097 			    (sel->sport & ~((__u16)0xff)))
   1098 				invarg("\"type\" value is invalid", *argv);
   1099 			sel->sport = htons(sel->sport);
   1100 			sel->sport_mask = ~((__u16)0);
   1101 
   1102 			filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL;
   1103 
   1104 
   1105 		} else if (strcmp(*argv, "code") == 0) {
   1106 			codep = *argv;
   1107 
   1108 			NEXT_ARG();
   1109 
   1110 			if (get_u16(&sel->dport, *argv, 0) ||
   1111 			    (sel->dport & ~((__u16)0xff)))
   1112 				invarg("\"code\" value is invalid", *argv);
   1113 			sel->dport = htons(sel->dport);
   1114 			sel->dport_mask = ~((__u16)0);
   1115 
   1116 			filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;
   1117 
   1118 		} else {
   1119 			PREV_ARG(); /* back track */
   1120 			break;
   1121 		}
   1122 
   1123 		if (!NEXT_ARG_OK())
   1124 			break;
   1125 		NEXT_ARG();
   1126 	}
   1127 	if (argc == *argcp)
   1128 		missarg("UPSPEC");
   1129 	if (sportp || dportp) {
   1130 		switch (sel->proto) {
   1131 		case IPPROTO_TCP:
   1132 		case IPPROTO_UDP:
   1133 		case IPPROTO_SCTP:
   1134 		case IPPROTO_DCCP:
   1135 			break;
   1136 		default:
   1137 			fprintf(stderr, "\"sport\" and \"dport\" are invalid with proto=%s\n", strxf_proto(sel->proto));
   1138 			exit(1);
   1139 		}
   1140 	}
   1141 	if (typep || codep) {
   1142 		switch (sel->proto) {
   1143 		case IPPROTO_ICMP:
   1144 		case IPPROTO_ICMPV6:
   1145 		case IPPROTO_MH:
   1146 			break;
   1147 		default:
   1148 			fprintf(stderr, "\"type\" and \"code\" are invalid with proto=%s\n", strxf_proto(sel->proto));
   1149 			exit(1);
   1150 		}
   1151 	}
   1152 
   1153 	*argcp = argc;
   1154 	*argvp = argv;
   1155 
   1156 	return 0;
   1157 }
   1158 
   1159 int xfrm_selector_parse(struct xfrm_selector *sel, int *argcp, char ***argvp)
   1160 {
   1161 	int argc = *argcp;
   1162 	char **argv = *argvp;
   1163 	inet_prefix dst;
   1164 	inet_prefix src;
   1165 	char *upspecp = NULL;
   1166 
   1167 	memset(&dst, 0, sizeof(dst));
   1168 	memset(&src, 0, sizeof(src));
   1169 
   1170 	while (1) {
   1171 		if (strcmp(*argv, "src") == 0) {
   1172 			NEXT_ARG();
   1173 
   1174 			get_prefix(&src, *argv, preferred_family);
   1175 			if (src.family == AF_UNSPEC)
   1176 				invarg("\"src\" address family is AF_UNSPEC", *argv);
   1177 			sel->family = src.family;
   1178 
   1179 			memcpy(&sel->saddr, &src.data, sizeof(sel->saddr));
   1180 			sel->prefixlen_s = src.bitlen;
   1181 
   1182 			filter.sel_src_mask = src.bitlen;
   1183 
   1184 		} else if (strcmp(*argv, "dst") == 0) {
   1185 			NEXT_ARG();
   1186 
   1187 			get_prefix(&dst, *argv, preferred_family);
   1188 			if (dst.family == AF_UNSPEC)
   1189 				invarg("\"dst\" address family is AF_UNSPEC", *argv);
   1190 			sel->family = dst.family;
   1191 
   1192 			memcpy(&sel->daddr, &dst.data, sizeof(sel->daddr));
   1193 			sel->prefixlen_d = dst.bitlen;
   1194 
   1195 			filter.sel_dst_mask = dst.bitlen;
   1196 
   1197 		} else if (strcmp(*argv, "dev") == 0) {
   1198 			int ifindex;
   1199 
   1200 			NEXT_ARG();
   1201 
   1202 			if (strcmp(*argv, "none") == 0)
   1203 				ifindex = 0;
   1204 			else {
   1205 				ifindex = ll_name_to_index(*argv);
   1206 				if (ifindex <= 0)
   1207 					invarg("\"DEV\" is invalid", *argv);
   1208 			}
   1209 			sel->ifindex = ifindex;
   1210 
   1211 			filter.sel_dev_mask = XFRM_FILTER_MASK_FULL;
   1212 
   1213 		} else {
   1214 			if (upspecp) {
   1215 				PREV_ARG(); /* back track */
   1216 				break;
   1217 			} else {
   1218 				upspecp = *argv;
   1219 				xfrm_selector_upspec_parse(sel, &argc, &argv);
   1220 			}
   1221 		}
   1222 
   1223 		if (!NEXT_ARG_OK())
   1224 			break;
   1225 
   1226 		NEXT_ARG();
   1227 	}
   1228 
   1229 	if (src.family && dst.family && (src.family != dst.family))
   1230 		invarg("the same address family is required between \"src\" and \"dst\"", *argv);
   1231 
   1232 	if (argc == *argcp)
   1233 		missarg("SELECTOR");
   1234 
   1235 	*argcp = argc;
   1236 	*argvp = argv;
   1237 
   1238 	return 0;
   1239 }
   1240 
   1241 int xfrm_lifetime_cfg_parse(struct xfrm_lifetime_cfg *lft,
   1242 			    int *argcp, char ***argvp)
   1243 {
   1244 	int argc = *argcp;
   1245 	char **argv = *argvp;
   1246 	int ret;
   1247 
   1248 	if (strcmp(*argv, "time-soft") == 0) {
   1249 		NEXT_ARG();
   1250 		ret = get_u64(&lft->soft_add_expires_seconds, *argv, 0);
   1251 		if (ret)
   1252 			invarg("\"time-soft\" value is invalid", *argv);
   1253 	} else if (strcmp(*argv, "time-hard") == 0) {
   1254 		NEXT_ARG();
   1255 		ret = get_u64(&lft->hard_add_expires_seconds, *argv, 0);
   1256 		if (ret)
   1257 			invarg("\"time-hard\" value is invalid", *argv);
   1258 	} else if (strcmp(*argv, "time-use-soft") == 0) {
   1259 		NEXT_ARG();
   1260 		ret = get_u64(&lft->soft_use_expires_seconds, *argv, 0);
   1261 		if (ret)
   1262 			invarg("\"time-use-soft\" value is invalid", *argv);
   1263 	} else if (strcmp(*argv, "time-use-hard") == 0) {
   1264 		NEXT_ARG();
   1265 		ret = get_u64(&lft->hard_use_expires_seconds, *argv, 0);
   1266 		if (ret)
   1267 			invarg("\"time-use-hard\" value is invalid", *argv);
   1268 	} else if (strcmp(*argv, "byte-soft") == 0) {
   1269 		NEXT_ARG();
   1270 		ret = get_u64(&lft->soft_byte_limit, *argv, 0);
   1271 		if (ret)
   1272 			invarg("\"byte-soft\" value is invalid", *argv);
   1273 	} else if (strcmp(*argv, "byte-hard") == 0) {
   1274 		NEXT_ARG();
   1275 		ret = get_u64(&lft->hard_byte_limit, *argv, 0);
   1276 		if (ret)
   1277 			invarg("\"byte-hard\" value is invalid", *argv);
   1278 	} else if (strcmp(*argv, "packet-soft") == 0) {
   1279 		NEXT_ARG();
   1280 		ret = get_u64(&lft->soft_packet_limit, *argv, 0);
   1281 		if (ret)
   1282 			invarg("\"packet-soft\" value is invalid", *argv);
   1283 	} else if (strcmp(*argv, "packet-hard") == 0) {
   1284 		NEXT_ARG();
   1285 		ret = get_u64(&lft->hard_packet_limit, *argv, 0);
   1286 		if (ret)
   1287 			invarg("\"packet-hard\" value is invalid", *argv);
   1288 	} else
   1289 		invarg("\"LIMIT\" is invalid", *argv);
   1290 
   1291 	*argcp = argc;
   1292 	*argvp = argv;
   1293 
   1294 	return 0;
   1295 }
   1296 
   1297 int do_xfrm(int argc, char **argv)
   1298 {
   1299 	memset(&filter, 0, sizeof(filter));
   1300 
   1301 	if (argc < 1)
   1302 		usage();
   1303 
   1304 	if (matches(*argv, "state") == 0 ||
   1305 	    matches(*argv, "sa") == 0)
   1306 		return do_xfrm_state(argc-1, argv+1);
   1307 	else if (matches(*argv, "policy") == 0)
   1308 		return do_xfrm_policy(argc-1, argv+1);
   1309 	else if (matches(*argv, "monitor") == 0)
   1310 		return do_xfrm_monitor(argc-1, argv+1);
   1311 	else if (matches(*argv, "help") == 0) {
   1312 		usage();
   1313 		fprintf(stderr, "xfrm Object \"%s\" is unknown.\n", *argv);
   1314 		exit(-1);
   1315 	}
   1316 	usage();
   1317 }
   1318