Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a9d4945 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mac80211: implement HS2.0 gratuitous ARP/unsolicited NA dropping" into msm-next

parents fccc68fd 7fc169bb
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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 */
+53 −0
Original line number Diff line number Diff line
@@ -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"

@@ -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);