Loading include/net/cfg80211.h +10 −0 Original line number Diff line number Diff line Loading @@ -6221,6 +6221,16 @@ void cfg80211_nan_func_terminated(struct wireless_dev *wdev, /* ethtool helper */ void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); /** * cfg80211_is_gratuitous_arp_unsolicited_na - packet is grat. ARP/unsol. NA * @skb: the input packet, must be an ethernet frame already * * Return: %true if the packet is a gratuitous ARP or unsolicited NA packet. * This is used to drop packets that shouldn't occur because the AP implements * a proxy service. */ bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb); /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ Loading net/wireless/util.c +53 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <linux/if_vlan.h> #include <linux/mpls.h> #include <linux/gcd.h> #include <net/ndisc.h> #include <linux/if_arp.h> #include "core.h" #include "rdev-ops.h" Loading Loading @@ -1871,3 +1873,54 @@ EXPORT_SYMBOL(rfc1042_header); const unsigned char bridge_tunnel_header[] __aligned(2) = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; EXPORT_SYMBOL(bridge_tunnel_header); bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb) { const struct ethhdr *eth = (void *)skb->data; const struct { struct arphdr hdr; u8 ar_sha[ETH_ALEN]; u8 ar_sip[4]; u8 ar_tha[ETH_ALEN]; u8 ar_tip[4]; } __packed *arp; const struct ipv6hdr *ipv6; const struct icmp6hdr *icmpv6; switch (eth->h_proto) { case cpu_to_be16(ETH_P_ARP): /* can't say - but will probably be dropped later anyway */ if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*arp))) return false; arp = (void *)(eth + 1); if ((arp->hdr.ar_op == cpu_to_be16(ARPOP_REPLY) || arp->hdr.ar_op == cpu_to_be16(ARPOP_REQUEST)) && !memcmp(arp->ar_sip, arp->ar_tip, sizeof(arp->ar_sip))) return true; break; case cpu_to_be16(ETH_P_IPV6): /* can't say - but will probably be dropped later anyway */ if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*ipv6) + sizeof(*icmpv6))) return false; ipv6 = (void *)(eth + 1); icmpv6 = (void *)(ipv6 + 1); if (icmpv6->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT && !memcmp(&ipv6->saddr, &ipv6->daddr, sizeof(ipv6->saddr))) return true; break; default: /* * no need to support other protocols, proxy service isn't * specified for any others */ break; } return false; } EXPORT_SYMBOL(cfg80211_is_gratuitous_arp_unsolicited_na); Loading
include/net/cfg80211.h +10 −0 Original line number Diff line number Diff line Loading @@ -6221,6 +6221,16 @@ void cfg80211_nan_func_terminated(struct wireless_dev *wdev, /* ethtool helper */ void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); /** * cfg80211_is_gratuitous_arp_unsolicited_na - packet is grat. ARP/unsol. NA * @skb: the input packet, must be an ethernet frame already * * Return: %true if the packet is a gratuitous ARP or unsolicited NA packet. * This is used to drop packets that shouldn't occur because the AP implements * a proxy service. */ bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb); /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ Loading
net/wireless/util.c +53 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <linux/if_vlan.h> #include <linux/mpls.h> #include <linux/gcd.h> #include <net/ndisc.h> #include <linux/if_arp.h> #include "core.h" #include "rdev-ops.h" Loading Loading @@ -1871,3 +1873,54 @@ EXPORT_SYMBOL(rfc1042_header); const unsigned char bridge_tunnel_header[] __aligned(2) = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; EXPORT_SYMBOL(bridge_tunnel_header); bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb) { const struct ethhdr *eth = (void *)skb->data; const struct { struct arphdr hdr; u8 ar_sha[ETH_ALEN]; u8 ar_sip[4]; u8 ar_tha[ETH_ALEN]; u8 ar_tip[4]; } __packed *arp; const struct ipv6hdr *ipv6; const struct icmp6hdr *icmpv6; switch (eth->h_proto) { case cpu_to_be16(ETH_P_ARP): /* can't say - but will probably be dropped later anyway */ if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*arp))) return false; arp = (void *)(eth + 1); if ((arp->hdr.ar_op == cpu_to_be16(ARPOP_REPLY) || arp->hdr.ar_op == cpu_to_be16(ARPOP_REQUEST)) && !memcmp(arp->ar_sip, arp->ar_tip, sizeof(arp->ar_sip))) return true; break; case cpu_to_be16(ETH_P_IPV6): /* can't say - but will probably be dropped later anyway */ if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*ipv6) + sizeof(*icmpv6))) return false; ipv6 = (void *)(eth + 1); icmpv6 = (void *)(ipv6 + 1); if (icmpv6->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT && !memcmp(&ipv6->saddr, &ipv6->daddr, sizeof(ipv6->saddr))) return true; break; default: /* * no need to support other protocols, proxy service isn't * specified for any others */ break; } return false; } EXPORT_SYMBOL(cfg80211_is_gratuitous_arp_unsolicited_na);