1 /* 2 * SR-IPv6 implementation 3 * 4 * Authors: 5 * David Lebrun <david.lebrun@uclouvain.be> 6 * eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com> 7 * 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation; either version 12 * 2 of the License, or (at your option) any later version. 13 */ 14 15 #include <linux/types.h> 16 #include <linux/skbuff.h> 17 #include <linux/net.h> 18 #include <linux/module.h> 19 #include <net/ip.h> 20 #include <net/lwtunnel.h> 21 #include <net/netevent.h> 22 #include <net/netns/generic.h> 23 #include <net/ip6_fib.h> 24 #include <net/route.h> 25 #include <net/seg6.h> 26 #include <linux/seg6.h> 27 #include <linux/seg6_local.h> 28 #include <net/addrconf.h> 29 #include <net/ip6_route.h> 30 #include <net/dst_cache.h> 31 #ifdef CONFIG_IPV6_SEG6_HMAC 32 #include <net/seg6_hmac.h> 33 #endif 34 #include <net/seg6_local.h> 35 #include <linux/etherdevice.h> 36 #include <linux/bpf.h> 37 38 struct seg6_local_lwt; 39 40 struct seg6_action_desc { 41 int action; 42 unsigned long attrs; 43 int (*input)(struct sk_buff *skb, struct seg6_local_lwt *slwt); 44 int static_headroom; 45 }; 46 47 struct bpf_lwt_prog { 48 struct bpf_prog *prog; 49 char *name; 50 }; 51 52 struct seg6_local_lwt { 53 int action; 54 struct ipv6_sr_hdr *srh; 55 int table; 56 struct in_addr nh4; 57 struct in6_addr nh6; 58 int iif; 59 int oif; 60 struct bpf_lwt_prog bpf; 61 62 int headroom; 63 struct seg6_action_desc *desc; 64 }; 65 66 static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt) 67 { 68 return (struct seg6_local_lwt *)lwt->data; 69 } 70 71 static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb) 72 { 73 struct ipv6_sr_hdr *srh; 74 int len, srhoff = 0; 75 76 if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0) 77 return NULL; 78 79 if (!pskb_may_pull(skb, srhoff + sizeof(*srh))) 80 return NULL; 81 82 srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); 83 84 len = (srh->hdrlen + 1) << 3; 85 86 if (!pskb_may_pull(skb, srhoff + len)) 87 return NULL; 88 89 if (!seg6_validate_srh(srh, len)) 90 return NULL; 91 92 return srh; 93 } 94 95 static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb) 96 { 97 struct ipv6_sr_hdr *srh; 98 99 srh = get_srh(skb); 100 if (!srh) 101 return NULL; 102 103 if (srh->segments_left == 0) 104 return NULL; 105 106 #ifdef CONFIG_IPV6_SEG6_HMAC 107 if (!seg6_hmac_validate_skb(skb)) 108 return NULL; 109 #endif 110 111 return srh; 112 } 113 114 static bool decap_and_validate(struct sk_buff *skb, int proto) 115 { 116 struct ipv6_sr_hdr *srh; 117 unsigned int off = 0; 118 119 srh = get_srh(skb); 120 if (srh && srh->segments_left > 0) 121 return false; 122 123 #ifdef CONFIG_IPV6_SEG6_HMAC 124 if (srh && !seg6_hmac_validate_skb(skb)) 125 return false; 126 #endif 127 128 if (ipv6_find_hdr(skb, &off, proto, NULL, NULL) < 0) 129 return false; 130 131 if (!pskb_pull(skb, off)) 132 return false; 133 134 skb_postpull_rcsum(skb, skb_network_header(skb), off); 135 136 skb_reset_network_header(skb); 137 skb_reset_transport_header(skb); 138 skb->encapsulation = 0; 139 140 return true; 141 } 142 143 static void advance_nextseg(struct ipv6_sr_hdr *srh, struct in6_addr *daddr) 144 { 145 struct in6_addr *addr; 146 147 srh->segments_left--; 148 addr = srh->segments + srh->segments_left; 149 *daddr = *addr; 150 } 151 152 int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr, 153 u32 tbl_id) 154 { 155 struct net *net = dev_net(skb->dev); 156 struct ipv6hdr *hdr = ipv6_hdr(skb); 157 int flags = RT6_LOOKUP_F_HAS_SADDR; 158 struct dst_entry *dst = NULL; 159 struct rt6_info *rt; 160 struct flowi6 fl6; 161 162 fl6.flowi6_iif = skb->dev->ifindex; 163 fl6.daddr = nhaddr ? *nhaddr : hdr->daddr; 164 fl6.saddr = hdr->saddr; 165 fl6.flowlabel = ip6_flowinfo(hdr); 166 fl6.flowi6_mark = skb->mark; 167 fl6.flowi6_proto = hdr->nexthdr; 168 169 if (nhaddr) 170 fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH; 171 172 if (!tbl_id) { 173 dst = ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags); 174 } else { 175 struct fib6_table *table; 176 177 table = fib6_get_table(net, tbl_id); 178 if (!table) 179 goto out; 180 181 rt = ip6_pol_route(net, table, 0, &fl6, skb, flags); 182 dst = &rt->dst; 183 } 184 185 if (dst && dst->dev->flags & IFF_LOOPBACK && !dst->error) { 186 dst_release(dst); 187 dst = NULL; 188 } 189 190 out: 191 if (!dst) { 192 rt = net->ipv6.ip6_blk_hole_entry; 193 dst = &rt->dst; 194 dst_hold(dst); 195 } 196 197 skb_dst_drop(skb); 198 skb_dst_set(skb, dst); 199 return dst->error; 200 } 201 202 /* regular endpoint function */ 203 static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt) 204 { 205 struct ipv6_sr_hdr *srh; 206 207 srh = get_and_validate_srh(skb); 208 if (!srh) 209 goto drop; 210 211 advance_nextseg(srh, &ipv6_hdr(skb)->daddr); 212 213 seg6_lookup_nexthop(skb, NULL, 0); 214 215 return dst_input(skb); 216 217 drop: 218 kfree_skb(skb); 219 return -EINVAL; 220 } 221 222 /* regular endpoint, and forward to specified nexthop */ 223 static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt) 224 { 225 struct ipv6_sr_hdr *srh; 226 227 srh = get_and_validate_srh(skb); 228 if (!srh) 229 goto drop; 230 231 advance_nextseg(srh, &ipv6_hdr(skb)->daddr); 232 233 seg6_lookup_nexthop(skb, &slwt->nh6, 0); 234 235 return dst_input(skb); 236 237 drop: 238 kfree_skb(skb); 239 return -EINVAL; 240 } 241 242 static int input_action_end_t(struct sk_buff *skb, struct seg6_local_lwt *slwt) 243 { 244 struct ipv6_sr_hdr *srh; 245 246 srh = get_and_validate_srh(skb); 247 if (!srh) 248 goto drop; 249 250 advance_nextseg(srh, &ipv6_hdr(skb)->daddr); 251 252 seg6_lookup_nexthop(skb, NULL, slwt->table); 253 254 return dst_input(skb); 255 256 drop: 257 kfree_skb(skb); 258 return -EINVAL; 259 } 260 261 /* decapsulate and forward inner L2 frame on specified interface */ 262 static int input_action_end_dx2(struct sk_buff *skb, 263 struct seg6_local_lwt *slwt) 264 { 265 struct net *net = dev_net(skb->dev); 266 struct net_device *odev; 267 struct ethhdr *eth; 268 269 if (!decap_and_validate(skb, NEXTHDR_NONE)) 270 goto drop; 271 272 if (!pskb_may_pull(skb, ETH_HLEN)) 273 goto drop; 274 275 skb_reset_mac_header(skb); 276 eth = (struct ethhdr *)skb->data; 277 278 /* To determine the frame's protocol, we assume it is 802.3. This avoids 279 * a call to eth_type_trans(), which is not really relevant for our 280 * use case. 281 */ 282 if (!eth_proto_is_802_3(eth->h_proto)) 283 goto drop; 284 285 odev = dev_get_by_index_rcu(net, slwt->oif); 286 if (!odev) 287 goto drop; 288 289 /* As we accept Ethernet frames, make sure the egress device is of 290 * the correct type. 291 */ 292 if (odev->type != ARPHRD_ETHER) 293 goto drop; 294 295 if (!(odev->flags & IFF_UP) || !netif_carrier_ok(odev)) 296 goto drop; 297 298 skb_orphan(skb); 299 300 if (skb_warn_if_lro(skb)) 301 goto drop; 302 303 skb_forward_csum(skb); 304 305 if (skb->len - ETH_HLEN > odev->mtu) 306 goto drop; 307 308 skb->dev = odev; 309 skb->protocol = eth->h_proto; 310 311 return dev_queue_xmit(skb); 312 313 drop: 314 kfree_skb(skb); 315 return -EINVAL; 316 } 317 318 /* decapsulate and forward to specified nexthop */ 319 static int input_action_end_dx6(struct sk_buff *skb, 320 struct seg6_local_lwt *slwt) 321 { 322 struct in6_addr *nhaddr = NULL; 323 324 /* this function accepts IPv6 encapsulated packets, with either 325 * an SRH with SL=0, or no SRH. 326 */ 327 328 if (!decap_and_validate(skb, IPPROTO_IPV6)) 329 goto drop; 330 331 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 332 goto drop; 333 334 /* The inner packet is not associated to any local interface, 335 * so we do not call netif_rx(). 336 * 337 * If slwt->nh6 is set to ::, then lookup the nexthop for the 338 * inner packet's DA. Otherwise, use the specified nexthop. 339 */ 340 341 if (!ipv6_addr_any(&slwt->nh6)) 342 nhaddr = &slwt->nh6; 343 344 seg6_lookup_nexthop(skb, nhaddr, 0); 345 346 return dst_input(skb); 347 drop: 348 kfree_skb(skb); 349 return -EINVAL; 350 } 351 352 static int input_action_end_dx4(struct sk_buff *skb, 353 struct seg6_local_lwt *slwt) 354 { 355 struct iphdr *iph; 356 __be32 nhaddr; 357 int err; 358 359 if (!decap_and_validate(skb, IPPROTO_IPIP)) 360 goto drop; 361 362 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 363 goto drop; 364 365 skb->protocol = htons(ETH_P_IP); 366 367 iph = ip_hdr(skb); 368 369 nhaddr = slwt->nh4.s_addr ?: iph->daddr; 370 371 skb_dst_drop(skb); 372 373 err = ip_route_input(skb, nhaddr, iph->saddr, 0, skb->dev); 374 if (err) 375 goto drop; 376 377 return dst_input(skb); 378 379 drop: 380 kfree_skb(skb); 381 return -EINVAL; 382 } 383 384 static int input_action_end_dt6(struct sk_buff *skb, 385 struct seg6_local_lwt *slwt) 386 { 387 if (!decap_and_validate(skb, IPPROTO_IPV6)) 388 goto drop; 389 390 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 391 goto drop; 392 393 seg6_lookup_nexthop(skb, NULL, slwt->table); 394 395 return dst_input(skb); 396 397 drop: 398 kfree_skb(skb); 399 return -EINVAL; 400 } 401 402 /* push an SRH on top of the current one */ 403 static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt) 404 { 405 struct ipv6_sr_hdr *srh; 406 int err = -EINVAL; 407 408 srh = get_and_validate_srh(skb); 409 if (!srh) 410 goto drop; 411 412 err = seg6_do_srh_inline(skb, slwt->srh); 413 if (err) 414 goto drop; 415 416 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 417 skb_set_transport_header(skb, sizeof(struct ipv6hdr)); 418 419 seg6_lookup_nexthop(skb, NULL, 0); 420 421 return dst_input(skb); 422 423 drop: 424 kfree_skb(skb); 425 return err; 426 } 427 428 /* encapsulate within an outer IPv6 header and a specified SRH */ 429 static int input_action_end_b6_encap(struct sk_buff *skb, 430 struct seg6_local_lwt *slwt) 431 { 432 struct ipv6_sr_hdr *srh; 433 int err = -EINVAL; 434 435 srh = get_and_validate_srh(skb); 436 if (!srh) 437 goto drop; 438 439 advance_nextseg(srh, &ipv6_hdr(skb)->daddr); 440 441 skb_reset_inner_headers(skb); 442 skb->encapsulation = 1; 443 444 err = seg6_do_srh_encap(skb, slwt->srh, IPPROTO_IPV6); 445 if (err) 446 goto drop; 447 448 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 449 skb_set_transport_header(skb, sizeof(struct ipv6hdr)); 450 451 seg6_lookup_nexthop(skb, NULL, 0); 452 453 return dst_input(skb); 454 455 drop: 456 kfree_skb(skb); 457 return err; 458 } 459 460 DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states); 461 462 static int input_action_end_bpf(struct sk_buff *skb, 463 struct seg6_local_lwt *slwt) 464 { 465 struct seg6_bpf_srh_state *srh_state = 466 this_cpu_ptr(&seg6_bpf_srh_states); 467 struct seg6_bpf_srh_state local_srh_state; 468 struct ipv6_sr_hdr *srh; 469 int srhoff = 0; 470 int ret; 471 472 srh = get_and_validate_srh(skb); 473 if (!srh) 474 goto drop; 475 advance_nextseg(srh, &ipv6_hdr(skb)->daddr); 476 477 /* preempt_disable is needed to protect the per-CPU buffer srh_state, 478 * which is also accessed by the bpf_lwt_seg6_* helpers 479 */ 480 preempt_disable(); 481 srh_state->hdrlen = srh->hdrlen << 3; 482 srh_state->valid = 1; 483 484 rcu_read_lock(); 485 bpf_compute_data_pointers(skb); 486 ret = bpf_prog_run_save_cb(slwt->bpf.prog, skb); 487 rcu_read_unlock(); 488 489 local_srh_state = *srh_state; 490 preempt_enable(); 491 492 switch (ret) { 493 case BPF_OK: 494 case BPF_REDIRECT: 495 break; 496 case BPF_DROP: 497 goto drop; 498 default: 499 pr_warn_once("bpf-seg6local: Illegal return value %u\n", ret); 500 goto drop; 501 } 502 503 if (unlikely((local_srh_state.hdrlen & 7) != 0)) 504 goto drop; 505 506 if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0) 507 goto drop; 508 srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); 509 srh->hdrlen = (u8)(local_srh_state.hdrlen >> 3); 510 511 if (!local_srh_state.valid && 512 unlikely(!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3))) 513 goto drop; 514 515 if (ret != BPF_REDIRECT) 516 seg6_lookup_nexthop(skb, NULL, 0); 517 518 return dst_input(skb); 519 520 drop: 521 kfree_skb(skb); 522 return -EINVAL; 523 } 524 525 static struct seg6_action_desc seg6_action_table[] = { 526 { 527 .action = SEG6_LOCAL_ACTION_END, 528 .attrs = 0, 529 .input = input_action_end, 530 }, 531 { 532 .action = SEG6_LOCAL_ACTION_END_X, 533 .attrs = (1 << SEG6_LOCAL_NH6), 534 .input = input_action_end_x, 535 }, 536 { 537 .action = SEG6_LOCAL_ACTION_END_T, 538 .attrs = (1 << SEG6_LOCAL_TABLE), 539 .input = input_action_end_t, 540 }, 541 { 542 .action = SEG6_LOCAL_ACTION_END_DX2, 543 .attrs = (1 << SEG6_LOCAL_OIF), 544 .input = input_action_end_dx2, 545 }, 546 { 547 .action = SEG6_LOCAL_ACTION_END_DX6, 548 .attrs = (1 << SEG6_LOCAL_NH6), 549 .input = input_action_end_dx6, 550 }, 551 { 552 .action = SEG6_LOCAL_ACTION_END_DX4, 553 .attrs = (1 << SEG6_LOCAL_NH4), 554 .input = input_action_end_dx4, 555 }, 556 { 557 .action = SEG6_LOCAL_ACTION_END_DT6, 558 .attrs = (1 << SEG6_LOCAL_TABLE), 559 .input = input_action_end_dt6, 560 }, 561 { 562 .action = SEG6_LOCAL_ACTION_END_B6, 563 .attrs = (1 << SEG6_LOCAL_SRH), 564 .input = input_action_end_b6, 565 }, 566 { 567 .action = SEG6_LOCAL_ACTION_END_B6_ENCAP, 568 .attrs = (1 << SEG6_LOCAL_SRH), 569 .input = input_action_end_b6_encap, 570 .static_headroom = sizeof(struct ipv6hdr), 571 }, 572 { 573 .action = SEG6_LOCAL_ACTION_END_BPF, 574 .attrs = (1 << SEG6_LOCAL_BPF), 575 .input = input_action_end_bpf, 576 }, 577 578 }; 579 580 static struct seg6_action_desc *__get_action_desc(int action) 581 { 582 struct seg6_action_desc *desc; 583 int i, count; 584 585 count = ARRAY_SIZE(seg6_action_table); 586 for (i = 0; i < count; i++) { 587 desc = &seg6_action_table[i]; 588 if (desc->action == action) 589 return desc; 590 } 591 592 return NULL; 593 } 594 595 static int seg6_local_input(struct sk_buff *skb) 596 { 597 struct dst_entry *orig_dst = skb_dst(skb); 598 struct seg6_action_desc *desc; 599 struct seg6_local_lwt *slwt; 600 601 if (skb->protocol != htons(ETH_P_IPV6)) { 602 kfree_skb(skb); 603 return -EINVAL; 604 } 605 606 slwt = seg6_local_lwtunnel(orig_dst->lwtstate); 607 desc = slwt->desc; 608 609 return desc->input(skb, slwt); 610 } 611 612 static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = { 613 [SEG6_LOCAL_ACTION] = { .type = NLA_U32 }, 614 [SEG6_LOCAL_SRH] = { .type = NLA_BINARY }, 615 [SEG6_LOCAL_TABLE] = { .type = NLA_U32 }, 616 [SEG6_LOCAL_NH4] = { .type = NLA_BINARY, 617 .len = sizeof(struct in_addr) }, 618 [SEG6_LOCAL_NH6] = { .type = NLA_BINARY, 619 .len = sizeof(struct in6_addr) }, 620 [SEG6_LOCAL_IIF] = { .type = NLA_U32 }, 621 [SEG6_LOCAL_OIF] = { .type = NLA_U32 }, 622 [SEG6_LOCAL_BPF] = { .type = NLA_NESTED }, 623 }; 624 625 static int parse_nla_srh(struct nlattr **attrs, struct seg6_local_lwt *slwt) 626 { 627 struct ipv6_sr_hdr *srh; 628 int len; 629 630 srh = nla_data(attrs[SEG6_LOCAL_SRH]); 631 len = nla_len(attrs[SEG6_LOCAL_SRH]); 632 633 /* SRH must contain at least one segment */ 634 if (len < sizeof(*srh) + sizeof(struct in6_addr)) 635 return -EINVAL; 636 637 if (!seg6_validate_srh(srh, len)) 638 return -EINVAL; 639 640 slwt->srh = kmemdup(srh, len, GFP_KERNEL); 641 if (!slwt->srh) 642 return -ENOMEM; 643 644 slwt->headroom += len; 645 646 return 0; 647 } 648 649 static int put_nla_srh(struct sk_buff *skb, struct seg6_local_lwt *slwt) 650 { 651 struct ipv6_sr_hdr *srh; 652 struct nlattr *nla; 653 int len; 654 655 srh = slwt->srh; 656 len = (srh->hdrlen + 1) << 3; 657 658 nla = nla_reserve(skb, SEG6_LOCAL_SRH, len); 659 if (!nla) 660 return -EMSGSIZE; 661 662 memcpy(nla_data(nla), srh, len); 663 664 return 0; 665 } 666 667 static int cmp_nla_srh(struct seg6_local_lwt *a, struct seg6_local_lwt *b) 668 { 669 int len = (a->srh->hdrlen + 1) << 3; 670 671 if (len != ((b->srh->hdrlen + 1) << 3)) 672 return 1; 673 674 return memcmp(a->srh, b->srh, len); 675 } 676 677 static int parse_nla_table(struct nlattr **attrs, struct seg6_local_lwt *slwt) 678 { 679 slwt->table = nla_get_u32(attrs[SEG6_LOCAL_TABLE]); 680 681 return 0; 682 } 683 684 static int put_nla_table(struct sk_buff *skb, struct seg6_local_lwt *slwt) 685 { 686 if (nla_put_u32(skb, SEG6_LOCAL_TABLE, slwt->table)) 687 return -EMSGSIZE; 688 689 return 0; 690 } 691 692 static int cmp_nla_table(struct seg6_local_lwt *a, struct seg6_local_lwt *b) 693 { 694 if (a->table != b->table) 695 return 1; 696 697 return 0; 698 } 699 700 static int parse_nla_nh4(struct nlattr **attrs, struct seg6_local_lwt *slwt) 701 { 702 memcpy(&slwt->nh4, nla_data(attrs[SEG6_LOCAL_NH4]), 703 sizeof(struct in_addr)); 704 705 return 0; 706 } 707 708 static int put_nla_nh4(struct sk_buff *skb, struct seg6_local_lwt *slwt) 709 { 710 struct nlattr *nla; 711 712 nla = nla_reserve(skb, SEG6_LOCAL_NH4, sizeof(struct in_addr)); 713 if (!nla) 714 return -EMSGSIZE; 715 716 memcpy(nla_data(nla), &slwt->nh4, sizeof(struct in_addr)); 717 718 return 0; 719 } 720 721 static int cmp_nla_nh4(struct seg6_local_lwt *a, struct seg6_local_lwt *b) 722 { 723 return memcmp(&a->nh4, &b->nh4, sizeof(struct in_addr)); 724 } 725 726 static int parse_nla_nh6(struct nlattr **attrs, struct seg6_local_lwt *slwt) 727 { 728 memcpy(&slwt->nh6, nla_data(attrs[SEG6_LOCAL_NH6]), 729 sizeof(struct in6_addr)); 730 731 return 0; 732 } 733 734 static int put_nla_nh6(struct sk_buff *skb, struct seg6_local_lwt *slwt) 735 { 736 struct nlattr *nla; 737 738 nla = nla_reserve(skb, SEG6_LOCAL_NH6, sizeof(struct in6_addr)); 739 if (!nla) 740 return -EMSGSIZE; 741 742 memcpy(nla_data(nla), &slwt->nh6, sizeof(struct in6_addr)); 743 744 return 0; 745 } 746 747 static int cmp_nla_nh6(struct seg6_local_lwt *a, struct seg6_local_lwt *b) 748 { 749 return memcmp(&a->nh6, &b->nh6, sizeof(struct in6_addr)); 750 } 751 752 static int parse_nla_iif(struct nlattr **attrs, struct seg6_local_lwt *slwt) 753 { 754 slwt->iif = nla_get_u32(attrs[SEG6_LOCAL_IIF]); 755 756 return 0; 757 } 758 759 static int put_nla_iif(struct sk_buff *skb, struct seg6_local_lwt *slwt) 760 { 761 if (nla_put_u32(skb, SEG6_LOCAL_IIF, slwt->iif)) 762 return -EMSGSIZE; 763 764 return 0; 765 } 766 767 static int cmp_nla_iif(struct seg6_local_lwt *a, struct seg6_local_lwt *b) 768 { 769 if (a->iif != b->iif) 770 return 1; 771 772 return 0; 773 } 774 775 static int parse_nla_oif(struct nlattr **attrs, struct seg6_local_lwt *slwt) 776 { 777 slwt->oif = nla_get_u32(attrs[SEG6_LOCAL_OIF]); 778 779 return 0; 780 } 781 782 static int put_nla_oif(struct sk_buff *skb, struct seg6_local_lwt *slwt) 783 { 784 if (nla_put_u32(skb, SEG6_LOCAL_OIF, slwt->oif)) 785 return -EMSGSIZE; 786 787 return 0; 788 } 789 790 static int cmp_nla_oif(struct seg6_local_lwt *a, struct seg6_local_lwt *b) 791 { 792 if (a->oif != b->oif) 793 return 1; 794 795 return 0; 796 } 797 798 #define MAX_PROG_NAME 256 799 static const struct nla_policy bpf_prog_policy[SEG6_LOCAL_BPF_PROG_MAX + 1] = { 800 [SEG6_LOCAL_BPF_PROG] = { .type = NLA_U32, }, 801 [SEG6_LOCAL_BPF_PROG_NAME] = { .type = NLA_NUL_STRING, 802 .len = MAX_PROG_NAME }, 803 }; 804 805 static int parse_nla_bpf(struct nlattr **attrs, struct seg6_local_lwt *slwt) 806 { 807 struct nlattr *tb[SEG6_LOCAL_BPF_PROG_MAX + 1]; 808 struct bpf_prog *p; 809 int ret; 810 u32 fd; 811 812 ret = nla_parse_nested(tb, SEG6_LOCAL_BPF_PROG_MAX, 813 attrs[SEG6_LOCAL_BPF], bpf_prog_policy, NULL); 814 if (ret < 0) 815 return ret; 816 817 if (!tb[SEG6_LOCAL_BPF_PROG] || !tb[SEG6_LOCAL_BPF_PROG_NAME]) 818 return -EINVAL; 819 820 slwt->bpf.name = nla_memdup(tb[SEG6_LOCAL_BPF_PROG_NAME], GFP_KERNEL); 821 if (!slwt->bpf.name) 822 return -ENOMEM; 823 824 fd = nla_get_u32(tb[SEG6_LOCAL_BPF_PROG]); 825 p = bpf_prog_get_type(fd, BPF_PROG_TYPE_LWT_SEG6LOCAL); 826 if (IS_ERR(p)) { 827 kfree(slwt->bpf.name); 828 return PTR_ERR(p); 829 } 830 831 slwt->bpf.prog = p; 832 return 0; 833 } 834 835 static int put_nla_bpf(struct sk_buff *skb, struct seg6_local_lwt *slwt) 836 { 837 struct nlattr *nest; 838 839 if (!slwt->bpf.prog) 840 return 0; 841 842 nest = nla_nest_start(skb, SEG6_LOCAL_BPF); 843 if (!nest) 844 return -EMSGSIZE; 845 846 if (nla_put_u32(skb, SEG6_LOCAL_BPF_PROG, slwt->bpf.prog->aux->id)) 847 return -EMSGSIZE; 848 849 if (slwt->bpf.name && 850 nla_put_string(skb, SEG6_LOCAL_BPF_PROG_NAME, slwt->bpf.name)) 851 return -EMSGSIZE; 852 853 return nla_nest_end(skb, nest); 854 } 855 856 static int cmp_nla_bpf(struct seg6_local_lwt *a, struct seg6_local_lwt *b) 857 { 858 if (!a->bpf.name && !b->bpf.name) 859 return 0; 860 861 if (!a->bpf.name || !b->bpf.name) 862 return 1; 863 864 return strcmp(a->bpf.name, b->bpf.name); 865 } 866 867 struct seg6_action_param { 868 int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt); 869 int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt); 870 int (*cmp)(struct seg6_local_lwt *a, struct seg6_local_lwt *b); 871 }; 872 873 static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = { 874 [SEG6_LOCAL_SRH] = { .parse = parse_nla_srh, 875 .put = put_nla_srh, 876 .cmp = cmp_nla_srh }, 877 878 [SEG6_LOCAL_TABLE] = { .parse = parse_nla_table, 879 .put = put_nla_table, 880 .cmp = cmp_nla_table }, 881 882 [SEG6_LOCAL_NH4] = { .parse = parse_nla_nh4, 883 .put = put_nla_nh4, 884 .cmp = cmp_nla_nh4 }, 885 886 [SEG6_LOCAL_NH6] = { .parse = parse_nla_nh6, 887 .put = put_nla_nh6, 888 .cmp = cmp_nla_nh6 }, 889 890 [SEG6_LOCAL_IIF] = { .parse = parse_nla_iif, 891 .put = put_nla_iif, 892 .cmp = cmp_nla_iif }, 893 894 [SEG6_LOCAL_OIF] = { .parse = parse_nla_oif, 895 .put = put_nla_oif, 896 .cmp = cmp_nla_oif }, 897 898 [SEG6_LOCAL_BPF] = { .parse = parse_nla_bpf, 899 .put = put_nla_bpf, 900 .cmp = cmp_nla_bpf }, 901 902 }; 903 904 static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt) 905 { 906 struct seg6_action_param *param; 907 struct seg6_action_desc *desc; 908 int i, err; 909 910 desc = __get_action_desc(slwt->action); 911 if (!desc) 912 return -EINVAL; 913 914 if (!desc->input) 915 return -EOPNOTSUPP; 916 917 slwt->desc = desc; 918 slwt->headroom += desc->static_headroom; 919 920 for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) { 921 if (desc->attrs & (1 << i)) { 922 if (!attrs[i]) 923 return -EINVAL; 924 925 param = &seg6_action_params[i]; 926 927 err = param->parse(attrs, slwt); 928 if (err < 0) 929 return err; 930 } 931 } 932 933 return 0; 934 } 935 936 static int seg6_local_build_state(struct nlattr *nla, unsigned int family, 937 const void *cfg, struct lwtunnel_state **ts, 938 struct netlink_ext_ack *extack) 939 { 940 struct nlattr *tb[SEG6_LOCAL_MAX + 1]; 941 struct lwtunnel_state *newts; 942 struct seg6_local_lwt *slwt; 943 int err; 944 945 if (family != AF_INET6) 946 return -EINVAL; 947 948 err = nla_parse_nested(tb, SEG6_LOCAL_MAX, nla, seg6_local_policy, 949 extack); 950 951 if (err < 0) 952 return err; 953 954 if (!tb[SEG6_LOCAL_ACTION]) 955 return -EINVAL; 956 957 newts = lwtunnel_state_alloc(sizeof(*slwt)); 958 if (!newts) 959 return -ENOMEM; 960 961 slwt = seg6_local_lwtunnel(newts); 962 slwt->action = nla_get_u32(tb[SEG6_LOCAL_ACTION]); 963 964 err = parse_nla_action(tb, slwt); 965 if (err < 0) 966 goto out_free; 967 968 newts->type = LWTUNNEL_ENCAP_SEG6_LOCAL; 969 newts->flags = LWTUNNEL_STATE_INPUT_REDIRECT; 970 newts->headroom = slwt->headroom; 971 972 *ts = newts; 973 974 return 0; 975 976 out_free: 977 kfree(slwt->srh); 978 kfree(newts); 979 return err; 980 } 981 982 static void seg6_local_destroy_state(struct lwtunnel_state *lwt) 983 { 984 struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt); 985 986 kfree(slwt->srh); 987 988 if (slwt->desc->attrs & (1 << SEG6_LOCAL_BPF)) { 989 kfree(slwt->bpf.name); 990 bpf_prog_put(slwt->bpf.prog); 991 } 992 993 return; 994 } 995 996 static int seg6_local_fill_encap(struct sk_buff *skb, 997 struct lwtunnel_state *lwt) 998 { 999 struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt); 1000 struct seg6_action_param *param; 1001 int i, err; 1002 1003 if (nla_put_u32(skb, SEG6_LOCAL_ACTION, slwt->action)) 1004 return -EMSGSIZE; 1005 1006 for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) { 1007 if (slwt->desc->attrs & (1 << i)) { 1008 param = &seg6_action_params[i]; 1009 err = param->put(skb, slwt); 1010 if (err < 0) 1011 return err; 1012 } 1013 } 1014 1015 return 0; 1016 } 1017 1018 static int seg6_local_get_encap_size(struct lwtunnel_state *lwt) 1019 { 1020 struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt); 1021 unsigned long attrs; 1022 int nlsize; 1023 1024 nlsize = nla_total_size(4); /* action */ 1025 1026 attrs = slwt->desc->attrs; 1027 1028 if (attrs & (1 << SEG6_LOCAL_SRH)) 1029 nlsize += nla_total_size((slwt->srh->hdrlen + 1) << 3); 1030 1031 if (attrs & (1 << SEG6_LOCAL_TABLE)) 1032 nlsize += nla_total_size(4); 1033 1034 if (attrs & (1 << SEG6_LOCAL_NH4)) 1035 nlsize += nla_total_size(4); 1036 1037 if (attrs & (1 << SEG6_LOCAL_NH6)) 1038 nlsize += nla_total_size(16); 1039 1040 if (attrs & (1 << SEG6_LOCAL_IIF)) 1041 nlsize += nla_total_size(4); 1042 1043 if (attrs & (1 << SEG6_LOCAL_OIF)) 1044 nlsize += nla_total_size(4); 1045 1046 if (attrs & (1 << SEG6_LOCAL_BPF)) 1047 nlsize += nla_total_size(sizeof(struct nlattr)) + 1048 nla_total_size(MAX_PROG_NAME) + 1049 nla_total_size(4); 1050 1051 return nlsize; 1052 } 1053 1054 static int seg6_local_cmp_encap(struct lwtunnel_state *a, 1055 struct lwtunnel_state *b) 1056 { 1057 struct seg6_local_lwt *slwt_a, *slwt_b; 1058 struct seg6_action_param *param; 1059 int i; 1060 1061 slwt_a = seg6_local_lwtunnel(a); 1062 slwt_b = seg6_local_lwtunnel(b); 1063 1064 if (slwt_a->action != slwt_b->action) 1065 return 1; 1066 1067 if (slwt_a->desc->attrs != slwt_b->desc->attrs) 1068 return 1; 1069 1070 for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) { 1071 if (slwt_a->desc->attrs & (1 << i)) { 1072 param = &seg6_action_params[i]; 1073 if (param->cmp(slwt_a, slwt_b)) 1074 return 1; 1075 } 1076 } 1077 1078 return 0; 1079 } 1080 1081 static const struct lwtunnel_encap_ops seg6_local_ops = { 1082 .build_state = seg6_local_build_state, 1083 .destroy_state = seg6_local_destroy_state, 1084 .input = seg6_local_input, 1085 .fill_encap = seg6_local_fill_encap, 1086 .get_encap_size = seg6_local_get_encap_size, 1087 .cmp_encap = seg6_local_cmp_encap, 1088 .owner = THIS_MODULE, 1089 }; 1090 1091 int __init seg6_local_init(void) 1092 { 1093 return lwtunnel_encap_add_ops(&seg6_local_ops, 1094 LWTUNNEL_ENCAP_SEG6_LOCAL); 1095 } 1096 1097 void seg6_local_exit(void) 1098 { 1099 lwtunnel_encap_del_ops(&seg6_local_ops, LWTUNNEL_ENCAP_SEG6_LOCAL); 1100 } 1101