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/netlink.h>
     33 #include <linux/xfrm.h>
     34 #include "utils.h"
     35 #include "xfrm.h"
     36 #include "ip_common.h"
     37 
     38 //#define NLMSG_DELETEALL_BUF_SIZE (4096-512)
     39 #define NLMSG_DELETEALL_BUF_SIZE 8192
     40 
     41 /*
     42  * Receiving buffer defines:
     43  * nlmsg
     44  *   data = struct xfrm_userpolicy_info
     45  *   rtattr
     46  *     data = struct xfrm_user_tmpl[]
     47  */
     48 #define NLMSG_BUF_SIZE 4096
     49 #define RTA_BUF_SIZE 2048
     50 #define XFRM_TMPLS_BUF_SIZE 1024
     51 
     52 static void usage(void) __attribute__((noreturn));
     53 
     54 static void usage(void)
     55 {
     56 	fprintf(stderr, "Usage: ip xfrm policy { add | update } dir DIR SELECTOR [ index INDEX ] [ ptype PTYPE ]\n");
     57 	fprintf(stderr, "        [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ] [ LIMIT-LIST ] [ TMPL-LIST ]\n");
     58 	fprintf(stderr, "Usage: ip xfrm policy { delete | get } dir DIR [ SELECTOR | index INDEX ] [ ptype PTYPE ]\n");
     59 	fprintf(stderr, "Usage: ip xfrm policy { deleteall | list } [ dir DIR ] [ SELECTOR ]\n");
     60 	fprintf(stderr, "        [ index INDEX ] [ action ACTION ] [ priority PRIORITY ]  [ flag FLAG-LIST ]\n");
     61 	fprintf(stderr, "Usage: ip xfrm policy flush [ ptype PTYPE ]\n");
     62 	fprintf(stderr, "Usage: ip xfrm count\n");
     63 	fprintf(stderr, "PTYPE := [ main | sub ](default=main)\n");
     64 	fprintf(stderr, "DIR := [ in | out | fwd ]\n");
     65 
     66 	fprintf(stderr, "SELECTOR := src ADDR[/PLEN] dst ADDR[/PLEN] [ UPSPEC ] [ dev DEV ]\n");
     67 
     68 	fprintf(stderr, "UPSPEC := proto PROTO [ [ sport PORT ] [ dport PORT ] |\n");
     69 	fprintf(stderr, "                        [ type NUMBER ] [ code NUMBER ] ]\n");
     70 
     71 	//fprintf(stderr, "DEV - device name(default=none)\n");
     72 
     73 	fprintf(stderr, "ACTION := [ allow | block ](default=allow)\n");
     74 
     75 	//fprintf(stderr, "PRIORITY - priority value(default=0)\n");
     76 
     77 	fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
     78 	fprintf(stderr, "FLAG := [ localok ]\n");
     79 
     80 	fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] | [ limit LIMIT ]\n");
     81 	fprintf(stderr, "LIMIT := [ [time-soft|time-hard|time-use-soft|time-use-hard] SECONDS ] |\n");
     82 	fprintf(stderr, "         [ [byte-soft|byte-hard] SIZE ] | [ [packet-soft|packet-hard] NUMBER ]\n");
     83 
     84 	fprintf(stderr, "TMPL-LIST := [ TMPL-LIST ] | [ tmpl TMPL ]\n");
     85 	fprintf(stderr, "TMPL := ID [ mode MODE ] [ reqid REQID ] [ level LEVEL ]\n");
     86 	fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM_PROTO ] [ spi SPI ]\n");
     87 
     88 	fprintf(stderr, "XFRM_PROTO := [ ");
     89 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
     90 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
     91 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
     92 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
     93 	fprintf(stderr, "%s ", strxf_xfrmproto(IPPROTO_DSTOPTS));
     94 	fprintf(stderr, "]\n");
     95 
     96  	fprintf(stderr, "MODE := [ transport | tunnel | beet ](default=transport)\n");
     97  	//fprintf(stderr, "REQID - number(default=0)\n");
     98 	fprintf(stderr, "LEVEL := [ required | use ](default=required)\n");
     99 
    100 	exit(-1);
    101 }
    102 
    103 static int xfrm_policy_dir_parse(__u8 *dir, int *argcp, char ***argvp)
    104 {
    105 	int argc = *argcp;
    106 	char **argv = *argvp;
    107 
    108 	if (strcmp(*argv, "in") == 0)
    109 		*dir = XFRM_POLICY_IN;
    110 	else if (strcmp(*argv, "out") == 0)
    111 		*dir = XFRM_POLICY_OUT;
    112 	else if (strcmp(*argv, "fwd") == 0)
    113 		*dir = XFRM_POLICY_FWD;
    114 	else
    115 		invarg("\"DIR\" is invalid", *argv);
    116 
    117 	*argcp = argc;
    118 	*argvp = argv;
    119 
    120 	return 0;
    121 }
    122 
    123 static int xfrm_policy_ptype_parse(__u8 *ptype, int *argcp, char ***argvp)
    124 {
    125 	int argc = *argcp;
    126 	char **argv = *argvp;
    127 
    128 	if (strcmp(*argv, "main") == 0)
    129 		*ptype = XFRM_POLICY_TYPE_MAIN;
    130 	else if (strcmp(*argv, "sub") == 0)
    131 		*ptype = XFRM_POLICY_TYPE_SUB;
    132 	else
    133 		invarg("\"PTYPE\" is invalid", *argv);
    134 
    135 	*argcp = argc;
    136 	*argvp = argv;
    137 
    138 	return 0;
    139 }
    140 
    141 static int xfrm_policy_flag_parse(__u8 *flags, int *argcp, char ***argvp)
    142 {
    143 	int argc = *argcp;
    144 	char **argv = *argvp;
    145 	int len = strlen(*argv);
    146 
    147 	if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
    148 		__u8 val = 0;
    149 
    150 		if (get_u8(&val, *argv, 16))
    151 			invarg("\"FLAG\" is invalid", *argv);
    152 		*flags = val;
    153 	} else {
    154 		while (1) {
    155 			if (strcmp(*argv, "localok") == 0)
    156 				*flags |= XFRM_POLICY_LOCALOK;
    157 			else {
    158 				PREV_ARG(); /* back track */
    159 				break;
    160 			}
    161 
    162 			if (!NEXT_ARG_OK())
    163 				break;
    164 			NEXT_ARG();
    165 		}
    166 	}
    167 
    168 	*argcp = argc;
    169 	*argvp = argv;
    170 
    171 	return 0;
    172 }
    173 
    174 static int xfrm_tmpl_parse(struct xfrm_user_tmpl *tmpl,
    175 			   int *argcp, char ***argvp)
    176 {
    177 	int argc = *argcp;
    178 	char **argv = *argvp;
    179 	char *idp = NULL;
    180 
    181 	while (1) {
    182 		if (strcmp(*argv, "mode") == 0) {
    183 			NEXT_ARG();
    184 			xfrm_mode_parse(&tmpl->mode,  &argc, &argv);
    185 		} else if (strcmp(*argv, "reqid") == 0) {
    186 			NEXT_ARG();
    187 			xfrm_reqid_parse(&tmpl->reqid, &argc, &argv);
    188 		} else if (strcmp(*argv, "level") == 0) {
    189 			NEXT_ARG();
    190 
    191 			if (strcmp(*argv, "required") == 0)
    192 				tmpl->optional = 0;
    193 			else if (strcmp(*argv, "use") == 0)
    194 				tmpl->optional = 1;
    195 			else
    196 				invarg("\"LEVEL\" is invalid\n", *argv);
    197 
    198 		} else {
    199 			if (idp) {
    200 				PREV_ARG(); /* back track */
    201 				break;
    202 			}
    203 			idp = *argv;
    204 			xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
    205 				      0, &argc, &argv);
    206 			if (preferred_family == AF_UNSPEC)
    207 				preferred_family = tmpl->family;
    208 		}
    209 
    210 		if (!NEXT_ARG_OK())
    211 			break;
    212 
    213 		NEXT_ARG();
    214 	}
    215 	if (argc == *argcp)
    216 		missarg("TMPL");
    217 
    218 	*argcp = argc;
    219 	*argvp = argv;
    220 
    221 	return 0;
    222 }
    223 
    224 static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv)
    225 {
    226 	struct rtnl_handle rth;
    227 	struct {
    228 		struct nlmsghdr			n;
    229 		struct xfrm_userpolicy_info	xpinfo;
    230 		char				buf[RTA_BUF_SIZE];
    231 	} req;
    232 	char *dirp = NULL;
    233 	char *selp = NULL;
    234 	char *ptypep = NULL;
    235 	struct xfrm_userpolicy_type upt;
    236 	char tmpls_buf[XFRM_TMPLS_BUF_SIZE];
    237 	int tmpls_len = 0;
    238 
    239 	memset(&req, 0, sizeof(req));
    240 	memset(&upt, 0, sizeof(upt));
    241 	memset(&tmpls_buf, 0, sizeof(tmpls_buf));
    242 
    243 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo));
    244 	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
    245 	req.n.nlmsg_type = cmd;
    246 	req.xpinfo.sel.family = preferred_family;
    247 
    248 	req.xpinfo.lft.soft_byte_limit = XFRM_INF;
    249 	req.xpinfo.lft.hard_byte_limit = XFRM_INF;
    250 	req.xpinfo.lft.soft_packet_limit = XFRM_INF;
    251 	req.xpinfo.lft.hard_packet_limit = XFRM_INF;
    252 
    253 	while (argc > 0) {
    254 		if (strcmp(*argv, "dir") == 0) {
    255 			if (dirp)
    256 				duparg("dir", *argv);
    257 			dirp = *argv;
    258 
    259 			NEXT_ARG();
    260 			xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv);
    261 		} else if (strcmp(*argv, "index") == 0) {
    262 			NEXT_ARG();
    263 			if (get_u32(&req.xpinfo.index, *argv, 0))
    264 				invarg("\"INDEX\" is invalid", *argv);
    265 		} else if (strcmp(*argv, "ptype") == 0) {
    266 			if (ptypep)
    267 				duparg("ptype", *argv);
    268 			ptypep = *argv;
    269 
    270 			NEXT_ARG();
    271 			xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
    272 		} else if (strcmp(*argv, "action") == 0) {
    273 			NEXT_ARG();
    274 			if (strcmp(*argv, "allow") == 0)
    275 				req.xpinfo.action = XFRM_POLICY_ALLOW;
    276 			else if (strcmp(*argv, "block") == 0)
    277 				req.xpinfo.action = XFRM_POLICY_BLOCK;
    278 			else
    279 				invarg("\"action\" value is invalid\n", *argv);
    280 		} else if (strcmp(*argv, "priority") == 0) {
    281 			NEXT_ARG();
    282 			if (get_u32(&req.xpinfo.priority, *argv, 0))
    283 				invarg("\"PRIORITY\" is invalid", *argv);
    284 		} else if (strcmp(*argv, "flag") == 0) {
    285 			NEXT_ARG();
    286 			xfrm_policy_flag_parse(&req.xpinfo.flags, &argc,
    287 					       &argv);
    288 		} else if (strcmp(*argv, "limit") == 0) {
    289 			NEXT_ARG();
    290 			xfrm_lifetime_cfg_parse(&req.xpinfo.lft, &argc, &argv);
    291 		} else if (strcmp(*argv, "tmpl") == 0) {
    292 			struct xfrm_user_tmpl *tmpl;
    293 
    294 			if (tmpls_len + sizeof(*tmpl) > sizeof(tmpls_buf)) {
    295 				fprintf(stderr, "Too many tmpls: buffer overflow\n");
    296 				exit(1);
    297 			}
    298 			tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
    299 
    300 			tmpl->family = preferred_family;
    301 			tmpl->aalgos = (~(__u32)0);
    302 			tmpl->ealgos = (~(__u32)0);
    303 			tmpl->calgos = (~(__u32)0);
    304 
    305 			NEXT_ARG();
    306 			xfrm_tmpl_parse(tmpl, &argc, &argv);
    307 
    308 			tmpls_len += sizeof(*tmpl);
    309 		} else {
    310 			if (selp)
    311 				duparg("unknown", *argv);
    312 			selp = *argv;
    313 
    314 			xfrm_selector_parse(&req.xpinfo.sel, &argc, &argv);
    315 			if (preferred_family == AF_UNSPEC)
    316 				preferred_family = req.xpinfo.sel.family;
    317 		}
    318 
    319 		argc--; argv++;
    320 	}
    321 
    322 	if (!dirp) {
    323 		fprintf(stderr, "Not enough information: \"DIR\" is required.\n");
    324 		exit(1);
    325 	}
    326 
    327 	if (ptypep) {
    328 		addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
    329 			  (void *)&upt, sizeof(upt));
    330 	}
    331 
    332 	if (tmpls_len > 0) {
    333 		addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
    334 			  (void *)tmpls_buf, tmpls_len);
    335 	}
    336 
    337 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    338 		exit(1);
    339 
    340 	if (req.xpinfo.sel.family == AF_UNSPEC)
    341 		req.xpinfo.sel.family = AF_INET;
    342 
    343 	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
    344 		exit(2);
    345 
    346 	rtnl_close(&rth);
    347 
    348 	return 0;
    349 }
    350 
    351 static int xfrm_policy_filter_match(struct xfrm_userpolicy_info *xpinfo,
    352 				    __u8 ptype)
    353 {
    354 	if (!filter.use)
    355 		return 1;
    356 
    357 	if ((xpinfo->dir^filter.xpinfo.dir)&filter.dir_mask)
    358 		return 0;
    359 
    360 	if ((ptype^filter.ptype)&filter.ptype_mask)
    361 		return 0;
    362 
    363 	if (filter.sel_src_mask) {
    364 		if (xfrm_addr_match(&xpinfo->sel.saddr, &filter.xpinfo.sel.saddr,
    365 				    filter.sel_src_mask))
    366 			return 0;
    367 	}
    368 
    369 	if (filter.sel_dst_mask) {
    370 		if (xfrm_addr_match(&xpinfo->sel.daddr, &filter.xpinfo.sel.daddr,
    371 				    filter.sel_dst_mask))
    372 			return 0;
    373 	}
    374 
    375 	if ((xpinfo->sel.ifindex^filter.xpinfo.sel.ifindex)&filter.sel_dev_mask)
    376 		return 0;
    377 
    378 	if ((xpinfo->sel.proto^filter.xpinfo.sel.proto)&filter.upspec_proto_mask)
    379 		return 0;
    380 
    381 	if (filter.upspec_sport_mask) {
    382 		if ((xpinfo->sel.sport^filter.xpinfo.sel.sport)&filter.upspec_sport_mask)
    383 			return 0;
    384 	}
    385 
    386 	if (filter.upspec_dport_mask) {
    387 		if ((xpinfo->sel.dport^filter.xpinfo.sel.dport)&filter.upspec_dport_mask)
    388 			return 0;
    389 	}
    390 
    391 	if ((xpinfo->index^filter.xpinfo.index)&filter.index_mask)
    392 		return 0;
    393 
    394 	if ((xpinfo->action^filter.xpinfo.action)&filter.action_mask)
    395 		return 0;
    396 
    397 	if ((xpinfo->priority^filter.xpinfo.priority)&filter.priority_mask)
    398 		return 0;
    399 
    400 	if (filter.policy_flags_mask)
    401 		if ((xpinfo->flags & filter.xpinfo.flags) == 0)
    402 			return 0;
    403 
    404 	return 1;
    405 }
    406 
    407 int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
    408 		      void *arg)
    409 {
    410 	struct rtattr * tb[XFRMA_MAX+1];
    411 	struct rtattr * rta;
    412 	struct xfrm_userpolicy_info *xpinfo = NULL;
    413 	struct xfrm_user_polexpire *xpexp = NULL;
    414 	struct xfrm_userpolicy_id *xpid = NULL;
    415 	__u8 ptype = XFRM_POLICY_TYPE_MAIN;
    416 	FILE *fp = (FILE*)arg;
    417 	int len = n->nlmsg_len;
    418 
    419 	if (n->nlmsg_type != XFRM_MSG_NEWPOLICY &&
    420 	    n->nlmsg_type != XFRM_MSG_DELPOLICY &&
    421 	    n->nlmsg_type != XFRM_MSG_UPDPOLICY &&
    422 	    n->nlmsg_type != XFRM_MSG_POLEXPIRE) {
    423 		fprintf(stderr, "Not a policy: %08x %08x %08x\n",
    424 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    425 		return 0;
    426 	}
    427 
    428 	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)  {
    429 		xpid = NLMSG_DATA(n);
    430 		len -= NLMSG_SPACE(sizeof(*xpid));
    431 	} else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
    432 		xpexp = NLMSG_DATA(n);
    433 		xpinfo = &xpexp->pol;
    434 		len -= NLMSG_SPACE(sizeof(*xpexp));
    435 	} else {
    436 		xpexp = NULL;
    437 		xpinfo = NLMSG_DATA(n);
    438 		len -= NLMSG_SPACE(sizeof(*xpinfo));
    439 	}
    440 
    441 	if (len < 0) {
    442 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    443 		return -1;
    444 	}
    445 
    446 	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
    447 		rta = XFRMPID_RTA(xpid);
    448 	else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
    449 		rta = XFRMPEXP_RTA(xpexp);
    450 	else
    451 		rta = XFRMP_RTA(xpinfo);
    452 
    453 	parse_rtattr(tb, XFRMA_MAX, rta, len);
    454 
    455 	if (tb[XFRMA_POLICY_TYPE]) {
    456 		struct xfrm_userpolicy_type *upt;
    457 
    458 		if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
    459 			fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
    460 			return -1;
    461 		}
    462 		upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
    463 		ptype = upt->type;
    464 	}
    465 
    466 	if (xpinfo && !xfrm_policy_filter_match(xpinfo, ptype))
    467 		return 0;
    468 
    469 	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
    470 		fprintf(fp, "Deleted ");
    471 	else if (n->nlmsg_type == XFRM_MSG_UPDPOLICY)
    472 		fprintf(fp, "Updated ");
    473 	else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
    474 		fprintf(fp, "Expired ");
    475 
    476 	if (n->nlmsg_type == XFRM_MSG_DELPOLICY) {
    477 		//xfrm_policy_id_print();
    478 		if (!tb[XFRMA_POLICY]) {
    479 			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: no XFRMA_POLICY\n");
    480 			return -1;
    481 		}
    482 		if (RTA_PAYLOAD(tb[XFRMA_POLICY]) < sizeof(*xpinfo)) {
    483 			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
    484 			return -1;
    485 		}
    486 		xpinfo = (struct xfrm_userpolicy_info *)RTA_DATA(tb[XFRMA_POLICY]);
    487 	}
    488 
    489 	xfrm_policy_info_print(xpinfo, tb, fp, NULL, NULL);
    490 
    491 	if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
    492 		fprintf(fp, "\t");
    493 		fprintf(fp, "hard %u", xpexp->hard);
    494 		fprintf(fp, "%s", _SL_);
    495 	}
    496 
    497 	if (oneline)
    498 		fprintf(fp, "\n");
    499 	fflush(fp);
    500 
    501 	return 0;
    502 }
    503 
    504 static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
    505 				     void *res_nlbuf)
    506 {
    507 	struct rtnl_handle rth;
    508 	struct {
    509 		struct nlmsghdr			n;
    510 		struct xfrm_userpolicy_id	xpid;
    511 		char				buf[RTA_BUF_SIZE];
    512 	} req;
    513 	char *dirp = NULL;
    514 	char *selp = NULL;
    515 	char *indexp = NULL;
    516 	char *ptypep = NULL;
    517 	struct xfrm_userpolicy_type upt;
    518 
    519 	memset(&req, 0, sizeof(req));
    520 	memset(&upt, 0, sizeof(upt));
    521 
    522 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid));
    523 	req.n.nlmsg_flags = NLM_F_REQUEST;
    524 	req.n.nlmsg_type = delete ? XFRM_MSG_DELPOLICY : XFRM_MSG_GETPOLICY;
    525 
    526 	while (argc > 0) {
    527 		if (strcmp(*argv, "dir") == 0) {
    528 			if (dirp)
    529 				duparg("dir", *argv);
    530 			dirp = *argv;
    531 
    532 			NEXT_ARG();
    533 			xfrm_policy_dir_parse(&req.xpid.dir, &argc, &argv);
    534 
    535 		} else if (strcmp(*argv, "index") == 0) {
    536 			if (indexp)
    537 				duparg("index", *argv);
    538 			indexp = *argv;
    539 
    540 			NEXT_ARG();
    541 			if (get_u32(&req.xpid.index, *argv, 0))
    542 				invarg("\"INDEX\" is invalid", *argv);
    543 
    544 		} else if (strcmp(*argv, "ptype") == 0) {
    545 			if (ptypep)
    546 				duparg("ptype", *argv);
    547 			ptypep = *argv;
    548 
    549 			NEXT_ARG();
    550 			xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
    551 
    552 		} else {
    553 			if (selp)
    554 				invarg("unknown", *argv);
    555 			selp = *argv;
    556 
    557 			xfrm_selector_parse(&req.xpid.sel, &argc, &argv);
    558 			if (preferred_family == AF_UNSPEC)
    559 				preferred_family = req.xpid.sel.family;
    560 
    561 		}
    562 
    563 		argc--; argv++;
    564 	}
    565 
    566 	if (!dirp) {
    567 		fprintf(stderr, "Not enough information: \"DIR\" is required.\n");
    568 		exit(1);
    569 	}
    570 	if (ptypep) {
    571 		addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
    572 			  (void *)&upt, sizeof(upt));
    573 	}
    574 	if (!selp && !indexp) {
    575 		fprintf(stderr, "Not enough information: either \"SELECTOR\" or \"INDEX\" is required.\n");
    576 		exit(1);
    577 	}
    578 	if (selp && indexp)
    579 		duparg2("SELECTOR", "INDEX");
    580 
    581 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    582 		exit(1);
    583 
    584 	if (req.xpid.sel.family == AF_UNSPEC)
    585 		req.xpid.sel.family = AF_INET;
    586 
    587 	if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf, NULL, NULL) < 0)
    588 		exit(2);
    589 
    590 	rtnl_close(&rth);
    591 
    592 	return 0;
    593 }
    594 
    595 static int xfrm_policy_delete(int argc, char **argv)
    596 {
    597 	return xfrm_policy_get_or_delete(argc, argv, 1, NULL);
    598 }
    599 
    600 static int xfrm_policy_get(int argc, char **argv)
    601 {
    602 	char buf[NLMSG_BUF_SIZE];
    603 	struct nlmsghdr *n = (struct nlmsghdr *)buf;
    604 
    605 	memset(buf, 0, sizeof(buf));
    606 
    607 	xfrm_policy_get_or_delete(argc, argv, 0, n);
    608 
    609 	if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) {
    610 		fprintf(stderr, "An error :-)\n");
    611 		exit(1);
    612 	}
    613 
    614 	return 0;
    615 }
    616 
    617 /*
    618  * With an existing policy of nlmsg, make new nlmsg for deleting the policy
    619  * and store it to buffer.
    620  */
    621 static int xfrm_policy_keep(const struct sockaddr_nl *who,
    622 			    struct nlmsghdr *n,
    623 			    void *arg)
    624 {
    625 	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
    626 	struct rtnl_handle *rth = xb->rth;
    627 	struct xfrm_userpolicy_info *xpinfo = NLMSG_DATA(n);
    628 	int len = n->nlmsg_len;
    629 	struct rtattr *tb[XFRMA_MAX+1];
    630 	__u8 ptype = XFRM_POLICY_TYPE_MAIN;
    631 	struct nlmsghdr *new_n;
    632 	struct xfrm_userpolicy_id *xpid;
    633 
    634 	if (n->nlmsg_type != XFRM_MSG_NEWPOLICY) {
    635 		fprintf(stderr, "Not a policy: %08x %08x %08x\n",
    636 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    637 		return 0;
    638 	}
    639 
    640 	len -= NLMSG_LENGTH(sizeof(*xpinfo));
    641 	if (len < 0) {
    642 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    643 		return -1;
    644 	}
    645 
    646 	parse_rtattr(tb, XFRMA_MAX, XFRMP_RTA(xpinfo), len);
    647 
    648 	if (tb[XFRMA_POLICY_TYPE]) {
    649 		struct xfrm_userpolicy_type *upt;
    650 
    651 		if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
    652 			fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
    653 			return -1;
    654 		}
    655 		upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
    656 		ptype = upt->type;
    657 	}
    658 
    659 	if (!xfrm_policy_filter_match(xpinfo, ptype))
    660 		return 0;
    661 
    662 	if (xb->offset > xb->size) {
    663 		fprintf(stderr, "Policy buffer overflow\n");
    664 		return -1;
    665 	}
    666 
    667 	new_n = (struct nlmsghdr *)(xb->buf + xb->offset);
    668 	new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xpid));
    669 	new_n->nlmsg_flags = NLM_F_REQUEST;
    670 	new_n->nlmsg_type = XFRM_MSG_DELPOLICY;
    671 	new_n->nlmsg_seq = ++rth->seq;
    672 
    673 	xpid = NLMSG_DATA(new_n);
    674 	memcpy(&xpid->sel, &xpinfo->sel, sizeof(xpid->sel));
    675 	xpid->dir = xpinfo->dir;
    676 	xpid->index = xpinfo->index;
    677 
    678 	xb->offset += new_n->nlmsg_len;
    679 	xb->nlmsg_count ++;
    680 
    681 	return 0;
    682 }
    683 
    684 static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall)
    685 {
    686 	char *selp = NULL;
    687 	struct rtnl_handle rth;
    688 
    689 	if (argc > 0)
    690 		filter.use = 1;
    691 	filter.xpinfo.sel.family = preferred_family;
    692 
    693 	while (argc > 0) {
    694 		if (strcmp(*argv, "dir") == 0) {
    695 			NEXT_ARG();
    696 			xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv);
    697 
    698 			filter.dir_mask = XFRM_FILTER_MASK_FULL;
    699 
    700 		} else if (strcmp(*argv, "index") == 0) {
    701 			NEXT_ARG();
    702 			if (get_u32(&filter.xpinfo.index, *argv, 0))
    703 				invarg("\"INDEX\" is invalid", *argv);
    704 
    705 			filter.index_mask = XFRM_FILTER_MASK_FULL;
    706 
    707 		} else if (strcmp(*argv, "ptype") == 0) {
    708 			NEXT_ARG();
    709 			xfrm_policy_ptype_parse(&filter.ptype, &argc, &argv);
    710 
    711 			filter.ptype_mask = XFRM_FILTER_MASK_FULL;
    712 
    713 		} else if (strcmp(*argv, "action") == 0) {
    714 			NEXT_ARG();
    715 			if (strcmp(*argv, "allow") == 0)
    716 				filter.xpinfo.action = XFRM_POLICY_ALLOW;
    717 			else if (strcmp(*argv, "block") == 0)
    718 				filter.xpinfo.action = XFRM_POLICY_BLOCK;
    719 			else
    720 				invarg("\"ACTION\" is invalid\n", *argv);
    721 
    722 			filter.action_mask = XFRM_FILTER_MASK_FULL;
    723 
    724 		} else if (strcmp(*argv, "priority") == 0) {
    725 			NEXT_ARG();
    726 			if (get_u32(&filter.xpinfo.priority, *argv, 0))
    727 				invarg("\"PRIORITY\" is invalid", *argv);
    728 
    729 			filter.priority_mask = XFRM_FILTER_MASK_FULL;
    730 
    731 		} else if (strcmp(*argv, "flag") == 0) {
    732 			NEXT_ARG();
    733 			xfrm_policy_flag_parse(&filter.xpinfo.flags, &argc,
    734 					       &argv);
    735 
    736 			filter.policy_flags_mask = XFRM_FILTER_MASK_FULL;
    737 
    738 		} else {
    739 			if (selp)
    740 				invarg("unknown", *argv);
    741 			selp = *argv;
    742 
    743 			xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv);
    744 			if (preferred_family == AF_UNSPEC)
    745 				preferred_family = filter.xpinfo.sel.family;
    746 
    747 		}
    748 
    749 		argc--; argv++;
    750 	}
    751 
    752 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    753 		exit(1);
    754 
    755 	if (deleteall) {
    756 		struct xfrm_buffer xb;
    757 		char buf[NLMSG_DELETEALL_BUF_SIZE];
    758 		int i;
    759 
    760 		xb.buf = buf;
    761 		xb.size = sizeof(buf);
    762 		xb.rth = &rth;
    763 
    764 		for (i = 0; ; i++) {
    765 			xb.offset = 0;
    766 			xb.nlmsg_count = 0;
    767 
    768 			if (show_stats > 1)
    769 				fprintf(stderr, "Delete-all round = %d\n", i);
    770 
    771 			if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) {
    772 				perror("Cannot send dump request");
    773 				exit(1);
    774 			}
    775 
    776 			if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb, NULL, NULL) < 0) {
    777 				fprintf(stderr, "Delete-all terminated\n");
    778 				exit(1);
    779 			}
    780 			if (xb.nlmsg_count == 0) {
    781 				if (show_stats > 1)
    782 					fprintf(stderr, "Delete-all completed\n");
    783 				break;
    784 			}
    785 
    786 			if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) {
    787 				perror("Failed to send delete-all request");
    788 				exit(1);
    789 			}
    790 			if (show_stats > 1)
    791 				fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);
    792 
    793 			xb.offset = 0;
    794 			xb.nlmsg_count = 0;
    795 		}
    796 	} else {
    797 		if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) {
    798 			perror("Cannot send dump request");
    799 			exit(1);
    800 		}
    801 
    802 		if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout, NULL, NULL) < 0) {
    803 			fprintf(stderr, "Dump terminated\n");
    804 			exit(1);
    805 		}
    806 	}
    807 
    808 	rtnl_close(&rth);
    809 
    810 	exit(0);
    811 }
    812 
    813 int print_spdinfo( struct nlmsghdr *n, void *arg)
    814 {
    815 	FILE *fp = (FILE*)arg;
    816 	__u32 *f = NLMSG_DATA(n);
    817 	struct rtattr * tb[XFRMA_SPD_MAX+1];
    818 	struct rtattr * rta;
    819 
    820 	int len = n->nlmsg_len;
    821 
    822 	len -= NLMSG_LENGTH(sizeof(__u32));
    823 	if (len < 0) {
    824 		fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
    825 		return -1;
    826 	}
    827 
    828 	rta = XFRMSAPD_RTA(f);
    829 	parse_rtattr(tb, XFRMA_SPD_MAX, rta, len);
    830 
    831 	fprintf(fp,"\t SPD");
    832 	if (tb[XFRMA_SPD_INFO]) {
    833 		struct xfrmu_spdinfo *si;
    834 
    835 		if (RTA_PAYLOAD(tb[XFRMA_SPD_INFO]) < sizeof(*si)) {
    836 			fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
    837 			return -1;
    838 		}
    839 		si = RTA_DATA(tb[XFRMA_SPD_INFO]);
    840 		fprintf(fp," IN  %d", si->incnt);
    841 		fprintf(fp," OUT %d", si->outcnt);
    842 		fprintf(fp," FWD %d", si->fwdcnt);
    843 
    844 		if (show_stats) {
    845 			fprintf(fp," (Sock:");
    846 			fprintf(fp," IN %d", si->inscnt);
    847 			fprintf(fp," OUT %d", si->outscnt);
    848 			fprintf(fp," FWD %d", si->fwdscnt);
    849 			fprintf(fp,")");
    850 		}
    851 
    852 		fprintf(fp,"\n");
    853 	}
    854 	if (show_stats > 1) {
    855 		struct xfrmu_spdhinfo *sh;
    856 
    857 		if (tb[XFRMA_SPD_HINFO]) {
    858 			if (RTA_PAYLOAD(tb[XFRMA_SPD_HINFO]) < sizeof(*sh)) {
    859 				fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
    860 				return -1;
    861 			}
    862 			sh = RTA_DATA(tb[XFRMA_SPD_HINFO]);
    863 			fprintf(fp,"\t SPD buckets:");
    864 			fprintf(fp," count %d", sh->spdhcnt);
    865 			fprintf(fp," Max %d", sh->spdhmcnt);
    866 		}
    867 	}
    868 	fprintf(fp,"\n");
    869 
    870         return 0;
    871 }
    872 
    873 static int xfrm_spd_getinfo(int argc, char **argv)
    874 {
    875 	struct rtnl_handle rth;
    876 	struct {
    877 		struct nlmsghdr			n;
    878 		__u32				flags;
    879 		char 				ans[128];
    880 	} req;
    881 
    882 	memset(&req, 0, sizeof(req));
    883 
    884 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(__u32));
    885 	req.n.nlmsg_flags = NLM_F_REQUEST;
    886 	req.n.nlmsg_type = XFRM_MSG_GETSPDINFO;
    887 	req.flags = 0XFFFFFFFF;
    888 
    889 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    890 		exit(1);
    891 
    892 	if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
    893 		exit(2);
    894 
    895 	print_spdinfo(&req.n, (void*)stdout);
    896 
    897 	rtnl_close(&rth);
    898 
    899 	return 0;
    900 }
    901 
    902 static int xfrm_policy_flush(int argc, char **argv)
    903 {
    904 	struct rtnl_handle rth;
    905 	struct {
    906 		struct nlmsghdr	n;
    907 		char		buf[RTA_BUF_SIZE];
    908 	} req;
    909 	char *ptypep = NULL;
    910 	struct xfrm_userpolicy_type upt;
    911 
    912 	memset(&req, 0, sizeof(req));
    913 	memset(&upt, 0, sizeof(upt));
    914 
    915 	req.n.nlmsg_len = NLMSG_LENGTH(0); /* nlmsg data is nothing */
    916 	req.n.nlmsg_flags = NLM_F_REQUEST;
    917 	req.n.nlmsg_type = XFRM_MSG_FLUSHPOLICY;
    918 
    919 	while (argc > 0) {
    920 		if (strcmp(*argv, "ptype") == 0) {
    921 			if (ptypep)
    922 				duparg("ptype", *argv);
    923 			ptypep = *argv;
    924 
    925 			NEXT_ARG();
    926 			xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
    927 		} else
    928 			invarg("unknown", *argv);
    929 
    930 		argc--; argv++;
    931 	}
    932 
    933 	if (ptypep) {
    934 		addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
    935 			  (void *)&upt, sizeof(upt));
    936 	}
    937 
    938 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
    939 		exit(1);
    940 
    941 	if (show_stats > 1)
    942 		fprintf(stderr, "Flush policy\n");
    943 
    944 	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
    945 		exit(2);
    946 
    947 	rtnl_close(&rth);
    948 
    949 	return 0;
    950 }
    951 
    952 int do_xfrm_policy(int argc, char **argv)
    953 {
    954 	if (argc < 1)
    955 		return xfrm_policy_list_or_deleteall(0, NULL, 0);
    956 
    957 	if (matches(*argv, "add") == 0)
    958 		return xfrm_policy_modify(XFRM_MSG_NEWPOLICY, 0,
    959 					  argc-1, argv+1);
    960 	if (matches(*argv, "update") == 0)
    961 		return xfrm_policy_modify(XFRM_MSG_UPDPOLICY, 0,
    962 					  argc-1, argv+1);
    963 	if (matches(*argv, "delete") == 0)
    964 		return xfrm_policy_delete(argc-1, argv+1);
    965 	if (matches(*argv, "deleteall") == 0 || matches(*argv, "delall") == 0)
    966 		return xfrm_policy_list_or_deleteall(argc-1, argv+1, 1);
    967 	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
    968 	    || matches(*argv, "lst") == 0)
    969 		return xfrm_policy_list_or_deleteall(argc-1, argv+1, 0);
    970 	if (matches(*argv, "get") == 0)
    971 		return xfrm_policy_get(argc-1, argv+1);
    972 	if (matches(*argv, "flush") == 0)
    973 		return xfrm_policy_flush(argc-1, argv+1);
    974 	if (matches(*argv, "count") == 0)
    975 		return xfrm_spd_getinfo(argc, argv);
    976 	if (matches(*argv, "help") == 0)
    977 		usage();
    978 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv);
    979 	exit(-1);
    980 }
    981