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, see <http://www.gnu.org/licenses>.
     18  */
     19 /*
     20  * based on iproute.c
     21  */
     22 /*
     23  * Authors:
     24  *	Masahide NAKAMURA @USAGI
     25  */
     26 
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <netdb.h>
     31 #include "utils.h"
     32 #include "xfrm.h"
     33 #include "ip_common.h"
     34 
     35 /* #define NLMSG_DELETEALL_BUF_SIZE (4096-512) */
     36 #define NLMSG_DELETEALL_BUF_SIZE 8192
     37 
     38 /*
     39  * Receiving buffer defines:
     40  * nlmsg
     41  *   data = struct xfrm_usersa_info
     42  *   rtattr
     43  *   rtattr
     44  *   ... (max count of rtattr is XFRM_MAX+1
     45  *
     46  *  each rtattr data = struct xfrm_algo(dynamic size) or xfrm_address_t
     47  */
     48 #define NLMSG_BUF_SIZE 4096
     49 #define RTA_BUF_SIZE 2048
     50 #define XFRM_ALGO_KEY_BUF_SIZE 512
     51 #define CTX_BUF_SIZE 256
     52 
     53 static void usage(void) __attribute__((noreturn));
     54 
     55 static void usage(void)
     56 {
     57 	fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ ALGO-LIST ] [ mode MODE ]\n");
     58 	fprintf(stderr, "        [ mark MARK [ mask MASK ] ] [ reqid REQID ] [ seq SEQ ]\n");
     59 	fprintf(stderr, "        [ replay-window SIZE ] [ replay-seq SEQ ] [ replay-oseq SEQ ]\n");
     60 	fprintf(stderr, "        [ replay-seq-hi SEQ ] [ replay-oseq-hi SEQ ]\n");
     61 	fprintf(stderr, "        [ flag FLAG-LIST ] [ sel SELECTOR ] [ LIMIT-LIST ] [ encap ENCAP ]\n");
     62 	fprintf(stderr, "        [ coa ADDR[/PLEN] ] [ ctx CTX ] [ extra-flag EXTRA-FLAG-LIST ]\n");
     63 	fprintf(stderr, "        [ offload [dev DEV] dir DIR ]\n");
     64 	fprintf(stderr, "        [ output-mark OUTPUT-MARK ]\n");
     65 	fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ mark MARK [ mask MASK ] ]\n");
     66 	fprintf(stderr, "        [ reqid REQID ] [ seq SEQ ] [ min SPI max SPI ]\n");
     67 	fprintf(stderr, "Usage: ip xfrm state { delete | get } ID [ mark MARK [ mask MASK ] ]\n");
     68 	fprintf(stderr, "Usage: ip xfrm state { deleteall | list } [ ID ] [ mode MODE ] [ reqid REQID ]\n");
     69 	fprintf(stderr, "        [ flag FLAG-LIST ]\n");
     70 	fprintf(stderr, "Usage: ip xfrm state flush [ proto XFRM-PROTO ]\n");
     71 	fprintf(stderr, "Usage: ip xfrm state count\n");
     72 	fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ]\n");
     73 	fprintf(stderr, "XFRM-PROTO := ");
     74 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
     75 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
     76 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
     77 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
     78 	fprintf(stderr, "%s\n", strxf_xfrmproto(IPPROTO_DSTOPTS));
     79 	fprintf(stderr, "ALGO-LIST := [ ALGO-LIST ] ALGO\n");
     80 	fprintf(stderr, "ALGO := { ");
     81 	fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_CRYPT));
     82 	fprintf(stderr, "%s", strxf_algotype(XFRMA_ALG_AUTH));
     83 	fprintf(stderr, " } ALGO-NAME ALGO-KEYMAT |\n");
     84 	fprintf(stderr, "        %s", strxf_algotype(XFRMA_ALG_AUTH_TRUNC));
     85 	fprintf(stderr, " ALGO-NAME ALGO-KEYMAT ALGO-TRUNC-LEN |\n");
     86 	fprintf(stderr, "        %s", strxf_algotype(XFRMA_ALG_AEAD));
     87 	fprintf(stderr, " ALGO-NAME ALGO-KEYMAT ALGO-ICV-LEN |\n");
     88 	fprintf(stderr, "        %s", strxf_algotype(XFRMA_ALG_COMP));
     89 	fprintf(stderr, " ALGO-NAME\n");
     90 	fprintf(stderr, "MODE := transport | tunnel | beet | ro | in_trigger\n");
     91 	fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
     92 	fprintf(stderr, "FLAG := noecn | decap-dscp | nopmtudisc | wildrecv | icmp | af-unspec | align4 | esn\n");
     93 	fprintf(stderr, "EXTRA-FLAG-LIST := [ EXTRA-FLAG-LIST ] EXTRA-FLAG\n");
     94 	fprintf(stderr, "EXTRA-FLAG := dont-encap-dscp\n");
     95 	fprintf(stderr, "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n");
     96 	fprintf(stderr, "UPSPEC := proto { { ");
     97 	fprintf(stderr, "%s | ", strxf_proto(IPPROTO_TCP));
     98 	fprintf(stderr, "%s | ", strxf_proto(IPPROTO_UDP));
     99 	fprintf(stderr, "%s | ", strxf_proto(IPPROTO_SCTP));
    100 	fprintf(stderr, "%s", strxf_proto(IPPROTO_DCCP));
    101 	fprintf(stderr, " } [ sport PORT ] [ dport PORT ] |\n");
    102 	fprintf(stderr, "                  { ");
    103 	fprintf(stderr, "%s | ", strxf_proto(IPPROTO_ICMP));
    104 	fprintf(stderr, "%s | ", strxf_proto(IPPROTO_ICMPV6));
    105 	fprintf(stderr, "%s", strxf_proto(IPPROTO_MH));
    106 	fprintf(stderr, " } [ type NUMBER ] [ code NUMBER ] |\n");
    107 	fprintf(stderr, "                  %s", strxf_proto(IPPROTO_GRE));
    108 	fprintf(stderr, " [ key { DOTTED-QUAD | NUMBER } ] | PROTO }\n");
    109 	fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] limit LIMIT\n");
    110 	fprintf(stderr, "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n");
    111 	fprintf(stderr, "         { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n");
    112 	fprintf(stderr, "ENCAP := { espinudp | espinudp-nonike } SPORT DPORT OADDR\n");
    113 	fprintf(stderr, "DIR := in | out\n");
    114 
    115 	exit(-1);
    116 }
    117 
    118 static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
    119 			   char *name, char *key, char *buf, int max)
    120 {
    121 	int len;
    122 	int slen = strlen(key);
    123 
    124 #if 0
    125 	/* XXX: verifying both name and key is required! */
    126 	fprintf(stderr, "warning: ALGO-NAME/ALGO-KEYMAT values will be sent to the kernel promiscuously! (verifying them isn't implemented yet)\n");
    127 #endif
    128 
    129 	strlcpy(alg->alg_name, name, sizeof(alg->alg_name));
    130 
    131 	if (slen > 2 && strncmp(key, "0x", 2) == 0) {
    132 		/* split two chars "0x" from the top */
    133 		char *p = key + 2;
    134 		int plen = slen - 2;
    135 		int i;
    136 		int j;
    137 
    138 		/* Converting hexadecimal numbered string into real key;
    139 		 * Convert each two chars into one char(value). If number
    140 		 * of the length is odd, add zero on the top for rounding.
    141 		 */
    142 
    143 		/* calculate length of the converted values(real key) */
    144 		len = (plen + 1) / 2;
    145 		if (len > max)
    146 			invarg("ALGO-KEYMAT value makes buffer overflow\n", key);
    147 
    148 		for (i = -(plen % 2), j = 0; j < len; i += 2, j++) {
    149 			char vbuf[3];
    150 			__u8 val;
    151 
    152 			vbuf[0] = i >= 0 ? p[i] : '0';
    153 			vbuf[1] = p[i + 1];
    154 			vbuf[2] = '\0';
    155 
    156 			if (get_u8(&val, vbuf, 16))
    157 				invarg("ALGO-KEYMAT value is invalid", key);
    158 
    159 			buf[j] = val;
    160 		}
    161 	} else {
    162 		len = slen;
    163 		if (len > 0) {
    164 			if (len > max)
    165 				invarg("ALGO-KEYMAT value makes buffer overflow\n", key);
    166 
    167 			memcpy(buf, key, len);
    168 		}
    169 	}
    170 
    171 	alg->alg_key_len = len * 8;
    172 
    173 	return 0;
    174 }
    175 
    176 static int xfrm_seq_parse(__u32 *seq, int *argcp, char ***argvp)
    177 {
    178 	int argc = *argcp;
    179 	char **argv = *argvp;
    180 
    181 	if (get_be32(seq, *argv, 0))
    182 		invarg("SEQ value is invalid", *argv);
    183 
    184 	*argcp = argc;
    185 	*argvp = argv;
    186 
    187 	return 0;
    188 }
    189 
    190 static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
    191 {
    192 	int argc = *argcp;
    193 	char **argv = *argvp;
    194 	int len = strlen(*argv);
    195 
    196 	if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
    197 		__u8 val = 0;
    198 
    199 		if (get_u8(&val, *argv, 16))
    200 			invarg("FLAG value is invalid", *argv);
    201 		*flags = val;
    202 	} else {
    203 		while (1) {
    204 			if (strcmp(*argv, "noecn") == 0)
    205 				*flags |= XFRM_STATE_NOECN;
    206 			else if (strcmp(*argv, "decap-dscp") == 0)
    207 				*flags |= XFRM_STATE_DECAP_DSCP;
    208 			else if (strcmp(*argv, "nopmtudisc") == 0)
    209 				*flags |= XFRM_STATE_NOPMTUDISC;
    210 			else if (strcmp(*argv, "wildrecv") == 0)
    211 				*flags |= XFRM_STATE_WILDRECV;
    212 			else if (strcmp(*argv, "icmp") == 0)
    213 				*flags |= XFRM_STATE_ICMP;
    214 			else if (strcmp(*argv, "af-unspec") == 0)
    215 				*flags |= XFRM_STATE_AF_UNSPEC;
    216 			else if (strcmp(*argv, "align4") == 0)
    217 				*flags |= XFRM_STATE_ALIGN4;
    218 			else if (strcmp(*argv, "esn") == 0)
    219 				*flags |= XFRM_STATE_ESN;
    220 			else {
    221 				PREV_ARG(); /* back track */
    222 				break;
    223 			}
    224 
    225 			if (!NEXT_ARG_OK())
    226 				break;
    227 			NEXT_ARG();
    228 		}
    229 	}
    230 
    231 	*argcp = argc;
    232 	*argvp = argv;
    233 
    234 	return 0;
    235 }
    236 
    237 static int xfrm_state_extra_flag_parse(__u32 *extra_flags, int *argcp, char ***argvp)
    238 {
    239 	int argc = *argcp;
    240 	char **argv = *argvp;
    241 	int len = strlen(*argv);
    242 
    243 	if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
    244 		__u32 val = 0;
    245 
    246 		if (get_u32(&val, *argv, 16))
    247 			invarg("\"EXTRA-FLAG\" is invalid", *argv);
    248 		*extra_flags = val;
    249 	} else {
    250 		while (1) {
    251 			if (strcmp(*argv, "dont-encap-dscp") == 0)
    252 				*extra_flags |= XFRM_SA_XFLAG_DONT_ENCAP_DSCP;
    253 			else {
    254 				PREV_ARG(); /* back track */
    255 				break;
    256 			}
    257 
    258 			if (!NEXT_ARG_OK())
    259 				break;
    260 			NEXT_ARG();
    261 		}
    262 	}
    263 
    264 	*argcp = argc;
    265 	*argvp = argv;
    266 
    267 	return 0;
    268 }
    269 
    270 static int xfrm_offload_dir_parse(__u8 *dir, int *argcp, char ***argvp)
    271 {
    272 	int argc = *argcp;
    273 	char **argv = *argvp;
    274 
    275 	if (strcmp(*argv, "in") == 0)
    276 		*dir = XFRM_OFFLOAD_INBOUND;
    277 	else if (strcmp(*argv, "out") == 0)
    278 		*dir = 0;
    279 	else
    280 		invarg("DIR value is invalid", *argv);
    281 
    282 	*argcp = argc;
    283 	*argvp = argv;
    284 
    285 	return 0;
    286 }
    287 
    288 static int xfrm_state_modify(int cmd, unsigned int flags, int argc, char **argv)
    289 {
    290 	struct rtnl_handle rth;
    291 	struct {
    292 		struct nlmsghdr	n;
    293 		struct xfrm_usersa_info xsinfo;
    294 		char			buf[RTA_BUF_SIZE];
    295 	} req = {
    296 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo)),
    297 		.n.nlmsg_flags = NLM_F_REQUEST | flags,
    298 		.n.nlmsg_type = cmd,
    299 		.xsinfo.family = preferred_family,
    300 		.xsinfo.lft.soft_byte_limit = XFRM_INF,
    301 		.xsinfo.lft.hard_byte_limit = XFRM_INF,
    302 		.xsinfo.lft.soft_packet_limit = XFRM_INF,
    303 		.xsinfo.lft.hard_packet_limit = XFRM_INF,
    304 	};
    305 	struct xfrm_replay_state replay = {};
    306 	struct xfrm_replay_state_esn replay_esn = {};
    307 	struct xfrm_user_offload xuo = {};
    308 	unsigned int ifindex = 0;
    309 	__u8 dir = 0;
    310 	bool is_offload = false;
    311 	__u32 replay_window = 0;
    312 	__u32 seq = 0, oseq = 0, seq_hi = 0, oseq_hi = 0;
    313 	char *idp = NULL;
    314 	char *aeadop = NULL;
    315 	char *ealgop = NULL;
    316 	char *aalgop = NULL;
    317 	char *calgop = NULL;
    318 	char *coap = NULL;
    319 	char *sctxp = NULL;
    320 	__u32 extra_flags = 0;
    321 	struct xfrm_mark mark = {0, 0};
    322 	struct {
    323 		struct xfrm_user_sec_ctx sctx;
    324 		char    str[CTX_BUF_SIZE];
    325 	} ctx = {};
    326 	__u32 output_mark = 0;
    327 
    328 	while (argc > 0) {
    329 		if (strcmp(*argv, "mode") == 0) {
    330 			NEXT_ARG();
    331 			xfrm_mode_parse(&req.xsinfo.mode, &argc, &argv);
    332 		} else if (strcmp(*argv, "mark") == 0) {
    333 			xfrm_parse_mark(&mark, &argc, &argv);
    334 		} else if (strcmp(*argv, "reqid") == 0) {
    335 			NEXT_ARG();
    336 			xfrm_reqid_parse(&req.xsinfo.reqid, &argc, &argv);
    337 		} else if (strcmp(*argv, "seq") == 0) {
    338 			NEXT_ARG();
    339 			xfrm_seq_parse(&req.xsinfo.seq, &argc, &argv);
    340 		} else if (strcmp(*argv, "replay-window") == 0) {
    341 			NEXT_ARG();
    342 			if (get_u32(&replay_window, *argv, 0))
    343 				invarg("value after \"replay-window\" is invalid", *argv);
    344 		} else if (strcmp(*argv, "replay-seq") == 0) {
    345 			NEXT_ARG();
    346 			if (get_u32(&seq, *argv, 0))
    347 				invarg("value after \"replay-seq\" is invalid", *argv);
    348 		} else if (strcmp(*argv, "replay-seq-hi") == 0) {
    349 			NEXT_ARG();
    350 			if (get_u32(&seq_hi, *argv, 0))
    351 				invarg("value after \"replay-seq-hi\" is invalid", *argv);
    352 		} else if (strcmp(*argv, "replay-oseq") == 0) {
    353 			NEXT_ARG();
    354 			if (get_u32(&oseq, *argv, 0))
    355 				invarg("value after \"replay-oseq\" is invalid", *argv);
    356 		} else if (strcmp(*argv, "replay-oseq-hi") == 0) {
    357 			NEXT_ARG();
    358 			if (get_u32(&oseq_hi, *argv, 0))
    359 				invarg("value after \"replay-oseq-hi\" is invalid", *argv);
    360 		} else if (strcmp(*argv, "flag") == 0) {
    361 			NEXT_ARG();
    362 			xfrm_state_flag_parse(&req.xsinfo.flags, &argc, &argv);
    363 		} else if (strcmp(*argv, "extra-flag") == 0) {
    364 			NEXT_ARG();
    365 			xfrm_state_extra_flag_parse(&extra_flags, &argc, &argv);
    366 		} else if (strcmp(*argv, "sel") == 0) {
    367 			NEXT_ARG();
    368 			preferred_family = AF_UNSPEC;
    369 			xfrm_selector_parse(&req.xsinfo.sel, &argc, &argv);
    370 			preferred_family = req.xsinfo.sel.family;
    371 		} else if (strcmp(*argv, "limit") == 0) {
    372 			NEXT_ARG();
    373 			xfrm_lifetime_cfg_parse(&req.xsinfo.lft, &argc, &argv);
    374 		} else if (strcmp(*argv, "encap") == 0) {
    375 			struct xfrm_encap_tmpl encap;
    376 			inet_prefix oa;
    377 			NEXT_ARG();
    378 			xfrm_encap_type_parse(&encap.encap_type, &argc, &argv);
    379 			NEXT_ARG();
    380 			if (get_be16(&encap.encap_sport, *argv, 0))
    381 				invarg("SPORT value after \"encap\" is invalid", *argv);
    382 			NEXT_ARG();
    383 			if (get_be16(&encap.encap_dport, *argv, 0))
    384 				invarg("DPORT value after \"encap\" is invalid", *argv);
    385 			NEXT_ARG();
    386 			get_addr(&oa, *argv, AF_UNSPEC);
    387 			memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa));
    388 			addattr_l(&req.n, sizeof(req.buf), XFRMA_ENCAP,
    389 				  (void *)&encap, sizeof(encap));
    390 		} else if (strcmp(*argv, "coa") == 0) {
    391 			inet_prefix coa;
    392 			xfrm_address_t xcoa = {};
    393 
    394 			if (coap)
    395 				duparg("coa", *argv);
    396 			coap = *argv;
    397 
    398 			NEXT_ARG();
    399 
    400 			get_prefix(&coa, *argv, preferred_family);
    401 			if (coa.family == AF_UNSPEC)
    402 				invarg("value after \"coa\" has an unrecognized address family", *argv);
    403 			if (coa.bytelen > sizeof(xcoa))
    404 				invarg("value after \"coa\" is too large", *argv);
    405 
    406 			memcpy(&xcoa, &coa.data, coa.bytelen);
    407 
    408 			addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR,
    409 				  (void *)&xcoa, sizeof(xcoa));
    410 		} else if (strcmp(*argv, "ctx") == 0) {
    411 			char *context;
    412 
    413 			if (sctxp)
    414 				duparg("ctx", *argv);
    415 			sctxp = *argv;
    416 
    417 			NEXT_ARG();
    418 			context = *argv;
    419 
    420 			xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx);
    421 			addattr_l(&req.n, sizeof(req.buf), XFRMA_SEC_CTX,
    422 				  (void *)&ctx, ctx.sctx.len);
    423 		} else if (strcmp(*argv, "offload") == 0) {
    424 			is_offload = true;
    425 			NEXT_ARG();
    426 			if (strcmp(*argv, "dev") == 0) {
    427 				NEXT_ARG();
    428 				ifindex = ll_name_to_index(*argv);
    429 				if (!ifindex) {
    430 					invarg("value after \"offload dev\" is invalid", *argv);
    431 					is_offload = false;
    432 				}
    433 				NEXT_ARG();
    434 			}
    435 			if (strcmp(*argv, "dir") == 0) {
    436 				NEXT_ARG();
    437 				xfrm_offload_dir_parse(&dir, &argc, &argv);
    438 			} else {
    439 				invarg("value after \"offload dir\" is invalid", *argv);
    440 				is_offload = false;
    441 			}
    442 		} else if (strcmp(*argv, "output-mark") == 0) {
    443 			NEXT_ARG();
    444 			if (get_u32(&output_mark, *argv, 0))
    445 				invarg("value after \"output-mark\" is invalid", *argv);
    446 		} else {
    447 			/* try to assume ALGO */
    448 			int type = xfrm_algotype_getbyname(*argv);
    449 
    450 			switch (type) {
    451 			case XFRMA_ALG_AEAD:
    452 			case XFRMA_ALG_CRYPT:
    453 			case XFRMA_ALG_AUTH:
    454 			case XFRMA_ALG_AUTH_TRUNC:
    455 			case XFRMA_ALG_COMP:
    456 			{
    457 				/* ALGO */
    458 				struct {
    459 					union {
    460 						struct xfrm_algo alg;
    461 						struct xfrm_algo_aead aead;
    462 						struct xfrm_algo_auth auth;
    463 					} u;
    464 					char buf[XFRM_ALGO_KEY_BUF_SIZE];
    465 				} alg = {};
    466 				int len;
    467 				__u32 icvlen, trunclen;
    468 				char *name;
    469 				char *key = "";
    470 				char *buf;
    471 
    472 				switch (type) {
    473 				case XFRMA_ALG_AEAD:
    474 					if (ealgop || aalgop || aeadop)
    475 						duparg("ALGO-TYPE", *argv);
    476 					aeadop = *argv;
    477 					break;
    478 				case XFRMA_ALG_CRYPT:
    479 					if (ealgop || aeadop)
    480 						duparg("ALGO-TYPE", *argv);
    481 					ealgop = *argv;
    482 					break;
    483 				case XFRMA_ALG_AUTH:
    484 				case XFRMA_ALG_AUTH_TRUNC:
    485 					if (aalgop || aeadop)
    486 						duparg("ALGO-TYPE", *argv);
    487 					aalgop = *argv;
    488 					break;
    489 				case XFRMA_ALG_COMP:
    490 					if (calgop)
    491 						duparg("ALGO-TYPE", *argv);
    492 					calgop = *argv;
    493 					break;
    494 				default:
    495 					/* not reached */
    496 					invarg("ALGO-TYPE value is invalid\n", *argv);
    497 				}
    498 
    499 				if (!NEXT_ARG_OK())
    500 					missarg("ALGO-NAME");
    501 				NEXT_ARG();
    502 				name = *argv;
    503 
    504 				switch (type) {
    505 				case XFRMA_ALG_AEAD:
    506 				case XFRMA_ALG_CRYPT:
    507 				case XFRMA_ALG_AUTH:
    508 				case XFRMA_ALG_AUTH_TRUNC:
    509 					if (!NEXT_ARG_OK())
    510 						missarg("ALGO-KEYMAT");
    511 					NEXT_ARG();
    512 					key = *argv;
    513 					break;
    514 				}
    515 
    516 				buf = alg.u.alg.alg_key;
    517 				len = sizeof(alg.u.alg);
    518 
    519 				switch (type) {
    520 				case XFRMA_ALG_AEAD:
    521 					if (!NEXT_ARG_OK())
    522 						missarg("ALGO-ICV-LEN");
    523 					NEXT_ARG();
    524 					if (get_u32(&icvlen, *argv, 0))
    525 						invarg("ALGO-ICV-LEN value is invalid",
    526 						       *argv);
    527 					alg.u.aead.alg_icv_len = icvlen;
    528 
    529 					buf = alg.u.aead.alg_key;
    530 					len = sizeof(alg.u.aead);
    531 					break;
    532 				case XFRMA_ALG_AUTH_TRUNC:
    533 					if (!NEXT_ARG_OK())
    534 						missarg("ALGO-TRUNC-LEN");
    535 					NEXT_ARG();
    536 					if (get_u32(&trunclen, *argv, 0))
    537 						invarg("ALGO-TRUNC-LEN value is invalid",
    538 						       *argv);
    539 					alg.u.auth.alg_trunc_len = trunclen;
    540 
    541 					buf = alg.u.auth.alg_key;
    542 					len = sizeof(alg.u.auth);
    543 					break;
    544 				}
    545 
    546 				xfrm_algo_parse((void *)&alg, type, name, key,
    547 						buf, sizeof(alg.buf));
    548 				len += alg.u.alg.alg_key_len / 8;
    549 
    550 				addattr_l(&req.n, sizeof(req.buf), type,
    551 					  (void *)&alg, len);
    552 				break;
    553 			}
    554 			default:
    555 				/* try to assume ID */
    556 				if (idp)
    557 					invarg("unknown", *argv);
    558 				idp = *argv;
    559 
    560 				/* ID */
    561 				xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id,
    562 					      &req.xsinfo.family, 0, &argc, &argv);
    563 				if (preferred_family == AF_UNSPEC)
    564 					preferred_family = req.xsinfo.family;
    565 			}
    566 		}
    567 		argc--; argv++;
    568 	}
    569 
    570 	if (req.xsinfo.flags & XFRM_STATE_ESN &&
    571 	    replay_window == 0) {
    572 		fprintf(stderr, "Error: esn flag set without replay-window.\n");
    573 		exit(-1);
    574 	}
    575 
    576 	if (replay_window > XFRMA_REPLAY_ESN_MAX) {
    577 		fprintf(stderr,
    578 			"Error: replay-window (%u) > XFRMA_REPLAY_ESN_MAX (%u).\n",
    579 			replay_window, XFRMA_REPLAY_ESN_MAX);
    580 		exit(-1);
    581 	}
    582 
    583 	if (is_offload) {
    584 		xuo.ifindex = ifindex;
    585 		xuo.flags = dir;
    586 		addattr_l(&req.n, sizeof(req.buf), XFRMA_OFFLOAD_DEV, &xuo,
    587 			  sizeof(xuo));
    588 	}
    589 	if (req.xsinfo.flags & XFRM_STATE_ESN ||
    590 	    replay_window > (sizeof(replay.bitmap) * 8)) {
    591 		replay_esn.seq = seq;
    592 		replay_esn.oseq = oseq;
    593 		replay_esn.seq_hi = seq_hi;
    594 		replay_esn.oseq_hi = oseq_hi;
    595 		replay_esn.replay_window = replay_window;
    596 		replay_esn.bmp_len = (replay_window + sizeof(__u32) * 8 - 1) /
    597 				     (sizeof(__u32) * 8);
    598 		addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_ESN_VAL,
    599 			  &replay_esn, sizeof(replay_esn));
    600 	} else {
    601 		if (seq || oseq) {
    602 			replay.seq = seq;
    603 			replay.oseq = oseq;
    604 			addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_VAL,
    605 				  &replay, sizeof(replay));
    606 		}
    607 		req.xsinfo.replay_window = replay_window;
    608 	}
    609 
    610 	if (extra_flags)
    611 		addattr32(&req.n, sizeof(req.buf), XFRMA_SA_EXTRA_FLAGS,
    612 			  extra_flags);
    613 
    614 	if (!idp) {
    615 		fprintf(stderr, "Not enough information: ID is required\n");
    616 		exit(1);
    617 	}
    618 
    619 	if (mark.m) {
    620 		int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
    621 				  (void *)&mark, sizeof(mark));
    622 		if (r < 0) {
    623 			fprintf(stderr, "XFRMA_MARK failed\n");
    624 			exit(1);
    625 		}
    626 	}
    627 
    628 	if (xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
    629 		switch (req.xsinfo.mode) {
    630 		case XFRM_MODE_TRANSPORT:
    631 		case XFRM_MODE_TUNNEL:
    632 			break;
    633 		case XFRM_MODE_BEET:
    634 			if (req.xsinfo.id.proto == IPPROTO_ESP)
    635 				break;
    636 		default:
    637 			fprintf(stderr, "MODE value is invalid with XFRM-PROTO value \"%s\"\n",
    638 				strxf_xfrmproto(req.xsinfo.id.proto));
    639 			exit(1);
    640 		}
    641 
    642 		switch (req.xsinfo.id.proto) {
    643 		case IPPROTO_ESP:
    644 			if (calgop) {
    645 				fprintf(stderr, "ALGO-TYPE value \"%s\" is invalid with XFRM-PROTO value \"%s\"\n",
    646 					strxf_algotype(XFRMA_ALG_COMP),
    647 					strxf_xfrmproto(req.xsinfo.id.proto));
    648 				exit(1);
    649 			}
    650 			if (!ealgop && !aeadop) {
    651 				fprintf(stderr, "ALGO-TYPE value \"%s\" or \"%s\" is required with XFRM-PROTO value \"%s\"\n",
    652 					strxf_algotype(XFRMA_ALG_CRYPT),
    653 					strxf_algotype(XFRMA_ALG_AEAD),
    654 					strxf_xfrmproto(req.xsinfo.id.proto));
    655 				exit(1);
    656 			}
    657 			break;
    658 		case IPPROTO_AH:
    659 			if (ealgop || aeadop || calgop) {
    660 				fprintf(stderr, "ALGO-TYPE values \"%s\", \"%s\", and \"%s\" are invalid with XFRM-PROTO value \"%s\"\n",
    661 					strxf_algotype(XFRMA_ALG_CRYPT),
    662 					strxf_algotype(XFRMA_ALG_AEAD),
    663 					strxf_algotype(XFRMA_ALG_COMP),
    664 					strxf_xfrmproto(req.xsinfo.id.proto));
    665 				exit(1);
    666 			}
    667 			if (!aalgop) {
    668 				fprintf(stderr, "ALGO-TYPE value \"%s\" or \"%s\" is required with XFRM-PROTO value \"%s\"\n",
    669 					strxf_algotype(XFRMA_ALG_AUTH),
    670 					strxf_algotype(XFRMA_ALG_AUTH_TRUNC),
    671 					strxf_xfrmproto(req.xsinfo.id.proto));
    672 				exit(1);
    673 			}
    674 			break;
    675 		case IPPROTO_COMP:
    676 			if (ealgop || aalgop || aeadop) {
    677 				fprintf(stderr, "ALGO-TYPE values \"%s\", \"%s\", \"%s\", and \"%s\" are invalid with XFRM-PROTO value \"%s\"\n",
    678 					strxf_algotype(XFRMA_ALG_CRYPT),
    679 					strxf_algotype(XFRMA_ALG_AUTH),
    680 					strxf_algotype(XFRMA_ALG_AUTH_TRUNC),
    681 					strxf_algotype(XFRMA_ALG_AEAD),
    682 					strxf_xfrmproto(req.xsinfo.id.proto));
    683 				exit(1);
    684 			}
    685 			if (!calgop) {
    686 				fprintf(stderr, "ALGO-TYPE value \"%s\" is required with XFRM-PROTO value \"%s\"\n",
    687 					strxf_algotype(XFRMA_ALG_COMP),
    688 					strxf_xfrmproto(req.xsinfo.id.proto));
    689 				exit(1);
    690 			}
    691 			break;
    692 		}
    693 	} else {
    694 		if (ealgop || aalgop || aeadop || calgop) {
    695 			fprintf(stderr, "ALGO is invalid with XFRM-PROTO value \"%s\"\n",
    696 				strxf_xfrmproto(req.xsinfo.id.proto));
    697 			exit(1);
    698 		}
    699 	}
    700 
    701 	if (xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
    702 		switch (req.xsinfo.mode) {
    703 		case XFRM_MODE_ROUTEOPTIMIZATION:
    704 		case XFRM_MODE_IN_TRIGGER:
    705 			break;
    706 		case 0:
    707 			fprintf(stderr, "\"mode\" is required with XFRM-PROTO value \"%s\"\n",
    708 				strxf_xfrmproto(req.xsinfo.id.proto));
    709 			exit(1);
    710 		default:
    711 			fprintf(stderr, "MODE value is invalid with XFRM-PROTO value \"%s\"\n",
    712 				strxf_xfrmproto(req.xsinfo.id.proto));
    713 			exit(1);
    714 		}
    715 
    716 		if (!coap) {
    717 			fprintf(stderr, "\"coa\" is required with XFRM-PROTO value \"%s\"\n",
    718 				strxf_xfrmproto(req.xsinfo.id.proto));
    719 			exit(1);
    720 		}
    721 	} else {
    722 		if (coap) {
    723 			fprintf(stderr, "\"coa\" is invalid with XFRM-PROTO value \"%s\"\n",
    724 				strxf_xfrmproto(req.xsinfo.id.proto));
    725 			exit(1);
    726 		}
    727 	}
    728 
    729 	if (output_mark)
    730 		addattr32(&req.n, sizeof(req.buf), XFRMA_OUTPUT_MARK, output_mark);
    731 
    732 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    733 		exit(1);
    734 
    735 	if (req.xsinfo.family == AF_UNSPEC)
    736 		req.xsinfo.family = AF_INET;
    737 
    738 	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
    739 		exit(2);
    740 
    741 	rtnl_close(&rth);
    742 
    743 	return 0;
    744 }
    745 
    746 static int xfrm_state_allocspi(int argc, char **argv)
    747 {
    748 	struct rtnl_handle rth;
    749 	struct {
    750 		struct nlmsghdr	n;
    751 		struct xfrm_userspi_info xspi;
    752 		char			buf[RTA_BUF_SIZE];
    753 	} req = {
    754 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xspi)),
    755 		.n.nlmsg_flags = NLM_F_REQUEST,
    756 		.n.nlmsg_type = XFRM_MSG_ALLOCSPI,
    757 		.xspi.info.family = preferred_family,
    758 #if 0
    759 		.xspi.lft.soft_byte_limit = XFRM_INF,
    760 		.xspi.lft.hard_byte_limit = XFRM_INF,
    761 		.xspi.lft.soft_packet_limit = XFRM_INF,
    762 		.xspi.lft.hard_packet_limit = XFRM_INF,
    763 #endif
    764 	};
    765 	char *idp = NULL;
    766 	char *minp = NULL;
    767 	char *maxp = NULL;
    768 	struct xfrm_mark mark = {0, 0};
    769 	char res_buf[NLMSG_BUF_SIZE] = {};
    770 	struct nlmsghdr *res_n = (struct nlmsghdr *)res_buf;
    771 
    772 	while (argc > 0) {
    773 		if (strcmp(*argv, "mode") == 0) {
    774 			NEXT_ARG();
    775 			xfrm_mode_parse(&req.xspi.info.mode, &argc, &argv);
    776 		} else if (strcmp(*argv, "mark") == 0) {
    777 			xfrm_parse_mark(&mark, &argc, &argv);
    778 		} else if (strcmp(*argv, "reqid") == 0) {
    779 			NEXT_ARG();
    780 			xfrm_reqid_parse(&req.xspi.info.reqid, &argc, &argv);
    781 		} else if (strcmp(*argv, "seq") == 0) {
    782 			NEXT_ARG();
    783 			xfrm_seq_parse(&req.xspi.info.seq, &argc, &argv);
    784 		} else if (strcmp(*argv, "min") == 0) {
    785 			if (minp)
    786 				duparg("min", *argv);
    787 			minp = *argv;
    788 
    789 			NEXT_ARG();
    790 
    791 			if (get_u32(&req.xspi.min, *argv, 0))
    792 				invarg("value after \"min\" is invalid", *argv);
    793 		} else if (strcmp(*argv, "max") == 0) {
    794 			if (maxp)
    795 				duparg("max", *argv);
    796 			maxp = *argv;
    797 
    798 			NEXT_ARG();
    799 
    800 			if (get_u32(&req.xspi.max, *argv, 0))
    801 				invarg("value after \"max\" is invalid", *argv);
    802 		} else {
    803 			/* try to assume ID */
    804 			if (idp)
    805 				invarg("unknown", *argv);
    806 			idp = *argv;
    807 
    808 			/* ID */
    809 			xfrm_id_parse(&req.xspi.info.saddr, &req.xspi.info.id,
    810 				      &req.xspi.info.family, 0, &argc, &argv);
    811 			if (req.xspi.info.id.spi) {
    812 				fprintf(stderr, "\"spi\" is invalid\n");
    813 				exit(1);
    814 			}
    815 			if (preferred_family == AF_UNSPEC)
    816 				preferred_family = req.xspi.info.family;
    817 		}
    818 		argc--; argv++;
    819 	}
    820 
    821 	if (!idp) {
    822 		fprintf(stderr, "Not enough information: ID is required\n");
    823 		exit(1);
    824 	}
    825 
    826 	if (minp) {
    827 		if (!maxp) {
    828 			fprintf(stderr, "\"max\" is missing\n");
    829 			exit(1);
    830 		}
    831 		if (req.xspi.min > req.xspi.max) {
    832 			fprintf(stderr, "value after \"min\" is larger than value after \"max\"\n");
    833 			exit(1);
    834 		}
    835 	} else {
    836 		if (maxp) {
    837 			fprintf(stderr, "\"min\" is missing\n");
    838 			exit(1);
    839 		}
    840 
    841 		/* XXX: Default value defined in PF_KEY;
    842 		 * See kernel's net/key/af_key.c(pfkey_getspi).
    843 		 */
    844 		req.xspi.min = 0x100;
    845 		req.xspi.max = 0x0fffffff;
    846 
    847 		/* XXX: IPCOMP spi is 16-bits;
    848 		 * See kernel's net/xfrm/xfrm_user(verify_userspi_info).
    849 		 */
    850 		if (req.xspi.info.id.proto == IPPROTO_COMP)
    851 			req.xspi.max = 0xffff;
    852 	}
    853 
    854 	if (mark.m & mark.v) {
    855 		int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
    856 				  (void *)&mark, sizeof(mark));
    857 		if (r < 0) {
    858 			fprintf(stderr, "XFRMA_MARK failed\n");
    859 			exit(1);
    860 		}
    861 	}
    862 
    863 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    864 		exit(1);
    865 
    866 	if (req.xspi.info.family == AF_UNSPEC)
    867 		req.xspi.info.family = AF_INET;
    868 
    869 
    870 	if (rtnl_talk(&rth, &req.n, res_n, sizeof(res_buf)) < 0)
    871 		exit(2);
    872 
    873 	if (xfrm_state_print(NULL, res_n, (void *)stdout) < 0) {
    874 		fprintf(stderr, "An error :-)\n");
    875 		exit(1);
    876 	}
    877 
    878 	rtnl_close(&rth);
    879 
    880 	return 0;
    881 }
    882 
    883 static int xfrm_state_filter_match(struct xfrm_usersa_info *xsinfo)
    884 {
    885 	if (!filter.use)
    886 		return 1;
    887 
    888 	if (filter.id_src_mask)
    889 		if (xfrm_addr_match(&xsinfo->saddr, &filter.xsinfo.saddr,
    890 				    filter.id_src_mask))
    891 			return 0;
    892 	if (filter.id_dst_mask)
    893 		if (xfrm_addr_match(&xsinfo->id.daddr, &filter.xsinfo.id.daddr,
    894 				    filter.id_dst_mask))
    895 			return 0;
    896 	if ((xsinfo->id.proto^filter.xsinfo.id.proto)&filter.id_proto_mask)
    897 		return 0;
    898 	if ((xsinfo->id.spi^filter.xsinfo.id.spi)&filter.id_spi_mask)
    899 		return 0;
    900 	if ((xsinfo->mode^filter.xsinfo.mode)&filter.mode_mask)
    901 		return 0;
    902 	if ((xsinfo->reqid^filter.xsinfo.reqid)&filter.reqid_mask)
    903 		return 0;
    904 	if (filter.state_flags_mask)
    905 		if ((xsinfo->flags & filter.xsinfo.flags) == 0)
    906 			return 0;
    907 
    908 	return 1;
    909 }
    910 
    911 int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
    912 		     void *arg)
    913 {
    914 	FILE *fp = (FILE *)arg;
    915 	struct rtattr *tb[XFRMA_MAX+1];
    916 	struct rtattr *rta;
    917 	struct xfrm_usersa_info *xsinfo = NULL;
    918 	struct xfrm_user_expire *xexp = NULL;
    919 	struct xfrm_usersa_id	*xsid = NULL;
    920 	int len = n->nlmsg_len;
    921 
    922 	if (n->nlmsg_type != XFRM_MSG_NEWSA &&
    923 	    n->nlmsg_type != XFRM_MSG_DELSA &&
    924 	    n->nlmsg_type != XFRM_MSG_UPDSA &&
    925 	    n->nlmsg_type != XFRM_MSG_EXPIRE) {
    926 		fprintf(stderr, "Not a state: %08x %08x %08x\n",
    927 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    928 		return 0;
    929 	}
    930 
    931 	if (n->nlmsg_type == XFRM_MSG_DELSA) {
    932 		/* Dont blame me for this .. Herbert made me do it */
    933 		xsid = NLMSG_DATA(n);
    934 		len -= NLMSG_SPACE(sizeof(*xsid));
    935 	} else if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
    936 		xexp = NLMSG_DATA(n);
    937 		xsinfo = &xexp->state;
    938 		len -= NLMSG_SPACE(sizeof(*xexp));
    939 	} else {
    940 		xexp = NULL;
    941 		xsinfo = NLMSG_DATA(n);
    942 		len -= NLMSG_SPACE(sizeof(*xsinfo));
    943 	}
    944 
    945 	if (len < 0) {
    946 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    947 		return -1;
    948 	}
    949 
    950 	if (xsinfo && !xfrm_state_filter_match(xsinfo))
    951 		return 0;
    952 
    953 	if (n->nlmsg_type == XFRM_MSG_DELSA)
    954 		fprintf(fp, "Deleted ");
    955 	else if (n->nlmsg_type == XFRM_MSG_UPDSA)
    956 		fprintf(fp, "Updated ");
    957 	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
    958 		fprintf(fp, "Expired ");
    959 
    960 	if (n->nlmsg_type == XFRM_MSG_DELSA)
    961 		rta = XFRMSID_RTA(xsid);
    962 	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
    963 		rta = XFRMEXP_RTA(xexp);
    964 	else
    965 		rta = XFRMS_RTA(xsinfo);
    966 
    967 	parse_rtattr(tb, XFRMA_MAX, rta, len);
    968 
    969 	if (n->nlmsg_type == XFRM_MSG_DELSA) {
    970 		/* xfrm_policy_id_print(); */
    971 
    972 		if (!tb[XFRMA_SA]) {
    973 			fprintf(stderr, "Buggy XFRM_MSG_DELSA: no XFRMA_SA\n");
    974 			return -1;
    975 		}
    976 		if (RTA_PAYLOAD(tb[XFRMA_SA]) < sizeof(*xsinfo)) {
    977 			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
    978 			return -1;
    979 		}
    980 		xsinfo = RTA_DATA(tb[XFRMA_SA]);
    981 	}
    982 
    983 	xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL);
    984 
    985 	if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
    986 		fprintf(fp, "\t");
    987 		fprintf(fp, "hard %u", xexp->hard);
    988 		fprintf(fp, "%s", _SL_);
    989 	}
    990 
    991 	if (oneline)
    992 		fprintf(fp, "\n");
    993 	fflush(fp);
    994 
    995 	return 0;
    996 }
    997 
    998 static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
    999 {
   1000 	struct rtnl_handle rth;
   1001 	struct {
   1002 		struct nlmsghdr	n;
   1003 		struct xfrm_usersa_id	xsid;
   1004 		char			buf[RTA_BUF_SIZE];
   1005 	} req = {
   1006 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid)),
   1007 		.n.nlmsg_flags = NLM_F_REQUEST,
   1008 		.n.nlmsg_type = delete ? XFRM_MSG_DELSA : XFRM_MSG_GETSA,
   1009 		.xsid.family = preferred_family,
   1010 	};
   1011 	struct xfrm_id id;
   1012 	char *idp = NULL;
   1013 	struct xfrm_mark mark = {0, 0};
   1014 
   1015 	while (argc > 0) {
   1016 		xfrm_address_t saddr;
   1017 
   1018 		if (strcmp(*argv, "mark") == 0) {
   1019 			xfrm_parse_mark(&mark, &argc, &argv);
   1020 		} else {
   1021 			if (idp)
   1022 				invarg("unknown", *argv);
   1023 			idp = *argv;
   1024 
   1025 			/* ID */
   1026 			memset(&id, 0, sizeof(id));
   1027 			memset(&saddr, 0, sizeof(saddr));
   1028 			xfrm_id_parse(&saddr, &id, &req.xsid.family, 0,
   1029 				      &argc, &argv);
   1030 
   1031 			memcpy(&req.xsid.daddr, &id.daddr, sizeof(req.xsid.daddr));
   1032 			req.xsid.spi = id.spi;
   1033 			req.xsid.proto = id.proto;
   1034 
   1035 			addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
   1036 				  (void *)&saddr, sizeof(saddr));
   1037 		}
   1038 
   1039 		argc--; argv++;
   1040 	}
   1041 
   1042 	if (mark.m & mark.v) {
   1043 		int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
   1044 				  (void *)&mark, sizeof(mark));
   1045 		if (r < 0) {
   1046 			fprintf(stderr, "XFRMA_MARK failed\n");
   1047 			exit(1);
   1048 		}
   1049 	}
   1050 
   1051 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
   1052 		exit(1);
   1053 
   1054 	if (req.xsid.family == AF_UNSPEC)
   1055 		req.xsid.family = AF_INET;
   1056 
   1057 	if (delete) {
   1058 		if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
   1059 			exit(2);
   1060 	} else {
   1061 		char buf[NLMSG_BUF_SIZE] = {};
   1062 		struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
   1063 
   1064 		if (rtnl_talk(&rth, &req.n, res_n, sizeof(req)) < 0)
   1065 			exit(2);
   1066 
   1067 		if (xfrm_state_print(NULL, res_n, (void *)stdout) < 0) {
   1068 			fprintf(stderr, "An error :-)\n");
   1069 			exit(1);
   1070 		}
   1071 	}
   1072 
   1073 	rtnl_close(&rth);
   1074 
   1075 	return 0;
   1076 }
   1077 
   1078 /*
   1079  * With an existing state of nlmsg, make new nlmsg for deleting the state
   1080  * and store it to buffer.
   1081  */
   1082 static int xfrm_state_keep(const struct sockaddr_nl *who,
   1083 			   struct nlmsghdr *n,
   1084 			   void *arg)
   1085 {
   1086 	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
   1087 	struct rtnl_handle *rth = xb->rth;
   1088 	struct xfrm_usersa_info *xsinfo = NLMSG_DATA(n);
   1089 	int len = n->nlmsg_len;
   1090 	struct nlmsghdr *new_n;
   1091 	struct xfrm_usersa_id *xsid;
   1092 	struct rtattr *tb[XFRMA_MAX+1];
   1093 
   1094 	if (n->nlmsg_type != XFRM_MSG_NEWSA) {
   1095 		fprintf(stderr, "Not a state: %08x %08x %08x\n",
   1096 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
   1097 		return 0;
   1098 	}
   1099 
   1100 	len -= NLMSG_LENGTH(sizeof(*xsinfo));
   1101 	if (len < 0) {
   1102 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
   1103 		return -1;
   1104 	}
   1105 
   1106 	if (!xfrm_state_filter_match(xsinfo))
   1107 		return 0;
   1108 
   1109 	if (xb->offset > xb->size) {
   1110 		fprintf(stderr, "State buffer overflow\n");
   1111 		return -1;
   1112 	}
   1113 
   1114 	new_n = (struct nlmsghdr *)(xb->buf + xb->offset);
   1115 	new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xsid));
   1116 	new_n->nlmsg_flags = NLM_F_REQUEST;
   1117 	new_n->nlmsg_type = XFRM_MSG_DELSA;
   1118 	new_n->nlmsg_seq = ++rth->seq;
   1119 
   1120 	xsid = NLMSG_DATA(new_n);
   1121 	xsid->family = xsinfo->family;
   1122 	memcpy(&xsid->daddr, &xsinfo->id.daddr, sizeof(xsid->daddr));
   1123 	xsid->spi = xsinfo->id.spi;
   1124 	xsid->proto = xsinfo->id.proto;
   1125 
   1126 	addattr_l(new_n, xb->size, XFRMA_SRCADDR, &xsinfo->saddr,
   1127 		  sizeof(xsid->daddr));
   1128 
   1129 	parse_rtattr(tb, XFRMA_MAX, XFRMS_RTA(xsinfo), len);
   1130 
   1131 	if (tb[XFRMA_MARK]) {
   1132 		int r = addattr_l(new_n, xb->size, XFRMA_MARK,
   1133 				(void *)RTA_DATA(tb[XFRMA_MARK]), tb[XFRMA_MARK]->rta_len);
   1134 		if (r < 0) {
   1135 			fprintf(stderr, "%s: XFRMA_MARK failed\n", __func__);
   1136 			exit(1);
   1137 		}
   1138 	}
   1139 
   1140 	xb->offset += new_n->nlmsg_len;
   1141 	xb->nlmsg_count++;
   1142 
   1143 	return 0;
   1144 }
   1145 
   1146 static int xfrm_state_list_or_deleteall(int argc, char **argv, int deleteall)
   1147 {
   1148 	char *idp = NULL;
   1149 	struct rtnl_handle rth;
   1150 
   1151 	if (argc > 0)
   1152 		filter.use = 1;
   1153 	filter.xsinfo.family = preferred_family;
   1154 
   1155 	while (argc > 0) {
   1156 		if (strcmp(*argv, "mode") == 0) {
   1157 			NEXT_ARG();
   1158 			xfrm_mode_parse(&filter.xsinfo.mode, &argc, &argv);
   1159 
   1160 			filter.mode_mask = XFRM_FILTER_MASK_FULL;
   1161 
   1162 		} else if (strcmp(*argv, "reqid") == 0) {
   1163 			NEXT_ARG();
   1164 			xfrm_reqid_parse(&filter.xsinfo.reqid, &argc, &argv);
   1165 
   1166 			filter.reqid_mask = XFRM_FILTER_MASK_FULL;
   1167 
   1168 		} else if (strcmp(*argv, "flag") == 0) {
   1169 			NEXT_ARG();
   1170 			xfrm_state_flag_parse(&filter.xsinfo.flags, &argc, &argv);
   1171 
   1172 			filter.state_flags_mask = XFRM_FILTER_MASK_FULL;
   1173 
   1174 		} else {
   1175 			if (idp)
   1176 				invarg("unknown", *argv);
   1177 			idp = *argv;
   1178 
   1179 			/* ID */
   1180 			xfrm_id_parse(&filter.xsinfo.saddr, &filter.xsinfo.id,
   1181 				      &filter.xsinfo.family, 1, &argc, &argv);
   1182 			if (preferred_family == AF_UNSPEC)
   1183 				preferred_family = filter.xsinfo.family;
   1184 		}
   1185 		argc--; argv++;
   1186 	}
   1187 
   1188 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
   1189 		exit(1);
   1190 
   1191 	if (deleteall) {
   1192 		struct xfrm_buffer xb;
   1193 		char buf[NLMSG_DELETEALL_BUF_SIZE];
   1194 		int i;
   1195 
   1196 		xb.buf = buf;
   1197 		xb.size = sizeof(buf);
   1198 		xb.rth = &rth;
   1199 
   1200 		for (i = 0; ; i++) {
   1201 			struct {
   1202 				struct nlmsghdr n;
   1203 				char buf[NLMSG_BUF_SIZE];
   1204 			} req = {
   1205 				.n.nlmsg_len = NLMSG_HDRLEN,
   1206 				.n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
   1207 				.n.nlmsg_type = XFRM_MSG_GETSA,
   1208 				.n.nlmsg_seq = rth.dump = ++rth.seq,
   1209 			};
   1210 
   1211 			xb.offset = 0;
   1212 			xb.nlmsg_count = 0;
   1213 
   1214 			if (show_stats > 1)
   1215 				fprintf(stderr, "Delete-all round = %d\n", i);
   1216 
   1217 			if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
   1218 				perror("Cannot send dump request");
   1219 				exit(1);
   1220 			}
   1221 
   1222 			if (rtnl_dump_filter(&rth, xfrm_state_keep, &xb) < 0) {
   1223 				fprintf(stderr, "Delete-all terminated\n");
   1224 				exit(1);
   1225 			}
   1226 			if (xb.nlmsg_count == 0) {
   1227 				if (show_stats > 1)
   1228 					fprintf(stderr, "Delete-all completed\n");
   1229 				break;
   1230 			}
   1231 
   1232 			if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) {
   1233 				perror("Failed to send delete-all request\n");
   1234 				exit(1);
   1235 			}
   1236 			if (show_stats > 1)
   1237 				fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);
   1238 
   1239 			xb.offset = 0;
   1240 			xb.nlmsg_count = 0;
   1241 		}
   1242 
   1243 	} else {
   1244 		struct xfrm_address_filter addrfilter = {
   1245 			.saddr = filter.xsinfo.saddr,
   1246 			.daddr = filter.xsinfo.id.daddr,
   1247 			.family = filter.xsinfo.family,
   1248 			.splen = filter.id_src_mask,
   1249 			.dplen = filter.id_dst_mask,
   1250 		};
   1251 		struct {
   1252 			struct nlmsghdr n;
   1253 			char buf[NLMSG_BUF_SIZE];
   1254 		} req = {
   1255 			.n.nlmsg_len = NLMSG_HDRLEN,
   1256 			.n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
   1257 			.n.nlmsg_type = XFRM_MSG_GETSA,
   1258 			.n.nlmsg_seq = rth.dump = ++rth.seq,
   1259 		};
   1260 
   1261 		if (filter.xsinfo.id.proto)
   1262 			addattr8(&req.n, sizeof(req), XFRMA_PROTO,
   1263 				 filter.xsinfo.id.proto);
   1264 		addattr_l(&req.n, sizeof(req), XFRMA_ADDRESS_FILTER,
   1265 			  &addrfilter, sizeof(addrfilter));
   1266 
   1267 		if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
   1268 			perror("Cannot send dump request");
   1269 			exit(1);
   1270 		}
   1271 
   1272 		if (rtnl_dump_filter(&rth, xfrm_state_print, stdout) < 0) {
   1273 			fprintf(stderr, "Dump terminated\n");
   1274 			exit(1);
   1275 		}
   1276 	}
   1277 
   1278 	rtnl_close(&rth);
   1279 
   1280 	exit(0);
   1281 }
   1282 
   1283 static int print_sadinfo(struct nlmsghdr *n, void *arg)
   1284 {
   1285 	FILE *fp = (FILE *)arg;
   1286 	__u32 *f = NLMSG_DATA(n);
   1287 	struct rtattr *tb[XFRMA_SAD_MAX+1];
   1288 	struct rtattr *rta;
   1289 	int len = n->nlmsg_len;
   1290 
   1291 	len -= NLMSG_LENGTH(sizeof(__u32));
   1292 	if (len < 0) {
   1293 		fprintf(stderr, "SADinfo: Wrong len %d\n", len);
   1294 		return -1;
   1295 	}
   1296 
   1297 	rta = XFRMSAPD_RTA(f);
   1298 	parse_rtattr(tb, XFRMA_SAD_MAX, rta, len);
   1299 
   1300 	if (tb[XFRMA_SAD_CNT]) {
   1301 		__u32 cnt;
   1302 
   1303 		fprintf(fp, "\t SAD");
   1304 		cnt = rta_getattr_u32(tb[XFRMA_SAD_CNT]);
   1305 		fprintf(fp, " count %u", cnt);
   1306 	} else {
   1307 		fprintf(fp, "BAD SAD info returned\n");
   1308 		return -1;
   1309 	}
   1310 
   1311 	if (show_stats) {
   1312 		if (tb[XFRMA_SAD_HINFO]) {
   1313 			struct xfrmu_sadhinfo *si;
   1314 
   1315 			if (RTA_PAYLOAD(tb[XFRMA_SAD_HINFO]) < sizeof(*si)) {
   1316 				fprintf(fp, "BAD SAD length returned\n");
   1317 				return -1;
   1318 			}
   1319 
   1320 			si = RTA_DATA(tb[XFRMA_SAD_HINFO]);
   1321 			fprintf(fp, " (buckets ");
   1322 			fprintf(fp, "count %d", si->sadhcnt);
   1323 			fprintf(fp, " Max %d", si->sadhmcnt);
   1324 			fprintf(fp, ")");
   1325 		}
   1326 	}
   1327 	fprintf(fp, "\n");
   1328 
   1329 	return 0;
   1330 }
   1331 
   1332 static int xfrm_sad_getinfo(int argc, char **argv)
   1333 {
   1334 	struct rtnl_handle rth;
   1335 	struct {
   1336 		struct nlmsghdr			n;
   1337 		__u32				flags;
   1338 		char				ans[64];
   1339 	} req = {
   1340 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.flags)),
   1341 		.n.nlmsg_flags = NLM_F_REQUEST,
   1342 		.n.nlmsg_type = XFRM_MSG_GETSADINFO,
   1343 		.flags = 0XFFFFFFFF,
   1344 	};
   1345 
   1346 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
   1347 		exit(1);
   1348 
   1349 	if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
   1350 		exit(2);
   1351 
   1352 	print_sadinfo(&req.n, (void *)stdout);
   1353 
   1354 	rtnl_close(&rth);
   1355 
   1356 	return 0;
   1357 }
   1358 
   1359 static int xfrm_state_flush(int argc, char **argv)
   1360 {
   1361 	struct rtnl_handle rth;
   1362 	struct {
   1363 		struct nlmsghdr			n;
   1364 		struct xfrm_usersa_flush	xsf;
   1365 	} req = {
   1366 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsf)),
   1367 		.n.nlmsg_flags = NLM_F_REQUEST,
   1368 		.n.nlmsg_type = XFRM_MSG_FLUSHSA,
   1369 	};
   1370 	char *protop = NULL;
   1371 
   1372 	while (argc > 0) {
   1373 		if (strcmp(*argv, "proto") == 0) {
   1374 			int ret;
   1375 
   1376 			if (protop)
   1377 				duparg("proto", *argv);
   1378 			protop = *argv;
   1379 
   1380 			NEXT_ARG();
   1381 
   1382 			ret = xfrm_xfrmproto_getbyname(*argv);
   1383 			if (ret < 0)
   1384 				invarg("XFRM-PROTO value is invalid", *argv);
   1385 
   1386 			req.xsf.proto = (__u8)ret;
   1387 		} else
   1388 			invarg("unknown", *argv);
   1389 
   1390 		argc--; argv++;
   1391 	}
   1392 
   1393 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
   1394 		exit(1);
   1395 
   1396 	if (show_stats > 1)
   1397 		fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n",
   1398 			strxf_xfrmproto(req.xsf.proto));
   1399 
   1400 	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
   1401 		exit(2);
   1402 
   1403 	rtnl_close(&rth);
   1404 
   1405 	return 0;
   1406 }
   1407 
   1408 int do_xfrm_state(int argc, char **argv)
   1409 {
   1410 	if (argc < 1)
   1411 		return xfrm_state_list_or_deleteall(0, NULL, 0);
   1412 
   1413 	if (matches(*argv, "add") == 0)
   1414 		return xfrm_state_modify(XFRM_MSG_NEWSA, 0,
   1415 					 argc-1, argv+1);
   1416 	if (matches(*argv, "update") == 0)
   1417 		return xfrm_state_modify(XFRM_MSG_UPDSA, 0,
   1418 					 argc-1, argv+1);
   1419 	if (matches(*argv, "allocspi") == 0)
   1420 		return xfrm_state_allocspi(argc-1, argv+1);
   1421 	if (matches(*argv, "delete") == 0)
   1422 		return xfrm_state_get_or_delete(argc-1, argv+1, 1);
   1423 	if (matches(*argv, "deleteall") == 0 || matches(*argv, "delall") == 0)
   1424 		return xfrm_state_list_or_deleteall(argc-1, argv+1, 1);
   1425 	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
   1426 	    || matches(*argv, "lst") == 0)
   1427 		return xfrm_state_list_or_deleteall(argc-1, argv+1, 0);
   1428 	if (matches(*argv, "get") == 0)
   1429 		return xfrm_state_get_or_delete(argc-1, argv+1, 0);
   1430 	if (matches(*argv, "flush") == 0)
   1431 		return xfrm_state_flush(argc-1, argv+1);
   1432 	if (matches(*argv, "count") == 0) {
   1433 		return xfrm_sad_getinfo(argc, argv);
   1434 	}
   1435 	if (matches(*argv, "help") == 0)
   1436 		usage();
   1437 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm state help\".\n", *argv);
   1438 	exit(-1);
   1439 }
   1440