.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * GRE over IPv6 protocol decoder. |
---|
3 | 4 | * |
---|
4 | 5 | * Authors: Dmitry Kozlov (xeb@mail.ru) |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License |
---|
8 | | - * as published by the Free Software Foundation; either version |
---|
9 | | - * 2 of the License, or (at your option) any later version. |
---|
10 | | - * |
---|
11 | 6 | */ |
---|
12 | 7 | |
---|
13 | 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
425 | 420 | } |
---|
426 | 421 | |
---|
427 | 422 | |
---|
428 | | -static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
---|
| 423 | +static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
---|
429 | 424 | u8 type, u8 code, int offset, __be32 info) |
---|
430 | 425 | { |
---|
431 | 426 | struct net *net = dev_net(skb->dev); |
---|
432 | | - const struct gre_base_hdr *greh; |
---|
433 | 427 | const struct ipv6hdr *ipv6h; |
---|
434 | | - int grehlen = sizeof(*greh); |
---|
| 428 | + struct tnl_ptk_info tpi; |
---|
435 | 429 | struct ip6_tnl *t; |
---|
436 | | - int key_off = 0; |
---|
437 | | - __be16 flags; |
---|
438 | | - __be32 key; |
---|
439 | 430 | |
---|
440 | | - if (!pskb_may_pull(skb, offset + grehlen)) |
---|
441 | | - return; |
---|
442 | | - greh = (const struct gre_base_hdr *)(skb->data + offset); |
---|
443 | | - flags = greh->flags; |
---|
444 | | - if (flags & (GRE_VERSION | GRE_ROUTING)) |
---|
445 | | - return; |
---|
446 | | - if (flags & GRE_CSUM) |
---|
447 | | - grehlen += 4; |
---|
448 | | - if (flags & GRE_KEY) { |
---|
449 | | - key_off = grehlen + offset; |
---|
450 | | - grehlen += 4; |
---|
451 | | - } |
---|
| 431 | + if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IPV6), |
---|
| 432 | + offset) < 0) |
---|
| 433 | + return -EINVAL; |
---|
452 | 434 | |
---|
453 | | - if (!pskb_may_pull(skb, offset + grehlen)) |
---|
454 | | - return; |
---|
455 | 435 | ipv6h = (const struct ipv6hdr *)skb->data; |
---|
456 | | - greh = (const struct gre_base_hdr *)(skb->data + offset); |
---|
457 | | - key = key_off ? *(__be32 *)(skb->data + key_off) : 0; |
---|
458 | | - |
---|
459 | 436 | t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, |
---|
460 | | - key, greh->protocol); |
---|
| 437 | + tpi.key, tpi.proto); |
---|
461 | 438 | if (!t) |
---|
462 | | - return; |
---|
| 439 | + return -ENOENT; |
---|
463 | 440 | |
---|
464 | 441 | switch (type) { |
---|
465 | | - struct ipv6_tlv_tnl_enc_lim *tel; |
---|
466 | | - __u32 teli; |
---|
467 | 442 | case ICMPV6_DEST_UNREACH: |
---|
468 | 443 | net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n", |
---|
469 | 444 | t->parms.name); |
---|
470 | 445 | if (code != ICMPV6_PORT_UNREACH) |
---|
471 | 446 | break; |
---|
472 | | - return; |
---|
| 447 | + return 0; |
---|
473 | 448 | case ICMPV6_TIME_EXCEED: |
---|
474 | 449 | if (code == ICMPV6_EXC_HOPLIMIT) { |
---|
475 | 450 | net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n", |
---|
476 | 451 | t->parms.name); |
---|
477 | 452 | break; |
---|
478 | 453 | } |
---|
479 | | - return; |
---|
480 | | - case ICMPV6_PARAMPROB: |
---|
| 454 | + return 0; |
---|
| 455 | + case ICMPV6_PARAMPROB: { |
---|
| 456 | + struct ipv6_tlv_tnl_enc_lim *tel; |
---|
| 457 | + __u32 teli; |
---|
| 458 | + |
---|
481 | 459 | teli = 0; |
---|
482 | 460 | if (code == ICMPV6_HDR_FIELD) |
---|
483 | 461 | teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); |
---|
.. | .. |
---|
492 | 470 | net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n", |
---|
493 | 471 | t->parms.name); |
---|
494 | 472 | } |
---|
495 | | - return; |
---|
| 473 | + return 0; |
---|
| 474 | + } |
---|
496 | 475 | case ICMPV6_PKT_TOOBIG: |
---|
497 | 476 | ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); |
---|
498 | | - return; |
---|
| 477 | + return 0; |
---|
499 | 478 | case NDISC_REDIRECT: |
---|
500 | 479 | ip6_redirect(skb, net, skb->dev->ifindex, 0, |
---|
501 | 480 | sock_net_uid(net, NULL)); |
---|
502 | | - return; |
---|
| 481 | + return 0; |
---|
503 | 482 | } |
---|
504 | 483 | |
---|
505 | 484 | if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) |
---|
.. | .. |
---|
507 | 486 | else |
---|
508 | 487 | t->err_count = 1; |
---|
509 | 488 | t->err_time = jiffies; |
---|
| 489 | + |
---|
| 490 | + return 0; |
---|
510 | 491 | } |
---|
511 | 492 | |
---|
512 | 493 | static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) |
---|
.. | .. |
---|
542 | 523 | return PACKET_REJECT; |
---|
543 | 524 | } |
---|
544 | 525 | |
---|
545 | | -static int ip6erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, |
---|
| 526 | +static int ip6erspan_rcv(struct sk_buff *skb, |
---|
| 527 | + struct tnl_ptk_info *tpi, |
---|
546 | 528 | int gre_hdr_len) |
---|
547 | 529 | { |
---|
548 | 530 | struct erspan_base_hdr *ershdr; |
---|
.. | .. |
---|
695 | 677 | |
---|
696 | 678 | tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; |
---|
697 | 679 | if (tel->encap_limit == 0) { |
---|
698 | | - icmpv6_send(skb, ICMPV6_PARAMPROB, |
---|
699 | | - ICMPV6_HDR_FIELD, offset + 2); |
---|
| 680 | + icmpv6_ndo_send(skb, ICMPV6_PARAMPROB, |
---|
| 681 | + ICMPV6_HDR_FIELD, offset + 2); |
---|
700 | 682 | return -1; |
---|
701 | 683 | } |
---|
702 | 684 | *encap_limit = tel->encap_limit - 1; |
---|
.. | .. |
---|
724 | 706 | return 0; |
---|
725 | 707 | } |
---|
726 | 708 | |
---|
| 709 | +static struct ip_tunnel_info *skb_tunnel_info_txcheck(struct sk_buff *skb) |
---|
| 710 | +{ |
---|
| 711 | + struct ip_tunnel_info *tun_info; |
---|
| 712 | + |
---|
| 713 | + tun_info = skb_tunnel_info(skb); |
---|
| 714 | + if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX))) |
---|
| 715 | + return ERR_PTR(-EINVAL); |
---|
| 716 | + |
---|
| 717 | + return tun_info; |
---|
| 718 | +} |
---|
| 719 | + |
---|
727 | 720 | static netdev_tx_t __gre6_xmit(struct sk_buff *skb, |
---|
728 | 721 | struct net_device *dev, __u8 dsfield, |
---|
729 | 722 | struct flowi6 *fl6, int encap_limit, |
---|
.. | .. |
---|
731 | 724 | { |
---|
732 | 725 | struct ip6_tnl *tunnel = netdev_priv(dev); |
---|
733 | 726 | __be16 protocol; |
---|
| 727 | + __be16 flags; |
---|
734 | 728 | |
---|
735 | 729 | if (dev->type == ARPHRD_ETHER) |
---|
736 | 730 | IPCB(skb)->flags = 0; |
---|
.. | .. |
---|
740 | 734 | else |
---|
741 | 735 | fl6->daddr = tunnel->parms.raddr; |
---|
742 | 736 | |
---|
743 | | - if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen)) |
---|
744 | | - return -ENOMEM; |
---|
745 | | - |
---|
746 | 737 | /* Push GRE header. */ |
---|
747 | 738 | protocol = (dev->type == ARPHRD_ETHER) ? htons(ETH_P_TEB) : proto; |
---|
748 | 739 | |
---|
749 | 740 | if (tunnel->parms.collect_md) { |
---|
750 | 741 | struct ip_tunnel_info *tun_info; |
---|
751 | 742 | const struct ip_tunnel_key *key; |
---|
752 | | - __be16 flags; |
---|
| 743 | + int tun_hlen; |
---|
753 | 744 | |
---|
754 | | - tun_info = skb_tunnel_info(skb); |
---|
755 | | - if (unlikely(!tun_info || |
---|
756 | | - !(tun_info->mode & IP_TUNNEL_INFO_TX) || |
---|
757 | | - ip_tunnel_info_af(tun_info) != AF_INET6)) |
---|
| 745 | + tun_info = skb_tunnel_info_txcheck(skb); |
---|
| 746 | + if (IS_ERR(tun_info) || |
---|
| 747 | + unlikely(ip_tunnel_info_af(tun_info) != AF_INET6)) |
---|
758 | 748 | return -EINVAL; |
---|
759 | 749 | |
---|
760 | 750 | key = &tun_info->key; |
---|
.. | .. |
---|
763 | 753 | fl6->daddr = key->u.ipv6.dst; |
---|
764 | 754 | fl6->flowlabel = key->label; |
---|
765 | 755 | fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); |
---|
| 756 | + fl6->fl6_gre_key = tunnel_id_to_key32(key->tun_id); |
---|
766 | 757 | |
---|
767 | 758 | dsfield = key->tos; |
---|
768 | 759 | flags = key->tun_flags & |
---|
769 | 760 | (TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ); |
---|
770 | | - tunnel->tun_hlen = gre_calc_hlen(flags); |
---|
| 761 | + tun_hlen = gre_calc_hlen(flags); |
---|
771 | 762 | |
---|
772 | | - gre_build_header(skb, tunnel->tun_hlen, |
---|
| 763 | + if (skb_cow_head(skb, dev->needed_headroom ?: tun_hlen + tunnel->encap_hlen)) |
---|
| 764 | + return -ENOMEM; |
---|
| 765 | + |
---|
| 766 | + gre_build_header(skb, tun_hlen, |
---|
773 | 767 | flags, protocol, |
---|
774 | 768 | tunnel_id_to_key32(tun_info->key.tun_id), |
---|
775 | | - (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) |
---|
| 769 | + (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) |
---|
776 | 770 | : 0); |
---|
777 | 771 | |
---|
778 | 772 | } else { |
---|
779 | | - if (tunnel->parms.o_flags & TUNNEL_SEQ) |
---|
780 | | - tunnel->o_seqno++; |
---|
| 773 | + if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen)) |
---|
| 774 | + return -ENOMEM; |
---|
781 | 775 | |
---|
782 | | - gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags, |
---|
| 776 | + flags = tunnel->parms.o_flags; |
---|
| 777 | + |
---|
| 778 | + gre_build_header(skb, tunnel->tun_hlen, flags, |
---|
783 | 779 | protocol, tunnel->parms.o_key, |
---|
784 | | - htonl(tunnel->o_seqno)); |
---|
| 780 | + (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) |
---|
| 781 | + : 0); |
---|
785 | 782 | } |
---|
786 | 783 | |
---|
787 | 784 | return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu, |
---|
.. | .. |
---|
812 | 809 | if (err != 0) { |
---|
813 | 810 | /* XXX: send ICMP error even if DF is not set. */ |
---|
814 | 811 | if (err == -EMSGSIZE) |
---|
815 | | - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
---|
816 | | - htonl(mtu)); |
---|
| 812 | + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
---|
| 813 | + htonl(mtu)); |
---|
817 | 814 | return -1; |
---|
818 | 815 | } |
---|
819 | 816 | |
---|
.. | .. |
---|
844 | 841 | &mtu, skb->protocol); |
---|
845 | 842 | if (err != 0) { |
---|
846 | 843 | if (err == -EMSGSIZE) |
---|
847 | | - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
---|
| 844 | + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
---|
848 | 845 | return -1; |
---|
849 | 846 | } |
---|
850 | 847 | |
---|
.. | .. |
---|
925 | 922 | return NETDEV_TX_OK; |
---|
926 | 923 | |
---|
927 | 924 | tx_err: |
---|
928 | | - stats->tx_errors++; |
---|
| 925 | + if (!t->parms.collect_md || !IS_ERR(skb_tunnel_info_txcheck(skb))) |
---|
| 926 | + stats->tx_errors++; |
---|
929 | 927 | stats->tx_dropped++; |
---|
930 | 928 | kfree_skb(skb); |
---|
931 | 929 | return NETDEV_TX_OK; |
---|
.. | .. |
---|
934 | 932 | static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, |
---|
935 | 933 | struct net_device *dev) |
---|
936 | 934 | { |
---|
| 935 | + struct ip_tunnel_info *tun_info = NULL; |
---|
937 | 936 | struct ip6_tnl *t = netdev_priv(dev); |
---|
938 | 937 | struct dst_entry *dst = skb_dst(skb); |
---|
939 | 938 | struct net_device_stats *stats; |
---|
.. | .. |
---|
945 | 944 | __be16 proto; |
---|
946 | 945 | __u32 mtu; |
---|
947 | 946 | int nhoff; |
---|
948 | | - int thoff; |
---|
949 | 947 | |
---|
950 | 948 | if (!pskb_inet_may_pull(skb)) |
---|
951 | 949 | goto tx_err; |
---|
.. | .. |
---|
957 | 955 | goto tx_err; |
---|
958 | 956 | |
---|
959 | 957 | if (skb->len > dev->mtu + dev->hard_header_len) { |
---|
960 | | - pskb_trim(skb, dev->mtu + dev->hard_header_len); |
---|
| 958 | + if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) |
---|
| 959 | + goto tx_err; |
---|
961 | 960 | truncate = true; |
---|
962 | 961 | } |
---|
963 | 962 | |
---|
964 | | - nhoff = skb_network_header(skb) - skb_mac_header(skb); |
---|
| 963 | + nhoff = skb_network_offset(skb); |
---|
965 | 964 | if (skb->protocol == htons(ETH_P_IP) && |
---|
966 | 965 | (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) |
---|
967 | 966 | truncate = true; |
---|
968 | 967 | |
---|
969 | | - thoff = skb_transport_header(skb) - skb_mac_header(skb); |
---|
970 | | - if (skb->protocol == htons(ETH_P_IPV6) && |
---|
971 | | - (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)) |
---|
972 | | - truncate = true; |
---|
| 968 | + if (skb->protocol == htons(ETH_P_IPV6)) { |
---|
| 969 | + int thoff; |
---|
| 970 | + |
---|
| 971 | + if (skb_transport_header_was_set(skb)) |
---|
| 972 | + thoff = skb_transport_offset(skb); |
---|
| 973 | + else |
---|
| 974 | + thoff = nhoff + sizeof(struct ipv6hdr); |
---|
| 975 | + if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff) |
---|
| 976 | + truncate = true; |
---|
| 977 | + } |
---|
973 | 978 | |
---|
974 | 979 | if (skb_cow_head(skb, dev->needed_headroom ?: t->hlen)) |
---|
975 | 980 | goto tx_err; |
---|
.. | .. |
---|
981 | 986 | * for native mode, call prepare_ip6gre_xmit_{ipv4,ipv6}. |
---|
982 | 987 | */ |
---|
983 | 988 | if (t->parms.collect_md) { |
---|
984 | | - struct ip_tunnel_info *tun_info; |
---|
985 | 989 | const struct ip_tunnel_key *key; |
---|
986 | 990 | struct erspan_metadata *md; |
---|
987 | 991 | __be32 tun_id; |
---|
988 | 992 | |
---|
989 | | - tun_info = skb_tunnel_info(skb); |
---|
990 | | - if (unlikely(!tun_info || |
---|
991 | | - !(tun_info->mode & IP_TUNNEL_INFO_TX) || |
---|
992 | | - ip_tunnel_info_af(tun_info) != AF_INET6)) |
---|
| 993 | + tun_info = skb_tunnel_info_txcheck(skb); |
---|
| 994 | + if (IS_ERR(tun_info) || |
---|
| 995 | + unlikely(ip_tunnel_info_af(tun_info) != AF_INET6)) |
---|
993 | 996 | goto tx_err; |
---|
994 | 997 | |
---|
995 | 998 | key = &tun_info->key; |
---|
.. | .. |
---|
998 | 1001 | fl6.daddr = key->u.ipv6.dst; |
---|
999 | 1002 | fl6.flowlabel = key->label; |
---|
1000 | 1003 | fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); |
---|
| 1004 | + fl6.fl6_gre_key = tunnel_id_to_key32(key->tun_id); |
---|
1001 | 1005 | |
---|
1002 | 1006 | dsfield = key->tos; |
---|
1003 | 1007 | if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT)) |
---|
.. | .. |
---|
1012 | 1016 | ntohl(tun_id), |
---|
1013 | 1017 | ntohl(md->u.index), truncate, |
---|
1014 | 1018 | false); |
---|
| 1019 | + proto = htons(ETH_P_ERSPAN); |
---|
1015 | 1020 | } else if (md->version == 2) { |
---|
1016 | 1021 | erspan_build_header_v2(skb, |
---|
1017 | 1022 | ntohl(tun_id), |
---|
1018 | 1023 | md->u.md2.dir, |
---|
1019 | 1024 | get_hwid(&md->u.md2), |
---|
1020 | 1025 | truncate, false); |
---|
| 1026 | + proto = htons(ETH_P_ERSPAN2); |
---|
1021 | 1027 | } else { |
---|
1022 | 1028 | goto tx_err; |
---|
1023 | 1029 | } |
---|
.. | .. |
---|
1040 | 1046 | break; |
---|
1041 | 1047 | } |
---|
1042 | 1048 | |
---|
1043 | | - if (t->parms.erspan_ver == 1) |
---|
| 1049 | + if (t->parms.erspan_ver == 1) { |
---|
1044 | 1050 | erspan_build_header(skb, ntohl(t->parms.o_key), |
---|
1045 | 1051 | t->parms.index, |
---|
1046 | 1052 | truncate, false); |
---|
1047 | | - else if (t->parms.erspan_ver == 2) |
---|
| 1053 | + proto = htons(ETH_P_ERSPAN); |
---|
| 1054 | + } else if (t->parms.erspan_ver == 2) { |
---|
1048 | 1055 | erspan_build_header_v2(skb, ntohl(t->parms.o_key), |
---|
1049 | 1056 | t->parms.dir, |
---|
1050 | 1057 | t->parms.hwid, |
---|
1051 | 1058 | truncate, false); |
---|
1052 | | - else |
---|
| 1059 | + proto = htons(ETH_P_ERSPAN2); |
---|
| 1060 | + } else { |
---|
1053 | 1061 | goto tx_err; |
---|
| 1062 | + } |
---|
1054 | 1063 | |
---|
1055 | 1064 | fl6.daddr = t->parms.raddr; |
---|
1056 | 1065 | } |
---|
1057 | 1066 | |
---|
1058 | 1067 | /* Push GRE header. */ |
---|
1059 | | - proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN) |
---|
1060 | | - : htons(ETH_P_ERSPAN2); |
---|
1061 | | - gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(t->o_seqno++)); |
---|
| 1068 | + gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(atomic_fetch_inc(&t->o_seqno))); |
---|
1062 | 1069 | |
---|
1063 | 1070 | /* TooBig packet may have updated dst->dev's mtu */ |
---|
1064 | 1071 | if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu) |
---|
.. | .. |
---|
1070 | 1077 | /* XXX: send ICMP error even if DF is not set. */ |
---|
1071 | 1078 | if (err == -EMSGSIZE) { |
---|
1072 | 1079 | if (skb->protocol == htons(ETH_P_IP)) |
---|
1073 | | - icmp_send(skb, ICMP_DEST_UNREACH, |
---|
1074 | | - ICMP_FRAG_NEEDED, htonl(mtu)); |
---|
| 1080 | + icmp_ndo_send(skb, ICMP_DEST_UNREACH, |
---|
| 1081 | + ICMP_FRAG_NEEDED, htonl(mtu)); |
---|
1075 | 1082 | else |
---|
1076 | | - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
---|
| 1083 | + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
---|
1077 | 1084 | } |
---|
1078 | 1085 | |
---|
1079 | 1086 | goto tx_err; |
---|
.. | .. |
---|
1082 | 1089 | |
---|
1083 | 1090 | tx_err: |
---|
1084 | 1091 | stats = &t->dev->stats; |
---|
1085 | | - stats->tx_errors++; |
---|
| 1092 | + if (!IS_ERR(tun_info)) |
---|
| 1093 | + stats->tx_errors++; |
---|
1086 | 1094 | stats->tx_dropped++; |
---|
1087 | 1095 | kfree_skb(skb); |
---|
1088 | 1096 | return NETDEV_TX_OK; |
---|
.. | .. |
---|
1105 | 1113 | fl6->flowi6_oif = p->link; |
---|
1106 | 1114 | fl6->flowlabel = 0; |
---|
1107 | 1115 | fl6->flowi6_proto = IPPROTO_GRE; |
---|
| 1116 | + fl6->fl6_gre_key = t->parms.o_key; |
---|
1108 | 1117 | |
---|
1109 | 1118 | if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) |
---|
1110 | 1119 | fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; |
---|
.. | .. |
---|
1148 | 1157 | dev->needed_headroom = dst_len; |
---|
1149 | 1158 | |
---|
1150 | 1159 | if (set_mtu) { |
---|
1151 | | - dev->mtu = rt->dst.dev->mtu - t_hlen; |
---|
1152 | | - if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) |
---|
1153 | | - dev->mtu -= 8; |
---|
1154 | | - if (dev->type == ARPHRD_ETHER) |
---|
1155 | | - dev->mtu -= ETH_HLEN; |
---|
| 1160 | + int mtu = rt->dst.dev->mtu - t_hlen; |
---|
1156 | 1161 | |
---|
1157 | | - if (dev->mtu < IPV6_MIN_MTU) |
---|
1158 | | - dev->mtu = IPV6_MIN_MTU; |
---|
| 1162 | + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) |
---|
| 1163 | + mtu -= 8; |
---|
| 1164 | + if (dev->type == ARPHRD_ETHER) |
---|
| 1165 | + mtu -= ETH_HLEN; |
---|
| 1166 | + |
---|
| 1167 | + if (mtu < IPV6_MIN_MTU) |
---|
| 1168 | + mtu = IPV6_MIN_MTU; |
---|
| 1169 | + WRITE_ONCE(dev->mtu, mtu); |
---|
1159 | 1170 | } |
---|
1160 | 1171 | } |
---|
1161 | 1172 | ip6_rt_put(rt); |
---|
.. | .. |
---|
1550 | 1561 | static struct inet6_protocol ip6gre_protocol __read_mostly = { |
---|
1551 | 1562 | .handler = gre_rcv, |
---|
1552 | 1563 | .err_handler = ip6gre_err, |
---|
1553 | | - .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
---|
| 1564 | + .flags = INET6_PROTO_FINAL, |
---|
1554 | 1565 | }; |
---|
1555 | 1566 | |
---|
1556 | 1567 | static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head) |
---|
.. | .. |
---|
1931 | 1942 | netif_keep_dst(dev); |
---|
1932 | 1943 | } |
---|
1933 | 1944 | |
---|
1934 | | -bool is_ip6gretap_dev(const struct net_device *dev) |
---|
1935 | | -{ |
---|
1936 | | - return dev->netdev_ops == &ip6gre_tap_netdev_ops; |
---|
1937 | | -} |
---|
1938 | | -EXPORT_SYMBOL_GPL(is_ip6gretap_dev); |
---|
1939 | | - |
---|
1940 | 1945 | static bool ip6gre_netlink_encap_parms(struct nlattr *data[], |
---|
1941 | 1946 | struct ip_tunnel_encap *ipencap) |
---|
1942 | 1947 | { |
---|
.. | .. |
---|
2205 | 2210 | [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, |
---|
2206 | 2211 | [IFLA_GRE_IKEY] = { .type = NLA_U32 }, |
---|
2207 | 2212 | [IFLA_GRE_OKEY] = { .type = NLA_U32 }, |
---|
2208 | | - [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct ipv6hdr, saddr) }, |
---|
2209 | | - [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct ipv6hdr, daddr) }, |
---|
| 2213 | + [IFLA_GRE_LOCAL] = { .len = sizeof_field(struct ipv6hdr, saddr) }, |
---|
| 2214 | + [IFLA_GRE_REMOTE] = { .len = sizeof_field(struct ipv6hdr, daddr) }, |
---|
2210 | 2215 | [IFLA_GRE_TTL] = { .type = NLA_U8 }, |
---|
2211 | 2216 | [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 }, |
---|
2212 | 2217 | [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 }, |
---|