Merge "mac80211: implement HS2.0 gratuitous ARP/unsolicited NA dropping"

This commit is contained in:
Linux Build Service Account
2014-05-05 15:13:07 -07:00
committed by Gerrit - the friendly Code Review server
2 changed files with 62 additions and 0 deletions
+9
View File
@@ -3799,6 +3799,15 @@ void cfg80211_ft_event(struct net_device *netdev,
* @gfp: context flags
*/
void cfg80211_ap_stopped(struct net_device *netdev, gfp_t gfp);
/**
* 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. */
+53
View File
@@ -10,6 +10,8 @@
#include <net/cfg80211.h>
#include <net/ip.h>
#include <net/dsfield.h>
#include <net/ndisc.h>
#include <linux/if_arp.h>
#include "core.h"
struct ieee80211_rate *
@@ -1150,3 +1152,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);