]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/wpa_supplicant.c
TDLS: Get TDLS related capabilities from driver
[thirdparty/hostap.git] / wpa_supplicant / wpa_supplicant.c
index 3d1fa9bae70b5f9133b5a7f60b2aa5f3844434e0..058feed1e80de044353ef7830626c936a3da3d41 100644 (file)
@@ -36,7 +36,6 @@
 #include "rsn_supp/preauth.h"
 #include "rsn_supp/pmksa_cache.h"
 #include "common/wpa_ctrl.h"
-#include "mlme.h"
 #include "common/ieee802_11_defs.h"
 #include "p2p/p2p.h"
 #include "blacklist.h"
@@ -371,6 +370,22 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
 }
 
 
+static void free_hw_features(struct wpa_supplicant *wpa_s)
+{
+       int i;
+       if (wpa_s->hw.modes == NULL)
+               return;
+
+       for (i = 0; i < wpa_s->hw.num_modes; i++) {
+               os_free(wpa_s->hw.modes[i].channels);
+               os_free(wpa_s->hw.modes[i].rates);
+       }
+
+       os_free(wpa_s->hw.modes);
+       wpa_s->hw.modes = NULL;
+}
+
+
 static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 {
        bgscan_deinit(wpa_s);
@@ -420,8 +435,6 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        wpa_supplicant_cancel_scan(wpa_s);
        wpa_supplicant_cancel_auth_timeout(wpa_s);
 
-       ieee80211_sta_deinit(wpa_s);
-
        wpas_wps_deinit(wpa_s);
 
        wpabuf_free(wpa_s->pending_eapol_rx);
@@ -446,11 +459,15 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        offchannel_deinit(wpa_s);
 #endif /* CONFIG_OFFCHANNEL */
 
+       wpa_supplicant_cancel_sched_scan(wpa_s);
+
        os_free(wpa_s->next_scan_freqs);
        wpa_s->next_scan_freqs = NULL;
 
        gas_query_deinit(wpa_s->gas);
        wpa_s->gas = NULL;
+
+       free_hw_features(wpa_s);
 }
 
 
@@ -1176,6 +1193,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                        wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
                os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
        }
+       wpa_supplicant_cancel_sched_scan(wpa_s);
        wpa_supplicant_cancel_scan(wpa_s);
 
        /* Starting new association, so clear the possibly used WPA IE from the
@@ -1286,6 +1304,22 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        }
 #endif /* CONFIG_P2P */
 
+#ifdef CONFIG_INTERWORKING
+       if (wpa_s->conf->interworking) {
+               u8 *pos = wpa_ie;
+               if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
+                       pos += 2 + pos[1];
+               os_memmove(pos + 6, pos, wpa_ie_len - (pos - wpa_ie));
+               wpa_ie_len += 6;
+               *pos++ = WLAN_EID_EXT_CAPAB;
+               *pos++ = 4;
+               *pos++ = 0x00;
+               *pos++ = 0x00;
+               *pos++ = 0x00;
+               *pos++ = 0x80; /* Bit 31 - Interworking */
+       }
+#endif /* CONFIG_INTERWORKING */
+
        wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
        use_crypt = 1;
        cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher);
@@ -1386,10 +1420,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        else
                params.uapsd = -1;
 
-       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
-               ret = ieee80211_sta_associate(wpa_s, &params);
-       else
-               ret = wpa_drv_associate(wpa_s, &params);
+       ret = wpa_drv_associate(wpa_s, &params);
        if (ret < 0) {
                wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
                        "failed");
@@ -1495,10 +1526,7 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s,
        u8 *addr = NULL;
 
        if (!is_zero_ether_addr(wpa_s->bssid)) {
-               if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
-                       ieee80211_sta_disassociate(wpa_s, reason_code);
-               else
-                       wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code);
+               wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code);
                addr = wpa_s->bssid;
        }
 
@@ -1520,11 +1548,7 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
        u8 *addr = NULL;
 
        if (!is_zero_ether_addr(wpa_s->bssid)) {
-               if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
-                       ieee80211_sta_deauthenticate(wpa_s, reason_code);
-               else
-                       wpa_drv_deauthenticate(wpa_s, wpa_s->bssid,
-                                              reason_code);
+               wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, reason_code);
                addr = wpa_s->bssid;
        }
 
@@ -1693,6 +1717,16 @@ int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
        if (ap_scan < 0 || ap_scan > 2)
                return -1;
 
+#ifdef ANDROID
+       if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
+           wpa_s->wpa_state >= WPA_ASSOCIATING &&
+           wpa_s->wpa_state < WPA_COMPLETED) {
+               wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
+                          "associating", wpa_s->conf->ap_scan, ap_scan);
+               return 0;
+       }
+#endif /* ANDROID */
+
        old_ap_scan = wpa_s->conf->ap_scan;
        wpa_s->conf->ap_scan = ap_scan;
 
