Skip to content

Commit 2fcf8ac

Browse files
committed
replace ieee80211_chan2mode() with ieee80211_node_abg_mode()
chan2mode() did not detect 11g APs properly. This can be fixed now that we are setting the ERP flag in client mode, not only in hostap mode. In 11g mode chan2mode() was wrongly selecting 11g mode for 11b-only peers. The CHAN_ANYC case of chan2mode() was irrelevant for all callers. Replace chan2mode() with node_abg_mode() which does not have these issues. ok phessler@, mpi@
1 parent ebebda9 commit 2fcf8ac

File tree

8 files changed

+79
-74
lines changed

8 files changed

+79
-74
lines changed

sys/dev/ic/ath.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ath.c,v 1.125 2023/11/10 15:51:20 bluhm Exp $ */
1+
/* $OpenBSD: ath.c,v 1.126 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ath.c,v 1.37 2004/08/18 21:59:39 dyoung Exp $ */
33

44
/*-
@@ -113,7 +113,7 @@ void ath_rx_proc(void *, int);
113113
int ath_tx_start(struct ath_softc *, struct ieee80211_node *,
114114
struct ath_buf *, struct mbuf *);
115115
void ath_tx_proc(void *, int);
116-
int ath_chan_set(struct ath_softc *, struct ieee80211_channel *);
116+
int ath_chan_set(struct ath_softc *, struct ieee80211_node *);
117117
void ath_draintxq(struct ath_softc *);
118118
void ath_stoprecv(struct ath_softc *);
119119
int ath_startrecv(struct ath_softc *);
@@ -675,7 +675,7 @@ ath_init1(struct ath_softc *sc)
675675
*/
676676
ni = ic->ic_bss;
677677
ni->ni_chan = ic->ic_ibss_chan;
678-
mode = ieee80211_chan2mode(ic, ni->ni_chan);
678+
mode = ieee80211_node_abg_mode(ic, ni);
679679
if (mode != sc->sc_curmode)
680680
ath_setcurmode(sc, mode);
681681
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
@@ -2570,11 +2570,12 @@ ath_startrecv(struct ath_softc *sc)
25702570
* ath_init.
25712571
*/
25722572
int
2573-
ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
2573+
ath_chan_set(struct ath_softc *sc, struct ieee80211_node *ni)
25742574
{
25752575
struct ath_hal *ah = sc->sc_ah;
25762576
struct ieee80211com *ic = &sc->sc_ic;
25772577
struct ifnet *ifp = &ic->ic_if;
2578+
struct ieee80211_channel *chan = ni->ni_chan;
25782579

25792580
DPRINTF(ATH_DEBUG_ANY, ("%s: %u (%u MHz) -> %u (%u MHz)\n", __func__,
25802581
ieee80211_chan2ieee(ic, ic->ic_ibss_chan),
@@ -2631,7 +2632,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
26312632
* if we're switching; e.g. 11a to 11b/g.
26322633
*/
26332634
ic->ic_ibss_chan = chan;
2634-
mode = ieee80211_chan2mode(ic, chan);
2635+
mode = ieee80211_node_abg_mode(ic, ni);
26352636
if (mode != sc->sc_curmode)
26362637
ath_setcurmode(sc, mode);
26372638

@@ -2775,7 +2776,7 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
27752776
return (*sc->sc_newstate)(ic, nstate, arg);
27762777
}
27772778
ni = ic->ic_bss;
2778-
error = ath_chan_set(sc, ni->ni_chan);
2779+
error = ath_chan_set(sc, ni);
27792780
if (error != 0)
27802781
goto bad;
27812782
rfilt = ath_calcrxfilter(sc);

sys/net80211/ieee80211.c

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ieee80211.c,v 1.90 2025/08/01 09:45:47 stsp Exp $ */
1+
/* $OpenBSD: ieee80211.c,v 1.91 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ieee80211.c,v 1.19 2004/06/06 05:45:29 dyoung Exp $ */
33

44
/*-
@@ -1173,55 +1173,6 @@ ieee80211_next_mode(struct ifnet *ifp)
11731173
return (ic->ic_curmode);
11741174
}
11751175

1176-
/*
1177-
* Return the phy mode for with the specified channel so the
1178-
* caller can select a rate set. This is problematic and the
1179-
* work here assumes how things work elsewhere in this code.
1180-
*
1181-
* Because the result of this function is ultimately used to select a
1182-
* rate from the rate set of the returned mode, it must return one of the
1183-
* legacy 11a/b/g modes; 11n and 11ac modes use MCS instead of rate sets.
1184-
*/
1185-
enum ieee80211_phymode
1186-
ieee80211_chan2mode(struct ieee80211com *ic,
1187-
const struct ieee80211_channel *chan)
1188-
{
1189-
/*
1190-
* Are we fixed in 11a/b/g mode?
1191-
* NB: this assumes the channel would not be supplied to us
1192-
* unless it was already compatible with the current mode.
1193-
*/
1194-
if (ic->ic_curmode == IEEE80211_MODE_11A ||
1195-
ic->ic_curmode == IEEE80211_MODE_11B ||
1196-
ic->ic_curmode == IEEE80211_MODE_11G)
1197-
return ic->ic_curmode;
1198-
1199-
/* If no channel was provided, return the most suitable legacy mode. */
1200-
if (chan == IEEE80211_CHAN_ANYC) {
1201-
switch (ic->ic_curmode) {
1202-
case IEEE80211_MODE_AUTO:
1203-
case IEEE80211_MODE_11N:
1204-
if (ic->ic_modecaps & (1 << IEEE80211_MODE_11A))
1205-
return IEEE80211_MODE_11A;
1206-
if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G))
1207-
return IEEE80211_MODE_11G;
1208-
return IEEE80211_MODE_11B;
1209-
case IEEE80211_MODE_11AC:
1210-
return IEEE80211_MODE_11A;
1211-
default:
1212-
return ic->ic_curmode;
1213-
}
1214-
}
1215-
1216-
/* Deduce a legacy mode based on the channel characteristics. */
1217-
if (IEEE80211_IS_CHAN_5GHZ(chan))
1218-
return IEEE80211_MODE_11A;
1219-
else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
1220-
return IEEE80211_MODE_11G;
1221-
else
1222-
return IEEE80211_MODE_11B;
1223-
}
1224-
12251176
/*
12261177
* Convert IEEE80211 MCS index to ifmedia subtype.
12271178
*/

