1 /* 2 * iproute_lwtunnel.c 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Roopa Prabhu, <roopa (at) cumulusnetworks.com> 10 * Thomas Graf <tgraf (at) suug.ch> 11 * 12 */ 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <unistd.h> 17 #include <fcntl.h> 18 #include <string.h> 19 #include <linux/ila.h> 20 #include <linux/lwtunnel.h> 21 #include <linux/mpls_iptunnel.h> 22 #include <errno.h> 23 24 #include "rt_names.h" 25 #include "utils.h" 26 #include "iproute_lwtunnel.h" 27 #include "bpf_util.h" 28 29 #include <linux/seg6.h> 30 #include <linux/seg6_iptunnel.h> 31 #include <linux/seg6_hmac.h> 32 #include <linux/seg6_local.h> 33 #include <net/if.h> 34 35 static const char *format_encap_type(int type) 36 { 37 switch (type) { 38 case LWTUNNEL_ENCAP_MPLS: 39 return "mpls"; 40 case LWTUNNEL_ENCAP_IP: 41 return "ip"; 42 case LWTUNNEL_ENCAP_IP6: 43 return "ip6"; 44 case LWTUNNEL_ENCAP_ILA: 45 return "ila"; 46 case LWTUNNEL_ENCAP_BPF: 47 return "bpf"; 48 case LWTUNNEL_ENCAP_SEG6: 49 return "seg6"; 50 case LWTUNNEL_ENCAP_SEG6_LOCAL: 51 return "seg6local"; 52 default: 53 return "unknown"; 54 } 55 } 56 57 static void encap_type_usage(void) 58 { 59 int i; 60 61 fprintf(stderr, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n"); 62 63 for (i = 1; i <= LWTUNNEL_ENCAP_MAX; i++) 64 fprintf(stderr, "%s %s\n", format_encap_type(i), 65 i == 1 ? "TYPE := " : " "); 66 67 exit(-1); 68 } 69 70 static int read_encap_type(const char *name) 71 { 72 if (strcmp(name, "mpls") == 0) 73 return LWTUNNEL_ENCAP_MPLS; 74 else if (strcmp(name, "ip") == 0) 75 return LWTUNNEL_ENCAP_IP; 76 else if (strcmp(name, "ip6") == 0) 77 return LWTUNNEL_ENCAP_IP6; 78 else if (strcmp(name, "ila") == 0) 79 return LWTUNNEL_ENCAP_ILA; 80 else if (strcmp(name, "bpf") == 0) 81 return LWTUNNEL_ENCAP_BPF; 82 else if (strcmp(name, "seg6") == 0) 83 return LWTUNNEL_ENCAP_SEG6; 84 else if (strcmp(name, "seg6local") == 0) 85 return LWTUNNEL_ENCAP_SEG6_LOCAL; 86 else if (strcmp(name, "help") == 0) 87 encap_type_usage(); 88 89 return LWTUNNEL_ENCAP_NONE; 90 } 91 92 static void print_srh(FILE *fp, struct ipv6_sr_hdr *srh) 93 { 94 int i; 95 96 fprintf(fp, "segs %d [ ", srh->first_segment + 1); 97 98 for (i = srh->first_segment; i >= 0; i--) 99 fprintf(fp, "%s ", 100 rt_addr_n2a(AF_INET6, 16, &srh->segments[i])); 101 102 fprintf(fp, "] "); 103 104 if (sr_has_hmac(srh)) { 105 unsigned int offset = ((srh->hdrlen + 1) << 3) - 40; 106 struct sr6_tlv_hmac *tlv; 107 108 tlv = (struct sr6_tlv_hmac *)((char *)srh + offset); 109 fprintf(fp, "hmac 0x%X ", ntohl(tlv->hmackeyid)); 110 } 111 } 112 113 static const char *seg6_mode_types[] = { 114 [SEG6_IPTUN_MODE_INLINE] = "inline", 115 [SEG6_IPTUN_MODE_ENCAP] = "encap", 116 [SEG6_IPTUN_MODE_L2ENCAP] = "l2encap", 117 }; 118 119 static const char *format_seg6mode_type(int mode) 120 { 121 if (mode < 0 || mode > ARRAY_SIZE(seg6_mode_types)) 122 return "<unknown>"; 123 124 return seg6_mode_types[mode]; 125 } 126 127 static int read_seg6mode_type(const char *mode) 128 { 129 int i; 130 131 for (i = 0; i < ARRAY_SIZE(seg6_mode_types); i++) { 132 if (strcmp(mode, seg6_mode_types[i]) == 0) 133 return i; 134 } 135 136 return -1; 137 } 138 139 static void print_encap_seg6(FILE *fp, struct rtattr *encap) 140 { 141 struct rtattr *tb[SEG6_IPTUNNEL_MAX+1]; 142 struct seg6_iptunnel_encap *tuninfo; 143 144 parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap); 145 146 if (!tb[SEG6_IPTUNNEL_SRH]) 147 return; 148 149 tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]); 150 fprintf(fp, "mode %s ", format_seg6mode_type(tuninfo->mode)); 151 152 print_srh(fp, tuninfo->srh); 153 } 154 155 static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = { 156 [SEG6_LOCAL_ACTION_END] = "End", 157 [SEG6_LOCAL_ACTION_END_X] = "End.X", 158 [SEG6_LOCAL_ACTION_END_T] = "End.T", 159 [SEG6_LOCAL_ACTION_END_DX2] = "End.DX2", 160 [SEG6_LOCAL_ACTION_END_DX6] = "End.DX6", 161 [SEG6_LOCAL_ACTION_END_DX4] = "End.DX4", 162 [SEG6_LOCAL_ACTION_END_DT6] = "End.DT6", 163 [SEG6_LOCAL_ACTION_END_DT4] = "End.DT4", 164 [SEG6_LOCAL_ACTION_END_B6] = "End.B6", 165 [SEG6_LOCAL_ACTION_END_B6_ENCAP] = "End.B6.Encaps", 166 [SEG6_LOCAL_ACTION_END_BM] = "End.BM", 167 [SEG6_LOCAL_ACTION_END_S] = "End.S", 168 [SEG6_LOCAL_ACTION_END_AS] = "End.AS", 169 [SEG6_LOCAL_ACTION_END_AM] = "End.AM", 170 }; 171 172 static const char *format_action_type(int action) 173 { 174 if (action < 0 || action > SEG6_LOCAL_ACTION_MAX) 175 return "<invalid>"; 176 177 return seg6_action_names[action] ?: "<unknown>"; 178 } 179 180 static int read_action_type(const char *name) 181 { 182 int i; 183 184 for (i = 0; i < SEG6_LOCAL_ACTION_MAX + 1; i++) { 185 if (!seg6_action_names[i]) 186 continue; 187 188 if (strcmp(seg6_action_names[i], name) == 0) 189 return i; 190 } 191 192 return SEG6_LOCAL_ACTION_UNSPEC; 193 } 194 195 static void print_encap_seg6local(FILE *fp, struct rtattr *encap) 196 { 197 struct rtattr *tb[SEG6_LOCAL_MAX + 1]; 198 char ifbuf[IFNAMSIZ]; 199 int action; 200 201 parse_rtattr_nested(tb, SEG6_LOCAL_MAX, encap); 202 203 if (!tb[SEG6_LOCAL_ACTION]) 204 return; 205 206 action = rta_getattr_u32(tb[SEG6_LOCAL_ACTION]); 207 208 fprintf(fp, "action %s ", format_action_type(action)); 209 210 if (tb[SEG6_LOCAL_SRH]) { 211 fprintf(fp, "srh "); 212 print_srh(fp, RTA_DATA(tb[SEG6_LOCAL_SRH])); 213 } 214 215 if (tb[SEG6_LOCAL_TABLE]) 216 fprintf(fp, "table %u ", rta_getattr_u32(tb[SEG6_LOCAL_TABLE])); 217 218 if (tb[SEG6_LOCAL_NH4]) { 219 fprintf(fp, "nh4 %s ", 220 rt_addr_n2a_rta(AF_INET, tb[SEG6_LOCAL_NH4])); 221 } 222 223 if (tb[SEG6_LOCAL_NH6]) { 224 fprintf(fp, "nh6 %s ", 225 rt_addr_n2a_rta(AF_INET6, tb[SEG6_LOCAL_NH6])); 226 } 227 228 if (tb[SEG6_LOCAL_IIF]) { 229 int iif = rta_getattr_u32(tb[SEG6_LOCAL_IIF]); 230 231 fprintf(fp, "iif %s ", 232 if_indextoname(iif, ifbuf) ?: "<unknown>"); 233 } 234 235 if (tb[SEG6_LOCAL_OIF]) { 236 int oif = rta_getattr_u32(tb[SEG6_LOCAL_OIF]); 237 238 fprintf(fp, "oif %s ", 239 if_indextoname(oif, ifbuf) ?: "<unknown>"); 240 } 241 } 242 243 static void print_encap_mpls(FILE *fp, struct rtattr *encap) 244 { 245 struct rtattr *tb[MPLS_IPTUNNEL_MAX+1]; 246 247 parse_rtattr_nested(tb, MPLS_IPTUNNEL_MAX, encap); 248 249 if (tb[MPLS_IPTUNNEL_DST]) 250 fprintf(fp, " %s ", 251 format_host_rta(AF_MPLS, tb[MPLS_IPTUNNEL_DST])); 252 if (tb[MPLS_IPTUNNEL_TTL]) 253 fprintf(fp, "ttl %u ", 254 rta_getattr_u8(tb[MPLS_IPTUNNEL_TTL])); 255 } 256 257 static void print_encap_ip(FILE *fp, struct rtattr *encap) 258 { 259 struct rtattr *tb[LWTUNNEL_IP_MAX+1]; 260 261 parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap); 262 263 if (tb[LWTUNNEL_IP_ID]) 264 fprintf(fp, "id %llu ", 265 ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID]))); 266 267 if (tb[LWTUNNEL_IP_SRC]) 268 fprintf(fp, "src %s ", 269 rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_SRC])); 270 271 if (tb[LWTUNNEL_IP_DST]) 272 fprintf(fp, "dst %s ", 273 rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_DST])); 274 275 if (tb[LWTUNNEL_IP_TTL]) 276 fprintf(fp, "ttl %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL])); 277 278 if (tb[LWTUNNEL_IP_TOS]) 279 fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS])); 280 } 281 282 static char *ila_csum_mode2name(__u8 csum_mode) 283 { 284 switch (csum_mode) { 285 case ILA_CSUM_ADJUST_TRANSPORT: 286 return "adj-transport"; 287 case ILA_CSUM_NEUTRAL_MAP: 288 return "neutral-map"; 289 case ILA_CSUM_NO_ACTION: 290 return "no-action"; 291 default: 292 return "unknown"; 293 } 294 } 295 296 static int ila_csum_name2mode(char *name) 297 { 298 if (strcmp(name, "adj-transport") == 0) 299 return ILA_CSUM_ADJUST_TRANSPORT; 300 else if (strcmp(name, "neutral-map") == 0) 301 return ILA_CSUM_NEUTRAL_MAP; 302 else if (strcmp(name, "no-action") == 0) 303 return ILA_CSUM_NO_ACTION; 304 else 305 return -1; 306 } 307 308 static void print_encap_ila(FILE *fp, struct rtattr *encap) 309 { 310 struct rtattr *tb[ILA_ATTR_MAX+1]; 311 312 parse_rtattr_nested(tb, ILA_ATTR_MAX, encap); 313 314 if (tb[ILA_ATTR_LOCATOR]) { 315 char abuf[ADDR64_BUF_SIZE]; 316 317 addr64_n2a(rta_getattr_u64(tb[ILA_ATTR_LOCATOR]), 318 abuf, sizeof(abuf)); 319 fprintf(fp, " %s ", abuf); 320 } 321 322 if (tb[ILA_ATTR_CSUM_MODE]) 323 fprintf(fp, " csum-mode %s ", 324 ila_csum_mode2name(rta_getattr_u8(tb[ILA_ATTR_CSUM_MODE]))); 325 } 326 327 static void print_encap_ip6(FILE *fp, struct rtattr *encap) 328 { 329 struct rtattr *tb[LWTUNNEL_IP6_MAX+1]; 330 331 parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap); 332 333 if (tb[LWTUNNEL_IP6_ID]) 334 fprintf(fp, "id %llu ", 335 ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID]))); 336 337 if (tb[LWTUNNEL_IP6_SRC]) 338 fprintf(fp, "src %s ", 339 rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_SRC])); 340 341 if (tb[LWTUNNEL_IP6_DST]) 342 fprintf(fp, "dst %s ", 343 rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_DST])); 344 345 if (tb[LWTUNNEL_IP6_HOPLIMIT]) 346 fprintf(fp, "hoplimit %d ", 347 rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT])); 348 349 if (tb[LWTUNNEL_IP6_TC]) 350 fprintf(fp, "tc %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC])); 351 } 352 353 static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap, 354 const char *str) 355 { 356 struct rtattr *tb[LWT_BPF_PROG_MAX+1]; 357 358 parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap); 359 fprintf(fp, "%s ", str); 360 361 if (tb[LWT_BPF_PROG_NAME]) 362 fprintf(fp, "%s ", rta_getattr_str(tb[LWT_BPF_PROG_NAME])); 363 } 364 365 static void print_encap_bpf(FILE *fp, struct rtattr *encap) 366 { 367 struct rtattr *tb[LWT_BPF_MAX+1]; 368 369 parse_rtattr_nested(tb, LWT_BPF_MAX, encap); 370 371 if (tb[LWT_BPF_IN]) 372 print_encap_bpf_prog(fp, tb[LWT_BPF_IN], "in"); 373 if (tb[LWT_BPF_OUT]) 374 print_encap_bpf_prog(fp, tb[LWT_BPF_OUT], "out"); 375 if (tb[LWT_BPF_XMIT]) 376 print_encap_bpf_prog(fp, tb[LWT_BPF_XMIT], "xmit"); 377 if (tb[LWT_BPF_XMIT_HEADROOM]) 378 fprintf(fp, "%d ", rta_getattr_u32(tb[LWT_BPF_XMIT_HEADROOM])); 379 } 380 381 void lwt_print_encap(FILE *fp, struct rtattr *encap_type, 382 struct rtattr *encap) 383 { 384 int et; 385 386 if (!encap_type) 387 return; 388 389 et = rta_getattr_u16(encap_type); 390 391 fprintf(fp, " encap %s ", format_encap_type(et)); 392 393 switch (et) { 394 case LWTUNNEL_ENCAP_MPLS: 395 print_encap_mpls(fp, encap); 396 break; 397 case LWTUNNEL_ENCAP_IP: 398 print_encap_ip(fp, encap); 399 break; 400 case LWTUNNEL_ENCAP_ILA: 401 print_encap_ila(fp, encap); 402 break; 403 case LWTUNNEL_ENCAP_IP6: 404 print_encap_ip6(fp, encap); 405 break; 406 case LWTUNNEL_ENCAP_BPF: 407 print_encap_bpf(fp, encap); 408 break; 409 case LWTUNNEL_ENCAP_SEG6: 410 print_encap_seg6(fp, encap); 411 break; 412 case LWTUNNEL_ENCAP_SEG6_LOCAL: 413 print_encap_seg6local(fp, encap); 414 break; 415 } 416 } 417 418 static struct ipv6_sr_hdr *parse_srh(char *segbuf, int hmac, bool encap) 419 { 420 struct ipv6_sr_hdr *srh; 421 int nsegs = 0; 422 int srhlen; 423 char *s; 424 int i; 425 426 s = segbuf; 427 for (i = 0; *s; *s++ == ',' ? i++ : *s); 428 nsegs = i + 1; 429 430 if (!encap) 431 nsegs++; 432 433 srhlen = 8 + 16*nsegs; 434 435 if (hmac) 436 srhlen += 40; 437 438 srh = malloc(srhlen); 439 memset(srh, 0, srhlen); 440 441 srh->hdrlen = (srhlen >> 3) - 1; 442 srh->type = 4; 443 srh->segments_left = nsegs - 1; 444 srh->first_segment = nsegs - 1; 445 446 if (hmac) 447 srh->flags |= SR6_FLAG1_HMAC; 448 449 i = srh->first_segment; 450 for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) { 451 inet_get_addr(s, NULL, &srh->segments[i]); 452 i--; 453 } 454 455 if (hmac) { 456 struct sr6_tlv_hmac *tlv; 457 458 tlv = (struct sr6_tlv_hmac *)((char *)srh + srhlen - 40); 459 tlv->tlvhdr.type = SR6_TLV_HMAC; 460 tlv->tlvhdr.len = 38; 461 tlv->hmackeyid = htonl(hmac); 462 } 463 464 return srh; 465 } 466 467 static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, 468 char ***argvp) 469 { 470 int mode_ok = 0, segs_ok = 0, hmac_ok = 0; 471 struct seg6_iptunnel_encap *tuninfo; 472 struct ipv6_sr_hdr *srh; 473 char **argv = *argvp; 474 char segbuf[1024]; 475 int argc = *argcp; 476 int encap = -1; 477 __u32 hmac = 0; 478 int srhlen; 479 480 while (argc > 0) { 481 if (strcmp(*argv, "mode") == 0) { 482 NEXT_ARG(); 483 if (mode_ok++) 484 duparg2("mode", *argv); 485 encap = read_seg6mode_type(*argv); 486 if (encap < 0) 487 invarg("\"mode\" value is invalid\n", *argv); 488 } else if (strcmp(*argv, "segs") == 0) { 489 NEXT_ARG(); 490 if (segs_ok++) 491 duparg2("segs", *argv); 492 if (encap == -1) 493 invarg("\"segs\" provided before \"mode\"\n", 494 *argv); 495 496 strlcpy(segbuf, *argv, 1024); 497 } else if (strcmp(*argv, "hmac") == 0) { 498 NEXT_ARG(); 499 if (hmac_ok++) 500 duparg2("hmac", *argv); 501 get_u32(&hmac, *argv, 0); 502 } else { 503 break; 504 } 505 argc--; argv++; 506 } 507 508 srh = parse_srh(segbuf, hmac, encap); 509 srhlen = (srh->hdrlen + 1) << 3; 510 511 tuninfo = malloc(sizeof(*tuninfo) + srhlen); 512 memset(tuninfo, 0, sizeof(*tuninfo) + srhlen); 513 514 tuninfo->mode = encap; 515 516 memcpy(tuninfo->srh, srh, srhlen); 517 518 rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, 519 sizeof(*tuninfo) + srhlen); 520 521 free(tuninfo); 522 free(srh); 523 524 *argcp = argc + 1; 525 *argvp = argv - 1; 526 527 return 0; 528 } 529 530 static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, 531 char ***argvp) 532 { 533 int segs_ok = 0, hmac_ok = 0, table_ok = 0, nh4_ok = 0, nh6_ok = 0; 534 int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0; 535 __u32 action = 0, table, iif, oif; 536 struct ipv6_sr_hdr *srh; 537 char **argv = *argvp; 538 int argc = *argcp; 539 char segbuf[1024]; 540 inet_prefix addr; 541 __u32 hmac = 0; 542 543 while (argc > 0) { 544 if (strcmp(*argv, "action") == 0) { 545 NEXT_ARG(); 546 if (action_ok++) 547 duparg2("action", *argv); 548 action = read_action_type(*argv); 549 if (!action) 550 invarg("\"action\" value is invalid\n", *argv); 551 rta_addattr32(rta, len, SEG6_LOCAL_ACTION, action); 552 } else if (strcmp(*argv, "table") == 0) { 553 NEXT_ARG(); 554 if (table_ok++) 555 duparg2("table", *argv); 556 get_u32(&table, *argv, 0); 557 rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table); 558 } else if (strcmp(*argv, "nh4") == 0) { 559 NEXT_ARG(); 560 if (nh4_ok++) 561 duparg2("nh4", *argv); 562 get_addr(&addr, *argv, AF_INET); 563 rta_addattr_l(rta, len, SEG6_LOCAL_NH4, &addr.data, 564 addr.bytelen); 565 } else if (strcmp(*argv, "nh6") == 0) { 566 NEXT_ARG(); 567 if (nh6_ok++) 568 duparg2("nh6", *argv); 569 get_addr(&addr, *argv, AF_INET6); 570 rta_addattr_l(rta, len, SEG6_LOCAL_NH6, &addr.data, 571 addr.bytelen); 572 } else if (strcmp(*argv, "iif") == 0) { 573 NEXT_ARG(); 574 if (iif_ok++) 575 duparg2("iif", *argv); 576 iif = if_nametoindex(*argv); 577 if (!iif) 578 invarg("\"iif\" interface not found\n", *argv); 579 rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif); 580 } else if (strcmp(*argv, "oif") == 0) { 581 NEXT_ARG(); 582 if (oif_ok++) 583 duparg2("oif", *argv); 584 oif = if_nametoindex(*argv); 585 if (!oif) 586 invarg("\"oif\" interface not found\n", *argv); 587 rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif); 588 } else if (strcmp(*argv, "srh") == 0) { 589 NEXT_ARG(); 590 if (srh_ok++) 591 duparg2("srh", *argv); 592 if (strcmp(*argv, "segs") != 0) 593 invarg("missing \"segs\" attribute for srh\n", 594 *argv); 595 NEXT_ARG(); 596 if (segs_ok++) 597 duparg2("segs", *argv); 598 strncpy(segbuf, *argv, 1024); 599 segbuf[1023] = 0; 600 if (!NEXT_ARG_OK()) 601 break; 602 NEXT_ARG(); 603 if (strcmp(*argv, "hmac") == 0) { 604 NEXT_ARG(); 605 if (hmac_ok++) 606 duparg2("hmac", *argv); 607 get_u32(&hmac, *argv, 0); 608 } else { 609 continue; 610 } 611 } else { 612 break; 613 } 614 argc--; argv++; 615 } 616 617 if (!action) { 618 fprintf(stderr, "Missing action type\n"); 619 exit(-1); 620 } 621 622 if (srh_ok) { 623 int srhlen; 624 625 srh = parse_srh(segbuf, hmac, 626 action == SEG6_LOCAL_ACTION_END_B6_ENCAP); 627 srhlen = (srh->hdrlen + 1) << 3; 628 rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen); 629 free(srh); 630 } 631 632 *argcp = argc + 1; 633 *argvp = argv - 1; 634 635 return 0; 636 } 637 638 static int parse_encap_mpls(struct rtattr *rta, size_t len, 639 int *argcp, char ***argvp) 640 { 641 inet_prefix addr; 642 int argc = *argcp; 643 char **argv = *argvp; 644 int ttl_ok = 0; 645 646 if (get_addr(&addr, *argv, AF_MPLS)) { 647 fprintf(stderr, 648 "Error: an inet address is expected rather than \"%s\".\n", 649 *argv); 650 exit(1); 651 } 652 653 rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data, 654 addr.bytelen); 655 656 argc--; 657 argv++; 658 659 while (argc > 0) { 660 if (strcmp(*argv, "ttl") == 0) { 661 __u8 ttl; 662 663 NEXT_ARG(); 664 if (ttl_ok++) 665 duparg2("ttl", *argv); 666 if (get_u8(&ttl, *argv, 0)) 667 invarg("\"ttl\" value is invalid\n", *argv); 668 rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl); 669 } else { 670 break; 671 } 672 argc--; argv++; 673 } 674 675 /* argv is currently the first unparsed argument, 676 * but the lwt_parse_encap() caller will move to the next, 677 * so step back 678 */ 679 *argcp = argc + 1; 680 *argvp = argv - 1; 681 682 return 0; 683 } 684 685 static int parse_encap_ip(struct rtattr *rta, size_t len, 686 int *argcp, char ***argvp) 687 { 688 int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; 689 char **argv = *argvp; 690 int argc = *argcp; 691 692 while (argc > 0) { 693 if (strcmp(*argv, "id") == 0) { 694 __u64 id; 695 696 NEXT_ARG(); 697 if (id_ok++) 698 duparg2("id", *argv); 699 if (get_be64(&id, *argv, 0)) 700 invarg("\"id\" value is invalid\n", *argv); 701 rta_addattr64(rta, len, LWTUNNEL_IP_ID, id); 702 } else if (strcmp(*argv, "dst") == 0) { 703 inet_prefix addr; 704 705 NEXT_ARG(); 706 if (dst_ok++) 707 duparg2("dst", *argv); 708 get_addr(&addr, *argv, AF_INET); 709 rta_addattr_l(rta, len, LWTUNNEL_IP_DST, 710 &addr.data, addr.bytelen); 711 } else if (strcmp(*argv, "tos") == 0) { 712 __u32 tos; 713 714 NEXT_ARG(); 715 if (tos_ok++) 716 duparg2("tos", *argv); 717 if (rtnl_dsfield_a2n(&tos, *argv)) 718 invarg("\"tos\" value is invalid\n", *argv); 719 rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos); 720 } else if (strcmp(*argv, "ttl") == 0) { 721 __u8 ttl; 722 723 NEXT_ARG(); 724 if (ttl_ok++) 725 duparg2("ttl", *argv); 726 if (get_u8(&ttl, *argv, 0)) 727 invarg("\"ttl\" value is invalid\n", *argv); 728 rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); 729 } else { 730 break; 731 } 732 argc--; argv++; 733 } 734 735 /* argv is currently the first unparsed argument, 736 * but the lwt_parse_encap() caller will move to the next, 737 * so step back 738 */ 739 *argcp = argc + 1; 740 *argvp = argv - 1; 741 742 return 0; 743 } 744 745 static int parse_encap_ila(struct rtattr *rta, size_t len, 746 int *argcp, char ***argvp) 747 { 748 __u64 locator; 749 int argc = *argcp; 750 char **argv = *argvp; 751 752 if (get_addr64(&locator, *argv) < 0) { 753 fprintf(stderr, "Bad locator: %s\n", *argv); 754 exit(1); 755 } 756 757 argc--; argv++; 758 759 rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator); 760 761 while (argc > 0) { 762 if (strcmp(*argv, "csum-mode") == 0) { 763 int csum_mode; 764 765 NEXT_ARG(); 766 767 csum_mode = ila_csum_name2mode(*argv); 768 if (csum_mode < 0) 769 invarg("\"csum-mode\" value is invalid\n", 770 *argv); 771 772 rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, 773 (__u8)csum_mode); 774 775 argc--; argv++; 776 } else { 777 break; 778 } 779 } 780 781 /* argv is currently the first unparsed argument, 782 * but the lwt_parse_encap() caller will move to the next, 783 * so step back 784 */ 785 *argcp = argc + 1; 786 *argvp = argv - 1; 787 788 return 0; 789 } 790 791 static int parse_encap_ip6(struct rtattr *rta, size_t len, 792 int *argcp, char ***argvp) 793 { 794 int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; 795 char **argv = *argvp; 796 int argc = *argcp; 797 798 while (argc > 0) { 799 if (strcmp(*argv, "id") == 0) { 800 __u64 id; 801 802 NEXT_ARG(); 803 if (id_ok++) 804 duparg2("id", *argv); 805 if (get_be64(&id, *argv, 0)) 806 invarg("\"id\" value is invalid\n", *argv); 807 rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id); 808 } else if (strcmp(*argv, "dst") == 0) { 809 inet_prefix addr; 810 811 NEXT_ARG(); 812 if (dst_ok++) 813 duparg2("dst", *argv); 814 get_addr(&addr, *argv, AF_INET6); 815 rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, 816 &addr.data, addr.bytelen); 817 } else if (strcmp(*argv, "tc") == 0) { 818 __u32 tc; 819 820 NEXT_ARG(); 821 if (tos_ok++) 822 duparg2("tc", *argv); 823 if (rtnl_dsfield_a2n(&tc, *argv)) 824 invarg("\"tc\" value is invalid\n", *argv); 825 rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc); 826 } else if (strcmp(*argv, "hoplimit") == 0) { 827 __u8 hoplimit; 828 829 NEXT_ARG(); 830 if (ttl_ok++) 831 duparg2("hoplimit", *argv); 832 if (get_u8(&hoplimit, *argv, 0)) 833 invarg("\"hoplimit\" value is invalid\n", 834 *argv); 835 rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit); 836 } else { 837 break; 838 } 839 argc--; argv++; 840 } 841 842 /* argv is currently the first unparsed argument, 843 * but the lwt_parse_encap() caller will move to the next, 844 * so step back 845 */ 846 *argcp = argc + 1; 847 *argvp = argv - 1; 848 849 return 0; 850 } 851 852 struct lwt_x { 853 struct rtattr *rta; 854 size_t len; 855 }; 856 857 static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation) 858 { 859 struct lwt_x *x = lwt_ptr; 860 861 rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd); 862 rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation, 863 strlen(annotation) + 1); 864 } 865 866 static const struct bpf_cfg_ops bpf_cb_ops = { 867 .ebpf_cb = bpf_lwt_cb, 868 }; 869 870 static int lwt_parse_bpf(struct rtattr *rta, size_t len, 871 int *argcp, char ***argvp, 872 int attr, const enum bpf_prog_type bpf_type) 873 { 874 struct bpf_cfg_in cfg = { 875 .argc = *argcp, 876 .argv = *argvp, 877 }; 878 struct lwt_x x = { 879 .rta = rta, 880 .len = len, 881 }; 882 struct rtattr *nest; 883 int err; 884 885 nest = rta_nest(rta, len, attr); 886 err = bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, &x); 887 if (err < 0) { 888 fprintf(stderr, "Failed to parse eBPF program: %s\n", 889 strerror(-err)); 890 return -1; 891 } 892 rta_nest_end(rta, nest); 893 894 *argcp = cfg.argc; 895 *argvp = cfg.argv; 896 897 return 0; 898 } 899 900 static void lwt_bpf_usage(void) 901 { 902 fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n"); 903 fprintf(stderr, "BPF := obj FILE [ section NAME ] [ verbose ]\n"); 904 exit(-1); 905 } 906 907 static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp, 908 char ***argvp) 909 { 910 char **argv = *argvp; 911 int argc = *argcp; 912 int headroom_set = 0; 913 914 while (argc > 0) { 915 if (strcmp(*argv, "in") == 0) { 916 NEXT_ARG(); 917 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_IN, 918 BPF_PROG_TYPE_LWT_IN) < 0) 919 return -1; 920 } else if (strcmp(*argv, "out") == 0) { 921 NEXT_ARG(); 922 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_OUT, 923 BPF_PROG_TYPE_LWT_OUT) < 0) 924 return -1; 925 } else if (strcmp(*argv, "xmit") == 0) { 926 NEXT_ARG(); 927 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_XMIT, 928 BPF_PROG_TYPE_LWT_XMIT) < 0) 929 return -1; 930 } else if (strcmp(*argv, "headroom") == 0) { 931 unsigned int headroom; 932 933 NEXT_ARG(); 934 if (get_unsigned(&headroom, *argv, 0) || headroom == 0) 935 invarg("headroom is invalid\n", *argv); 936 if (!headroom_set) 937 rta_addattr32(rta, 1024, LWT_BPF_XMIT_HEADROOM, 938 headroom); 939 headroom_set = 1; 940 } else if (strcmp(*argv, "help") == 0) { 941 lwt_bpf_usage(); 942 } else { 943 break; 944 } 945 NEXT_ARG_FWD(); 946 } 947 948 /* argv is currently the first unparsed argument, 949 * but the lwt_parse_encap() caller will move to the next, 950 * so step back 951 */ 952 *argcp = argc + 1; 953 *argvp = argv - 1; 954 955 return 0; 956 } 957 958 int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) 959 { 960 struct rtattr *nest; 961 int argc = *argcp; 962 char **argv = *argvp; 963 __u16 type; 964 965 NEXT_ARG(); 966 type = read_encap_type(*argv); 967 if (!type) 968 invarg("\"encap type\" value is invalid\n", *argv); 969 970 NEXT_ARG(); 971 if (argc <= 1) { 972 fprintf(stderr, 973 "Error: unexpected end of line after \"encap\"\n"); 974 exit(-1); 975 } 976 977 nest = rta_nest(rta, 1024, RTA_ENCAP); 978 switch (type) { 979 case LWTUNNEL_ENCAP_MPLS: 980 parse_encap_mpls(rta, len, &argc, &argv); 981 break; 982 case LWTUNNEL_ENCAP_IP: 983 parse_encap_ip(rta, len, &argc, &argv); 984 break; 985 case LWTUNNEL_ENCAP_ILA: 986 parse_encap_ila(rta, len, &argc, &argv); 987 break; 988 case LWTUNNEL_ENCAP_IP6: 989 parse_encap_ip6(rta, len, &argc, &argv); 990 break; 991 case LWTUNNEL_ENCAP_BPF: 992 if (parse_encap_bpf(rta, len, &argc, &argv) < 0) 993 exit(-1); 994 break; 995 case LWTUNNEL_ENCAP_SEG6: 996 parse_encap_seg6(rta, len, &argc, &argv); 997 break; 998 case LWTUNNEL_ENCAP_SEG6_LOCAL: 999 parse_encap_seg6local(rta, len, &argc, &argv); 1000 break; 1001 default: 1002 fprintf(stderr, "Error: unsupported encap type\n"); 1003 break; 1004 } 1005 rta_nest_end(rta, nest); 1006 1007 rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); 1008 1009 *argcp = argc; 1010 *argvp = argv; 1011 1012 return 0; 1013 } 1014