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