From: Peter Hessler Subject: Re: qwx wpa handshake race To: tech@openbsd.org Date: Mon, 24 Nov 2025 07:58:53 +0100 On 2025 Nov 19 (Wed) at 12:00:20 +0100 (+0100), Stefan Sperling wrote: :Improve chances of qwx receiving the initial WPA handshake message. : :Run some qwx firmware commands earlier during the association sequence. :We need to wait for these commands to complete, and timing is much less :critical before we have sent our association request. Once we have sent :this request, the AP may try to send the first WPA handshake message :immediately after sending the association response frame. And we could miss :the first WPA message while still setting up firmware state for association. :In the case I observed, losing this race would result in a loop of failed :attempts to join the network. : :ok? : OK :M sys/dev/ic/qwx.c | 32+ 12- : :1 file changed, 32 insertions(+), 12 deletions(-) : :commit - fac7d93c02bbab40f1f2e9b9118ae92fcaad733d :commit + e22c289135c2e5adcf38aacb10e888e3d7ba7562 :blob - ad3588d5c0f88b8de4171f7617551bfc058e6a36 :blob + dac4cfd24dabbbce8ff50e7596797c687257cd77 :--- sys/dev/ic/qwx.c :+++ sys/dev/ic/qwx.c :@@ -178,6 +178,7 @@ int qwx_scan(struct qwx_softc *, int); : void qwx_scan_abort(struct qwx_softc *); : int qwx_auth(struct qwx_softc *); : int qwx_deauth(struct qwx_softc *); :+int qwx_assoc(struct qwx_softc *); : int qwx_run(struct qwx_softc *); : int qwx_run_stop(struct qwx_softc *); : :@@ -1148,6 +1149,7 @@ next_scan: : break; : : case IEEE80211_S_ASSOC: :+ err = qwx_assoc(sc); : break; : : case IEEE80211_S_RUN: :@@ -26057,15 +26059,6 @@ qwx_deauth(struct qwx_softc *sc) : return ret; : } : :- :- ret = qwx_wmi_set_peer_param(sc, peer->addr, arvif->vdev_id, :- pdev_id, WMI_PEER_AUTHORIZE, 0); :- if (ret) { :- printf("%s: unable to deauthorize BSS peer: %d\n", :- sc->sc_dev.dv_xname, ret); :- return ret; :- } :- : qwx_clear_pn_replay_config(sc, peer); : qwx_clear_hwkeys(sc, peer); : :@@ -26472,7 +26465,7 @@ qwx_setup_peer_smps(struct qwx_softc *sc, uint8_t pdev : } : : int :-qwx_run(struct qwx_softc *sc) :+qwx_assoc(struct qwx_softc *sc) : { : struct ieee80211com *ic = &sc->sc_ic; : struct ieee80211_node *ni = ic->ic_bss; :@@ -26535,6 +26528,25 @@ qwx_run(struct qwx_softc *sc) : IEEE80211_ADDR_COPY(arvif->bssid, ni->ni_bssid); : sc->bss_peer_id = nq->peer_id; : :+ /* :+ * Enable reception of data frames now, if not already enabled. :+ * We may need to receive EAPOL data frames very soon after the :+ * AP sends a response to our assoc request. :+ */ :+ sc->ops.irq_enable(sc); :+ :+ return 0; :+} :+ :+int :+qwx_run(struct qwx_softc *sc) :+{ :+ struct ieee80211com *ic = &sc->sc_ic; :+ struct ieee80211_node *ni = ic->ic_bss; :+ struct qwx_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */ :+ uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */ :+ int ret; :+ : ret = qwx_wmi_vdev_up(sc, arvif->vdev_id, pdev_id, arvif->aid, : arvif->bssid, NULL, 0, 0); : if (ret) { :@@ -26559,7 +26571,6 @@ qwx_run(struct qwx_softc *sc) : return ret; : } : :- sc->ops.irq_enable(sc); : return 0; : } : :@@ -26569,11 +26580,20 @@ qwx_run_stop(struct qwx_softc *sc) : struct ieee80211com *ic = &sc->sc_ic; : struct qwx_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */ : uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */ :- struct qwx_node *nq = (void *)ic->ic_bss; :+ struct ieee80211_node *ni = ic->ic_bss; :+ struct qwx_node *nq = (void *)ni; : int ret; : : sc->ops.irq_disable(sc); : :+ ret = qwx_wmi_set_peer_param(sc, ni->ni_macaddr, arvif->vdev_id, :+ pdev_id, WMI_PEER_AUTHORIZE, 0); :+ if (ret) { :+ printf("%s: unable to deauthorize BSS peer: %d\n", :+ sc->sc_dev.dv_xname, ret); :+ return ret; :+ } :+ : if (ic->ic_opmode == IEEE80211_M_STA) { : ic->ic_bss->ni_txrate = 0; : nq->flags = 0; : -- In Corning, Iowa, it's a misdemeanor for a man to ask his wife to ride in any motor vehicle.