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