summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/vxlan/vxlan_core.c21
-rw-r--r--drivers/net/vxlan/vxlan_mdb.c4
2 files changed, 16 insertions, 9 deletions
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index d834a4865aec..1ded27768a97 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -1850,7 +1850,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
if (dev->flags & IFF_NOARP)
goto out;
- if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
+ if (!pskb_network_may_pull(skb, arp_hdr_len(dev))) {
dev_dstats_tx_dropped(dev);
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_TX_DROPS, 0);
@@ -2111,7 +2111,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
{
struct iphdr *pip;
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
return false;
pip = ip_hdr(skb);
n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
@@ -2137,7 +2137,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
*/
if (!ipv6_mod_enabled())
return false;
- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
return false;
pip6 = ipv6_hdr(skb);
n = neigh_lookup(&nd_tbl, &pip6->daddr, dev);
@@ -2159,13 +2159,19 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
}
if (n) {
+ u8 haddr[ETH_ALEN];
bool diff;
- diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha);
+ neigh_ha_snapshot(haddr, n, dev);
+ diff = !ether_addr_equal_unaligned(eth_hdr(skb)->h_dest, haddr);
if (diff) {
+ if (skb_cow_head(skb, 0)) {
+ neigh_release(n);
+ return false;
+ }
memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
dev->addr_len);
- memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);
+ memcpy(eth_hdr(skb)->h_dest, haddr, dev->addr_len);
}
neigh_release(n);
return diff;
@@ -2757,8 +2763,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
return arp_reduce(dev, skb, vni);
#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)) &&
+ pskb_network_may_pull(skb, sizeof(struct ipv6hdr) +
+ sizeof(struct nd_msg)) &&
ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
struct nd_msg *m = (struct nd_msg *)(ipv6_hdr(skb) + 1);
@@ -2796,6 +2802,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
(ntohs(eth->h_proto) == ETH_P_IP ||
ntohs(eth->h_proto) == ETH_P_IPV6)) {
did_rsc = route_shortcircuit(dev, skb);
+ eth = eth_hdr(skb);
if (did_rsc)
f = vxlan_find_mac_tx(vxlan, eth->h_dest, vni);
}
diff --git a/drivers/net/vxlan/vxlan_mdb.c b/drivers/net/vxlan/vxlan_mdb.c
index af7a0d7f95a5..9a9038ae90c1 100644
--- a/drivers/net/vxlan/vxlan_mdb.c
+++ b/drivers/net/vxlan/vxlan_mdb.c
@@ -1631,7 +1631,7 @@ struct vxlan_mdb_entry *vxlan_mdb_entry_skb_get(struct vxlan_dev *vxlan,
switch (skb->protocol) {
case htons(ETH_P_IP):
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
return NULL;
group.dst.sa.sa_family = AF_INET;
group.dst.sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
@@ -1640,7 +1640,7 @@ struct vxlan_mdb_entry *vxlan_mdb_entry_skb_get(struct vxlan_dev *vxlan,
break;
#if IS_ENABLED(CONFIG_IPV6)
case htons(ETH_P_IPV6):
- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
return NULL;
group.dst.sa.sa_family = AF_INET6;
group.dst.sin6.sin6_addr = ipv6_hdr(skb)->daddr;