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 ip.c, 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 <sys/types.h> 32 #include <sys/socket.h> 33 #include <time.h> 34 #include <netdb.h> 35 #include <linux/netlink.h> 36 #include <linux/rtnetlink.h> 37 #include <linux/xfrm.h> 38 39 #include "utils.h" 40 #include "xfrm.h" 41 42 #define STRBUF_SIZE (128) 43 #define STRBUF_CAT(buf, str) \ 44 do { \ 45 int rest = sizeof(buf) - 1 - strlen(buf); \ 46 if (rest > 0) { \ 47 int len = strlen(str); \ 48 if (len > rest) \ 49 len = rest; \ 50 strncat(buf, str, len); \ 51 buf[sizeof(buf) - 1] = '\0'; \ 52 } \ 53 } while(0); 54 55 struct xfrm_filter filter; 56 57 static void usage(void) __attribute__((noreturn)); 58 59 static void usage(void) 60 { 61 fprintf(stderr, 62 "Usage: ip xfrm XFRM_OBJECT { COMMAND | help }\n" 63 "where XFRM_OBJECT := { state | policy | monitor }\n"); 64 exit(-1); 65 } 66 67 /* This is based on utils.c(inet_addr_match) */ 68 int xfrm_addr_match(xfrm_address_t *x1, xfrm_address_t *x2, int bits) 69 { 70 __u32 *a1 = (__u32 *)x1; 71 __u32 *a2 = (__u32 *)x2; 72 int words = bits >> 0x05; 73 74 bits &= 0x1f; 75 76 if (words) 77 if (memcmp(a1, a2, words << 2)) 78 return -1; 79 80 if (bits) { 81 __u32 w1, w2; 82 __u32 mask; 83 84 w1 = a1[words]; 85 w2 = a2[words]; 86 87 mask = htonl((0xffffffff) << (0x20 - bits)); 88 89 if ((w1 ^ w2) & mask) 90 return 1; 91 } 92 93 return 0; 94 } 95 96 int xfrm_xfrmproto_is_ipsec(__u8 proto) 97 { 98 return (proto == IPPROTO_ESP || 99 proto == IPPROTO_AH || 100 proto == IPPROTO_COMP); 101 } 102 103 int xfrm_xfrmproto_is_ro(__u8 proto) 104 { 105 return (proto == IPPROTO_ROUTING || 106 proto == IPPROTO_DSTOPTS); 107 } 108 109 struct typeent { 110 const char *t_name; 111 int t_type; 112 }; 113 114 static const struct typeent xfrmproto_types[]= { 115 { "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "comp", IPPROTO_COMP }, 116 { "route2", IPPROTO_ROUTING }, { "hao", IPPROTO_DSTOPTS }, 117 { "ipsec-any", IPSEC_PROTO_ANY }, 118 { NULL, -1 } 119 }; 120 121 int xfrm_xfrmproto_getbyname(char *name) 122 { 123 int i; 124 125 for (i = 0; ; i++) { 126 const struct typeent *t = &xfrmproto_types[i]; 127 if (!t->t_name || t->t_type == -1) 128 break; 129 130 if (strcmp(t->t_name, name) == 0) 131 return t->t_type; 132 } 133 134 return -1; 135 } 136 137 const char *strxf_xfrmproto(__u8 proto) 138 { 139 static char str[16]; 140 int i; 141 142 for (i = 0; ; i++) { 143 const struct typeent *t = &xfrmproto_types[i]; 144 if (!t->t_name || t->t_type == -1) 145 break; 146 147 if (t->t_type == proto) 148 return t->t_name; 149 } 150 151 sprintf(str, "%u", proto); 152 return str; 153 } 154 155 static const struct typeent algo_types[]= { 156 { "enc", XFRMA_ALG_CRYPT }, { "auth", XFRMA_ALG_AUTH }, 157 { "comp", XFRMA_ALG_COMP }, { "aead", XFRMA_ALG_AEAD }, 158 { NULL, -1 } 159 }; 160 161 int xfrm_algotype_getbyname(char *name) 162 { 163 int i; 164 165 for (i = 0; ; i++) { 166 const struct typeent *t = &algo_types[i]; 167 if (!t->t_name || t->t_type == -1) 168 break; 169 170 if (strcmp(t->t_name, name) == 0) 171 return t->t_type; 172 } 173 174 return -1; 175 } 176 177 const char *strxf_algotype(int type) 178 { 179 static char str[32]; 180 int i; 181 182 for (i = 0; ; i++) { 183 const struct typeent *t = &algo_types[i]; 184 if (!t->t_name || t->t_type == -1) 185 break; 186 187 if (t->t_type == type) 188 return t->t_name; 189 } 190 191 sprintf(str, "%d", type); 192 return str; 193 } 194 195 const char *strxf_mask8(__u8 mask) 196 { 197 static char str[16]; 198 const int sn = sizeof(mask) * 8 - 1; 199 __u8 b; 200 int i = 0; 201 202 for (b = (1 << sn); b > 0; b >>= 1) 203 str[i++] = ((b & mask) ? '1' : '0'); 204 str[i] = '\0'; 205 206 return str; 207 } 208 209 const char *strxf_mask32(__u32 mask) 210 { 211 static char str[16]; 212 213 sprintf(str, "%.8x", mask); 214 215 return str; 216 } 217 218 const char *strxf_share(__u8 share) 219 { 220 static char str[32]; 221 222 switch (share) { 223 case XFRM_SHARE_ANY: 224 strcpy(str, "any"); 225 break; 226 case XFRM_SHARE_SESSION: 227 strcpy(str, "session"); 228 break; 229 case XFRM_SHARE_USER: 230 strcpy(str, "user"); 231 break; 232 case XFRM_SHARE_UNIQUE: 233 strcpy(str, "unique"); 234 break; 235 default: 236 sprintf(str, "%u", share); 237 break; 238 } 239 240 return str; 241 } 242 243 const char *strxf_proto(__u8 proto) 244 { 245 static char buf[32]; 246 struct protoent *pp; 247 const char *p; 248 249 pp = getprotobynumber(proto); 250 if (pp) 251 p = pp->p_name; 252 else { 253 sprintf(buf, "%u", proto); 254 p = buf; 255 } 256 257 return p; 258 } 259 260 const char *strxf_ptype(__u8 ptype) 261 { 262 static char str[16]; 263 264 switch (ptype) { 265 case XFRM_POLICY_TYPE_MAIN: 266 strcpy(str, "main"); 267 break; 268 case XFRM_POLICY_TYPE_SUB: 269 strcpy(str, "sub"); 270 break; 271 default: 272 sprintf(str, "%u", ptype); 273 break; 274 } 275 276 return str; 277 } 278 279 void xfrm_id_info_print(xfrm_address_t *saddr, struct xfrm_id *id, 280 __u8 mode, __u32 reqid, __u16 family, int force_spi, 281 FILE *fp, const char *prefix, const char *title) 282 { 283 char abuf[256]; 284 285 if (title) 286 fputs(title, fp); 287 288 memset(abuf, '\0', sizeof(abuf)); 289 fprintf(fp, "src %s ", rt_addr_n2a(family, sizeof(*saddr), 290 saddr, abuf, sizeof(abuf))); 291 memset(abuf, '\0', sizeof(abuf)); 292 fprintf(fp, "dst %s", rt_addr_n2a(family, sizeof(id->daddr), 293 &id->daddr, abuf, sizeof(abuf))); 294 fprintf(fp, "%s", _SL_); 295 296 if (prefix) 297 fputs(prefix, fp); 298 fprintf(fp, "\t"); 299 300 fprintf(fp, "proto %s ", strxf_xfrmproto(id->proto)); 301 302 if (show_stats > 0 || force_spi || id->spi) { 303 __u32 spi = ntohl(id->spi); 304 fprintf(fp, "spi 0x%08x", spi); 305 if (show_stats > 0) 306 fprintf(fp, "(%u)", spi); 307 fprintf(fp, " "); 308 } 309 310 fprintf(fp, "reqid %u", reqid); 311 if (show_stats > 0) 312 fprintf(fp, "(0x%08x)", reqid); 313 fprintf(fp, " "); 314 315 fprintf(fp, "mode "); 316 switch (mode) { 317 case XFRM_MODE_TRANSPORT: 318 fprintf(fp, "transport"); 319 break; 320 case XFRM_MODE_TUNNEL: 321 fprintf(fp, "tunnel"); 322 break; 323 case XFRM_MODE_ROUTEOPTIMIZATION: 324 fprintf(fp, "ro"); 325 break; 326 case XFRM_MODE_IN_TRIGGER: 327 fprintf(fp, "in_trigger"); 328 break; 329 case XFRM_MODE_BEET: 330 fprintf(fp, "beet"); 331 break; 332 default: 333 fprintf(fp, "%u", mode); 334 break; 335 } 336 fprintf(fp, "%s", _SL_); 337 } 338 339 static const char *strxf_limit(__u64 limit) 340 { 341 static char str[32]; 342 if (limit == XFRM_INF) 343 strcpy(str, "(INF)"); 344 else 345 sprintf(str, "%llu", (unsigned long long) limit); 346 347 return str; 348 } 349 350 void xfrm_stats_print(struct xfrm_stats *s, FILE *fp, const char *prefix) 351 { 352 if (prefix) 353 fputs(prefix, fp); 354 fprintf(fp, "stats:%s", _SL_); 355 356 if (prefix) 357 fputs(prefix, fp); 358 fprintf(fp, " replay-window %u replay %u failed %u%s", 359 s->replay_window, s->replay, s->integrity_failed, _SL_); 360 } 361 362 static const char *strxf_time(__u64 time) 363 { 364 static char str[32]; 365 366 if (time == 0) 367 strcpy(str, "-"); 368 else { 369 time_t t; 370 struct tm *tp; 371 372 /* XXX: treat time in the same manner of kernel's 373 * net/xfrm/xfrm_{user,state}.c 374 */ 375 t = (long)time; 376 tp = localtime(&t); 377 378 strftime(str, sizeof(str), "%Y-%m-%d %T", tp); 379 } 380 381 return str; 382 } 383 384 void xfrm_lifetime_print(struct xfrm_lifetime_cfg *cfg, 385 struct xfrm_lifetime_cur *cur, 386 FILE *fp, const char *prefix) 387 { 388 if (cfg) { 389 if (prefix) 390 fputs(prefix, fp); 391 fprintf(fp, "lifetime config:%s",_SL_); 392 393 if (prefix) 394 fputs(prefix, fp); 395 fprintf(fp, " limit: soft %s(bytes),", 396 strxf_limit(cfg->soft_byte_limit)); 397 fprintf(fp, " hard %s(bytes)%s", 398 strxf_limit(cfg->hard_byte_limit), _SL_); 399 400 if (prefix) 401 fputs(prefix, fp); 402 fprintf(fp, " limit: soft %s(packets),", 403 strxf_limit(cfg->soft_packet_limit)); 404 fprintf(fp, " hard %s(packets)%s", 405 strxf_limit(cfg->hard_packet_limit), _SL_); 406 407 if (prefix) 408 fputs(prefix, fp); 409 fprintf(fp, " expire add: soft %llu(sec), hard %llu(sec)%s", 410 (unsigned long long) cfg->soft_add_expires_seconds, 411 (unsigned long long) cfg->hard_add_expires_seconds, 412 _SL_); 413 414 if (prefix) 415 fputs(prefix, fp); 416 fprintf(fp, " expire use: soft %llu(sec), hard %llu(sec)%s", 417 (unsigned long long) cfg->soft_use_expires_seconds, 418 (unsigned long long) cfg->hard_use_expires_seconds, 419 _SL_); 420 } 421 if (cur) { 422 if (prefix) 423 fputs(prefix, fp); 424 fprintf(fp, "lifetime current:%s", _SL_); 425 426 if (prefix) 427 fputs(prefix, fp); 428 fprintf(fp, " %llu(bytes), %llu(packets)%s", 429 (unsigned long long) cur->bytes, 430 (unsigned long long) cur->packets, 431 _SL_); 432 433 if (prefix) 434 fputs(prefix, fp); 435 fprintf(fp, " add %s ", strxf_time(cur->add_time)); 436 fprintf(fp, "use %s%s", strxf_time(cur->use_time), _SL_); 437 } 438 } 439 440 void xfrm_selector_print(struct xfrm_selector *sel, __u16 family, 441 FILE *fp, const char *prefix) 442 { 443 char abuf[256]; 444 __u16 f; 445 446 f = sel->family; 447 if (f == AF_UNSPEC) 448 f = family; 449 if (f == AF_UNSPEC) 450 f = preferred_family; 451 452 if (prefix) 453 fputs(prefix, fp); 454 455 memset(abuf, '\0', sizeof(abuf)); 456 fprintf(fp, "src %s/%u ", rt_addr_n2a(f, sizeof(sel->saddr), 457 &sel->saddr, abuf, sizeof(abuf)), 458 sel->prefixlen_s); 459 460 memset(abuf, '\0', sizeof(abuf)); 461 fprintf(fp, "dst %s/%u ", rt_addr_n2a(f, sizeof(sel->daddr), 462 &sel->daddr, abuf, sizeof(abuf)), 463 sel->prefixlen_d); 464 465 if (sel->proto) 466 fprintf(fp, "proto %s ", strxf_proto(sel->proto)); 467 switch (sel->proto) { 468 case IPPROTO_TCP: 469 case IPPROTO_UDP: 470 case IPPROTO_SCTP: 471 case IPPROTO_DCCP: 472 default: /* XXX */ 473 if (sel->sport_mask) 474 fprintf(fp, "sport %u ", ntohs(sel->sport)); 475 if (sel->dport_mask) 476 fprintf(fp, "dport %u ", ntohs(sel->dport)); 477 break; 478 case IPPROTO_ICMP: 479 case IPPROTO_ICMPV6: 480 /* type/code is stored at sport/dport in selector */ 481 if (sel->sport_mask) 482 fprintf(fp, "type %u ", ntohs(sel->sport)); 483 if (sel->dport_mask) 484 fprintf(fp, "code %u ", ntohs(sel->dport)); 485 break; 486 case IPPROTO_MH: 487 if (sel->sport_mask) 488 fprintf(fp, "type %u ", ntohs(sel->sport)); 489 if (sel->dport_mask) { 490 if (show_stats > 0) 491 fprintf(fp, "(dport) 0x%.4x ", sel->dport); 492 } 493 break; 494 } 495 496 if (sel->ifindex > 0) 497 fprintf(fp, "dev %s ", ll_index_to_name(sel->ifindex)); 498 499 if (show_stats > 0) 500 fprintf(fp, "uid %u", sel->user); 501 502 fprintf(fp, "%s", _SL_); 503 } 504 505 static void __xfrm_algo_print(struct xfrm_algo *algo, int type, int len, 506 FILE *fp, const char *prefix, int newline) 507 { 508 int keylen; 509 int i; 510 511 if (prefix) 512 fputs(prefix, fp); 513 514 fprintf(fp, "%s ", strxf_algotype(type)); 515 516 if (len < sizeof(*algo)) { 517 fprintf(fp, "(ERROR truncated)"); 518 goto fin; 519 } 520 len -= sizeof(*algo); 521 522 fprintf(fp, "%s ", algo->alg_name); 523 524 keylen = algo->alg_key_len / 8; 525 if (len < keylen) { 526 fprintf(fp, "(ERROR truncated)"); 527 goto fin; 528 } 529 530 fprintf(fp, "0x"); 531 for (i = 0; i < keylen; i ++) 532 fprintf(fp, "%.2x", (unsigned char)algo->alg_key[i]); 533 534 if (show_stats > 0) 535 fprintf(fp, " (%d bits)", algo->alg_key_len); 536 537 fin: 538 if (newline) 539 fprintf(fp, "%s", _SL_); 540 } 541 542 static inline void xfrm_algo_print(struct xfrm_algo *algo, int type, int len, 543 FILE *fp, const char *prefix) 544 { 545 return __xfrm_algo_print(algo, type, len, fp, prefix, 1); 546 } 547 548 static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len, 549 FILE *fp, const char *prefix) 550 { 551 struct { 552 struct xfrm_algo algo; 553 char key[algo->alg_key_len / 8]; 554 } base; 555 556 memcpy(base.algo.alg_name, algo->alg_name, sizeof(base.algo.alg_name)); 557 base.algo.alg_key_len = algo->alg_key_len; 558 memcpy(base.algo.alg_key, algo->alg_key, algo->alg_key_len / 8); 559 560 __xfrm_algo_print(&base.algo, XFRMA_ALG_AEAD, len, fp, prefix, 0); 561 562 fprintf(fp, " %d", algo->alg_icv_len); 563 564 fprintf(fp, "%s", _SL_); 565 } 566 567 static void xfrm_tmpl_print(struct xfrm_user_tmpl *tmpls, int len, 568 __u16 family, FILE *fp, const char *prefix) 569 { 570 int ntmpls = len / sizeof(struct xfrm_user_tmpl); 571 int i; 572 573 if (ntmpls <= 0) { 574 if (prefix) 575 fputs(prefix, fp); 576 fprintf(fp, "(ERROR \"tmpl\" truncated)"); 577 fprintf(fp, "%s", _SL_); 578 return; 579 } 580 581 for (i = 0; i < ntmpls; i++) { 582 struct xfrm_user_tmpl *tmpl = &tmpls[i]; 583 584 if (prefix) 585 fputs(prefix, fp); 586 587 xfrm_id_info_print(&tmpl->saddr, &tmpl->id, tmpl->mode, 588 tmpl->reqid, tmpl->family, 0, fp, prefix, "tmpl "); 589 590 if (show_stats > 0 || tmpl->optional) { 591 if (prefix) 592 fputs(prefix, fp); 593 fprintf(fp, "\t"); 594 switch (tmpl->optional) { 595 case 0: 596 if (show_stats > 0) 597 fprintf(fp, "level required "); 598 break; 599 case 1: 600 fprintf(fp, "level use "); 601 break; 602 default: 603 fprintf(fp, "level %u ", tmpl->optional); 604 break; 605 } 606 607 if (show_stats > 0) 608 fprintf(fp, "share %s ", strxf_share(tmpl->share)); 609 610 fprintf(fp, "%s", _SL_); 611 } 612 613 if (show_stats > 0) { 614 if (prefix) 615 fputs(prefix, fp); 616 fprintf(fp, "\t"); 617 fprintf(fp, "%s-mask %s ", 618 strxf_algotype(XFRMA_ALG_CRYPT), 619 strxf_mask32(tmpl->ealgos)); 620 fprintf(fp, "%s-mask %s ", 621 strxf_algotype(XFRMA_ALG_AUTH), 622 strxf_mask32(tmpl->aalgos)); 623 fprintf(fp, "%s-mask %s", 624 strxf_algotype(XFRMA_ALG_COMP), 625 strxf_mask32(tmpl->calgos)); 626 627 fprintf(fp, "%s", _SL_); 628 } 629 } 630 } 631 632 void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, 633 FILE *fp, const char *prefix) 634 { 635 if (tb[XFRMA_ALG_AUTH]) { 636 struct rtattr *rta = tb[XFRMA_ALG_AUTH]; 637 xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), 638 XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix); 639 } 640 641 if (tb[XFRMA_ALG_AEAD]) { 642 struct rtattr *rta = tb[XFRMA_ALG_AEAD]; 643 xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta), 644 RTA_PAYLOAD(rta), fp, prefix); 645 } 646 647 if (tb[XFRMA_ALG_CRYPT]) { 648 struct rtattr *rta = tb[XFRMA_ALG_CRYPT]; 649 xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), 650 XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix); 651 } 652 653 if (tb[XFRMA_ALG_COMP]) { 654 struct rtattr *rta = tb[XFRMA_ALG_COMP]; 655 xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), 656 XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix); 657 } 658 659 if (tb[XFRMA_ENCAP]) { 660 struct xfrm_encap_tmpl *e; 661 char abuf[256]; 662 663 if (prefix) 664 fputs(prefix, fp); 665 fprintf(fp, "encap "); 666 667 if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) { 668 fprintf(fp, "(ERROR truncated)"); 669 fprintf(fp, "%s", _SL_); 670 return; 671 } 672 e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]); 673 674 fprintf(fp, "type "); 675 switch (e->encap_type) { 676 case 1: 677 fprintf(fp, "espinudp-nonike "); 678 break; 679 case 2: 680 fprintf(fp, "espinudp "); 681 break; 682 default: 683 fprintf(fp, "%u ", e->encap_type); 684 break; 685 } 686 fprintf(fp, "sport %u ", ntohs(e->encap_sport)); 687 fprintf(fp, "dport %u ", ntohs(e->encap_dport)); 688 689 memset(abuf, '\0', sizeof(abuf)); 690 fprintf(fp, "addr %s", 691 rt_addr_n2a(family, sizeof(e->encap_oa), 692 &e->encap_oa, abuf, sizeof(abuf))); 693 fprintf(fp, "%s", _SL_); 694 } 695 696 if (tb[XFRMA_TMPL]) { 697 struct rtattr *rta = tb[XFRMA_TMPL]; 698 xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta), 699 RTA_PAYLOAD(rta), family, fp, prefix); 700 } 701 702 if (tb[XFRMA_COADDR]) { 703 char abuf[256]; 704 xfrm_address_t *coa; 705 706 if (prefix) 707 fputs(prefix, fp); 708 fprintf(fp, "coa "); 709 710 coa = (xfrm_address_t *)RTA_DATA(tb[XFRMA_COADDR]); 711 712 if (RTA_PAYLOAD(tb[XFRMA_COADDR]) < sizeof(*coa)) { 713 fprintf(fp, "(ERROR truncated)"); 714 fprintf(fp, "%s", _SL_); 715 return; 716 } 717 718 memset(abuf, '\0', sizeof(abuf)); 719 fprintf(fp, "%s", 720 rt_addr_n2a(family, sizeof(*coa), coa, 721 abuf, sizeof(abuf))); 722 fprintf(fp, "%s", _SL_); 723 } 724 725 if (tb[XFRMA_LASTUSED]) { 726 __u64 lastused; 727 728 if (prefix) 729 fputs(prefix, fp); 730 fprintf(fp, "lastused "); 731 732 if (RTA_PAYLOAD(tb[XFRMA_LASTUSED]) < sizeof(lastused)) { 733 fprintf(fp, "(ERROR truncated)"); 734 fprintf(fp, "%s", _SL_); 735 return; 736 } 737 738 lastused = *(__u64 *)RTA_DATA(tb[XFRMA_LASTUSED]); 739 740 fprintf(fp, "%s", strxf_time(lastused)); 741 fprintf(fp, "%s", _SL_); 742 } 743 } 744 745 static int xfrm_selector_iszero(struct xfrm_selector *s) 746 { 747 struct xfrm_selector s0; 748 749 memset(&s0, 0, sizeof(s0)); 750 751 return (memcmp(&s0, s, sizeof(s0)) == 0); 752 } 753 754 void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo, 755 struct rtattr *tb[], FILE *fp, const char *prefix, 756 const char *title) 757 { 758 char buf[STRBUF_SIZE]; 759 int force_spi = xfrm_xfrmproto_is_ipsec(xsinfo->id.proto); 760 761 memset(buf, '\0', sizeof(buf)); 762 763 xfrm_id_info_print(&xsinfo->saddr, &xsinfo->id, xsinfo->mode, 764 xsinfo->reqid, xsinfo->family, force_spi, fp, 765 prefix, title); 766 767 if (prefix) 768 STRBUF_CAT(buf, prefix); 769 STRBUF_CAT(buf, "\t"); 770 771 fputs(buf, fp); 772 fprintf(fp, "replay-window %u ", xsinfo->replay_window); 773 if (show_stats > 0) 774 fprintf(fp, "seq 0x%08u ", xsinfo->seq); 775 if (show_stats > 0 || xsinfo->flags) { 776 __u8 flags = xsinfo->flags; 777 778 fprintf(fp, "flag "); 779 XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_NOECN, "noecn"); 780 XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_DECAP_DSCP, "decap-dscp"); 781 XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_NOPMTUDISC, "nopmtudisc"); 782 XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_WILDRECV, "wildrecv"); 783 if (flags) 784 fprintf(fp, "%x", flags); 785 } 786 if (show_stats > 0) 787 fprintf(fp, " (0x%s)", strxf_mask8(xsinfo->flags)); 788 fprintf(fp, "%s", _SL_); 789 790 xfrm_xfrma_print(tb, xsinfo->family, fp, buf); 791 792 if (!xfrm_selector_iszero(&xsinfo->sel)) { 793 char sbuf[STRBUF_SIZE]; 794 795 memcpy(sbuf, buf, sizeof(sbuf)); 796 STRBUF_CAT(sbuf, "sel "); 797 798 xfrm_selector_print(&xsinfo->sel, xsinfo->family, fp, sbuf); 799 } 800 801 if (show_stats > 0) { 802 xfrm_lifetime_print(&xsinfo->lft, &xsinfo->curlft, fp, buf); 803 xfrm_stats_print(&xsinfo->stats, fp, buf); 804 } 805 } 806 807 void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo, 808 struct rtattr *tb[], FILE *fp, const char *prefix, 809 const char *title) 810 { 811 char buf[STRBUF_SIZE]; 812 813 memset(buf, '\0', sizeof(buf)); 814 815 xfrm_selector_print(&xpinfo->sel, preferred_family, fp, title); 816 817 if (prefix) 818 STRBUF_CAT(buf, prefix); 819 STRBUF_CAT(buf, "\t"); 820 821 fputs(buf, fp); 822 fprintf(fp, "dir "); 823 switch (xpinfo->dir) { 824 case XFRM_POLICY_IN: 825 fprintf(fp, "in"); 826 break; 827 case XFRM_POLICY_OUT: 828 fprintf(fp, "out"); 829 break; 830 case XFRM_POLICY_FWD: 831 fprintf(fp, "fwd"); 832 break; 833 default: 834 fprintf(fp, "%u", xpinfo->dir); 835 break; 836 } 837 fprintf(fp, " "); 838 839 switch (xpinfo->action) { 840 case XFRM_POLICY_ALLOW: 841 if (show_stats > 0) 842 fprintf(fp, "action allow "); 843 break; 844 case XFRM_POLICY_BLOCK: 845 fprintf(fp, "action block "); 846 break; 847 default: 848 fprintf(fp, "action %u ", xpinfo->action); 849 break; 850 } 851 852 if (show_stats) 853 fprintf(fp, "index %u ", xpinfo->index); 854 fprintf(fp, "priority %u ", xpinfo->priority); 855 856 if (tb[XFRMA_POLICY_TYPE]) { 857 struct xfrm_userpolicy_type *upt; 858 859 fprintf(fp, "ptype "); 860 861 if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) 862 fprintf(fp, "(ERROR truncated)"); 863 864 upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]); 865 fprintf(fp, "%s ", strxf_ptype(upt->type)); 866 } 867 868 if (show_stats > 0) 869 fprintf(fp, "share %s ", strxf_share(xpinfo->share)); 870 871 if (show_stats > 0 || xpinfo->flags) { 872 __u8 flags = xpinfo->flags; 873 874 fprintf(fp, "flag "); 875 XFRM_FLAG_PRINT(fp, flags, XFRM_POLICY_LOCALOK, "localok"); 876 if (flags) 877 fprintf(fp, "%x", flags); 878 } 879 if (show_stats > 0) 880 fprintf(fp, " (0x%s)", strxf_mask8(xpinfo->flags)); 881 fprintf(fp, "%s", _SL_); 882 883 if (show_stats > 0) 884 xfrm_lifetime_print(&xpinfo->lft, &xpinfo->curlft, fp, buf); 885 886 xfrm_xfrma_print(tb, xpinfo->sel.family, fp, buf); 887 } 888 889 int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family, 890 int loose, int *argcp, char ***argvp) 891 { 892 int argc = *argcp; 893 char **argv = *argvp; 894 inet_prefix dst; 895 inet_prefix src; 896 897 memset(&dst, 0, sizeof(dst)); 898 memset(&src, 0, sizeof(src)); 899 900 while (1) { 901 if (strcmp(*argv, "src") == 0) { 902 NEXT_ARG(); 903 904 get_prefix(&src, *argv, preferred_family); 905 if (src.family == AF_UNSPEC) 906 invarg("\"src\" address family is AF_UNSPEC", *argv); 907 if (family) 908 *family = src.family; 909 910 memcpy(saddr, &src.data, sizeof(*saddr)); 911 912 filter.id_src_mask = src.bitlen; 913 914 } else if (strcmp(*argv, "dst") == 0) { 915 NEXT_ARG(); 916 917 get_prefix(&dst, *argv, preferred_family); 918 if (dst.family == AF_UNSPEC) 919 invarg("\"dst\" address family is AF_UNSPEC", *argv); 920 if (family) 921 *family = dst.family; 922 923 memcpy(&id->daddr, &dst.data, sizeof(id->daddr)); 924 925 filter.id_dst_mask = dst.bitlen; 926 927 } else if (strcmp(*argv, "proto") == 0) { 928 int ret; 929 930 NEXT_ARG(); 931 932 ret = xfrm_xfrmproto_getbyname(*argv); 933 if (ret < 0) 934 invarg("\"XFRM_PROTO\" is invalid", *argv); 935 936 id->proto = (__u8)ret; 937 938 filter.id_proto_mask = XFRM_FILTER_MASK_FULL; 939 940 } else if (strcmp(*argv, "spi") == 0) { 941 __u32 spi; 942 943 NEXT_ARG(); 944 if (get_u32(&spi, *argv, 0)) 945 invarg("\"SPI\" is invalid", *argv); 946 947 spi = htonl(spi); 948 id->spi = spi; 949 950 filter.id_spi_mask = XFRM_FILTER_MASK_FULL; 951 952 } else { 953 PREV_ARG(); /* back track */ 954 break; 955 } 956 957 if (!NEXT_ARG_OK()) 958 break; 959 NEXT_ARG(); 960 } 961 962 if (src.family && dst.family && (src.family != dst.family)) 963 invarg("the same address family is required between \"src\" and \"dst\"", *argv); 964 965 if (loose == 0 && id->proto == 0) 966 missarg("XFRM_PROTO"); 967 if (argc == *argcp) 968 missarg("ID"); 969 970 *argcp = argc; 971 *argvp = argv; 972 973 return 0; 974 } 975 976 int xfrm_mode_parse(__u8 *mode, int *argcp, char ***argvp) 977 { 978 int argc = *argcp; 979 char **argv = *argvp; 980 981 if (matches(*argv, "transport") == 0) 982 *mode = XFRM_MODE_TRANSPORT; 983 else if (matches(*argv, "tunnel") == 0) 984 *mode = XFRM_MODE_TUNNEL; 985 else if (matches(*argv, "ro") == 0) 986 *mode = XFRM_MODE_ROUTEOPTIMIZATION; 987 else if (matches(*argv, "in_trigger") == 0) 988 *mode = XFRM_MODE_IN_TRIGGER; 989 else if (matches(*argv, "beet") == 0) 990 *mode = XFRM_MODE_BEET; 991 else 992 invarg("\"MODE\" is invalid", *argv); 993 994 *argcp = argc; 995 *argvp = argv; 996 997 return 0; 998 } 999 1000 int xfrm_encap_type_parse(__u16 *type, int *argcp, char ***argvp) 1001 { 1002 int argc = *argcp; 1003 char **argv = *argvp; 1004 1005 if (strcmp(*argv, "espinudp-nonike") == 0) 1006 *type = 1; 1007 else if (strcmp(*argv, "espinudp") == 0) 1008 *type = 2; 1009 else 1010 invarg("\"ENCAP-TYPE\" is invalid", *argv); 1011 1012 *argcp = argc; 1013 *argvp = argv; 1014 1015 return 0; 1016 } 1017 1018 /* NOTE: reqid is used by host-byte order */ 1019 int xfrm_reqid_parse(__u32 *reqid, int *argcp, char ***argvp) 1020 { 1021 int argc = *argcp; 1022 char **argv = *argvp; 1023 1024 if (get_u32(reqid, *argv, 0)) 1025 invarg("\"REQID\" is invalid", *argv); 1026 1027 *argcp = argc; 1028 *argvp = argv; 1029 1030 return 0; 1031 } 1032 1033 static int xfrm_selector_upspec_parse(struct xfrm_selector *sel, 1034 int *argcp, char ***argvp) 1035 { 1036 int argc = *argcp; 1037 char **argv = *argvp; 1038 char *sportp = NULL; 1039 char *dportp = NULL; 1040 char *typep = NULL; 1041 char *codep = NULL; 1042 1043 while (1) { 1044 if (strcmp(*argv, "proto") == 0) { 1045 __u8 upspec; 1046 1047 NEXT_ARG(); 1048 1049 if (strcmp(*argv, "any") == 0) 1050 upspec = 0; 1051 else { 1052 struct protoent *pp; 1053 pp = getprotobyname(*argv); 1054 if (pp) 1055 upspec = pp->p_proto; 1056 else { 1057 if (get_u8(&upspec, *argv, 0)) 1058 invarg("\"PROTO\" is invalid", *argv); 1059 } 1060 } 1061 sel->proto = upspec; 1062 1063 filter.upspec_proto_mask = XFRM_FILTER_MASK_FULL; 1064 1065 } else if (strcmp(*argv, "sport") == 0) { 1066 sportp = *argv; 1067 1068 NEXT_ARG(); 1069 1070 if (get_u16(&sel->sport, *argv, 0)) 1071 invarg("\"PORT\" is invalid", *argv); 1072 sel->sport = htons(sel->sport); 1073 if (sel->sport) 1074 sel->sport_mask = ~((__u16)0); 1075 1076 filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL; 1077 1078 } else if (strcmp(*argv, "dport") == 0) { 1079 dportp = *argv; 1080 1081 NEXT_ARG(); 1082 1083 if (get_u16(&sel->dport, *argv, 0)) 1084 invarg("\"PORT\" is invalid", *argv); 1085 sel->dport = htons(sel->dport); 1086 if (sel->dport) 1087 sel->dport_mask = ~((__u16)0); 1088 1089 filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL; 1090 1091 } else if (strcmp(*argv, "type") == 0) { 1092 typep = *argv; 1093 1094 NEXT_ARG(); 1095 1096 if (get_u16(&sel->sport, *argv, 0) || 1097 (sel->sport & ~((__u16)0xff))) 1098 invarg("\"type\" value is invalid", *argv); 1099 sel->sport = htons(sel->sport); 1100 sel->sport_mask = ~((__u16)0); 1101 1102 filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL; 1103 1104 1105 } else if (strcmp(*argv, "code") == 0) { 1106 codep = *argv; 1107 1108 NEXT_ARG(); 1109 1110 if (get_u16(&sel->dport, *argv, 0) || 1111 (sel->dport & ~((__u16)0xff))) 1112 invarg("\"code\" value is invalid", *argv); 1113 sel->dport = htons(sel->dport); 1114 sel->dport_mask = ~((__u16)0); 1115 1116 filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL; 1117 1118 } else { 1119 PREV_ARG(); /* back track */ 1120 break; 1121 } 1122 1123 if (!NEXT_ARG_OK()) 1124 break; 1125 NEXT_ARG(); 1126 } 1127 if (argc == *argcp) 1128 missarg("UPSPEC"); 1129 if (sportp || dportp) { 1130 switch (sel->proto) { 1131 case IPPROTO_TCP: 1132 case IPPROTO_UDP: 1133 case IPPROTO_SCTP: 1134 case IPPROTO_DCCP: 1135 break; 1136 default: 1137 fprintf(stderr, "\"sport\" and \"dport\" are invalid with proto=%s\n", strxf_proto(sel->proto)); 1138 exit(1); 1139 } 1140 } 1141 if (typep || codep) { 1142 switch (sel->proto) { 1143 case IPPROTO_ICMP: 1144 case IPPROTO_ICMPV6: 1145 case IPPROTO_MH: 1146 break; 1147 default: 1148 fprintf(stderr, "\"type\" and \"code\" are invalid with proto=%s\n", strxf_proto(sel->proto)); 1149 exit(1); 1150 } 1151 } 1152 1153 *argcp = argc; 1154 *argvp = argv; 1155 1156 return 0; 1157 } 1158 1159 int xfrm_selector_parse(struct xfrm_selector *sel, int *argcp, char ***argvp) 1160 { 1161 int argc = *argcp; 1162 char **argv = *argvp; 1163 inet_prefix dst; 1164 inet_prefix src; 1165 char *upspecp = NULL; 1166 1167 memset(&dst, 0, sizeof(dst)); 1168 memset(&src, 0, sizeof(src)); 1169 1170 while (1) { 1171 if (strcmp(*argv, "src") == 0) { 1172 NEXT_ARG(); 1173 1174 get_prefix(&src, *argv, preferred_family); 1175 if (src.family == AF_UNSPEC) 1176 invarg("\"src\" address family is AF_UNSPEC", *argv); 1177 sel->family = src.family; 1178 1179 memcpy(&sel->saddr, &src.data, sizeof(sel->saddr)); 1180 sel->prefixlen_s = src.bitlen; 1181 1182 filter.sel_src_mask = src.bitlen; 1183 1184 } else if (strcmp(*argv, "dst") == 0) { 1185 NEXT_ARG(); 1186 1187 get_prefix(&dst, *argv, preferred_family); 1188 if (dst.family == AF_UNSPEC) 1189 invarg("\"dst\" address family is AF_UNSPEC", *argv); 1190 sel->family = dst.family; 1191 1192 memcpy(&sel->daddr, &dst.data, sizeof(sel->daddr)); 1193 sel->prefixlen_d = dst.bitlen; 1194 1195 filter.sel_dst_mask = dst.bitlen; 1196 1197 } else if (strcmp(*argv, "dev") == 0) { 1198 int ifindex; 1199 1200 NEXT_ARG(); 1201 1202 if (strcmp(*argv, "none") == 0) 1203 ifindex = 0; 1204 else { 1205 ifindex = ll_name_to_index(*argv); 1206 if (ifindex <= 0) 1207 invarg("\"DEV\" is invalid", *argv); 1208 } 1209 sel->ifindex = ifindex; 1210 1211 filter.sel_dev_mask = XFRM_FILTER_MASK_FULL; 1212 1213 } else { 1214 if (upspecp) { 1215 PREV_ARG(); /* back track */ 1216 break; 1217 } else { 1218 upspecp = *argv; 1219 xfrm_selector_upspec_parse(sel, &argc, &argv); 1220 } 1221 } 1222 1223 if (!NEXT_ARG_OK()) 1224 break; 1225 1226 NEXT_ARG(); 1227 } 1228 1229 if (src.family && dst.family && (src.family != dst.family)) 1230 invarg("the same address family is required between \"src\" and \"dst\"", *argv); 1231 1232 if (argc == *argcp) 1233 missarg("SELECTOR"); 1234 1235 *argcp = argc; 1236 *argvp = argv; 1237 1238 return 0; 1239 } 1240 1241 int xfrm_lifetime_cfg_parse(struct xfrm_lifetime_cfg *lft, 1242 int *argcp, char ***argvp) 1243 { 1244 int argc = *argcp; 1245 char **argv = *argvp; 1246 int ret; 1247 1248 if (strcmp(*argv, "time-soft") == 0) { 1249 NEXT_ARG(); 1250 ret = get_u64(&lft->soft_add_expires_seconds, *argv, 0); 1251 if (ret) 1252 invarg("\"time-soft\" value is invalid", *argv); 1253 } else if (strcmp(*argv, "time-hard") == 0) { 1254 NEXT_ARG(); 1255 ret = get_u64(&lft->hard_add_expires_seconds, *argv, 0); 1256 if (ret) 1257 invarg("\"time-hard\" value is invalid", *argv); 1258 } else if (strcmp(*argv, "time-use-soft") == 0) { 1259 NEXT_ARG(); 1260 ret = get_u64(&lft->soft_use_expires_seconds, *argv, 0); 1261 if (ret) 1262 invarg("\"time-use-soft\" value is invalid", *argv); 1263 } else if (strcmp(*argv, "time-use-hard") == 0) { 1264 NEXT_ARG(); 1265 ret = get_u64(&lft->hard_use_expires_seconds, *argv, 0); 1266 if (ret) 1267 invarg("\"time-use-hard\" value is invalid", *argv); 1268 } else if (strcmp(*argv, "byte-soft") == 0) { 1269 NEXT_ARG(); 1270 ret = get_u64(&lft->soft_byte_limit, *argv, 0); 1271 if (ret) 1272 invarg("\"byte-soft\" value is invalid", *argv); 1273 } else if (strcmp(*argv, "byte-hard") == 0) { 1274 NEXT_ARG(); 1275 ret = get_u64(&lft->hard_byte_limit, *argv, 0); 1276 if (ret) 1277 invarg("\"byte-hard\" value is invalid", *argv); 1278 } else if (strcmp(*argv, "packet-soft") == 0) { 1279 NEXT_ARG(); 1280 ret = get_u64(&lft->soft_packet_limit, *argv, 0); 1281 if (ret) 1282 invarg("\"packet-soft\" value is invalid", *argv); 1283 } else if (strcmp(*argv, "packet-hard") == 0) { 1284 NEXT_ARG(); 1285 ret = get_u64(&lft->hard_packet_limit, *argv, 0); 1286 if (ret) 1287 invarg("\"packet-hard\" value is invalid", *argv); 1288 } else 1289 invarg("\"LIMIT\" is invalid", *argv); 1290 1291 *argcp = argc; 1292 *argvp = argv; 1293 1294 return 0; 1295 } 1296 1297 int do_xfrm(int argc, char **argv) 1298 { 1299 memset(&filter, 0, sizeof(filter)); 1300 1301 if (argc < 1) 1302 usage(); 1303 1304 if (matches(*argv, "state") == 0 || 1305 matches(*argv, "sa") == 0) 1306 return do_xfrm_state(argc-1, argv+1); 1307 else if (matches(*argv, "policy") == 0) 1308 return do_xfrm_policy(argc-1, argv+1); 1309 else if (matches(*argv, "monitor") == 0) 1310 return do_xfrm_monitor(argc-1, argv+1); 1311 else if (matches(*argv, "help") == 0) { 1312 usage(); 1313 fprintf(stderr, "xfrm Object \"%s\" is unknown.\n", *argv); 1314 exit(-1); 1315 } 1316 usage(); 1317 } 1318