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