[RFC] don't join BSS if rates don't match

Christian Lamparter chunkeey at googlemail.com
Sat Oct 15 18:41:27 EDT 2011


Hi Jouni,

since you insisted on fixing the supplicant as well. Here's a
RFC patch that adds a few checks into wpa_supplicant so
it can make an early educated guess whenever the AP will
deny a STA association based on its supported rate set or
not.

For now, the patch is relativly simple. But during development
I asked myself if it wouldn't make sense to fetch the hardware
features data just once during init and keep the data around
for everyone else.

Note: There still some other places which use the (ext.)
supported rates IEs a bit carelessly. But fixing them is
as far as I can tell not an issue.

Regards,
	Chr

---
OnT: Do you have any comments on the v2 mac80211 patch? 
---
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 9d83e4d..cf7a180 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -477,6 +477,112 @@ static int freq_allowed(int *freqs, int freq)
 }
 
 
+static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss)
+{
+	struct hostapd_hw_modes *mode = NULL;
+	const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES };
+	const u8 *rate_ie;
+	int i, j, k, match = 0;
+
+	u16 num_modes, flags;
+	struct hostapd_hw_modes *modes;
+
+	modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags);
+	if (modes == NULL) {
+		/*
+		 * The driver does not provide any additional information
+		 * about the utilized hardware. But we don't fail in this
+		 * event since accesspoints can also validate the stations
+		 * supported rate set and deny the BSS Join Request if it
+		 * does not comply with the minimal required standard of
+		 * the BSS.
+		 */
+		return 1;
+	}
+
+	for (i = 0; i < num_modes; i++) {
+		for (j = 0; j < modes[i].num_channels; j++) {
+			int freq = modes[i].channels[j].freq;
+			if (freq == bss->freq) {
+				mode = &modes[i];
+				break;
+			}
+		}
+	}
+
+	if (mode == NULL)
+		goto out;
+
+	for (i = 0; i < sizeof(scan_ie); i++) {
+		rate_ie = wpa_scan_get_ie(bss, scan_ie[i]);
+		if (rate_ie == NULL)
+			break;
+
+		for (j = 2; j < rate_ie[1] + 2; j++) {
+			int flagged = !!(rate_ie[j] & 0x80);
+			int r = (rate_ie[j] & 0x7f) * 5;
+
+			/*
+			 * 802.11n-2009 7.3.2.2
+			 * The new BSS Membership selector value encoding
+			 * is encoded like a legacy rate. But it is not
+			 * a rate and only indicates if the BSS members
+			 * are required to support the mandatory features
+			 * of Clause 20 [HT PHY] in order to join the BSS.
+			 */
+			if (flagged && ((rate_ie[j] & 0x7f) ==
+			     BSS_MEMBERSHIP_SELECTOR_HT_PHY)) {
+				/*
+				 * 802.11n-2009 20.1.1
+				 *
+				 * An HT non-AP STA shall support all EQM
+				 * rates for one spatial stream.
+				 */
+				if (mode->mcs_set[0] != 0xff) {
+					wpa_dbg(wpa_s, MSG_DEBUG, "   hardware "
+						"does not support HT PHY");
+					return 0;
+				}
+				continue;
+			}
+
+			/* check for legacy [basic] rates */
+
+			/*
+			 * Shortcut. We have already found a matching rate
+			 * and this particular rate is not marked as basic.
+			 * Therefore it's not necessary to support the rate
+			 * and we can skip the expensive check.
+			 */
+			if (match && !flagged)
+				continue;
+
+			for (k = 0; k < mode->num_rates; k++) {
+				if (mode->rates[k] == r) {
+					match = 1;
+					break;
+				}
+			}
+			if (flagged && (k == mode->num_rates)) {
+				/*
+				 * 802.11-2007 7.3.2.2 demands that in
+				 * order to join a BSS all required rates
+				 * have to be supported by the hardware.
+				 */
+				wpa_dbg(wpa_s, MSG_DEBUG, "   hardware does not"
+					" support required rate %d.%d Mbit",
+					r / 10, r % 10);
+
+				match = 0;
+				break;
+			}
+		}
+	}
+out:
+	ieee80211_sta_free_hw_features(modes, num_modes);
+	return match;
+}
+
 static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
 					    int i, struct wpa_scan_res *bss,
 					    struct wpa_ssid *group)
@@ -609,6 +715,12 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
 			continue;
 		}
 
+		if (!rate_match(wpa_s, bss)) {
+			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - rate sets do "
+				"not match");
+			continue;
+		}
+
 #ifdef CONFIG_P2P
 		/*
 		 * TODO: skip the AP if its P2P IE has Group Formation



More information about the HostAP mailing list