Reset external_scan_running on interface deletion
Currently, the external_scan_running flag is not reset when an interface is removed. Thus, if a connection attempt is made on another iface, it will fail due to wpa_supplicant incorrectly assuming the radio is still busy due to the ongoing scan. To fix this, convert external_scan_running to a pointer to the interface that started the scan. If this interface is removed, also reset the pointer to NULL so that other operations may continue on this radio. Test: 1. Start scan on wlan0 2. Remove wlan0 3. Can connect to a network on wlan1 Signed-off-by: David Su <dysu@google.com>
This commit is contained in:
parent
630b1fdba8
commit
11355a122d
4 changed files with 23 additions and 8 deletions
|
@ -4792,7 +4792,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
}
|
||||
} else {
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
|
||||
wpa_s->radio->external_scan_running = 1;
|
||||
wpa_s->radio->external_scan_req_interface = wpa_s;
|
||||
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
|
||||
}
|
||||
break;
|
||||
|
@ -4800,7 +4800,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
|
||||
wpa_s->scan_res_handler = NULL;
|
||||
wpa_s->own_scan_running = 0;
|
||||
wpa_s->radio->external_scan_running = 0;
|
||||
wpa_s->radio->external_scan_req_interface = NULL;
|
||||
wpa_s->last_scan_req = NORMAL_SCAN_REQ;
|
||||
break;
|
||||
}
|
||||
|
@ -4820,7 +4820,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
if (!(data && data->scan_info.external_scan))
|
||||
wpa_s->own_scan_running = 0;
|
||||
if (data && data->scan_info.nl_scan_event)
|
||||
wpa_s->radio->external_scan_running = 0;
|
||||
wpa_s->radio->external_scan_req_interface = NULL;
|
||||
radio_work_check_next(wpa_s);
|
||||
break;
|
||||
#endif /* CONFIG_NO_SCAN_PROCESSING */
|
||||
|
|
|
@ -247,7 +247,7 @@ static void wpas_p2p_scan_res_handled(struct wpa_supplicant *wpa_s)
|
|||
unsigned int delay = wpas_p2p_search_delay(wpa_s);
|
||||
|
||||
/* In case of concurrent P2P and external scans, delay P2P search. */
|
||||
if (wpa_s->radio->external_scan_running) {
|
||||
if (external_scan_running(wpa_s->radio)) {
|
||||
delay = wpa_s->conf->p2p_search_delay;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"P2P: Delay next P2P search by %d ms to let externally triggered scan complete",
|
||||
|
|
|
@ -5868,7 +5868,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
|
|||
dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
|
||||
list) {
|
||||
if (os_strcmp(tmp->type, "scan") == 0 &&
|
||||
radio->external_scan_running &&
|
||||
external_scan_running(radio) &&
|
||||
(((struct wpa_driver_scan_params *)
|
||||
tmp->ctx)->only_new_results ||
|
||||
tmp->wpa_s->clear_driver_scan_cache))
|
||||
|
@ -5924,7 +5924,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
|
|||
* rejected by kernel.
|
||||
*/
|
||||
if (os_strcmp(tmp->type, "scan") == 0 &&
|
||||
radio->external_scan_running &&
|
||||
external_scan_running(radio) &&
|
||||
(((struct wpa_driver_scan_params *)
|
||||
tmp->ctx)->only_new_results ||
|
||||
tmp->wpa_s->clear_driver_scan_cache))
|
||||
|
@ -5963,7 +5963,7 @@ static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
|
|||
if (work->started)
|
||||
return; /* already started and still in progress */
|
||||
|
||||
if (wpa_s && wpa_s->radio->external_scan_running) {
|
||||
if (wpa_s && external_scan_running(wpa_s->radio)) {
|
||||
wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
|
||||
return;
|
||||
}
|
||||
|
@ -6059,6 +6059,10 @@ static void radio_remove_interface(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->ifname, radio->name);
|
||||
dl_list_del(&wpa_s->radio_list);
|
||||
radio_remove_works(wpa_s, NULL, 0);
|
||||
/* If the interface that triggered the external scan was removed, the
|
||||
* external scan is no longer running. */
|
||||
if (wpa_s == radio->external_scan_req_interface)
|
||||
radio->external_scan_req_interface = NULL;
|
||||
wpa_s->radio = NULL;
|
||||
if (!dl_list_empty(&radio->ifaces))
|
||||
return; /* Interfaces remain for this radio */
|
||||
|
|
|
@ -332,12 +332,23 @@ struct wpa_global {
|
|||
struct wpa_radio {
|
||||
char name[16]; /* from driver_ops get_radio_name() or empty if not
|
||||
* available */
|
||||
unsigned int external_scan_running:1;
|
||||
/** NULL if no external scan running. */
|
||||
struct wpa_supplicant *external_scan_req_interface;
|
||||
unsigned int num_active_works;
|
||||
struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
|
||||
struct dl_list work; /* struct wpa_radio_work::list entries */
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether an external scan is running on a given radio.
|
||||
* @radio: Pointer to radio struct
|
||||
* Returns: true if an external scan is running, false otherwise.
|
||||
*/
|
||||
static inline bool external_scan_running(struct wpa_radio *radio)
|
||||
{
|
||||
return radio && radio->external_scan_req_interface;
|
||||
}
|
||||
|
||||
#define MAX_ACTIVE_WORKS 2
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue