driver_ndis: Added a workaround for a driver that removes SSID IE in scan
[libeap.git] / src / drivers / driver_ndis.c
index baa95e6..e245b30 100644 (file)
@@ -40,7 +40,9 @@ int close(int fd);
 #include "driver_ndis.h"
 
 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
+#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
 void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data);
+#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
 
 static void wpa_driver_ndis_deinit(void *priv);
 static void wpa_driver_ndis_poll(void *drv);
@@ -729,6 +731,32 @@ static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len)
 }
 
 
+static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid(
+       struct wpa_scan_res *r, NDIS_802_11_SSID *ssid)
+{
+       struct wpa_scan_res *nr;
+       u8 *pos;
+
+       if (wpa_scan_get_ie(r, WLAN_EID_SSID))
+               return r; /* SSID IE already present */
+
+       if (ssid->SsidLength == 0 || ssid->SsidLength > 32)
+               return r; /* No valid SSID inside scan data */
+
+       nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength);
+       if (nr == NULL)
+               return r;
+
+       pos = ((u8 *) (nr + 1)) + nr->ie_len;
+       *pos++ = WLAN_EID_SSID;
+       *pos++ = ssid->SsidLength;
+       os_memcpy(pos, ssid->Ssid, ssid->SsidLength);
+       nr->ie_len += 2 + ssid->SsidLength;
+
+       return nr;
+}
+
+
 static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv)
 {
        struct wpa_driver_ndis_data *drv = priv;
@@ -802,6 +830,7 @@ static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv)
                os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs),
                          bss->IELength - sizeof(NDIS_802_11_FIXED_IEs));
                r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
+               r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid);
 
                results->res[results->num++] = r;
 
@@ -1175,6 +1204,7 @@ static int wpa_driver_ndis_flush_pmkid(void *priv)
        struct wpa_driver_ndis_data *drv = priv;
        NDIS_802_11_PMKID p;
        struct ndis_pmkid_entry *pmkid, *prev;
+       int prev_authmode, ret;
 
        if (drv->no_of_pmkid == 0)
                return 0;
@@ -1187,12 +1217,25 @@ static int wpa_driver_ndis_flush_pmkid(void *priv)
                os_free(prev);
        }
 
+       /*
+        * Some drivers may refuse OID_802_11_PMKID if authMode is not set to
+        * WPA2, so change authMode temporarily, if needed.
+        */
+       prev_authmode = ndis_get_auth_mode(drv);
+       if (prev_authmode != Ndis802_11AuthModeWPA2)
+               ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2);
+
        os_memset(&p, 0, sizeof(p));
        p.Length = 8;
        p.BSSIDInfoCount = 0;
        wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
                    (char *) &p, 8);
-       return ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
+       ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
+
+       if (prev_authmode != Ndis802_11AuthModeWPA2)
+               ndis_set_auth_mode(drv, prev_authmode);
+
+       return ret;
 }
 
 
@@ -2827,5 +2870,7 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
        NULL /* mlme_remove_sta */,
        NULL /* update_ft_ies */,
        NULL /* send_ft_action */,
-       wpa_driver_ndis_get_scan_results
+       wpa_driver_ndis_get_scan_results,
+       NULL /* set_probe_req_ie */,
+       NULL /* set_mode */
 };