root/net/ipv6/seg6_local.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. seg6_local_lwtunnel
  2. get_srh
  3. get_and_validate_srh
  4. decap_and_validate
  5. advance_nextseg
  6. seg6_lookup_nexthop
  7. input_action_end
  8. input_action_end_x
  9. input_action_end_t
  10. input_action_end_dx2
  11. input_action_end_dx6
  12. input_action_end_dx4
  13. input_action_end_dt6
  14. input_action_end_b6
  15. input_action_end_b6_encap
  16. seg6_bpf_has_valid_srh
  17. input_action_end_bpf
  18. __get_action_desc
  19. seg6_local_input
  20. parse_nla_srh
  21. put_nla_srh
  22. cmp_nla_srh
  23. parse_nla_table
  24. put_nla_table
  25. cmp_nla_table
  26. parse_nla_nh4
  27. put_nla_nh4
  28. cmp_nla_nh4
  29. parse_nla_nh6
  30. put_nla_nh6
  31. cmp_nla_nh6
  32. parse_nla_iif
  33. put_nla_iif
  34. cmp_nla_iif
  35. parse_nla_oif
  36. put_nla_oif
  37. cmp_nla_oif
  38. parse_nla_bpf
  39. put_nla_bpf
  40. cmp_nla_bpf
  41. parse_nla_action
  42. seg6_local_build_state
  43. seg6_local_destroy_state
  44. seg6_local_fill_encap
  45. seg6_local_get_encap_size
  46. seg6_local_cmp_encap
  47. seg6_local_init
  48. seg6_local_exit

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

/* [<][>][^][v][top][bottom][index][help] */