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 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 <netdb.h>
     32 #include <linux/xfrm.h>
     33 #include "utils.h"
     34 #include "xfrm.h"
     35 #include "ip_common.h"
     36 
     37 //#define NLMSG_DELETEALL_BUF_SIZE (4096-512)
     38 #define NLMSG_DELETEALL_BUF_SIZE 8192
     39 
     40 /*
     41  * Receiving buffer defines:
     42  * nlmsg
     43  *   data = struct xfrm_usersa_info
     44  *   rtattr
     45  *   rtattr
     46  *   ... (max count of rtattr is XFRM_MAX+1
     47  *
     48  *  each rtattr data = struct xfrm_algo(dynamic size) or xfrm_address_t
     49  */
     50 #define NLMSG_BUF_SIZE 4096
     51 #define RTA_BUF_SIZE 2048
     52 #define XFRM_ALGO_KEY_BUF_SIZE 512
     53 
     54 static void usage(void) __attribute__((noreturn));
     55 
     56 static void usage(void)
     57 {
     58 	fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ XFRM_OPT ] [ mode MODE ]\n");
     59 	fprintf(stderr, "        [ reqid REQID ] [ seq SEQ ] [ replay-window SIZE ] [ flag FLAG-LIST ]\n");
     60 	fprintf(stderr, "        [ encap ENCAP ] [ sel SELECTOR ] [ replay-seq SEQ ]\n");
     61 	fprintf(stderr, "        [ replay-oseq SEQ ] [ LIMIT-LIST ]\n");
     62 	fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ reqid REQID ] [ seq SEQ ]\n");
     63 	fprintf(stderr, "        [ min SPI max SPI ]\n");
     64 	fprintf(stderr, "Usage: ip xfrm state { delete | get } ID\n");
     65 	fprintf(stderr, "Usage: ip xfrm state { deleteall | list } [ ID ] [ mode MODE ] [ reqid REQID ]\n");
     66 	fprintf(stderr, "        [ flag FLAG-LIST ]\n");
     67 	fprintf(stderr, "Usage: ip xfrm state flush [ proto XFRM_PROTO ]\n");
     68 	fprintf(stderr, "Usage: ip xfrm state count \n");
     69 
     70 	fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM_PROTO ] [ spi SPI ]\n");
     71 	//fprintf(stderr, "XFRM_PROTO := [ esp | ah | comp ]\n");
     72 	fprintf(stderr, "XFRM_PROTO := [ ");
     73 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
     74 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
     75 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
     76 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
     77 	fprintf(stderr, "%s ", strxf_xfrmproto(IPPROTO_DSTOPTS));
     78 	fprintf(stderr, "]\n");
     79 
     80 	//fprintf(stderr, "SPI - security parameter index(default=0)\n");
     81 
     82  	fprintf(stderr, "MODE := [ transport | tunnel | ro | beet ](default=transport)\n");
     83  	//fprintf(stderr, "REQID - number(default=0)\n");
     84 
     85 	fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
     86 	fprintf(stderr, "FLAG := [ noecn | decap-dscp | nopmtudisc | wildrecv ]\n");
     87 
     88         fprintf(stderr, "ENCAP := ENCAP-TYPE SPORT DPORT OADDR\n");
     89         fprintf(stderr, "ENCAP-TYPE := espinudp | espinudp-nonike\n");
     90 
     91 	fprintf(stderr, "ALGO-LIST := [ ALGO-LIST ] | [ ALGO ]\n");
     92 	fprintf(stderr, "ALGO := ALGO_TYPE ALGO_NAME ALGO_KEY "
     93 			"[ ALGO_ICV_LEN ]\n");
     94 	fprintf(stderr, "ALGO_TYPE := [ ");
     95 	fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AEAD));
     96 	fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_CRYPT));
     97 	fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AUTH));
     98 	fprintf(stderr, "%s ", strxf_algotype(XFRMA_ALG_COMP));
     99 	fprintf(stderr, "]\n");
    100 
    101 	//fprintf(stderr, "ALGO_NAME - algorithm name\n");
    102 	//fprintf(stderr, "ALGO_KEY - algorithm key\n");
    103 
    104 	fprintf(stderr, "SELECTOR := src ADDR[/PLEN] dst ADDR[/PLEN] [ UPSPEC ] [ dev DEV ]\n");
    105 
    106 	fprintf(stderr, "UPSPEC := proto PROTO [ [ sport PORT ] [ dport PORT ] |\n");
    107 	fprintf(stderr, "                        [ type NUMBER ] [ code NUMBER ] ]\n");
    108 
    109 
    110 	//fprintf(stderr, "DEV - device name(default=none)\n");
    111 	fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] | [ limit LIMIT ]\n");
    112 	fprintf(stderr, "LIMIT := [ [time-soft|time-hard|time-use-soft|time-use-hard] SECONDS ] |\n");
    113 	fprintf(stderr, "         [ [byte-soft|byte-hard] SIZE ] | [ [packet-soft|packet-hard] COUNT ]\n");
    114 	exit(-1);
    115 }
    116 
    117 static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
    118 			   char *name, char *key, char *buf, int max)
    119 {
    120 	int len;
    121 	int slen = strlen(key);
    122 
    123 #if 0
    124 	/* XXX: verifying both name and key is required! */
    125 	fprintf(stderr, "warning: ALGONAME/ALGOKEY will send to kernel promiscuously!(verifying them isn't implemented yet)\n");
    126 #endif
    127 
    128 	strncpy(alg->alg_name, name, sizeof(alg->alg_name));
    129 
    130 	if (slen > 2 && strncmp(key, "0x", 2) == 0) {
    131 		/* split two chars "0x" from the top */
    132 		char *p = key + 2;
    133 		int plen = slen - 2;
    134 		int i;
    135 		int j;
    136 
    137 		/* Converting hexadecimal numbered string into real key;
    138 		 * Convert each two chars into one char(value). If number
    139 		 * of the length is odd, add zero on the top for rounding.
    140 		 */
    141 
    142 		/* calculate length of the converted values(real key) */
    143 		len = (plen + 1) / 2;
    144 		if (len > max)
    145 			invarg("\"ALGOKEY\" makes buffer overflow\n", key);
    146 
    147 		for (i = - (plen % 2), j = 0; j < len; i += 2, j++) {
    148 			char vbuf[3];
    149 			__u8 val;
    150 
    151 			vbuf[0] = i >= 0 ? p[i] : '0';
    152 			vbuf[1] = p[i + 1];
    153 			vbuf[2] = '\0';
    154 
    155 			if (get_u8(&val, vbuf, 16))
    156 				invarg("\"ALGOKEY\" is invalid", key);
    157 
    158 			buf[j] = val;
    159 		}
    160 	} else {
    161 		len = slen;
    162 		if (len > 0) {
    163 			if (len > max)
    164 				invarg("\"ALGOKEY\" makes buffer overflow\n", key);
    165 
    166 			strncpy(buf, key, len);
    167 		}
    168 	}
    169 
    170 	alg->alg_key_len = len * 8;
    171 
    172 	return 0;
    173 }
    174 
    175 static int xfrm_seq_parse(__u32 *seq, int *argcp, char ***argvp)
    176 {
    177 	int argc = *argcp;
    178 	char **argv = *argvp;
    179 
    180 	if (get_u32(seq, *argv, 0))
    181 		invarg("\"SEQ\" is invalid", *argv);
    182 
    183 	*seq = htonl(*seq);
    184 
    185 	*argcp = argc;
    186 	*argvp = argv;
    187 
    188 	return 0;
    189 }
    190 
    191 static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
    192 {
    193 	int argc = *argcp;
    194 	char **argv = *argvp;
    195 	int len = strlen(*argv);
    196 
    197 	if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
    198 		__u8 val = 0;
    199 
    200 		if (get_u8(&val, *argv, 16))
    201 			invarg("\"FLAG\" is invalid", *argv);
    202 		*flags = val;
    203 	} else {
    204 		while (1) {
    205 			if (strcmp(*argv, "noecn") == 0)
    206 				*flags |= XFRM_STATE_NOECN;
    207 			else if (strcmp(*argv, "decap-dscp") == 0)
    208 				*flags |= XFRM_STATE_DECAP_DSCP;
    209 			else if (strcmp(*argv, "nopmtudisc") == 0)
    210 				*flags |= XFRM_STATE_NOPMTUDISC;
    211 			else if (strcmp(*argv, "wildrecv") == 0)
    212 				*flags |= XFRM_STATE_WILDRECV;
    213 			else {
    214 				PREV_ARG(); /* back track */
    215 				break;
    216 			}
    217 
    218 			if (!NEXT_ARG_OK())
    219 				break;
    220 			NEXT_ARG();
    221 		}
    222 	}
    223 
    224 	*argcp = argc;
    225 	*argvp = argv;
    226 
    227 	return 0;
    228 }
    229 
    230 static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
    231 {
    232 	struct rtnl_handle rth;
    233 	struct {
    234 		struct nlmsghdr 	n;
    235 		struct xfrm_usersa_info xsinfo;
    236 		char   			buf[RTA_BUF_SIZE];
    237 	} req;
    238 	struct xfrm_replay_state replay;
    239 	char *idp = NULL;
    240 	char *aeadop = NULL;
    241 	char *ealgop = NULL;
    242 	char *aalgop = NULL;
    243 	char *calgop = NULL;
    244 	char *coap = NULL;
    245 
    246 	memset(&req, 0, sizeof(req));
    247 	memset(&replay, 0, sizeof(replay));
    248 
    249 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo));
    250 	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
    251 	req.n.nlmsg_type = cmd;
    252 	req.xsinfo.family = preferred_family;
    253 
    254 	req.xsinfo.lft.soft_byte_limit = XFRM_INF;
    255 	req.xsinfo.lft.hard_byte_limit = XFRM_INF;
    256 	req.xsinfo.lft.soft_packet_limit = XFRM_INF;
    257 	req.xsinfo.lft.hard_packet_limit = XFRM_INF;
    258 
    259 	while (argc > 0) {
    260 		if (strcmp(*argv, "mode") == 0) {
    261 			NEXT_ARG();
    262 			xfrm_mode_parse(&req.xsinfo.mode, &argc, &argv);
    263 		} else if (strcmp(*argv, "reqid") == 0) {
    264 			NEXT_ARG();
    265 			xfrm_reqid_parse(&req.xsinfo.reqid, &argc, &argv);
    266 		} else if (strcmp(*argv, "seq") == 0) {
    267 			NEXT_ARG();
    268 			xfrm_seq_parse(&req.xsinfo.seq, &argc, &argv);
    269 		} else if (strcmp(*argv, "replay-window") == 0) {
    270 			NEXT_ARG();
    271 			if (get_u8(&req.xsinfo.replay_window, *argv, 0))
    272 				invarg("\"replay-window\" value is invalid", *argv);
    273 		} else if (strcmp(*argv, "replay-seq") == 0) {
    274 			NEXT_ARG();
    275 			if (get_u32(&replay.seq, *argv, 0))
    276 				invarg("\"replay-seq\" value is invalid", *argv);
    277 		} else if (strcmp(*argv, "replay-oseq") == 0) {
    278 			NEXT_ARG();
    279 			if (get_u32(&replay.oseq, *argv, 0))
    280 				invarg("\"replay-oseq\" value is invalid", *argv);
    281 		} else if (strcmp(*argv, "flag") == 0) {
    282 			NEXT_ARG();
    283 			xfrm_state_flag_parse(&req.xsinfo.flags, &argc, &argv);
    284 		} else if (strcmp(*argv, "sel") == 0) {
    285 			NEXT_ARG();
    286 			xfrm_selector_parse(&req.xsinfo.sel, &argc, &argv);
    287 		} else if (strcmp(*argv, "limit") == 0) {
    288 			NEXT_ARG();
    289 			xfrm_lifetime_cfg_parse(&req.xsinfo.lft, &argc, &argv);
    290 		} else if (strcmp(*argv, "encap") == 0) {
    291 			struct xfrm_encap_tmpl encap;
    292 			inet_prefix oa;
    293 		        NEXT_ARG();
    294 			xfrm_encap_type_parse(&encap.encap_type, &argc, &argv);
    295 			NEXT_ARG();
    296 			if (get_u16(&encap.encap_sport, *argv, 0))
    297 				invarg("\"encap\" sport value is invalid", *argv);
    298 			encap.encap_sport = htons(encap.encap_sport);
    299 			NEXT_ARG();
    300 			if (get_u16(&encap.encap_dport, *argv, 0))
    301 				invarg("\"encap\" dport value is invalid", *argv);
    302 			encap.encap_dport = htons(encap.encap_dport);
    303 			NEXT_ARG();
    304 			get_addr(&oa, *argv, AF_UNSPEC);
    305 			memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa));
    306 			addattr_l(&req.n, sizeof(req.buf), XFRMA_ENCAP,
    307 				  (void *)&encap, sizeof(encap));
    308 		} else if (strcmp(*argv, "coa") == 0) {
    309 			inet_prefix coa;
    310 			xfrm_address_t xcoa;
    311 
    312 			if (coap)
    313 				duparg("coa", *argv);
    314 			coap = *argv;
    315 
    316 			NEXT_ARG();
    317 
    318 			get_prefix(&coa, *argv, preferred_family);
    319 			if (coa.family == AF_UNSPEC)
    320 				invarg("\"coa\" address family is AF_UNSPEC", *argv);
    321 			if (coa.bytelen > sizeof(xcoa))
    322 				invarg("\"coa\" address length is too large", *argv);
    323 
    324 			memset(&xcoa, 0, sizeof(xcoa));
    325 			memcpy(&xcoa, &coa.data, coa.bytelen);
    326 
    327 			addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR,
    328 				  (void *)&xcoa, sizeof(xcoa));
    329 		} else {
    330 			/* try to assume ALGO */
    331 			int type = xfrm_algotype_getbyname(*argv);
    332 			switch (type) {
    333 			case XFRMA_ALG_AEAD:
    334 			case XFRMA_ALG_CRYPT:
    335 			case XFRMA_ALG_AUTH:
    336 			case XFRMA_ALG_COMP:
    337 			{
    338 				/* ALGO */
    339 				struct {
    340 					union {
    341 						struct xfrm_algo alg;
    342 						struct xfrm_algo_aead aead;
    343 					} u;
    344 					char buf[XFRM_ALGO_KEY_BUF_SIZE];
    345 				} alg = {};
    346 				int len;
    347 				__u32 icvlen;
    348 				char *name;
    349 				char *key;
    350 				char *buf;
    351 
    352 				switch (type) {
    353 				case XFRMA_ALG_AEAD:
    354 					if (aeadop)
    355 						duparg("ALGOTYPE", *argv);
    356 					aeadop = *argv;
    357 					break;
    358 				case XFRMA_ALG_CRYPT:
    359 					if (ealgop)
    360 						duparg("ALGOTYPE", *argv);
    361 					ealgop = *argv;
    362 					break;
    363 				case XFRMA_ALG_AUTH:
    364 					if (aalgop)
    365 						duparg("ALGOTYPE", *argv);
    366 					aalgop = *argv;
    367 					break;
    368 				case XFRMA_ALG_COMP:
    369 					if (calgop)
    370 						duparg("ALGOTYPE", *argv);
    371 					calgop = *argv;
    372 					break;
    373 				default:
    374 					/* not reached */
    375 					invarg("\"ALGOTYPE\" is invalid\n", *argv);
    376 				}
    377 
    378 				if (!NEXT_ARG_OK())
    379 					missarg("ALGONAME");
    380 				NEXT_ARG();
    381 				name = *argv;
    382 
    383 				if (!NEXT_ARG_OK())
    384 					missarg("ALGOKEY");
    385 				NEXT_ARG();
    386 				key = *argv;
    387 
    388 				buf = alg.u.alg.alg_key;
    389 				len = sizeof(alg.u.alg);
    390 
    391 				if (type != XFRMA_ALG_AEAD)
    392 					goto parse_algo;
    393 
    394 				if (!NEXT_ARG_OK())
    395 					missarg("ALGOICVLEN");
    396 				NEXT_ARG();
    397 				if (get_u32(&icvlen, *argv, 0))
    398 					invarg("\"aead\" ICV length is invalid",
    399 					       *argv);
    400 				alg.u.aead.alg_icv_len = icvlen;
    401 
    402 				buf = alg.u.aead.alg_key;
    403 				len = sizeof(alg.u.aead);
    404 
    405 parse_algo:
    406 				xfrm_algo_parse((void *)&alg, type, name, key,
    407 						buf, sizeof(alg.buf));
    408 				len += alg.u.alg.alg_key_len;
    409 
    410 				addattr_l(&req.n, sizeof(req.buf), type,
    411 					  (void *)&alg, len);
    412 				break;
    413 			}
    414 			default:
    415 				/* try to assume ID */
    416 				if (idp)
    417 					invarg("unknown", *argv);
    418 				idp = *argv;
    419 
    420 				/* ID */
    421 				xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id,
    422 					      &req.xsinfo.family, 0, &argc, &argv);
    423 				if (preferred_family == AF_UNSPEC)
    424 					preferred_family = req.xsinfo.family;
    425 			}
    426 		}
    427 		argc--; argv++;
    428 	}
    429 
    430 	if (replay.seq || replay.oseq)
    431 		addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_VAL,
    432 			  (void *)&replay, sizeof(replay));
    433 
    434 	if (!idp) {
    435 		fprintf(stderr, "Not enough information: \"ID\" is required\n");
    436 		exit(1);
    437 	}
    438 
    439 	switch (req.xsinfo.mode) {
    440 	case XFRM_MODE_TRANSPORT:
    441 	case XFRM_MODE_TUNNEL:
    442 		if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
    443 			fprintf(stderr, "\"mode\" is invalid with proto=%s\n",
    444 				strxf_xfrmproto(req.xsinfo.id.proto));
    445 			exit(1);
    446 		}
    447 		break;
    448 	case XFRM_MODE_ROUTEOPTIMIZATION:
    449 	case XFRM_MODE_IN_TRIGGER:
    450 		if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
    451 			fprintf(stderr, "\"mode\" is invalid with proto=%s\n",
    452 				strxf_xfrmproto(req.xsinfo.id.proto));
    453 			exit(1);
    454 		}
    455 		if (req.xsinfo.id.spi != 0) {
    456 			fprintf(stderr, "\"spi\" must be 0 with proto=%s\n",
    457 				strxf_xfrmproto(req.xsinfo.id.proto));
    458 			exit(1);
    459 		}
    460 		break;
    461 	default:
    462 		break;
    463 	}
    464 
    465 	if (aeadop || ealgop || aalgop || calgop) {
    466 		if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
    467 			fprintf(stderr, "\"ALGO\" is invalid with proto=%s\n",
    468 				strxf_xfrmproto(req.xsinfo.id.proto));
    469 			exit(1);
    470 		}
    471 	} else {
    472 		if (xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
    473 			fprintf(stderr, "\"ALGO\" is required with proto=%s\n",
    474 				strxf_xfrmproto(req.xsinfo.id.proto));
    475 			exit (1);
    476 		}
    477 	}
    478 
    479 	if (coap) {
    480 		if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
    481 			fprintf(stderr, "\"coa\" is invalid with proto=%s\n",
    482 				strxf_xfrmproto(req.xsinfo.id.proto));
    483 			exit(1);
    484 		}
    485 	} else {
    486 		if (xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
    487 			fprintf(stderr, "\"coa\" is required with proto=%s\n",
    488 				strxf_xfrmproto(req.xsinfo.id.proto));
    489 			exit (1);
    490 		}
    491 	}
    492 
    493 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    494 		exit(1);
    495 
    496 	if (req.xsinfo.family == AF_UNSPEC)
    497 		req.xsinfo.family = AF_INET;
    498 
    499 	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
    500 		exit(2);
    501 
    502 	rtnl_close(&rth);
    503 
    504 	return 0;
    505 }
    506 
    507 static int xfrm_state_allocspi(int argc, char **argv)
    508 {
    509 	struct rtnl_handle rth;
    510 	struct {
    511 		struct nlmsghdr 	n;
    512 		struct xfrm_userspi_info xspi;
    513 		char   			buf[RTA_BUF_SIZE];
    514 	} req;
    515 	char *idp = NULL;
    516 	char *minp = NULL;
    517 	char *maxp = NULL;
    518 	char res_buf[NLMSG_BUF_SIZE];
    519 	struct nlmsghdr *res_n = (struct nlmsghdr *)res_buf;
    520 
    521 	memset(res_buf, 0, sizeof(res_buf));
    522 
    523 	memset(&req, 0, sizeof(req));
    524 
    525 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xspi));
    526 	req.n.nlmsg_flags = NLM_F_REQUEST;
    527 	req.n.nlmsg_type = XFRM_MSG_ALLOCSPI;
    528 	req.xspi.info.family = preferred_family;
    529 
    530 #if 0
    531 	req.xsinfo.lft.soft_byte_limit = XFRM_INF;
    532 	req.xsinfo.lft.hard_byte_limit = XFRM_INF;
    533 	req.xsinfo.lft.soft_packet_limit = XFRM_INF;
    534 	req.xsinfo.lft.hard_packet_limit = XFRM_INF;
    535 #endif
    536 
    537 	while (argc > 0) {
    538 		if (strcmp(*argv, "mode") == 0) {
    539 			NEXT_ARG();
    540 			xfrm_mode_parse(&req.xspi.info.mode, &argc, &argv);
    541 		} else if (strcmp(*argv, "reqid") == 0) {
    542 			NEXT_ARG();
    543 			xfrm_reqid_parse(&req.xspi.info.reqid, &argc, &argv);
    544 		} else if (strcmp(*argv, "seq") == 0) {
    545 			NEXT_ARG();
    546 			xfrm_seq_parse(&req.xspi.info.seq, &argc, &argv);
    547 		} else if (strcmp(*argv, "min") == 0) {
    548 			if (minp)
    549 				duparg("min", *argv);
    550 			minp = *argv;
    551 
    552 			NEXT_ARG();
    553 
    554 			if (get_u32(&req.xspi.min, *argv, 0))
    555 				invarg("\"min\" value is invalid", *argv);
    556 		} else if (strcmp(*argv, "max") == 0) {
    557 			if (maxp)
    558 				duparg("max", *argv);
    559 			maxp = *argv;
    560 
    561 			NEXT_ARG();
    562 
    563 			if (get_u32(&req.xspi.max, *argv, 0))
    564 				invarg("\"max\" value is invalid", *argv);
    565 		} else {
    566 			/* try to assume ID */
    567 			if (idp)
    568 				invarg("unknown", *argv);
    569 			idp = *argv;
    570 
    571 			/* ID */
    572 			xfrm_id_parse(&req.xspi.info.saddr, &req.xspi.info.id,
    573 				      &req.xspi.info.family, 0, &argc, &argv);
    574 			if (req.xspi.info.id.spi) {
    575 				fprintf(stderr, "\"SPI\" must be zero\n");
    576 				exit(1);
    577 			}
    578 			if (preferred_family == AF_UNSPEC)
    579 				preferred_family = req.xspi.info.family;
    580 		}
    581 		argc--; argv++;
    582 	}
    583 
    584 	if (!idp) {
    585 		fprintf(stderr, "Not enough information: \"ID\" is required\n");
    586 		exit(1);
    587 	}
    588 
    589 	if (minp) {
    590 		if (!maxp) {
    591 			fprintf(stderr, "\"max\" is missing\n");
    592 			exit(1);
    593 		}
    594 		if (req.xspi.min > req.xspi.max) {
    595 			fprintf(stderr, "\"min\" valie is larger than \"max\" one\n");
    596 			exit(1);
    597 		}
    598 	} else {
    599 		if (maxp) {
    600 			fprintf(stderr, "\"min\" is missing\n");
    601 			exit(1);
    602 		}
    603 
    604 		/* XXX: Default value defined in PF_KEY;
    605 		 * See kernel's net/key/af_key.c(pfkey_getspi).
    606 		 */
    607 		req.xspi.min = 0x100;
    608 		req.xspi.max = 0x0fffffff;
    609 
    610 		/* XXX: IPCOMP spi is 16-bits;
    611 		 * See kernel's net/xfrm/xfrm_user(verify_userspi_info).
    612 		 */
    613 		if (req.xspi.info.id.proto == IPPROTO_COMP)
    614 			req.xspi.max = 0xffff;
    615 	}
    616 
    617 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    618 		exit(1);
    619 
    620 	if (req.xspi.info.family == AF_UNSPEC)
    621 		req.xspi.info.family = AF_INET;
    622 
    623 
    624 	if (rtnl_talk(&rth, &req.n, 0, 0, res_n, NULL, NULL) < 0)
    625 		exit(2);
    626 
    627 	if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
    628 		fprintf(stderr, "An error :-)\n");
    629 		exit(1);
    630 	}
    631 
    632 	rtnl_close(&rth);
    633 
    634 	return 0;
    635 }
    636 
    637 static int xfrm_state_filter_match(struct xfrm_usersa_info *xsinfo)
    638 {
    639 	if (!filter.use)
    640 		return 1;
    641 
    642 	if (filter.id_src_mask)
    643 		if (xfrm_addr_match(&xsinfo->saddr, &filter.xsinfo.saddr,
    644 				    filter.id_src_mask))
    645 			return 0;
    646 	if (filter.id_dst_mask)
    647 		if (xfrm_addr_match(&xsinfo->id.daddr, &filter.xsinfo.id.daddr,
    648 				    filter.id_dst_mask))
    649 			return 0;
    650 	if ((xsinfo->id.proto^filter.xsinfo.id.proto)&filter.id_proto_mask)
    651 		return 0;
    652 	if ((xsinfo->id.spi^filter.xsinfo.id.spi)&filter.id_spi_mask)
    653 		return 0;
    654 	if ((xsinfo->mode^filter.xsinfo.mode)&filter.mode_mask)
    655 		return 0;
    656 	if ((xsinfo->reqid^filter.xsinfo.reqid)&filter.reqid_mask)
    657 		return 0;
    658 	if (filter.state_flags_mask)
    659 		if ((xsinfo->flags & filter.xsinfo.flags) == 0)
    660 			return 0;
    661 
    662 	return 1;
    663 }
    664 
    665 int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
    666 		     void *arg)
    667 {
    668 	FILE *fp = (FILE*)arg;
    669 	struct rtattr * tb[XFRMA_MAX+1];
    670 	struct rtattr * rta;
    671 	struct xfrm_usersa_info *xsinfo = NULL;
    672 	struct xfrm_user_expire *xexp = NULL;
    673 	struct xfrm_usersa_id	*xsid = NULL;
    674 	int len = n->nlmsg_len;
    675 
    676 	if (n->nlmsg_type != XFRM_MSG_NEWSA &&
    677 	    n->nlmsg_type != XFRM_MSG_DELSA &&
    678 	    n->nlmsg_type != XFRM_MSG_UPDSA &&
    679 	    n->nlmsg_type != XFRM_MSG_EXPIRE) {
    680 		fprintf(stderr, "Not a state: %08x %08x %08x\n",
    681 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    682 		return 0;
    683 	}
    684 
    685 	if (n->nlmsg_type == XFRM_MSG_DELSA) {
    686 		/* Dont blame me for this .. Herbert made me do it */
    687 		xsid = NLMSG_DATA(n);
    688 		len -= NLMSG_SPACE(sizeof(*xsid));
    689 	} else if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
    690 		xexp = NLMSG_DATA(n);
    691 		xsinfo = &xexp->state;
    692 		len -= NLMSG_SPACE(sizeof(*xexp));
    693 	} else {
    694 		xexp = NULL;
    695 		xsinfo = NLMSG_DATA(n);
    696 		len -= NLMSG_SPACE(sizeof(*xsinfo));
    697 	}
    698 
    699 	if (len < 0) {
    700 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    701 		return -1;
    702 	}
    703 
    704 	if (xsinfo && !xfrm_state_filter_match(xsinfo))
    705 		return 0;
    706 
    707 	if (n->nlmsg_type == XFRM_MSG_DELSA)
    708 		fprintf(fp, "Deleted ");
    709 	else if (n->nlmsg_type == XFRM_MSG_UPDSA)
    710 		fprintf(fp, "Updated ");
    711 	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
    712 		fprintf(fp, "Expired ");
    713 
    714 	if (n->nlmsg_type == XFRM_MSG_DELSA)
    715 		rta = XFRMSID_RTA(xsid);
    716 	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
    717 		rta = XFRMEXP_RTA(xexp);
    718 	else
    719 		rta = XFRMS_RTA(xsinfo);
    720 
    721 	parse_rtattr(tb, XFRMA_MAX, rta, len);
    722 
    723 	if (n->nlmsg_type == XFRM_MSG_DELSA) {
    724 		//xfrm_policy_id_print();
    725 
    726 		if (!tb[XFRMA_SA]) {
    727 			fprintf(stderr, "Buggy XFRM_MSG_DELSA: no XFRMA_SA\n");
    728 			return -1;
    729 		}
    730 		if (RTA_PAYLOAD(tb[XFRMA_SA]) < sizeof(*xsinfo)) {
    731 			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
    732 			return -1;
    733 		}
    734 		xsinfo = RTA_DATA(tb[XFRMA_SA]);
    735 	}
    736 
    737 	xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL);
    738 
    739 	if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
    740 		fprintf(fp, "\t");
    741 		fprintf(fp, "hard %u", xexp->hard);
    742 		fprintf(fp, "%s", _SL_);
    743 	}
    744 
    745 	if (oneline)
    746 		fprintf(fp, "\n");
    747 	fflush(fp);
    748 
    749 	return 0;
    750 }
    751 
    752 static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
    753 {
    754 	struct rtnl_handle rth;
    755 	struct {
    756 		struct nlmsghdr 	n;
    757 		struct xfrm_usersa_id	xsid;
    758 		char   			buf[RTA_BUF_SIZE];
    759 	} req;
    760 	struct xfrm_id id;
    761 	char *idp = NULL;
    762 
    763 	memset(&req, 0, sizeof(req));
    764 
    765 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid));
    766 	req.n.nlmsg_flags = NLM_F_REQUEST;
    767 	req.n.nlmsg_type = delete ? XFRM_MSG_DELSA : XFRM_MSG_GETSA;
    768 	req.xsid.family = preferred_family;
    769 
    770 	while (argc > 0) {
    771 		xfrm_address_t saddr;
    772 
    773 		if (idp)
    774 			invarg("unknown", *argv);
    775 		idp = *argv;
    776 
    777 		/* ID */
    778 		memset(&id, 0, sizeof(id));
    779 		memset(&saddr, 0, sizeof(saddr));
    780 		xfrm_id_parse(&saddr, &id, &req.xsid.family, 0,
    781 			      &argc, &argv);
    782 
    783 		memcpy(&req.xsid.daddr, &id.daddr, sizeof(req.xsid.daddr));
    784 		req.xsid.spi = id.spi;
    785 		req.xsid.proto = id.proto;
    786 
    787 		addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
    788 			  (void *)&saddr, sizeof(saddr));
    789 
    790 		argc--; argv++;
    791 	}
    792 
    793 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    794 		exit(1);
    795 
    796 	if (req.xsid.family == AF_UNSPEC)
    797 		req.xsid.family = AF_INET;
    798 
    799 	if (delete) {
    800 		if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
    801 			exit(2);
    802 	} else {
    803 		char buf[NLMSG_BUF_SIZE];
    804 		struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
    805 
    806 		memset(buf, 0, sizeof(buf));
    807 
    808 		if (rtnl_talk(&rth, &req.n, 0, 0, res_n, NULL, NULL) < 0)
    809 			exit(2);
    810 
    811 		if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
    812 			fprintf(stderr, "An error :-)\n");
    813 			exit(1);
    814 		}
    815 	}
    816 
    817 	rtnl_close(&rth);
    818 
    819 	return 0;
    820 }
    821 
    822 /*
    823  * With an existing state of nlmsg, make new nlmsg for deleting the state
    824  * and store it to buffer.
    825  */
    826 static int xfrm_state_keep(const struct sockaddr_nl *who,
    827 			   struct nlmsghdr *n,
    828 			   void *arg)
    829 {
    830 	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
    831 	struct rtnl_handle *rth = xb->rth;
    832 	struct xfrm_usersa_info *xsinfo = NLMSG_DATA(n);
    833 	int len = n->nlmsg_len;
    834 	struct nlmsghdr *new_n;
    835 	struct xfrm_usersa_id *xsid;
    836 
    837 	if (n->nlmsg_type != XFRM_MSG_NEWSA) {
    838 		fprintf(stderr, "Not a state: %08x %08x %08x\n",
    839 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    840 		return 0;
    841 	}
    842 
    843 	len -= NLMSG_LENGTH(sizeof(*xsinfo));
    844 	if (len < 0) {
    845 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    846 		return -1;
    847 	}
    848 
    849 	if (!xfrm_state_filter_match(xsinfo))
    850 		return 0;
    851 
    852 	if (xb->offset > xb->size) {
    853 		fprintf(stderr, "State buffer overflow\n");
    854 		return -1;
    855 	}
    856 
    857 	new_n = (struct nlmsghdr *)(xb->buf + xb->offset);
    858 	new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xsid));
    859 	new_n->nlmsg_flags = NLM_F_REQUEST;
    860 	new_n->nlmsg_type = XFRM_MSG_DELSA;
    861 	new_n->nlmsg_seq = ++rth->seq;
    862 
    863 	xsid = NLMSG_DATA(new_n);
    864 	xsid->family = xsinfo->family;
    865 	memcpy(&xsid->daddr, &xsinfo->id.daddr, sizeof(xsid->daddr));
    866 	xsid->spi = xsinfo->id.spi;
    867 	xsid->proto = xsinfo->id.proto;
    868 
    869 	addattr_l(new_n, xb->size, XFRMA_SRCADDR, &xsinfo->saddr,
    870 		  sizeof(xsid->daddr));
    871 
    872 	xb->offset += new_n->nlmsg_len;
    873 	xb->nlmsg_count ++;
    874 
    875 	return 0;
    876 }
    877 
    878 static int xfrm_state_list_or_deleteall(int argc, char **argv, int deleteall)
    879 {
    880 	char *idp = NULL;
    881 	struct rtnl_handle rth;
    882 
    883 	if(argc > 0)
    884 		filter.use = 1;
    885 	filter.xsinfo.family = preferred_family;
    886 
    887 	while (argc > 0) {
    888 		if (strcmp(*argv, "mode") == 0) {
    889 			NEXT_ARG();
    890 			xfrm_mode_parse(&filter.xsinfo.mode, &argc, &argv);
    891 
    892 			filter.mode_mask = XFRM_FILTER_MASK_FULL;
    893 
    894 		} else if (strcmp(*argv, "reqid") == 0) {
    895 			NEXT_ARG();
    896 			xfrm_reqid_parse(&filter.xsinfo.reqid, &argc, &argv);
    897 
    898 			filter.reqid_mask = XFRM_FILTER_MASK_FULL;
    899 
    900 		} else if (strcmp(*argv, "flag") == 0) {
    901 			NEXT_ARG();
    902 			xfrm_state_flag_parse(&filter.xsinfo.flags, &argc, &argv);
    903 
    904 			filter.state_flags_mask = XFRM_FILTER_MASK_FULL;
    905 
    906 		} else {
    907 			if (idp)
    908 				invarg("unknown", *argv);
    909 			idp = *argv;
    910 
    911 			/* ID */
    912 			xfrm_id_parse(&filter.xsinfo.saddr, &filter.xsinfo.id,
    913 				      &filter.xsinfo.family, 1, &argc, &argv);
    914 			if (preferred_family == AF_UNSPEC)
    915 				preferred_family = filter.xsinfo.family;
    916 		}
    917 		argc--; argv++;
    918 	}
    919 
    920 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    921 		exit(1);
    922 
    923 	if (deleteall) {
    924 		struct xfrm_buffer xb;
    925 		char buf[NLMSG_DELETEALL_BUF_SIZE];
    926 		int i;
    927 
    928 		xb.buf = buf;
    929 		xb.size = sizeof(buf);
    930 		xb.rth = &rth;
    931 
    932 		for (i = 0; ; i++) {
    933 			xb.offset = 0;
    934 			xb.nlmsg_count = 0;
    935 
    936 			if (show_stats > 1)
    937 				fprintf(stderr, "Delete-all round = %d\n", i);
    938 
    939 			if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETSA) < 0) {
    940 				perror("Cannot send dump request");
    941 				exit(1);
    942 			}
    943 
    944 			if (rtnl_dump_filter(&rth, xfrm_state_keep, &xb, NULL, NULL) < 0) {
    945 				fprintf(stderr, "Delete-all terminated\n");
    946 				exit(1);
    947 			}
    948 			if (xb.nlmsg_count == 0) {
    949 				if (show_stats > 1)
    950 					fprintf(stderr, "Delete-all completed\n");
    951 				break;
    952 			}
    953 
    954 			if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) {
    955 				perror("Failed to send delete-all request\n");
    956 				exit(1);
    957 			}
    958 			if (show_stats > 1)
    959 				fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);
    960 
    961 			xb.offset = 0;
    962 			xb.nlmsg_count = 0;
    963 		}
    964 
    965 	} else {
    966 		if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETSA) < 0) {
    967 			perror("Cannot send dump request");
    968 			exit(1);
    969 		}
    970 
    971 		if (rtnl_dump_filter(&rth, xfrm_state_print, stdout, NULL, NULL) < 0) {
    972 			fprintf(stderr, "Dump terminated\n");
    973 			exit(1);
    974 		}
    975 	}
    976 
    977 	rtnl_close(&rth);
    978 
    979 	exit(0);
    980 }
    981 
    982 int print_sadinfo(struct nlmsghdr *n, void *arg)
    983 {
    984 	FILE *fp = (FILE*)arg;
    985 	__u32 *f = NLMSG_DATA(n);
    986 	struct rtattr *tb[XFRMA_SAD_MAX+1];
    987 	struct rtattr *rta;
    988 	__u32 *cnt;
    989 
    990 	int len = n->nlmsg_len;
    991 
    992 	len -= NLMSG_LENGTH(sizeof(__u32));
    993 	if (len < 0) {
    994 		fprintf(stderr, "SADinfo: Wrong len %d\n", len);
    995 		return -1;
    996 	}
    997 
    998 	rta = XFRMSAPD_RTA(f);
    999 	parse_rtattr(tb, XFRMA_SAD_MAX, rta, len);
   1000 
   1001 	if (tb[XFRMA_SAD_CNT]) {
   1002 		fprintf(fp,"\t SAD");
   1003 		cnt = (__u32 *)RTA_DATA(tb[XFRMA_SAD_CNT]);
   1004 		fprintf(fp," count %d", *cnt);
   1005 	} else {
   1006 		fprintf(fp,"BAD SAD info returned\n");
   1007 		return -1;
   1008 	}
   1009 
   1010 	if (show_stats) {
   1011 		if (tb[XFRMA_SAD_HINFO]) {
   1012 			struct xfrmu_sadhinfo *si;
   1013 
   1014 			if (RTA_PAYLOAD(tb[XFRMA_SAD_HINFO]) < sizeof(*si)) {
   1015 				fprintf(fp,"BAD SAD length returned\n");
   1016 				return -1;
   1017 			}
   1018 
   1019 			si = RTA_DATA(tb[XFRMA_SAD_HINFO]);
   1020 			fprintf(fp," (buckets ");
   1021 			fprintf(fp,"count %d", si->sadhcnt);
   1022 			fprintf(fp," Max %d", si->sadhmcnt);
   1023 			fprintf(fp,")");
   1024 		}
   1025 	}
   1026 	fprintf(fp,"\n");
   1027 
   1028         return 0;
   1029 }
   1030 
   1031 static int xfrm_sad_getinfo(int argc, char **argv)
   1032 {
   1033 	struct rtnl_handle rth;
   1034 	struct {
   1035 		struct nlmsghdr			n;
   1036 		__u32				flags;
   1037 		char				ans[64];
   1038 	} req;
   1039 
   1040 	memset(&req, 0, sizeof(req));
   1041 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.flags));
   1042 	req.n.nlmsg_flags = NLM_F_REQUEST;
   1043 	req.n.nlmsg_type = XFRM_MSG_GETSADINFO;
   1044 	req.flags = 0XFFFFFFFF;
   1045 
   1046 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
   1047 		exit(1);
   1048 
   1049 	if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
   1050 		exit(2);
   1051 
   1052 	print_sadinfo(&req.n, (void*)stdout);
   1053 
   1054 	rtnl_close(&rth);
   1055 
   1056 	return 0;
   1057 }
   1058 
   1059 static int xfrm_state_flush(int argc, char **argv)
   1060 {
   1061 	struct rtnl_handle rth;
   1062 	struct {
   1063 		struct nlmsghdr			n;
   1064 		struct xfrm_usersa_flush	xsf;
   1065 	} req;
   1066 	char *protop = NULL;
   1067 
   1068 	memset(&req, 0, sizeof(req));
   1069 
   1070 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsf));
   1071 	req.n.nlmsg_flags = NLM_F_REQUEST;
   1072 	req.n.nlmsg_type = XFRM_MSG_FLUSHSA;
   1073 	req.xsf.proto = 0;
   1074 
   1075 	while (argc > 0) {
   1076 		if (strcmp(*argv, "proto") == 0) {
   1077 			int ret;
   1078 
   1079 			if (protop)
   1080 				duparg("proto", *argv);
   1081 			protop = *argv;
   1082 
   1083 			NEXT_ARG();
   1084 
   1085 			ret = xfrm_xfrmproto_getbyname(*argv);
   1086 			if (ret < 0)
   1087 				invarg("\"XFRM_PROTO\" is invalid", *argv);
   1088 
   1089 			req.xsf.proto = (__u8)ret;
   1090 		} else
   1091 			invarg("unknown", *argv);
   1092 
   1093 		argc--; argv++;
   1094 	}
   1095 
   1096 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
   1097 		exit(1);
   1098 
   1099 	if (show_stats > 1)
   1100 		fprintf(stderr, "Flush state proto=%s\n",
   1101 			strxf_xfrmproto(req.xsf.proto));
   1102 
   1103 	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
   1104 		exit(2);
   1105 
   1106 	rtnl_close(&rth);
   1107 
   1108 	return 0;
   1109 }
   1110 
   1111 int do_xfrm_state(int argc, char **argv)
   1112 {
   1113 	if (argc < 1)
   1114 		return xfrm_state_list_or_deleteall(0, NULL, 0);
   1115 
   1116 	if (matches(*argv, "add") == 0)
   1117 		return xfrm_state_modify(XFRM_MSG_NEWSA, 0,
   1118 					 argc-1, argv+1);
   1119 	if (matches(*argv, "update") == 0)
   1120 		return xfrm_state_modify(XFRM_MSG_UPDSA, 0,
   1121 					 argc-1, argv+1);
   1122 	if (matches(*argv, "allocspi") == 0)
   1123 		return xfrm_state_allocspi(argc-1, argv+1);
   1124 	if (matches(*argv, "delete") == 0)
   1125 		return xfrm_state_get_or_delete(argc-1, argv+1, 1);
   1126 	if (matches(*argv, "deleteall") == 0 || matches(*argv, "delall") == 0)
   1127 		return xfrm_state_list_or_deleteall(argc-1, argv+1, 1);
   1128 	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
   1129 	    || matches(*argv, "lst") == 0)
   1130 		return xfrm_state_list_or_deleteall(argc-1, argv+1, 0);
   1131 	if (matches(*argv, "get") == 0)
   1132 		return xfrm_state_get_or_delete(argc-1, argv+1, 0);
   1133 	if (matches(*argv, "flush") == 0)
   1134 		return xfrm_state_flush(argc-1, argv+1);
   1135 	if (matches(*argv, "count") == 0) {
   1136 		return xfrm_sad_getinfo(argc, argv);
   1137 	}
   1138 	if (matches(*argv, "help") == 0)
   1139 		usage();
   1140 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm state help\".\n", *argv);
   1141 	exit(-1);
   1142 }
   1143