aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211')
-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 a7f2a642a512..604b7b0097bc 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,
780 return 0; 780 return 0;
781} 781}
782 782
783/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
784int ieee80211_rx_any(struct ieee80211_device *ieee,
785 struct sk_buff *skb, struct ieee80211_rx_stats *stats)
786{
787 struct ieee80211_hdr_4addr *hdr;
788 int is_packet_for_us;
789 u16 fc;
790
791 if (ieee->iw_mode == IW_MODE_MONITOR)
792 return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
793
794 hdr = (struct ieee80211_hdr_4addr *)skb->data;
795 fc = le16_to_cpu(hdr->frame_ctl);
796
797 if ((fc & IEEE80211_FCTL_VERS) != 0)
798 return -EINVAL;
799
800 switch (fc & IEEE80211_FCTL_FTYPE) {
801 case IEEE80211_FTYPE_MGMT:
802 ieee80211_rx_mgt(ieee, hdr, stats);
803 return 0;
804 case IEEE80211_FTYPE_DATA:
805 break;
806 case IEEE80211_FTYPE_CTL:
807 return 0;
808 default:
809 return -EINVAL;
810 }
811
812 is_packet_for_us = 0;
813 switch (ieee->iw_mode) {
814 case IW_MODE_ADHOC:
815 /* our BSS and not from/to DS */
816 if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
817 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
818 /* promisc: get all */
819 if (ieee->dev->flags & IFF_PROMISC)
820 is_packet_for_us = 1;
821 /* to us */
822 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
823 is_packet_for_us = 1;
824 /* mcast */
825 else if (is_multicast_ether_addr(hdr->addr1))
826 is_packet_for_us = 1;
827 }
828 break;
829 case IW_MODE_INFRA:
830 /* our BSS (== from our AP) and from DS */
831 if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
832 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
833 /* promisc: get all */
834 if (ieee->dev->flags & IFF_PROMISC)
835 is_packet_for_us = 1;
836 /* to us */
837 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
838 is_packet_for_us = 1;
839 /* mcast */
840 else if (is_multicast_ether_addr(hdr->addr1)) {
841 /* not our own packet bcasted from AP */
842 if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
843 is_packet_for_us = 1;
844 }
845 }
846 break;
847 default:
848 /* ? */
849 break;
850 }
851
852 if (is_packet_for_us)
853 return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
854 return 0;
855}
856
783#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 857#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
784 858
785static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; 859static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };