]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Fix AP scan with STA fallback error path
authorNicolas Escande <nico.escande@gmail.com>
Fri, 26 Apr 2024 12:35:53 +0000 (14:35 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 12 Jul 2024 13:44:30 +0000 (16:44 +0300)
I've run into a case where I can bring a 2.4 GHz AP up without it being
in a bridge while I used the 'bridge=' config option. This happens when
the HT scan needed for 40 MHz operation failed to start from the get go
because another dev on the same phy was already in a scan. At the end
the AP is up and running but not added into any bridge.

Upon looking at the code, it seems that some hardware fails to issue a
scan while in AP and thus we have a fallback that switches the interface
from AP to STA before retrying another scan (it will change it back to
AP later on when finished). As we cannot have a (non-WDS) STA in a
bridge, during that procedure, we also remove/add the AP/STA from/to the
bridge as needed.

However, in wpa_driver_nl80211_scan() we do not set
drv->ap_scan_as_station until the end of the switch-to-sta &
retry-scan-start block. This means that when the recursive call to
wpa_driver_nl80211_scan() fails (the hardware is busy in my case) we
restore the interface to AP with wpa_driver_nl80211_set_mode() but that
will not add it back to the bridge. Problem.

To fix this lets always set drv->ap_scan_as_station before calling
wpa_driver_nl80211_set_mode(). In case wpa_driver_nl80211_set_mode() or
wpa_driver_nl80211_scan() fails lets call nl80211_restore_ap_mode() that
will set the mode back to AP but also handle the bridge thing as needed.

Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
src/drivers/driver_nl80211_scan.c

index 1eb4374052e53aaf787ec2c8549b5b9ebd2ac6b2..b055e684a9f865b4dee48672f60455ff92074afd 100644 (file)
@@ -402,23 +402,18 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
                wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
                           "(%s)", ret, strerror(-ret));
                if (drv->hostapd && is_ap_interface(drv->nlmode)) {
-                       enum nl80211_iftype old_mode = drv->nlmode;
-
                        /*
                         * mac80211 does not allow scan requests in AP mode, so
                         * try to do this in station mode.
                         */
+                       drv->ap_scan_as_station = drv->nlmode;
                        if (wpa_driver_nl80211_set_mode(
-                                   bss, NL80211_IFTYPE_STATION))
-                               goto fail;
-
-                       if (wpa_driver_nl80211_scan(bss, params)) {
-                               wpa_driver_nl80211_set_mode(bss, old_mode);
+                                   bss, NL80211_IFTYPE_STATION) ||
+                           wpa_driver_nl80211_scan(bss, params)) {
+                               nl80211_restore_ap_mode(bss);
                                goto fail;
                        }
 
-                       /* Restore AP mode when processing scan results */
-                       drv->ap_scan_as_station = old_mode;
                        ret = 0;
                } else
                        goto fail;