Do not start another connect work while one is pending
authorJouni Malinen <jouni@qca.qualcomm.com>
Mon, 24 Feb 2014 13:22:35 +0000 (15:22 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 24 Feb 2014 13:22:35 +0000 (15:22 +0200)
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>
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index e712ac4..5ce9da7 100644 (file)
@@ -475,6 +475,11 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
                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));
        if (cwork == NULL)
                return;
index e942b62..60e7a66 100644 (file)
@@ -1366,6 +1366,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                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));
        if (cwork == NULL)
                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,
                            struct wpa_interface *iface)
 {
index bcdb4d0..3dcc900 100644 (file)
@@ -308,6 +308,7 @@ void radio_work_done(struct wpa_radio_work *work);
 void radio_remove_works(struct wpa_supplicant *wpa_s,
                        const char *type, int remove_all);
 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 {
        unsigned int sme:1;