Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
fix association to 11g-only APs
To:
tech@openbsd.org
Date:
Wed, 8 Oct 2025 11:49:11 +0200

Download raw body.

Thread
When I replaced ieee80211_iserp_sta() with a check for the extended
rates information element I wrongly assumed that this information
element would always be present if 11g is supported. However, the
xrates IE only appears in 11b/g mixed mode. APs which have 802.11b
rates completely disabled can announce all rates via the regular
rates IE and never send the xrates IE.

Ensure that we recognize such APs as 11g-capable regardless of the
missing xrates IE. Otherwise assocation can fail due to a mismatch
of basic rates.

Problem reported by landry@


M  sys/net80211/ieee80211_node.c  |  27+  3-

1 file changed, 27 insertions(+), 3 deletions(-)

commit - b8b7e987f417088024ed43ff3a6ae432124e0952
commit + 6c9aaa207a9b063d2d0aeab7053af3632a5034a6
blob - 8251692acf39a015ec12afa4f342e5518f9e42de
blob + 7c6f51ab9831d139571c9ae2eb35c6fcfc300243
--- sys/net80211/ieee80211_node.c
+++ sys/net80211/ieee80211_node.c
@@ -2625,6 +2625,28 @@ ieee80211_clear_vhtcaps(struct ieee80211_node *ni)
 }
 #endif
 
+int
+ieee80211_node_is_11g(struct ieee80211_node *ni)
+{
+	struct ieee80211_rateset *rs = &ni->ni_rates;
+	const struct ieee80211_rateset *rs_ofdm = &ieee80211_std_rateset_11a;
+	int i, j;
+
+	if (!IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
+		return 0;
+
+	/* 2GHz station which supports 11a OFDM rates implies 11g. */
+	for (i = 0; i < rs->rs_nrates; i++) {
+		for (j = 0; j < rs_ofdm->rs_nrates; j++) {
+			if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) ==
+			    (rs_ofdm->rs_rates[j] & IEEE80211_RATE_VAL))
+			    	return 1;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * Install received rate set information in the node's state block.
  */
@@ -2653,10 +2675,12 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct 
 		memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
 		rs->rs_nrates += nxrates;
 
-		/* 11g support implies ERP support */
-		if (nxrates > 0 && IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
-			ni->ni_flags |= IEEE80211_NODE_ERP;
 	}
+
+	/* 11g support implies ERP support */
+	if (ieee80211_node_is_11g(ni))
+		ni->ni_flags |= IEEE80211_NODE_ERP;
+
 	return ieee80211_fix_rate(ic, ni, flags);
 }