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

Commit 1a995b45 authored by Denis Vlasenko's avatar Denis Vlasenko Committed by John W. Linville
Browse files

[PATCH] ieee80211_rx_any: filter out packets, call ieee80211_rx or ieee80211_rx_mgt



Version 2 of the patch. Added checks for version 0
and proper from/to DS bits. Even in promisc
mode we won't receive packets from another BSSes.

bcm43xx_rx() contains code to filter out packets from
foreign BSSes and decide whether to call ieee80211_rx
or ieee80211_rx_mgt. This is not bcm specific.

Patch adapts that code and adds it to 80211
as ieee80211_rx_any() function.

Signed-off-by: default avatarDenis Vlasenko <vda@ilport.com.ua>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 4c718cfd
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
@@ -780,6 +780,80 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
	return 0;
}

/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
int ieee80211_rx_any(struct ieee80211_device *ieee,
		     struct sk_buff *skb, struct ieee80211_rx_stats *stats)
{
	struct ieee80211_hdr_4addr *hdr;
	int is_packet_for_us;
	u16 fc;

	if (ieee->iw_mode == IW_MODE_MONITOR)
		return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;

	hdr = (struct ieee80211_hdr_4addr *)skb->data;
	fc = le16_to_cpu(hdr->frame_ctl);

	if ((fc & IEEE80211_FCTL_VERS) != 0)
		return -EINVAL;
		
	switch (fc & IEEE80211_FCTL_FTYPE) {
	case IEEE80211_FTYPE_MGMT:
		ieee80211_rx_mgt(ieee, hdr, stats);
		return 0;
	case IEEE80211_FTYPE_DATA:
		break;
	case IEEE80211_FTYPE_CTL:
		return 0;
	default:
		return -EINVAL;
	}

	is_packet_for_us = 0;
	switch (ieee->iw_mode) {
	case IW_MODE_ADHOC:
		/* our BSS and not from/to DS */
		if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
		if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
			/* promisc: get all */
			if (ieee->dev->flags & IFF_PROMISC)
				is_packet_for_us = 1;
			/* to us */
			else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
				is_packet_for_us = 1;
			/* mcast */
			else if (is_multicast_ether_addr(hdr->addr1))
				is_packet_for_us = 1;
		}
		break;
	case IW_MODE_INFRA:
		/* our BSS (== from our AP) and from DS */
		if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
		if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
			/* promisc: get all */
			if (ieee->dev->flags & IFF_PROMISC)
				is_packet_for_us = 1;
			/* to us */
			else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
				is_packet_for_us = 1;
			/* mcast */
			else if (is_multicast_ether_addr(hdr->addr1)) {
				/* not our own packet bcasted from AP */
				if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
					is_packet_for_us = 1;
			}
		}
		break;
	default:
		/* ? */
		break;
	}

	if (is_packet_for_us)
		return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
	return 0;
}

#define MGMT_FRAME_FIXED_PART_LENGTH		0x24

static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };