Return-path: Received: from mx2.redhat.com ([66.187.237.31]:40975 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753151AbZBDQKm (ORCPT ); Wed, 4 Feb 2009 11:10:42 -0500 Subject: Re: [PATCH RFC] mac80211: Filter scan results From: Dan Williams To: Samuel Ortiz Cc: John Linville , Reinette Chatre , linux-wireless@vger.kernel.org In-Reply-To: <20090204150857.GA5069@sortiz.org> References: <20090204150857.GA5069@sortiz.org> Content-Type: text/plain Date: Wed, 04 Feb 2009 11:09:12 -0500 Message-Id: <1233763752.21577.10.camel@localhost.localdomain> (sfid-20090204_171046_117583_6EE26D0E) Mime-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org List-ID: On Wed, 2009-02-04 at 16:08 +0100, Samuel Ortiz wrote: > From: Samuel Ortiz > > 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 NAK. Use cfg80211. Module parameters are the wrong way to work around API limitations; the API gets fixed or replaced instead. Furthermore, the stack/drivers should *NOT* be filtering scan results at all. That's the job of the userspace program requesting the results; otherwise passive listeners will get only filtered results, and not the complete scan list. Dan > Signed-off-by: Samuel Ortiz > --- > 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);