nl80211: Remove AP mode interface from bridge for STA-mode-scan
Linux bridging code does not allow a station mode WLAN interface in a bridge and this prevents the AP mode scan workaround from working if the AP interface is in a bridge and scanning can be only done by moving to STA mode. Extend this workaround to remove the interface from the bridge temporarily for the duration of the scan, i.e., for the same duration as the interface needs to be moved into the station. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
7adea21d2f
commit
04030e8c0d
4 changed files with 43 additions and 10 deletions
|
@ -6274,6 +6274,20 @@ static int wpa_driver_nl80211_set_mode_impl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i == 0 && was_ap && !is_ap_interface(nlmode) &&
|
||||||
|
bss->brname[0] &&
|
||||||
|
(bss->added_if_into_bridge || bss->already_in_bridge)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Remove AP interface %s temporarily from the bridge %s to allow its mode to be set to STATION",
|
||||||
|
bss->ifname, bss->brname);
|
||||||
|
if (linux_br_del_if(drv->global->ioctl_sock,
|
||||||
|
bss->brname, bss->ifname) < 0)
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"nl80211: Failed to remove interface %s from bridge %s: %s",
|
||||||
|
bss->ifname, bss->brname,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to set the mode again while the interface is down */
|
/* Try to set the mode again while the interface is down */
|
||||||
mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
|
mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
|
||||||
if (mode_switch_res == -EBUSY) {
|
if (mode_switch_res == -EBUSY) {
|
||||||
|
@ -6346,6 +6360,29 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void nl80211_restore_ap_mode(struct i802_bss *bss)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
int was_ap = is_ap_interface(drv->nlmode);
|
||||||
|
|
||||||
|
wpa_driver_nl80211_set_mode(bss, drv->ap_scan_as_station);
|
||||||
|
if (!was_ap && is_ap_interface(drv->ap_scan_as_station) &&
|
||||||
|
bss->brname[0] &&
|
||||||
|
(bss->added_if_into_bridge || bss->already_in_bridge)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Add AP interface %s back into the bridge %s",
|
||||||
|
bss->ifname, bss->brname);
|
||||||
|
if (linux_br_add_if(drv->global->ioctl_sock, bss->brname,
|
||||||
|
bss->ifname) < 0) {
|
||||||
|
wpa_printf(MSG_WARNING,
|
||||||
|
"nl80211: Failed to add interface %s into bridge %s: %s",
|
||||||
|
bss->ifname, bss->brname, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
|
int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
|
||||||
enum nl80211_iftype nlmode)
|
enum nl80211_iftype nlmode)
|
||||||
{
|
{
|
||||||
|
|
|
@ -275,6 +275,8 @@ int process_bss_event(struct nl_msg *msg, void *arg);
|
||||||
|
|
||||||
const char * nl80211_iftype_str(enum nl80211_iftype mode);
|
const char * nl80211_iftype_str(enum nl80211_iftype mode);
|
||||||
|
|
||||||
|
void nl80211_restore_ap_mode(struct i802_bss *bss);
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
int android_nl_socket_set_nonblocking(struct nl_sock *handle);
|
int android_nl_socket_set_nonblocking(struct nl_sock *handle);
|
||||||
int android_pno_start(struct i802_bss *bss,
|
int android_pno_start(struct i802_bss *bss,
|
||||||
|
|
|
@ -2581,11 +2581,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
|
|
||||||
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
|
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
|
||||||
(cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
|
(cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
|
||||||
cmd == NL80211_CMD_SCAN_ABORTED)) {
|
cmd == NL80211_CMD_SCAN_ABORTED))
|
||||||
wpa_driver_nl80211_set_mode(drv->first_bss,
|
nl80211_restore_ap_mode(bss);
|
||||||
drv->ap_scan_as_station);
|
|
||||||
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case NL80211_CMD_TRIGGER_SCAN:
|
case NL80211_CMD_TRIGGER_SCAN:
|
||||||
|
|
|
@ -166,11 +166,8 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
|
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
|
||||||
|
|
||||||
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
|
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
|
||||||
wpa_driver_nl80211_set_mode(drv->first_bss,
|
nl80211_restore_ap_mode(drv->first_bss);
|
||||||
drv->ap_scan_as_station);
|
|
||||||
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
|
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
|
||||||
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
||||||
|
|
Loading…
Reference in a new issue