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 52static void usage(void) __attribute__((noreturn)); 53 54static void usage(void) 55{ 56 fprintf(stderr, "Usage: ip xfrm policy { add | update } dir DIR SELECTOR [ index INDEX ] \n"); 57 fprintf(stderr, " [ action ACTION ] [ priority PRIORITY ] [ LIMIT-LIST ] [ TMPL-LIST ]\n"); 58 fprintf(stderr, "Usage: ip xfrm policy { delete | get } dir DIR [ SELECTOR | index INDEX ]\n"); 59 fprintf(stderr, "Usage: ip xfrm policy { deleteall | list } [ dir DIR ] [ SELECTOR ]\n"); 60 fprintf(stderr, " [ index INDEX ] [ action ACTION ] [ priority PRIORITY ]\n"); 61 fprintf(stderr, "Usage: ip xfrm policy flush\n"); 62 fprintf(stderr, "DIR := [ in | out | fwd ]\n"); 63 64 fprintf(stderr, "SELECTOR := src ADDR[/PLEN] dst ADDR[/PLEN] [ UPSPEC ] [ dev DEV ]\n"); 65 66 fprintf(stderr, "UPSPEC := proto PROTO [ [ sport PORT ] [ dport PORT ] |\n"); 67 fprintf(stderr, " [ type NUMBER ] [ code NUMBER ] ]\n"); 68 69 //fprintf(stderr, "DEV - device name(default=none)\n"); 70 71 fprintf(stderr, "ACTION := [ allow | block ](default=allow)\n"); 72 73 //fprintf(stderr, "PRIORITY - priority value(default=0)\n"); 74 75 fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] | [ limit LIMIT ]\n"); 76 fprintf(stderr, "LIMIT := [ [time-soft|time-hard|time-use-soft|time-use-hard] SECONDS ] |\n"); 77 fprintf(stderr, " [ [byte-soft|byte-hard] SIZE ] | [ [packet-soft|packet-hard] NUMBER ]\n"); 78 79 fprintf(stderr, "TMPL-LIST := [ TMPL-LIST ] | [ tmpl TMPL ]\n"); 80 fprintf(stderr, "TMPL := ID [ mode MODE ] [ reqid REQID ] [ level LEVEL ]\n"); 81 fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM_PROTO ] [ spi SPI ]\n"); 82 83 //fprintf(stderr, "XFRM_PROTO := [ esp | ah | comp ]\n"); 84 fprintf(stderr, "XFRM_PROTO := [ "); 85 fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP)); 86 fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH)); 87 fprintf(stderr, "%s", strxf_xfrmproto(IPPROTO_COMP)); 88 fprintf(stderr, " ]\n"); 89 90 fprintf(stderr, "MODE := [ transport | tunnel ](default=transport)\n"); 91 //fprintf(stderr, "REQID - number(default=0)\n"); 92 fprintf(stderr, "LEVEL := [ required | use ](default=required)\n"); 93 94 exit(-1); 95} 96 97static int xfrm_policy_dir_parse(__u8 *dir, int *argcp, char ***argvp) 98{ 99 int argc = *argcp; 100 char **argv = *argvp; 101 102 if (strcmp(*argv, "in") == 0) 103 *dir = XFRM_POLICY_IN; 104 else if (strcmp(*argv, "out") == 0) 105 *dir = XFRM_POLICY_OUT; 106 else if (strcmp(*argv, "fwd") == 0) 107 *dir = XFRM_POLICY_FWD; 108 else 109 invarg("\"DIR\" is invalid", *argv); 110 111 *argcp = argc; 112 *argvp = argv; 113 114 return 0; 115} 116 117static int xfrm_tmpl_parse(struct xfrm_user_tmpl *tmpl, 118 int *argcp, char ***argvp) 119{ 120 int argc = *argcp; 121 char **argv = *argvp; 122 char *idp = NULL; 123 124 while (1) { 125 if (strcmp(*argv, "mode") == 0) { 126 NEXT_ARG(); 127 xfrm_mode_parse(&tmpl->mode, &argc, &argv); 128 } else if (strcmp(*argv, "reqid") == 0) { 129 NEXT_ARG(); 130 xfrm_reqid_parse(&tmpl->reqid, &argc, &argv); 131 } else if (strcmp(*argv, "level") == 0) { 132 NEXT_ARG(); 133 134 if (strcmp(*argv, "required") == 0) 135 tmpl->optional = 0; 136 else if (strcmp(*argv, "use") == 0) 137 tmpl->optional = 1; 138 else 139 invarg("\"LEVEL\" is invalid\n", *argv); 140 141 } else { 142 if (idp) { 143 PREV_ARG(); /* back track */ 144 break; 145 } 146 idp = *argv; 147 xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family, 148 0, &argc, &argv); 149 if (preferred_family == AF_UNSPEC) 150 preferred_family = tmpl->family; 151 } 152 153 if (!NEXT_ARG_OK()) 154 break; 155 156 NEXT_ARG(); 157 } 158 if (argc == *argcp) 159 missarg("TMPL"); 160 161 *argcp = argc; 162 *argvp = argv; 163 164 return 0; 165} 166 167static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) 168{ 169 struct rtnl_handle rth; 170 struct { 171 struct nlmsghdr n; 172 struct xfrm_userpolicy_info xpinfo; 173 char buf[RTA_BUF_SIZE]; 174 } req; 175 char *dirp = NULL; 176 char *selp = NULL; 177 char tmpls_buf[XFRM_TMPLS_BUF_SIZE]; 178 int tmpls_len = 0; 179 180 memset(&req, 0, sizeof(req)); 181 memset(&tmpls_buf, 0, sizeof(tmpls_buf)); 182 183 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo)); 184 req.n.nlmsg_flags = NLM_F_REQUEST|flags; 185 req.n.nlmsg_type = cmd; 186 req.xpinfo.sel.family = preferred_family; 187 188 req.xpinfo.lft.soft_byte_limit = XFRM_INF; 189 req.xpinfo.lft.hard_byte_limit = XFRM_INF; 190 req.xpinfo.lft.soft_packet_limit = XFRM_INF; 191 req.xpinfo.lft.hard_packet_limit = XFRM_INF; 192 193 while (argc > 0) { 194 if (strcmp(*argv, "dir") == 0) { 195 if (dirp) 196 duparg("dir", *argv); 197 dirp = *argv; 198 199 NEXT_ARG(); 200 xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv); 201 202 filter.dir_mask = XFRM_FILTER_MASK_FULL; 203 204 } else if (strcmp(*argv, "index") == 0) { 205 NEXT_ARG(); 206 if (get_u32(&req.xpinfo.index, *argv, 0)) 207 invarg("\"INDEX\" is invalid", *argv); 208 209 filter.index_mask = XFRM_FILTER_MASK_FULL; 210 211 } else if (strcmp(*argv, "action") == 0) { 212 NEXT_ARG(); 213 if (strcmp(*argv, "allow") == 0) 214 req.xpinfo.action = XFRM_POLICY_ALLOW; 215 else if (strcmp(*argv, "block") == 0) 216 req.xpinfo.action = XFRM_POLICY_BLOCK; 217 else 218 invarg("\"action\" value is invalid\n", *argv); 219 220 filter.action_mask = XFRM_FILTER_MASK_FULL; 221 222 } else if (strcmp(*argv, "priority") == 0) { 223 NEXT_ARG(); 224 if (get_u32(&req.xpinfo.priority, *argv, 0)) 225 invarg("\"PRIORITY\" is invalid", *argv); 226 227 filter.priority_mask = XFRM_FILTER_MASK_FULL; 228 229 } else if (strcmp(*argv, "limit") == 0) { 230 NEXT_ARG(); 231 xfrm_lifetime_cfg_parse(&req.xpinfo.lft, &argc, &argv); 232 } else if (strcmp(*argv, "tmpl") == 0) { 233 struct xfrm_user_tmpl *tmpl; 234 235 if (tmpls_len + sizeof(*tmpl) > sizeof(tmpls_buf)) { 236 fprintf(stderr, "Too many tmpls: buffer overflow\n"); 237 exit(1); 238 } 239 tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len); 240 241 tmpl->family = preferred_family; 242 tmpl->aalgos = (~(__u32)0); 243 tmpl->ealgos = (~(__u32)0); 244 tmpl->calgos = (~(__u32)0); 245 246 NEXT_ARG(); 247 xfrm_tmpl_parse(tmpl, &argc, &argv); 248 249 tmpls_len += sizeof(*tmpl); 250 } else { 251 if (selp) 252 duparg("unknown", *argv); 253 selp = *argv; 254 255 xfrm_selector_parse(&req.xpinfo.sel, &argc, &argv); 256 if (preferred_family == AF_UNSPEC) 257 preferred_family = req.xpinfo.sel.family; 258 } 259 260 argc--; argv++; 261 } 262 263 if (!dirp) { 264 fprintf(stderr, "Not enough information: \"DIR\" is required.\n"); 265 exit(1); 266 } 267 268 if (tmpls_len > 0) { 269 addattr_l(&req.n, sizeof(req), XFRMA_TMPL, 270 (void *)tmpls_buf, tmpls_len); 271 } 272 273 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) 274 exit(1); 275 276 if (req.xpinfo.sel.family == AF_UNSPEC) 277 req.xpinfo.sel.family = AF_INET; 278 279 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) 280 exit(2); 281 282 rtnl_close(&rth); 283 284 return 0; 285} 286 287static int xfrm_policy_filter_match(struct xfrm_userpolicy_info *xpinfo) 288{ 289 if (!filter.use) 290 return 1; 291 292 if ((xpinfo->dir^filter.xpinfo.dir)&filter.dir_mask) 293 return 0; 294 295 if (filter.sel_src_mask) { 296 if (xfrm_addr_match(&xpinfo->sel.saddr, &filter.xpinfo.sel.saddr, 297 filter.sel_src_mask)) 298 return 0; 299 } 300 301 if (filter.sel_dst_mask) { 302 if (xfrm_addr_match(&xpinfo->sel.daddr, &filter.xpinfo.sel.daddr, 303 filter.sel_dst_mask)) 304 return 0; 305 } 306 307 if ((xpinfo->sel.ifindex^filter.xpinfo.sel.ifindex)&filter.sel_dev_mask) 308 return 0; 309 310 if ((xpinfo->sel.proto^filter.xpinfo.sel.proto)&filter.upspec_proto_mask) 311 return 0; 312 313 if (filter.upspec_sport_mask) { 314 if ((xpinfo->sel.sport^filter.xpinfo.sel.sport)&filter.upspec_sport_mask) 315 return 0; 316 } 317 318 if (filter.upspec_dport_mask) { 319 if ((xpinfo->sel.dport^filter.xpinfo.sel.dport)&filter.upspec_dport_mask) 320 return 0; 321 } 322 323 if ((xpinfo->index^filter.xpinfo.index)&filter.index_mask) 324 return 0; 325 326 if ((xpinfo->action^filter.xpinfo.action)&filter.action_mask) 327 return 0; 328 329 if ((xpinfo->priority^filter.xpinfo.priority)&filter.priority_mask) 330 return 0; 331 332 return 1; 333} 334 335int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n, 336 void *arg) 337{ 338 FILE *fp = (FILE*)arg; 339 struct xfrm_userpolicy_info *xpinfo; 340 struct xfrm_user_polexpire *xpexp; 341 int len = n->nlmsg_len; 342 struct rtattr * tb[XFRMA_MAX+1]; 343 struct rtattr * rta; 344 345 if (n->nlmsg_type != XFRM_MSG_NEWPOLICY && 346 n->nlmsg_type != XFRM_MSG_DELPOLICY && 347 n->nlmsg_type != XFRM_MSG_POLEXPIRE) { 348 fprintf(stderr, "Not a policy: %08x %08x %08x\n", 349 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 350 return 0; 351 } 352 353 if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) { 354 xpexp = NLMSG_DATA(n); 355 xpinfo = &xpexp->pol; 356 357 len -= NLMSG_LENGTH(sizeof(*xpexp)); 358 } else { 359 xpexp = NULL; 360 xpinfo = NLMSG_DATA(n); 361 362 len -= NLMSG_LENGTH(sizeof(*xpinfo)); 363 } 364 365 if (len < 0) { 366 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 367 return -1; 368 } 369 370 if (!xfrm_policy_filter_match(xpinfo)) 371 return 0; 372 373 if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) 374 rta = XFRMPEXP_RTA(xpexp); 375 else 376 rta = XFRMP_RTA(xpinfo); 377 378 parse_rtattr(tb, XFRMA_MAX, rta, len); 379 380 if (n->nlmsg_type == XFRM_MSG_DELPOLICY) 381 fprintf(fp, "Deleted "); 382 else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) 383 fprintf(fp, "Expired "); 384 385 xfrm_policy_info_print(xpinfo, tb, fp, NULL, NULL); 386 387 if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) { 388 fprintf(fp, "\t"); 389 fprintf(fp, "hard %u", xpexp->hard); 390 fprintf(fp, "%s", _SL_); 391 } 392 393 if (oneline) 394 fprintf(fp, "\n"); 395 396 return 0; 397} 398 399static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, 400 void *res_nlbuf) 401{ 402 struct rtnl_handle rth; 403 struct { 404 struct nlmsghdr n; 405 struct xfrm_userpolicy_id xpid; 406 } req; 407 char *dirp = NULL; 408 char *selp = NULL; 409 char *indexp = NULL; 410 411 memset(&req, 0, sizeof(req)); 412 413 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid)); 414 req.n.nlmsg_flags = NLM_F_REQUEST; 415 req.n.nlmsg_type = delete ? XFRM_MSG_DELPOLICY : XFRM_MSG_GETPOLICY; 416 417 while (argc > 0) { 418 if (strcmp(*argv, "dir") == 0) { 419 if (dirp) 420 duparg("dir", *argv); 421 dirp = *argv; 422 423 NEXT_ARG(); 424 xfrm_policy_dir_parse(&req.xpid.dir, &argc, &argv); 425 426 } else if (strcmp(*argv, "index") == 0) { 427 if (indexp) 428 duparg("index", *argv); 429 indexp = *argv; 430 431 NEXT_ARG(); 432 if (get_u32(&req.xpid.index, *argv, 0)) 433 invarg("\"INDEX\" is invalid", *argv); 434 435 } else { 436 if (selp) 437 invarg("unknown", *argv); 438 selp = *argv; 439 440 xfrm_selector_parse(&req.xpid.sel, &argc, &argv); 441 if (preferred_family == AF_UNSPEC) 442 preferred_family = req.xpid.sel.family; 443 444 } 445 446 argc--; argv++; 447 } 448 449 if (!dirp) { 450 fprintf(stderr, "Not enough information: \"DIR\" is required.\n"); 451 exit(1); 452 } 453 if (!selp && !indexp) { 454 fprintf(stderr, "Not enough information: either \"SELECTOR\" or \"INDEX\" is required.\n"); 455 exit(1); 456 } 457 if (selp && indexp) 458 duparg2("SELECTOR", "INDEX"); 459 460 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) 461 exit(1); 462 463 if (req.xpid.sel.family == AF_UNSPEC) 464 req.xpid.sel.family = AF_INET; 465 466 if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf, NULL, NULL) < 0) 467 exit(2); 468 469 rtnl_close(&rth); 470 471 return 0; 472} 473 474static int xfrm_policy_delete(int argc, char **argv) 475{ 476 return xfrm_policy_get_or_delete(argc, argv, 1, NULL); 477} 478 479static int xfrm_policy_get(int argc, char **argv) 480{ 481 char buf[NLMSG_BUF_SIZE]; 482 struct nlmsghdr *n = (struct nlmsghdr *)buf; 483 484 memset(buf, 0, sizeof(buf)); 485 486 xfrm_policy_get_or_delete(argc, argv, 0, n); 487 488 if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) { 489 fprintf(stderr, "An error :-)\n"); 490 exit(1); 491 } 492 493 return 0; 494} 495 496/* 497 * With an existing policy of nlmsg, make new nlmsg for deleting the policy 498 * and store it to buffer. 499 */ 500static int xfrm_policy_keep(const struct sockaddr_nl *who, 501 struct nlmsghdr *n, 502 void *arg) 503{ 504 struct xfrm_buffer *xb = (struct xfrm_buffer *)arg; 505 struct rtnl_handle *rth = xb->rth; 506 struct xfrm_userpolicy_info *xpinfo = NLMSG_DATA(n); 507 int len = n->nlmsg_len; 508 struct nlmsghdr *new_n; 509 struct xfrm_userpolicy_id *xpid; 510 511 if (n->nlmsg_type != XFRM_MSG_NEWPOLICY) { 512 fprintf(stderr, "Not a policy: %08x %08x %08x\n", 513 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 514 return 0; 515 } 516 517 len -= NLMSG_LENGTH(sizeof(*xpinfo)); 518 if (len < 0) { 519 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 520 return -1; 521 } 522 523 if (!xfrm_policy_filter_match(xpinfo)) 524 return 0; 525 526 if (xb->offset > xb->size) { 527 fprintf(stderr, "Policy buffer overflow\n"); 528 return -1; 529 } 530 531 new_n = (struct nlmsghdr *)(xb->buf + xb->offset); 532 new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xpid)); 533 new_n->nlmsg_flags = NLM_F_REQUEST; 534 new_n->nlmsg_type = XFRM_MSG_DELPOLICY; 535 new_n->nlmsg_seq = ++rth->seq; 536 537 xpid = NLMSG_DATA(new_n); 538 memcpy(&xpid->sel, &xpinfo->sel, sizeof(xpid->sel)); 539 xpid->dir = xpinfo->dir; 540 xpid->index = xpinfo->index; 541 542 xb->offset += new_n->nlmsg_len; 543 xb->nlmsg_count ++; 544 545 return 0; 546} 547 548static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall) 549{ 550 char *selp = NULL; 551 struct rtnl_handle rth; 552 553 if (argc > 0) 554 filter.use = 1; 555 filter.xpinfo.sel.family = preferred_family; 556 557 while (argc > 0) { 558 if (strcmp(*argv, "dir") == 0) { 559 NEXT_ARG(); 560 xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv); 561 562 filter.dir_mask = XFRM_FILTER_MASK_FULL; 563 564 } else if (strcmp(*argv, "index") == 0) { 565 NEXT_ARG(); 566 if (get_u32(&filter.xpinfo.index, *argv, 0)) 567 invarg("\"INDEX\" is invalid", *argv); 568 569 filter.index_mask = XFRM_FILTER_MASK_FULL; 570 571 } else if (strcmp(*argv, "action") == 0) { 572 NEXT_ARG(); 573 if (strcmp(*argv, "allow") == 0) 574 filter.xpinfo.action = XFRM_POLICY_ALLOW; 575 else if (strcmp(*argv, "block") == 0) 576 filter.xpinfo.action = XFRM_POLICY_BLOCK; 577 else 578 invarg("\"ACTION\" is invalid\n", *argv); 579 580 filter.action_mask = XFRM_FILTER_MASK_FULL; 581 582 } else if (strcmp(*argv, "priority") == 0) { 583 NEXT_ARG(); 584 if (get_u32(&filter.xpinfo.priority, *argv, 0)) 585 invarg("\"PRIORITY\" is invalid", *argv); 586 587 filter.priority_mask = XFRM_FILTER_MASK_FULL; 588 589 } else { 590 if (selp) 591 invarg("unknown", *argv); 592 selp = *argv; 593 594 xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv); 595 if (preferred_family == AF_UNSPEC) 596 preferred_family = filter.xpinfo.sel.family; 597 598 } 599 600 argc--; argv++; 601 } 602 603 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) 604 exit(1); 605 606 if (deleteall) { 607 struct xfrm_buffer xb; 608 char buf[NLMSG_DELETEALL_BUF_SIZE]; 609 int i; 610 611 xb.buf = buf; 612 xb.size = sizeof(buf); 613 xb.rth = &rth; 614 615 for (i = 0; ; i++) { 616 xb.offset = 0; 617 xb.nlmsg_count = 0; 618 619 if (show_stats > 1) 620 fprintf(stderr, "Delete-all round = %d\n", i); 621 622 if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) { 623 perror("Cannot send dump request"); 624 exit(1); 625 } 626 627 if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb, NULL, NULL) < 0) { 628 fprintf(stderr, "Delete-all terminated\n"); 629 exit(1); 630 } 631 if (xb.nlmsg_count == 0) { 632 if (show_stats > 1) 633 fprintf(stderr, "Delete-all completed\n"); 634 break; 635 } 636 637 if (rtnl_send(&rth, xb.buf, xb.offset) < 0) { 638 perror("Failed to send delete-all request\n"); 639 exit(1); 640 } 641 if (show_stats > 1) 642 fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count); 643 644 xb.offset = 0; 645 xb.nlmsg_count = 0; 646 } 647 } else { 648 if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) { 649 perror("Cannot send dump request"); 650 exit(1); 651 } 652 653 if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout, NULL, NULL) < 0) { 654 fprintf(stderr, "Dump terminated\n"); 655 exit(1); 656 } 657 } 658 659 rtnl_close(&rth); 660 661 exit(0); 662} 663 664static int xfrm_policy_flush(void) 665{ 666 struct rtnl_handle rth; 667 struct { 668 struct nlmsghdr n; 669 } req; 670 671 memset(&req, 0, sizeof(req)); 672 673 req.n.nlmsg_len = NLMSG_LENGTH(0); /* nlmsg data is nothing */ 674 req.n.nlmsg_flags = NLM_F_REQUEST; 675 req.n.nlmsg_type = XFRM_MSG_FLUSHPOLICY; 676 677 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) 678 exit(1); 679 680 if (show_stats > 1) 681 fprintf(stderr, "Flush policy\n"); 682 683 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) 684 exit(2); 685 686 rtnl_close(&rth); 687 688 return 0; 689} 690 691int do_xfrm_policy(int argc, char **argv) 692{ 693 if (argc < 1) 694 return xfrm_policy_list_or_deleteall(0, NULL, 0); 695 696 if (matches(*argv, "add") == 0) 697 return xfrm_policy_modify(XFRM_MSG_NEWPOLICY, 0, 698 argc-1, argv+1); 699 if (matches(*argv, "update") == 0) 700 return xfrm_policy_modify(XFRM_MSG_UPDPOLICY, 0, 701 argc-1, argv+1); 702 if (matches(*argv, "delete") == 0) 703 return xfrm_policy_delete(argc-1, argv+1); 704 if (matches(*argv, "deleteall") == 0 || matches(*argv, "delall") == 0) 705 return xfrm_policy_list_or_deleteall(argc-1, argv+1, 1); 706 if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 707 || matches(*argv, "lst") == 0) 708 return xfrm_policy_list_or_deleteall(argc-1, argv+1, 0); 709 if (matches(*argv, "get") == 0) 710 return xfrm_policy_get(argc-1, argv+1); 711 if (matches(*argv, "flush") == 0) 712 return xfrm_policy_flush(); 713 if (matches(*argv, "help") == 0) 714 usage(); 715 fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv); 716 exit(-1); 717} 718