[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: Denis Vlasenko <vda@ilport.com.ua> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
4c718cfd7d
commit
1a995b45a5
|
@ -780,6 +780,80 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
||||||
return 0;
|
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
|
#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
|
||||||
|
|
||||||
static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
|
static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
|
||||||
|
|
Loading…
Reference in New Issue