Do not start another connect work while one is pending

It was possible for the connect or sme-connect radio work to get
re-scheduled while an earlier request was still pending, e.g.,
select_network is issued at the moment a scan radio work is in progress
and the old scan results are recent enough for starting the connection.
This could result in unexpected attempt to re-associate immediately
after completing the first connection.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2014-02-24 15:22:35 +02:00 committed by Jouni Malinen
parent 47c549fd8e
commit f0e30c8410
3 changed files with 25 additions and 0 deletions

View file

@ -475,6 +475,11 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
return; return;
} }
if (radio_work_pending(wpa_s, "sme-connect")) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since pending work exist");
return;
}
cwork = os_zalloc(sizeof(*cwork)); cwork = os_zalloc(sizeof(*cwork));
if (cwork == NULL) if (cwork == NULL)
return; return;

View file

@ -1366,6 +1366,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return; return;
} }
if (radio_work_pending(wpa_s, "connect")) {
wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
return;
}
cwork = os_zalloc(sizeof(*cwork)); cwork = os_zalloc(sizeof(*cwork));
if (cwork == NULL) if (cwork == NULL)
return; return;
@ -3237,6 +3242,20 @@ void radio_work_done(struct wpa_radio_work *work)
} }
int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
{
struct wpa_radio_work *work;
struct wpa_radio *radio = wpa_s->radio;
dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
return 1;
}
return 0;
}
static int wpas_init_driver(struct wpa_supplicant *wpa_s, static int wpas_init_driver(struct wpa_supplicant *wpa_s,
struct wpa_interface *iface) struct wpa_interface *iface)
{ {

View file

@ -308,6 +308,7 @@ void radio_work_done(struct wpa_radio_work *work);
void radio_remove_works(struct wpa_supplicant *wpa_s, void radio_remove_works(struct wpa_supplicant *wpa_s,
const char *type, int remove_all); const char *type, int remove_all);
void radio_work_check_next(struct wpa_supplicant *wpa_s); void radio_work_check_next(struct wpa_supplicant *wpa_s);
int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type);
struct wpa_connect_work { struct wpa_connect_work {
unsigned int sme:1; unsigned int sme:1;