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