@@ -1805,25 +1839,15 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
        u8 bssid[ETH_ALEN];
        int wired;
 
-       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) {
-               if (ieee80211_sta_get_ssid(wpa_s, ssid, &ssid_len)) {
-                       wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
-                               "MLME");
-                       return NULL;
-               }
-       } else {
-               res = wpa_drv_get_ssid(wpa_s, ssid);
-               if (res < 0) {
-                       wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
-                               "driver");
-                       return NULL;
-               }
-               ssid_len = res;
+       res = wpa_drv_get_ssid(wpa_s, ssid);
+       if (res < 0) {
+               wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
+                       "driver");
+               return NULL;
        }
+       ssid_len = res;
 
-       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
-               os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
-       else if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
+       if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
                wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
                        "driver");
                return NULL;
@@ -1861,6 +1885,26 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
 }
 
 
+static int select_driver(struct wpa_supplicant *wpa_s, int i)
+{
+       struct wpa_global *global = wpa_s->global;
+
+       if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
+               global->drv_priv[i] = wpa_drivers[i]->global_init();
+               if (global->drv_priv[i] == NULL) {
+                       wpa_printf(MSG_ERROR, "Failed to initialize driver "
+                                  "'%s'", wpa_drivers[i]->name);
+                       return -1;
+               }
+       }
+
+       wpa_s->driver = wpa_drivers[i];
+       wpa_s->global_drv_priv = global->drv_priv[i];
+
+       return 0;
+}
+
+
 static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
                                     const char *name)
 {
@@ -1879,9 +1923,7 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
 
        if (name == NULL) {
                /* default to first driver in the list */
-               wpa_s->driver = wpa_drivers[0];
-               wpa_s->global_drv_priv = wpa_s->global->drv_priv[0];
-               return 0;
+               return select_driver(wpa_s, 0);
        }
 
        do {
@@ -1894,12 +1936,8 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
                for (i = 0; wpa_drivers[i]; i++) {
                        if (os_strlen(wpa_drivers[i]->name) == len &&
                            os_strncmp(driver, wpa_drivers[i]->name, len) ==
-                           0) {
-                               wpa_s->driver = wpa_drivers[i];
-                               wpa_s->global_drv_priv =
-                                       wpa_s->global->drv_priv[i];
-                               return 0;
-                       }
+                           0)
+                               return select_driver(wpa_s, i);
                }
 
                driver = pos + 1;
@@ -2087,7 +2125,10 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
 
        wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
        if (wpa_supplicant_enabled_networks(wpa_s->conf)) {
-               wpa_supplicant_req_scan(wpa_s, interface_count, 100000);
+               if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
+                                                     100000))
+                       wpa_supplicant_req_scan(wpa_s, interface_count,
+                                               100000);
                interface_count++;
        } else
                wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
@@ -2272,15 +2313,17 @@ next_driver:
                return -1;
        }
 
+       wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
+                                                     &wpa_s->hw.num_modes,
+                                                     &wpa_s->hw.flags);
+
        if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
+               wpa_s->drv_capa_known = 1;
                wpa_s->drv_flags = capa.flags;
-               if (capa.flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) {
-                       if (ieee80211_sta_init(wpa_s))
-                               return -1;
-               }
                wpa_s->max_scan_ssids = capa.max_scan_ssids;
                wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
                wpa_s->sched_scan_supported = capa.sched_scan_supported;
+               wpa_s->max_match_sets = capa.max_match_sets;
                wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
                wpa_s->max_stations = capa.max_stations;
        }
@@ -2619,17 +2662,6 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
                wpa_supplicant_deinit(global);
                return NULL;
        }
-       for (i = 0; wpa_drivers[i]; i++) {
-               if (!wpa_drivers[i]->global_init)
-                       continue;
-               global->drv_priv[i] = wpa_drivers[i]->global_init();
-               if (global->drv_priv[i] == NULL) {
-                       wpa_printf(MSG_ERROR, "Failed to initialize driver "
-                                  "'%s'", wpa_drivers[i]->name);
-                       wpa_supplicant_deinit(global);
-                       return NULL;
-               }
-       }
 
        return global;
 }
@@ -2750,23 +2782,6 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
 }
 
 
-void ieee80211_sta_free_hw_features(struct hostapd_hw_modes *hw_features,
-                                   size_t num_hw_features)
-{
-       size_t i;
-
-       if (hw_features == NULL)
-               return;
-
-       for (i = 0; i < num_hw_features; i++) {
-               os_free(hw_features[i].channels);
-               os_free(hw_features[i].rates);
-       }
-
-       os_free(hw_features);
-}
-
-
 static void add_freq(int *freqs, int *num_freqs, int freq)
 {
        int i;