sys/net80211/ieee80211_input.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ieee80211_input.c,v 1.255 2025/03/22 07:24:08 kevlo Exp $ */
1+
/* $OpenBSD: ieee80211_input.c,v 1.256 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ieee80211_input.c,v 1.24 2004/05/31 11:12:24 dyoung Exp $ */
33

44
/*-
@@ -2671,7 +2671,7 @@ ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m,
26712671
else if (ni->ni_flags & IEEE80211_NODE_HT)
26722672
ieee80211_setmode(ic, IEEE80211_MODE_11N);
26732673
else
2674-
ieee80211_setmode(ic, ieee80211_chan2mode(ic, ni->ni_chan));
2674+
ieee80211_setmode(ic, ieee80211_node_abg_mode(ic, ni));
26752675
/*
26762676
* Reset the erp state (mostly the slot time) now that
26772677
* our operating mode has been nailed down.

sys/net80211/ieee80211_node.c

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ieee80211_node.c,v 1.202 2025/08/01 09:13:11 stsp Exp $ */
1+
/* $OpenBSD: ieee80211_node.c,v 1.203 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $ */
33

44
/*-
@@ -931,8 +931,29 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
931931
mode = IEEE80211_MODE_11AC;
932932
else if (ic->ic_flags & IEEE80211_F_HTON)
933933
mode = IEEE80211_MODE_11N;
934-
else
935-
mode = ieee80211_chan2mode(ic, ni->ni_chan);
934+
else {
935+
/* Was a specific 11a/b/g phy mode set by ifconfig? */
936+
switch (IFM_MODE(ic->ic_media.ifm_cur->ifm_media)) {
937+
case IFM_IEEE80211_11A:
938+
mode = IEEE80211_MODE_11A;
939+
break;
940+
case IFM_IEEE80211_11G:
941+
mode = IEEE80211_MODE_11G;
942+
break;
943+
case IFM_IEEE80211_11B:
944+
mode = IEEE80211_MODE_11B;
945+
break;
946+
default: /* If we get here, our phy mode is MODE_AUTO. */
947+
if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan))
948+
mode = IEEE80211_MODE_11A;
949+
else if ((ni->ni_chan->ic_flags &
950+
(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN)) != 0)
951+
mode = IEEE80211_MODE_11G;
952+
else
953+
mode = IEEE80211_MODE_11B;
954+
break;
955+
}
956+
}
936957
ieee80211_setmode(ic, mode);
937958
/* Pick an appropriate mode for supported legacy rates. */
938959
if (ic->ic_curmode == IEEE80211_MODE_11AC) {
@@ -1303,7 +1324,7 @@ ieee80211_node_join_bss(struct ieee80211com *ic, struct ieee80211_node *selbs)
13031324
uint32_t assoc_fail = 0;
13041325

13051326
/* Reinitialize media mode and channels if needed. */
1306-
mode = ieee80211_chan2mode(ic, selbs->ni_chan);
1327+
mode = ieee80211_node_abg_mode(ic, selbs);
13071328
if (mode != ic->ic_curmode)
13081329
ieee80211_setmode(ic, mode);
13091330

@@ -1317,8 +1338,6 @@ ieee80211_node_join_bss(struct ieee80211com *ic, struct ieee80211_node *selbs)
13171338
ni = ic->ic_bss;
13181339
ni->ni_assoc_fail |= assoc_fail;
13191340

1320-
ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan);
1321-
13221341
/* Make sure we send valid rates in an association request. */
13231342
if (ic->ic_opmode == IEEE80211_M_STA)
13241343
ieee80211_fix_rate(ic, ni,
@@ -1561,7 +1580,7 @@ ieee80211_end_scan(struct ifnet *ifp)
15611580
ieee80211_setmode(ic, IEEE80211_MODE_11N);
15621581
else
15631582
ieee80211_setmode(ic,
1564-
ieee80211_chan2mode(ic, ni->ni_chan));
1583+
ieee80211_node_abg_mode(ic, ni));
15651584
return;
15661585
}
15671586

