summaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_rx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-03-23 16:25:49 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-23 16:25:49 -0800
commitaca361c1a0dc0165ac3148137983cb4b1458b5c1 (patch)
tree3527ff422fe90e97657d5996499fa4a9d30e2d5a /net/ieee80211/ieee80211_rx.c
parentcec6062037783a762aa5606b06b8bc5c14d9657f (diff)
parent9b7c84899ea6bfc4f8932a83b28db313e7397bd1 (diff)
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (45 commits) [PATCH] Restore channel setting after scan. [PATCH] hostap: Fix memory leak on PCI probe error path [PATCH] hostap: Remove dead code (duplicated idx != 0) [PATCH] hostap: Fix unlikely read overrun in CIS parsing [PATCH] hostap: Fix double free in prism2_config() error path [PATCH] hostap: Fix ap_add_sta() return value verification [PATCH] hostap: Fix hw reset after CMDCODE_ACCESS_WRITE timeout [PATCH] wireless/airo: cache wireless scans [PATCH] wireless/airo: define default MTU [PATCH] wireless/airo: clean up printk usage to print device name [PATCH] WE-20 for kernel 2.6.16 [PATCH] softmac: remove function_enter() [PATCH] skge: version 1.5 [PATCH] skge: compute available ring buffers [PATCH] skge: dont free skb until multi-part transmit complete [PATCH] skge: multicast statistics fix [PATCH] skge: rx_reuse called twice [PATCH] skge: dont use dev_alloc_skb for rx buffs [PATCH] skge: align receive buffers [PATCH] sky2: dont need to use dev_kfree_skb_any ...
Diffstat (limited to 'net/ieee80211/ieee80211_rx.c')
-rw-r--r--net/ieee80211/ieee80211_rx.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index a7f2a642a51..604b7b0097b 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -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 };