Commit f2060f039e8a8bc83b10e6d0f8fb440425560569

Authored by Daniel Drake
Committed by John W. Linville
1 parent d7712ac254

[PATCH] ieee80211: Make ieee80211_rx_any usable

ieee80211_rx_any is new to 2.6.18-rc1, even though it appears this function
was never completed:

http://lists.sipsolutions.net/pipermail/softmac-dev/2006-February/000103.html

This patch changes ieee80211_rx_any to always claim the skb, which avoids
further driver complexity and the possibility of leaking management frames.
It also exports the function so that people can actually use it.

Signed-off-by: Daniel Drake <dsd@gentoo.org>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 2 changed files with 30 additions and 10 deletions Side-by-side Diff

include/net/ieee80211.h
... ... @@ -1259,6 +1259,8 @@
1259 1259 int total_len, int encrypt_mpdu);
1260 1260  
1261 1261 /* ieee80211_rx.c */
  1262 +extern void ieee80211_rx_any(struct ieee80211_device *ieee,
  1263 + struct sk_buff *skb, struct ieee80211_rx_stats *stats);
1262 1264 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
1263 1265 struct ieee80211_rx_stats *rx_stats);
1264 1266 /* make sure to set stats->len */
net/ieee80211/ieee80211_rx.c
... ... @@ -779,33 +779,44 @@
779 779 return 0;
780 780 }
781 781  
782   -/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
783   -int ieee80211_rx_any(struct ieee80211_device *ieee,
  782 +/* Filter out unrelated packets, call ieee80211_rx[_mgt]
  783 + * This function takes over the skb, it should not be used again after calling
  784 + * this function. */
  785 +void ieee80211_rx_any(struct ieee80211_device *ieee,
784 786 struct sk_buff *skb, struct ieee80211_rx_stats *stats)
785 787 {
786 788 struct ieee80211_hdr_4addr *hdr;
787 789 int is_packet_for_us;
788 790 u16 fc;
789 791  
790   - if (ieee->iw_mode == IW_MODE_MONITOR)
791   - return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
  792 + if (ieee->iw_mode == IW_MODE_MONITOR) {
  793 + if (!ieee80211_rx(ieee, skb, stats))
  794 + dev_kfree_skb_irq(skb);
  795 + return;
  796 + }
792 797  
  798 + if (skb->len < sizeof(struct ieee80211_hdr))
  799 + goto drop_free;
  800 +
793 801 hdr = (struct ieee80211_hdr_4addr *)skb->data;
794 802 fc = le16_to_cpu(hdr->frame_ctl);
795 803  
796 804 if ((fc & IEEE80211_FCTL_VERS) != 0)
797   - return -EINVAL;
  805 + goto drop_free;
798 806  
799 807 switch (fc & IEEE80211_FCTL_FTYPE) {
800 808 case IEEE80211_FTYPE_MGMT:
  809 + if (skb->len < sizeof(struct ieee80211_hdr_3addr))
  810 + goto drop_free;
801 811 ieee80211_rx_mgt(ieee, hdr, stats);
802   - return 0;
  812 + dev_kfree_skb_irq(skb);
  813 + return;
803 814 case IEEE80211_FTYPE_DATA:
804 815 break;
805 816 case IEEE80211_FTYPE_CTL:
806   - return 0;
  817 + return;
807 818 default:
808   - return -EINVAL;
  819 + return;
809 820 }
810 821  
811 822 is_packet_for_us = 0;
... ... @@ -849,8 +860,14 @@
849 860 }
850 861  
851 862 if (is_packet_for_us)
852   - return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
853   - return 0;
  863 + if (!ieee80211_rx(ieee, skb, stats))
  864 + dev_kfree_skb_irq(skb);
  865 + return;
  866 +
  867 +drop_free:
  868 + dev_kfree_skb_irq(skb);
  869 + ieee->stats.rx_dropped++;
  870 + return;
854 871 }
855 872  
856 873 #define MGMT_FRAME_FIXED_PART_LENGTH 0x24
... ... @@ -1730,6 +1747,7 @@
1730 1747 }
1731 1748 }
1732 1749  
  1750 +EXPORT_SYMBOL_GPL(ieee80211_rx_any);
1733 1751 EXPORT_SYMBOL(ieee80211_rx_mgt);
1734 1752 EXPORT_SYMBOL(ieee80211_rx);