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