@@ -2641,6 +2660,40 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
26412660
return ieee80211_fix_rate(ic, ni, flags);
26422661
}
26432662

2663+
/*
2664+
* Return the 11a/b/g mode mutually supported for the given node.
2665+
* ni->ni_chan must be set before calling this, and ieee80211_setup_rates()
2666+
* should be called beforehand to properly differentiate 11b and 11g.
2667+
*/
2668+
enum ieee80211_phymode
2669+
ieee80211_node_abg_mode(struct ieee80211com *ic, struct ieee80211_node *ni)
2670+
{
2671+
/* Handle the case where our own phy mode was fixed by ifconfig. */
2672+
switch (IFM_MODE(ic->ic_media.ifm_cur->ifm_media)) {
2673+
case IFM_IEEE80211_11A:
2674+
return IEEE80211_MODE_11A; /* Peer uses 11a. */
2675+
case IFM_IEEE80211_11B:
2676+
return IEEE80211_MODE_11B; /* Peer uses 11b. */
2677+
case IFM_IEEE80211_11G:
2678+
/* Peer could be using either 11g or 11b, check below. */
2679+
break;
2680+
default:
2681+
break;
2682+
}
2683+
2684+
/* Our own phy mode is either 11G or AUTO. */
2685+
2686+
if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan))
2687+
return IEEE80211_MODE_11A;
2688+
2689+
if ((ni->ni_flags & IEEE80211_NODE_ERP) &&
2690+
(ni->ni_chan->ic_flags &
2691+
(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN)) != 0)
2692+
return IEEE80211_MODE_11G;
2693+
2694+
return IEEE80211_MODE_11B;
2695+
}
2696+
26442697
void
26452698
ieee80211_node_trigger_addba_req(struct ieee80211_node *ni, int tid)
26462699
{

sys/net80211/ieee80211_node.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ieee80211_node.h,v 1.96 2025/08/01 09:13:11 stsp Exp $ */
1+
/* $OpenBSD: ieee80211_node.h,v 1.97 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
33

44
/*-
@@ -644,6 +644,8 @@ int ieee80211_setup_vhtop(struct ieee80211_node *, const uint8_t *,
644644
uint8_t, int);
645645
int ieee80211_setup_rates(struct ieee80211com *,
646646
struct ieee80211_node *, const u_int8_t *, const u_int8_t *, int);
647+
enum ieee80211_phymode ieee80211_node_abg_mode(struct ieee80211com *,
648+
struct ieee80211_node *);
647649
void ieee80211_node_trigger_addba_req(struct ieee80211_node *, int);
648650
void ieee80211_count_longslotsta(void *, struct ieee80211_node *);
649651
void ieee80211_count_nonerpsta(void *, struct ieee80211_node *);

sys/net80211/ieee80211_output.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ieee80211_output.c,v 1.141 2025/06/14 08:46:34 jsg Exp $ */
1+
/* $OpenBSD: ieee80211_output.c,v 1.142 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $ */
33

44
/*-
@@ -1258,7 +1258,7 @@ struct mbuf *
12581258
ieee80211_get_probe_req(struct ieee80211com *ic, struct ieee80211_node *ni)
12591259
{
12601260
const struct ieee80211_rateset *rs =
1261-
&ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
1261+
&ic->ic_sup_rates[ieee80211_node_abg_mode(ic, ni)];
12621262
struct mbuf *m;
12631263
u_int8_t *frm;
12641264

sys/net80211/ieee80211_proto.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ieee80211_proto.c,v 1.109 2024/02/08 00:05:46 jsg Exp $ */
1+
/* $OpenBSD: ieee80211_proto.c,v 1.110 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $ */
33

44
/*-
@@ -221,7 +221,7 @@ ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
221221

222222
error = 0;
223223
okrate = badrate = fixedrate = 0;
224-
srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
224+
srs = &ic->ic_sup_rates[ieee80211_node_abg_mode(ic, ni)];
225225
nrs = &ni->ni_rates;
226226
for (i = 0; i < nrs->rs_nrates; ) {
227227
ignore = 0;
@@ -1154,7 +1154,7 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
11541154
IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
11551155
IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
11561156
ni->ni_rates = ic->ic_sup_rates[
1157-
ieee80211_chan2mode(ic, ni->ni_chan)];
1157+
ieee80211_node_abg_mode(ic, ni)];
11581158
ni->ni_associd = 0;
11591159
ni->ni_rstamp = 0;
11601160
ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;

sys/net80211/ieee80211_var.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ieee80211_var.h,v 1.111 2022/03/14 15:07:24 stsp Exp $ */
1+
/* $OpenBSD: ieee80211_var.h,v 1.112 2025/08/01 20:39:26 stsp Exp $ */
22
/* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
33

44
/*-
@@ -496,8 +496,6 @@ int ieee80211_min_basic_rate(struct ieee80211com *);
496496
int ieee80211_max_basic_rate(struct ieee80211com *);
497497
int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
498498
enum ieee80211_phymode ieee80211_next_mode(struct ifnet *);
499-
enum ieee80211_phymode ieee80211_chan2mode(struct ieee80211com *,
500-
const struct ieee80211_channel *);
501499
void ieee80211_disable_wep(struct ieee80211com *);
502500
void ieee80211_disable_rsn(struct ieee80211com *);
503501
int ieee80211_add_ess(struct ieee80211com *, struct ieee80211_join *);

0 commit comments

Comments
 (0)