wext: Add cfg80211-specific optimization to avoid silly behavior
authorJouni Malinen <j@w1.fi>
Tue, 12 Jan 2010 18:01:09 +0000 (20:01 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 12 Jan 2010 18:01:09 +0000 (20:01 +0200)
If the driver is detected to use cfg80211, we can rely on it being able
to disconnect with SIOCSIWMLME commands and to use empty SSID as a way
to stop it from associating when we are in progress of configuring the
driver for association. Consequently, we can remove the hack that uses
random 32-octet SSID to force disconnection and re-order association
commands to match the expectations that cfg80211 has for WEXT ioctls.
This gets rid of extra scan rounds and attempts to associate with the
silly 32-octet SSID.

src/drivers/driver_wext.c
src/drivers/driver_wext.h

index 3fe1329..2614f23 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant - driver interaction with generic Linux Wireless Extensions
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Driver interaction with generic Linux Wireless Extensions
+ * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -20,6 +20,7 @@
 
 #include "includes.h"
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <net/if_arp.h>
 
 #include "wireless_copy.h"
@@ -697,6 +698,8 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
 {
        struct wpa_driver_wext_data *drv;
        struct netlink_config *cfg;
+       char path[128];
+       struct stat buf;
 
        drv = os_zalloc(sizeof(*drv));
        if (drv == NULL)
@@ -704,6 +707,12 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
        drv->ctx = ctx;
        os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
 
+       os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);
+       if (stat(path, &buf) == 0) {
+               wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected");
+               drv->cfg80211 = 1;
+       }
+
        drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
        if (drv->ioctl_sock < 0) {
                perror("socket(PF_INET,SOCK_DGRAM)");
@@ -1709,6 +1718,19 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
        }
 
        if (iwr.u.mode == IW_MODE_INFRA) {
+               if (drv->cfg80211) {
+                       /*
+                        * cfg80211 supports SIOCSIWMLME commands, so there is
+                        * no need for the random SSID hack, but clear the
+                        * BSSID and SSID.
+                        */
+                       if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 ||
+                           wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
+                               wpa_printf(MSG_DEBUG, "WEXT: Failed to clear "
+                                          "to disconnect");
+                       }
+                       return;
+               }
                /*
                 * Clear the BSSID selection and set a random SSID to make sure
                 * the driver will not be trying to associate with something
@@ -1858,6 +1880,14 @@ int wpa_driver_wext_associate(void *priv,
 
        wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
+       if (drv->cfg80211) {
+               /*
+                * Stop cfg80211 from trying to associate before we are done
+                * with all parameters.
+                */
+               wpa_driver_wext_set_ssid(drv, (u8 *) "", 0);
+       }
+
        if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted)
            < 0)
                ret = -1;
@@ -1945,11 +1975,15 @@ int wpa_driver_wext_associate(void *priv,
 #endif /* CONFIG_IEEE80211W */
        if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0)
                ret = -1;
-       if (wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
+       if (!drv->cfg80211 &&
+           wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
                ret = -1;
        if (params->bssid &&
            wpa_driver_wext_set_bssid(drv, params->bssid) < 0)
                ret = -1;
+       if (drv->cfg80211 &&
+           wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
+               ret = -1;
 
        return ret;
 }
index 81ec25f..602c7e1 100644 (file)
@@ -43,6 +43,8 @@ struct wpa_driver_wext_data {
        char mlmedev[IFNAMSIZ + 1];
 
        int scan_complete_events;
+
+       int cfg80211; /* whether driver is using cfg80211 */
 };
 
 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid);