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