diff options
Diffstat (limited to 'net/ipv6/ip6_gre.c')
| -rw-r--r-- | net/ipv6/ip6_gre.c | 92 |
1 files changed, 54 insertions, 38 deletions
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 09d0826742f8..26f25b6e2833 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -534,13 +534,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, | |||
| 534 | struct ip6_tnl *tunnel; | 534 | struct ip6_tnl *tunnel; |
| 535 | u8 ver; | 535 | u8 ver; |
| 536 | 536 | ||
| 537 | if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) | ||
| 538 | return PACKET_REJECT; | ||
| 539 | |||
| 540 | ipv6h = ipv6_hdr(skb); | 537 | ipv6h = ipv6_hdr(skb); |
| 541 | ershdr = (struct erspan_base_hdr *)skb->data; | 538 | ershdr = (struct erspan_base_hdr *)skb->data; |
| 542 | ver = ershdr->ver; | 539 | ver = ershdr->ver; |
| 543 | tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||
| 544 | 540 | ||
| 545 | tunnel = ip6gre_tunnel_lookup(skb->dev, | 541 | tunnel = ip6gre_tunnel_lookup(skb->dev, |
| 546 | &ipv6h->saddr, &ipv6h->daddr, tpi->key, | 542 | &ipv6h->saddr, &ipv6h->daddr, tpi->key, |
| @@ -922,6 +918,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, | |||
| 922 | __u8 dsfield = false; | 918 | __u8 dsfield = false; |
| 923 | struct flowi6 fl6; | 919 | struct flowi6 fl6; |
| 924 | int err = -EINVAL; | 920 | int err = -EINVAL; |
| 921 | __be16 proto; | ||
| 925 | __u32 mtu; | 922 | __u32 mtu; |
| 926 | int nhoff; | 923 | int nhoff; |
| 927 | int thoff; | 924 | int thoff; |
| @@ -1035,8 +1032,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, | |||
| 1035 | } | 1032 | } |
| 1036 | 1033 | ||
| 1037 | /* Push GRE header. */ | 1034 | /* Push GRE header. */ |
| 1038 | gre_build_header(skb, 8, TUNNEL_SEQ, | 1035 | proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN) |
| 1039 | htons(ETH_P_ERSPAN), 0, htonl(t->o_seqno++)); | 1036 | : htons(ETH_P_ERSPAN2); |
| 1037 | gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(t->o_seqno++)); | ||
| 1040 | 1038 | ||
| 1041 | /* TooBig packet may have updated dst->dev's mtu */ | 1039 | /* TooBig packet may have updated dst->dev's mtu */ |
| 1042 | if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu) | 1040 | if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu) |
| @@ -1169,6 +1167,10 @@ static void ip6gre_tnl_copy_tnl_parm(struct ip6_tnl *t, | |||
| 1169 | t->parms.i_flags = p->i_flags; | 1167 | t->parms.i_flags = p->i_flags; |
| 1170 | t->parms.o_flags = p->o_flags; | 1168 | t->parms.o_flags = p->o_flags; |
| 1171 | t->parms.fwmark = p->fwmark; | 1169 | t->parms.fwmark = p->fwmark; |
| 1170 | t->parms.erspan_ver = p->erspan_ver; | ||
| 1171 | t->parms.index = p->index; | ||
| 1172 | t->parms.dir = p->dir; | ||
| 1173 | t->parms.hwid = p->hwid; | ||
| 1172 | dst_cache_reset(&t->dst_cache); | 1174 | dst_cache_reset(&t->dst_cache); |
| 1173 | } | 1175 | } |
| 1174 | 1176 | ||
| @@ -1717,6 +1719,27 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[], | |||
| 1717 | return 0; | 1719 | return 0; |
| 1718 | } | 1720 | } |
| 1719 | 1721 | ||
| 1722 | static void ip6erspan_set_version(struct nlattr *data[], | ||
| 1723 | struct __ip6_tnl_parm *parms) | ||
| 1724 | { | ||
| 1725 | if (!data) | ||
| 1726 | return; | ||
| 1727 | |||
| 1728 | parms->erspan_ver = 1; | ||
| 1729 | if (data[IFLA_GRE_ERSPAN_VER]) | ||
| 1730 | parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); | ||
| 1731 | |||
| 1732 | if (parms->erspan_ver == 1) { | ||
| 1733 | if (data[IFLA_GRE_ERSPAN_INDEX]) | ||
| 1734 | parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); | ||
| 1735 | } else if (parms->erspan_ver == 2) { | ||
| 1736 | if (data[IFLA_GRE_ERSPAN_DIR]) | ||
| 1737 | parms->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); | ||
| 1738 | if (data[IFLA_GRE_ERSPAN_HWID]) | ||
| 1739 | parms->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); | ||
| 1740 | } | ||
| 1741 | } | ||
| 1742 | |||
| 1720 | static void ip6gre_netlink_parms(struct nlattr *data[], | 1743 | static void ip6gre_netlink_parms(struct nlattr *data[], |
| 1721 | struct __ip6_tnl_parm *parms) | 1744 | struct __ip6_tnl_parm *parms) |
| 1722 | { | 1745 | { |
| @@ -1765,20 +1788,6 @@ static void ip6gre_netlink_parms(struct nlattr *data[], | |||
| 1765 | 1788 | ||
| 1766 | if (data[IFLA_GRE_COLLECT_METADATA]) | 1789 | if (data[IFLA_GRE_COLLECT_METADATA]) |
| 1767 | parms->collect_md = true; | 1790 | parms->collect_md = true; |
| 1768 | |||
| 1769 | parms->erspan_ver = 1; | ||
| 1770 | if (data[IFLA_GRE_ERSPAN_VER]) | ||
| 1771 | parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); | ||
| 1772 | |||
| 1773 | if (parms->erspan_ver == 1) { | ||
| 1774 | if (data[IFLA_GRE_ERSPAN_INDEX]) | ||
| 1775 | parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); | ||
| 1776 | } else if (parms->erspan_ver == 2) { | ||
| 1777 | if (data[IFLA_GRE_ERSPAN_DIR]) | ||
| 1778 | parms->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); | ||
| 1779 | if (data[IFLA_GRE_ERSPAN_HWID]) | ||
| 1780 | parms->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); | ||
| 1781 | } | ||
| 1782 | } | 1791 | } |
| 1783 | 1792 | ||
| 1784 | static int ip6gre_tap_init(struct net_device *dev) | 1793 | static int ip6gre_tap_init(struct net_device *dev) |
| @@ -2025,9 +2034,9 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], | |||
| 2025 | struct nlattr *data[], | 2034 | struct nlattr *data[], |
| 2026 | struct netlink_ext_ack *extack) | 2035 | struct netlink_ext_ack *extack) |
| 2027 | { | 2036 | { |
| 2028 | struct ip6gre_net *ign = net_generic(dev_net(dev), ip6gre_net_id); | 2037 | struct ip6_tnl *t = netdev_priv(dev); |
| 2038 | struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); | ||
| 2029 | struct __ip6_tnl_parm p; | 2039 | struct __ip6_tnl_parm p; |
| 2030 | struct ip6_tnl *t; | ||
| 2031 | 2040 | ||
| 2032 | t = ip6gre_changelink_common(dev, tb, data, &p, extack); | 2041 | t = ip6gre_changelink_common(dev, tb, data, &p, extack); |
| 2033 | if (IS_ERR(t)) | 2042 | if (IS_ERR(t)) |
| @@ -2096,12 +2105,31 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 2096 | { | 2105 | { |
| 2097 | struct ip6_tnl *t = netdev_priv(dev); | 2106 | struct ip6_tnl *t = netdev_priv(dev); |
| 2098 | struct __ip6_tnl_parm *p = &t->parms; | 2107 | struct __ip6_tnl_parm *p = &t->parms; |
| 2108 | __be16 o_flags = p->o_flags; | ||
| 2109 | |||
| 2110 | if (p->erspan_ver == 1 || p->erspan_ver == 2) { | ||
| 2111 | if (!p->collect_md) | ||
| 2112 | o_flags |= TUNNEL_KEY; | ||
| 2113 | |||
| 2114 | if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, p->erspan_ver)) | ||
| 2115 | goto nla_put_failure; | ||
| 2116 | |||
| 2117 | if (p->erspan_ver == 1) { | ||
| 2118 | if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index)) | ||
| 2119 | goto nla_put_failure; | ||
| 2120 | } else { | ||
| 2121 | if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, p->dir)) | ||
| 2122 | goto nla_put_failure; | ||
| 2123 | if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, p->hwid)) | ||
| 2124 | goto nla_put_failure; | ||
| 2125 | } | ||
| 2126 | } | ||
| 2099 | 2127 | ||
| 2100 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || | 2128 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || |
| 2101 | nla_put_be16(skb, IFLA_GRE_IFLAGS, | 2129 | nla_put_be16(skb, IFLA_GRE_IFLAGS, |
| 2102 | gre_tnl_flags_to_gre_flags(p->i_flags)) || | 2130 | gre_tnl_flags_to_gre_flags(p->i_flags)) || |
| 2103 | nla_put_be16(skb, IFLA_GRE_OFLAGS, | 2131 | nla_put_be16(skb, IFLA_GRE_OFLAGS, |
| 2104 | gre_tnl_flags_to_gre_flags(p->o_flags)) || | 2132 | gre_tnl_flags_to_gre_flags(o_flags)) || |
| 2105 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || | 2133 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || |
| 2106 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || | 2134 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || |
| 2107 | nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) || | 2135 | nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) || |
| @@ -2110,8 +2138,7 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 2110 | nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) || | 2138 | nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) || |
| 2111 | nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) || | 2139 | nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) || |
| 2112 | nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags) || | 2140 | nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags) || |
| 2113 | nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark) || | 2141 | nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark)) |
| 2114 | nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index)) | ||
| 2115 | goto nla_put_failure; | 2142 | goto nla_put_failure; |
| 2116 | 2143 | ||
| 2117 | if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, | 2144 | if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, |
| @@ -2129,19 +2156,6 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 2129 | goto nla_put_failure; | 2156 | goto nla_put_failure; |
| 2130 | } | 2157 | } |
| 2131 | 2158 | ||
| 2132 | if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, p->erspan_ver)) | ||
| 2133 | goto nla_put_failure; | ||
| 2134 | |||
| 2135 | if (p->erspan_ver == 1) { | ||
| 2136 | if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index)) | ||
| 2137 | goto nla_put_failure; | ||
| 2138 | } else if (p->erspan_ver == 2) { | ||
| 2139 | if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, p->dir)) | ||
| 2140 | goto nla_put_failure; | ||
| 2141 | if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, p->hwid)) | ||
| 2142 | goto nla_put_failure; | ||
| 2143 | } | ||
| 2144 | |||
| 2145 | return 0; | 2159 | return 0; |
| 2146 | 2160 | ||
| 2147 | nla_put_failure: | 2161 | nla_put_failure: |
| @@ -2196,6 +2210,7 @@ static int ip6erspan_newlink(struct net *src_net, struct net_device *dev, | |||
| 2196 | int err; | 2210 | int err; |
| 2197 | 2211 | ||
| 2198 | ip6gre_netlink_parms(data, &nt->parms); | 2212 | ip6gre_netlink_parms(data, &nt->parms); |
| 2213 | ip6erspan_set_version(data, &nt->parms); | ||
| 2199 | ign = net_generic(net, ip6gre_net_id); | 2214 | ign = net_generic(net, ip6gre_net_id); |
| 2200 | 2215 | ||
| 2201 | if (nt->parms.collect_md) { | 2216 | if (nt->parms.collect_md) { |
| @@ -2241,6 +2256,7 @@ static int ip6erspan_changelink(struct net_device *dev, struct nlattr *tb[], | |||
| 2241 | if (IS_ERR(t)) | 2256 | if (IS_ERR(t)) |
| 2242 | return PTR_ERR(t); | 2257 | return PTR_ERR(t); |
| 2243 | 2258 | ||
| 2259 | ip6erspan_set_version(data, &p); | ||
| 2244 | ip6gre_tunnel_unlink_md(ign, t); | 2260 | ip6gre_tunnel_unlink_md(ign, t); |
| 2245 | ip6gre_tunnel_unlink(ign, t); | 2261 | ip6gre_tunnel_unlink(ign, t); |
| 2246 | ip6erspan_tnl_change(t, &p, !tb[IFLA_MTU]); | 2262 | ip6erspan_tnl_change(t, &p, !tb[IFLA_MTU]); |
