Search Linux Wireless

[PATCH RFC] mac80211: Filter scan results

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Samuel Ortiz <samuel.ortiz@xxxxxxxxx>

In very dense environment, the scan result buffer can get really large, mostly
due to the addition of proprietary IEs. iwlist fails, typically warning about:
"print_scanning_info: Allocation failed". wpa_supplicant fails as well, after
reallocating the scan result buffer several times, up to 132 Kbytes:
	[snip]
	Scan results did not fit - trying larger buffer (131072 bytes)
	ioctl[SIOCGIWSCAN]: Argument list too long

By adding a mac80211 module parameter, we can filter the scan results and keep
only the ones userspace currently worries about, i.e. WPA1, WPA2, WMM and WPS.

To activate this feature, 1 has to be written to
/sys/module/mac80211/parameters/ieee80211_scan_ie_filter

Signed-off-by: Samuel Ortiz <samuel.ortiz@xxxxxxxxx>
---
 net/mac80211/ieee80211_i.h |    1 
 net/mac80211/scan.c        |   65 ++++++++++++++++++++++++++++++---------------
 net/mac80211/util.c        |   40 +++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 21 deletions(-)

Index: wireless-testing/net/mac80211/scan.c
===================================================================
--- wireless-testing.orig/net/mac80211/scan.c	2009-01-28 11:37:55.000000000 +0100
+++ wireless-testing/net/mac80211/scan.c	2009-01-28 17:32:48.000000000 +0100
@@ -31,6 +31,11 @@
 #define IEEE80211_CHANNEL_TIME (HZ / 33)
 #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
 
+static int ieee80211_scan_ie_filter;
+module_param(ieee80211_scan_ie_filter, bool, 0644);
+MODULE_PARM_DESC(ieee80211_scan_ie_filter,
+		 "Filter IEs from scan results");
+
 void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
 {
 	spin_lock_init(&local->bss_lock);
@@ -725,33 +730,51 @@ static void ieee80211_scan_add_ies(struc
 	if (bss == NULL || bss->ies == NULL)
 		return;
 
-	/*
-	 * If needed, fragment the IEs buffer (at IE boundaries) into short
-	 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
-	 */
 	pos = bss->ies;
 	end = pos + bss->ies_len;
 
-	while (end - pos > IW_GENERIC_IE_MAX) {
-		next = pos + 2 + pos[1];
-		while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
-			next = next + 2 + next[1];
+	if (ieee80211_scan_ie_filter) {
+		while (pos - end) {
+			next = pos + 2 + pos[1];
+			if (ieee80211_filter_ie(pos)) {
+				memset(&iwe, 0, sizeof(iwe));
+				iwe.cmd = IWEVGENIE;
+				iwe.u.data.length = next - pos;
+				*current_ev =
+					iwe_stream_add_point(info, *current_ev,
+							     end_buf, &iwe,
+							     pos);
+			}
+			pos = next;
+		}
+	} else {
+		/*
+		 * If needed, fragment the IEs buffer (at IE boundaries) into
+		 * short enough fragments to fit into IW_GENERIC_IE_MAX octet
+		 * messages.
+		 */
+
+		while (end - pos > IW_GENERIC_IE_MAX) {
+			next = pos + 2 + pos[1];
+			while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
+				next = next + 2 + next[1];
 
-		memset(&iwe, 0, sizeof(iwe));
-		iwe.cmd = IWEVGENIE;
-		iwe.u.data.length = next - pos;
-		*current_ev = iwe_stream_add_point(info, *current_ev,
-						   end_buf, &iwe, pos);
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = IWEVGENIE;
+			iwe.u.data.length = next - pos;
+			*current_ev = iwe_stream_add_point(info, *current_ev,
+							   end_buf, &iwe, pos);
 
-		pos = next;
-	}
+			pos = next;
+		}
 
-	if (end > pos) {
-		memset(&iwe, 0, sizeof(iwe));
-		iwe.cmd = IWEVGENIE;
-		iwe.u.data.length = end - pos;
-		*current_ev = iwe_stream_add_point(info, *current_ev,
-						   end_buf, &iwe, pos);
+		if (end > pos) {
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = IWEVGENIE;
+			iwe.u.data.length = end - pos;
+			*current_ev = iwe_stream_add_point(info, *current_ev,
+							   end_buf, &iwe, pos);
+		}
 	}
 }
 
Index: wireless-testing/net/mac80211/util.c
===================================================================
--- wireless-testing.orig/net/mac80211/util.c	2009-01-28 11:37:41.000000000 +0100
+++ wireless-testing/net/mac80211/util.c	2009-01-28 15:57:03.000000000 +0100
@@ -675,6 +675,46 @@ void ieee802_11_parse_elems(u8 *start, s
 	}
 }
 
+/*
+ * ieee80211_filter_ie() tries to keep only the relevant IEs for
+ * userspace (mostly hostap code).
+ */
+int ieee80211_filter_ie(u8 *ie)
+{
+	u8 id, ie_len, *pos;
+	u8 microsoft_oui[4] = {0x00, 0x50, 0xf2};
+	u8 wpa2_oui[3] = {0x00, 0x0f, 0xac};
+
+	pos = ie;
+	id = *pos++;
+	ie_len = *pos++;
+
+	switch (id) {
+	case WLAN_EID_RSN:
+		/* WPA2 */
+		if (ie_len >= 3 &&
+		    !memcmp(pos, wpa2_oui, 3))
+			return 1;
+
+		return 0;
+
+	case WLAN_EID_VENDOR_SPECIFIC:
+		/* We're trying to catch WPA1, WMM and WPS IEs. */
+		if (ie_len >= 3 &&
+		    !memcmp(pos, microsoft_oui, 3)) {
+			if ((pos[3] == 1) || /* WPA1 */
+			    (pos[3] == 2) || /* WMM */
+			    (pos[3] == 4))   /* WPS */
+				return 1;
+		}
+
+		return 0;
+
+	default:
+		return 0;
+	}
+}
+
 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
Index: wireless-testing/net/mac80211/ieee80211_i.h
===================================================================
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2009-01-28 11:37:41.000000000 +0100
+++ wireless-testing/net/mac80211/ieee80211_i.h	2009-01-28 13:49:17.000000000 +0100
@@ -1028,6 +1028,7 @@ void ieee80211_tx_skb(struct ieee80211_s
 		      int encrypt);
 void ieee802_11_parse_elems(u8 *start, size_t len,
 			    struct ieee802_11_elems *elems);
+int ieee80211_filter_ie(u8 *ie);
 int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
 u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
 			      enum ieee80211_band band);
-- 
Intel Open Source Technology Centre
http://oss.intel.com/
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux