diff options
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 74 |
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] */ | ||
784 | int 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 | ||
785 | static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; | 859 | static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; |