|
@@ -1515,7 +1515,7 @@ static struct sk_buff *vxlan_na_create(struct sk_buff *request,
|
|
int ns_olen;
|
|
int ns_olen;
|
|
int i, len;
|
|
int i, len;
|
|
|
|
|
|
- if (dev == NULL)
|
|
|
|
|
|
+ if (dev == NULL || !pskb_may_pull(request, request->len))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
|
|
len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
|
|
@@ -1530,10 +1530,11 @@ static struct sk_buff *vxlan_na_create(struct sk_buff *request,
|
|
skb_push(reply, sizeof(struct ethhdr));
|
|
skb_push(reply, sizeof(struct ethhdr));
|
|
skb_reset_mac_header(reply);
|
|
skb_reset_mac_header(reply);
|
|
|
|
|
|
- ns = (struct nd_msg *)skb_transport_header(request);
|
|
|
|
|
|
+ ns = (struct nd_msg *)(ipv6_hdr(request) + 1);
|
|
|
|
|
|
daddr = eth_hdr(request)->h_source;
|
|
daddr = eth_hdr(request)->h_source;
|
|
- ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns);
|
|
|
|
|
|
+ ns_olen = request->len - skb_network_offset(request) -
|
|
|
|
+ sizeof(struct ipv6hdr) - sizeof(*ns);
|
|
for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
|
|
for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
|
|
if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
|
|
if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
|
|
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
|
|
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
|
|
@@ -1604,10 +1605,13 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|
if (!in6_dev)
|
|
if (!in6_dev)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
|
|
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg)))
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
iphdr = ipv6_hdr(skb);
|
|
iphdr = ipv6_hdr(skb);
|
|
daddr = &iphdr->daddr;
|
|
daddr = &iphdr->daddr;
|
|
|
|
|
|
- msg = (struct nd_msg *)skb_transport_header(skb);
|
|
|
|
|
|
+ msg = (struct nd_msg *)(iphdr + 1);
|
|
if (msg->icmph.icmp6_code != 0 ||
|
|
if (msg->icmph.icmp6_code != 0 ||
|
|
msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
|
|
msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
|
|
goto out;
|
|
goto out;
|
|
@@ -2242,16 +2246,13 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
if (ntohs(eth->h_proto) == ETH_P_ARP)
|
|
if (ntohs(eth->h_proto) == ETH_P_ARP)
|
|
return arp_reduce(dev, skb, vni);
|
|
return arp_reduce(dev, skb, vni);
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
- else if (ntohs(eth->h_proto) == ETH_P_IPV6 &&
|
|
|
|
- pskb_may_pull(skb, sizeof(struct ipv6hdr)
|
|
|
|
- + sizeof(struct nd_msg)) &&
|
|
|
|
- ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
|
|
|
|
- struct nd_msg *msg;
|
|
|
|
-
|
|
|
|
- msg = (struct nd_msg *)skb_transport_header(skb);
|
|
|
|
- if (msg->icmph.icmp6_code == 0 &&
|
|
|
|
- msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
|
|
|
|
- return neigh_reduce(dev, skb, vni);
|
|
|
|
|
|
+ else if (ntohs(eth->h_proto) == ETH_P_IPV6) {
|
|
|
|
+ struct ipv6hdr *hdr, _hdr;
|
|
|
|
+ if ((hdr = skb_header_pointer(skb,
|
|
|
|
+ skb_network_offset(skb),
|
|
|
|
+ sizeof(_hdr), &_hdr)) &&
|
|
|
|
+ hdr->nexthdr == IPPROTO_ICMPV6)
|
|
|
|
+ return neigh_reduce(dev, skb, vni);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|