Preparations for v0.7.1 release
[libeap.git] / wpa_supplicant / wpa_supplicant.c
index f715000..d62937b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant
- * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
+ * 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
@@ -22,7 +22,7 @@
 #include "eapol_supp/eapol_supp_sm.h"
 #include "eap_peer/eap.h"
 #include "eap_server/eap_methods.h"
-#include "wpa.h"
+#include "rsn_supp/wpa.h"
 #include "eloop.h"
 #include "config.h"
 #include "l2_packet/l2_packet.h"
 #include "driver_i.h"
 #include "ctrl_iface.h"
 #include "pcsc_funcs.h"
-#include "version.h"
-#include "preauth.h"
-#include "pmksa_cache.h"
-#include "wpa_ctrl.h"
+#include "common/version.h"
+#include "rsn_supp/preauth.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "common/wpa_ctrl.h"
 #include "mlme.h"
-#include "ieee802_11_defs.h"
+#include "common/ieee802_11_defs.h"
 #include "blacklist.h"
 #include "wpas_glue.h"
 #include "wps_supplicant.h"
 #include "ap.h"
 #include "notify.h"
 #include "bgscan.h"
+#include "bss.h"
+#include "scan.h"
 
 const char *wpa_supplicant_version =
 "wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi> and contributors";
 
 const char *wpa_supplicant_license =
 "This program is free software. You can distribute it and/or modify it\n"
@@ -143,13 +145,13 @@ static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
 {
        u8 key[32];
        size_t keylen;
-       wpa_alg alg;
+       enum wpa_alg alg;
        u8 seq[6] = { 0 };
 
        /* IBSS/WPA-None uses only one key (Group) for both receiving and
         * sending unicast and multicast packets. */
 
-       if (ssid->mode != IEEE80211_MODE_IBSS) {
+       if (ssid->mode != WPAS_MODE_IBSS) {
                wpa_printf(MSG_INFO, "WPA: Invalid mode %d (not IBSS/ad-hoc) "
                           "for WPA-None", ssid->mode);
                return -1;
@@ -256,7 +258,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
        struct wpa_ssid *ssid = wpa_s->current_ssid;
 
 #ifdef CONFIG_IBSS_RSN
-       if (ssid->mode == IEEE80211_MODE_IBSS &&
+       if (ssid->mode == WPAS_MODE_IBSS &&
            wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
            wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
                /*
@@ -378,6 +380,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
                wpa_s->ctrl_iface = NULL;
        }
        if (wpa_s->conf != NULL) {
+               struct wpa_ssid *ssid;
+               for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
+                       wpas_notify_network_removed(wpa_s, ssid);
                wpa_config_free(wpa_s->conf);
                wpa_s->conf = NULL;
        }
@@ -396,8 +401,7 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        wpa_s->wpa = NULL;
        wpa_blacklist_clear(wpa_s);
 
-       wpa_scan_results_free(wpa_s->scan_res);
-       wpa_s->scan_res = NULL;
+       wpa_bss_deinit(wpa_s);
 
        wpa_supplicant_cancel_scan(wpa_s);
        wpa_supplicant_cancel_auth_timeout(wpa_s);
@@ -478,7 +482,7 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
  * @state: State (wpa_state; WPA_*)
  * Returns: The state name as a printable text string
  */
-const char * wpa_supplicant_state_txt(int state)
+const char * wpa_supplicant_state_txt(enum wpa_states state)
 {
        switch (state) {
        case WPA_DISCONNECTED:
@@ -513,8 +517,11 @@ const char * wpa_supplicant_state_txt(int state)
  * This function is called whenever the connection state changes, e.g.,
  * association is completed for WPA/WPA2 4-Way Handshake is started.
  */
-void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
+void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
+                             enum wpa_states state)
 {
+       enum wpa_states old_state = wpa_s->wpa_state;
+
        wpa_printf(MSG_DEBUG, "State: %s -> %s",
                   wpa_supplicant_state_txt(wpa_s->wpa_state),
                   wpa_supplicant_state_txt(state));
@@ -522,8 +529,6 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
        if (state != WPA_SCANNING)
                wpa_supplicant_notify_scanning(wpa_s, 0);
 
-       wpas_notify_state_changed(wpa_s, state, wpa_s->wpa_state);
-
        if (state == WPA_COMPLETED && wpa_s->new_connection) {
 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
                struct wpa_ssid *ssid = wpa_s->current_ssid;
@@ -543,31 +548,53 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
                wpa_drv_set_operstate(wpa_s, 0);
        }
        wpa_s->wpa_state = state;
+
+       if (wpa_s->wpa_state != old_state)
+               wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
 }
 
 
-static void wpa_supplicant_terminate(int sig, void *eloop_ctx,
-                                    void *signal_ctx)
+void wpa_supplicant_terminate_proc(struct wpa_global *global)
 {
-       struct wpa_global *global = eloop_ctx;
+       int pending = 0;
+#ifdef CONFIG_WPS
+       struct wpa_supplicant *wpa_s = global->ifaces;
+       while (wpa_s) {
+               if (wpas_wps_terminate_pending(wpa_s) == 1)
+                       pending = 1;
+               wpa_s = wpa_s->next;
+       }
+#endif /* CONFIG_WPS */
+       if (pending)
+               return;
+       eloop_terminate();
+}
+
+
+static void wpa_supplicant_terminate(int sig, void *signal_ctx)
+{
+       struct wpa_global *global = signal_ctx;
        struct wpa_supplicant *wpa_s;
        for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
                wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING "- signal %d "
                        "received", sig);
        }
-       eloop_terminate();
+       wpa_supplicant_terminate_proc(global);
 }
 
 
 static void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
 {
-       wpa_states old_state = wpa_s->wpa_state;
+       enum wpa_states old_state = wpa_s->wpa_state;
+
        wpa_s->pairwise_cipher = 0;
        wpa_s->group_cipher = 0;
        wpa_s->mgmt_group_cipher = 0;
        wpa_s->key_mgmt = 0;
        wpa_s->wpa_state = WPA_DISCONNECTED;
-       wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
+
+       if (wpa_s->wpa_state != old_state)
+               wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
 }
 
 
@@ -647,21 +674,20 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
 }
 
 
-static void wpa_supplicant_reconfig(int sig, void *eloop_ctx,
-                                   void *signal_ctx)
+static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
 {
-       struct wpa_global *global = eloop_ctx;
+       struct wpa_global *global = signal_ctx;
        struct wpa_supplicant *wpa_s;
        wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig);
        for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
                if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
-                       eloop_terminate();
+                       wpa_supplicant_terminate_proc(global);
                }
        }
 }
 
 
-static wpa_cipher cipher_suite2driver(int cipher)
+static enum wpa_cipher cipher_suite2driver(int cipher)
 {
        switch (cipher) {
        case WPA_CIPHER_NONE:
@@ -679,7 +705,7 @@ static wpa_cipher cipher_suite2driver(int cipher)
 }
 
 
-static wpa_key_mgmt key_mgmt2driver(int key_mgmt)
+static enum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
 {
        switch (key_mgmt) {
        case WPA_KEY_MGMT_NONE:
@@ -743,7 +769,7 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_IEEE80211W
        if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
-           ssid->ieee80211w == IEEE80211W_REQUIRED) {
+           ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
                wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
                        "that does not support management frame protection - "
                        "reject");
@@ -770,8 +796,7 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
  * available).
  */
 int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
-                             struct wpa_scan_res *bss,
-                             struct wpa_ssid *ssid,
+                             struct wpa_bss *bss, struct wpa_ssid *ssid,
                              u8 *wpa_ie, size_t *wpa_ie_len)
 {
        struct wpa_ie_data ie;
@@ -779,8 +804,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
        const u8 *bss_wpa, *bss_rsn;
 
        if (bss) {
-               bss_wpa = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
-               bss_rsn = wpa_scan_get_ie(bss, WLAN_EID_RSN);
+               bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+               bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
        } else
                bss_wpa = bss_rsn = NULL;
 
@@ -813,7 +838,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                        ie.key_mgmt = ssid->key_mgmt;
 #ifdef CONFIG_IEEE80211W
                        ie.mgmt_group_cipher =
-                               ssid->ieee80211w != NO_IEEE80211W ?
+                               ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
                                WPA_CIPHER_AES_128_CMAC : 0;
 #endif /* CONFIG_IEEE80211W */
                        wpa_printf(MSG_DEBUG, "WPA: Set cipher suites based "
@@ -920,7 +945,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_IEEE80211W
        sel = ie.mgmt_group_cipher;
-       if (ssid->ieee80211w == NO_IEEE80211W ||
+       if (ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION ||
            !(ie.capabilities & WPA_CAPABILITY_MFPC))
                sel = 0;
        if (sel & WPA_CIPHER_AES_128_CMAC) {
@@ -959,20 +984,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
  * This function is used to request %wpa_supplicant to associate with a BSS.
  */
 void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
-                             struct wpa_scan_res *bss, struct wpa_ssid *ssid)
+                             struct wpa_bss *bss, struct wpa_ssid *ssid)
 {
        u8 wpa_ie[80];
        size_t wpa_ie_len;
        int use_crypt, ret, i, bssid_changed;
-       int algs = AUTH_ALG_OPEN_SYSTEM;
-       wpa_cipher cipher_pairwise, cipher_group;
+       int algs = WPA_AUTH_ALG_OPEN;
+       enum wpa_cipher cipher_pairwise, cipher_group;
        struct wpa_driver_associate_params params;
        int wep_keys_set = 0;
        struct wpa_driver_capa capa;
        int assoc_failed = 0;
        struct wpa_ssid *old_ssid;
 
-       if (ssid->mode == 2) {
+       if (ssid->mode == WPAS_MODE_AP) {
 #ifdef CONFIG_AP
                if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
                        wpa_printf(MSG_INFO, "Driver does not support AP "
@@ -980,6 +1005,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                        return;
                }
                wpa_supplicant_create_ap(wpa_s, ssid);
+               wpa_s->current_bss = bss;
 #else /* CONFIG_AP */
                wpa_printf(MSG_ERROR, "AP mode support not included in the "
                           "build");
@@ -987,7 +1013,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                return;
        }
 
-       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
+       if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+           ssid->mode == IEEE80211_MODE_INFRA) {
                sme_authenticate(wpa_s, bss, ssid);
                return;
        }
@@ -995,19 +1022,18 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        wpa_s->reassociate = 0;
        if (bss) {
 #ifdef CONFIG_IEEE80211R
-               const u8 *md = NULL;
+               const u8 *ie, *md = NULL;
 #endif /* CONFIG_IEEE80211R */
-               const u8 *ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
                wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
                        " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
-                       ie ? wpa_ssid_txt(ie + 2, ie[1]) : "", bss->freq);
+                       wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
                bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
                os_memset(wpa_s->bssid, 0, ETH_ALEN);
                os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
                if (bssid_changed)
                        wpas_notify_bssid_changed(wpa_s);
 #ifdef CONFIG_IEEE80211R
-               ie = wpa_scan_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
+               ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
                if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
                        md = ie + 2;
                wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL);
@@ -1038,37 +1064,25 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
         * previous association. */
        wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
 
-       if (wpa_drv_set_mode(wpa_s, ssid->mode)) {
-               wpa_printf(MSG_WARNING, "Failed to set operating mode");
-               assoc_failed = 1;
-       }
-
 #ifdef IEEE8021X_EAPOL
        if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
                if (ssid->leap) {
                        if (ssid->non_leap == 0)
-                               algs = AUTH_ALG_LEAP;
+                               algs = WPA_AUTH_ALG_LEAP;
                        else
-                               algs |= AUTH_ALG_LEAP;
+                               algs |= WPA_AUTH_ALG_LEAP;
                }
        }
 #endif /* IEEE8021X_EAPOL */
        wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
        if (ssid->auth_alg) {
-               algs = 0;
-               if (ssid->auth_alg & WPA_AUTH_ALG_OPEN)
-                       algs |= AUTH_ALG_OPEN_SYSTEM;
-               if (ssid->auth_alg & WPA_AUTH_ALG_SHARED)
-                       algs |= AUTH_ALG_SHARED_KEY;
-               if (ssid->auth_alg & WPA_AUTH_ALG_LEAP)
-                       algs |= AUTH_ALG_LEAP;
+               algs = ssid->auth_alg;
                wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x",
                           algs);
        }
-       wpa_drv_set_auth_alg(wpa_s, algs);
 
-       if (bss && (wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
-                   wpa_scan_get_ie(bss, WLAN_EID_RSN)) &&
+       if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
+                   wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
            (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK |
                               WPA_KEY_MGMT_FT_IEEE8021X |
                               WPA_KEY_MGMT_FT_PSK |
@@ -1155,20 +1169,19 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
        }
 
-       wpa_drv_set_drop_unencrypted(wpa_s, use_crypt);
        wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
        os_memset(&params, 0, sizeof(params));
        if (bss) {
-               const u8 *ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
                params.bssid = bss->bssid;
-               params.ssid = ie ? ie + 2 : (u8 *) "";
-               params.ssid_len = ie ? ie[1] : 0;
+               params.ssid = bss->ssid;
+               params.ssid_len = bss->ssid_len;
                params.freq = bss->freq;
        } else {
                params.ssid = ssid->ssid;
                params.ssid_len = ssid->ssid_len;
        }
-       if (ssid->mode == 1 && ssid->frequency > 0 && params.freq == 0)
+       if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
+           params.freq == 0)
                params.freq = ssid->frequency; /* Initial channel for IBSS */
        params.wpa_ie = wpa_ie;
        params.wpa_ie_len = wpa_ie_len;
@@ -1195,19 +1208,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        params.drop_unencrypted = use_crypt;
 
 #ifdef CONFIG_IEEE80211W
-       switch (ssid->ieee80211w) {
-       case NO_IEEE80211W:
-               params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
-               break;
-       case IEEE80211W_OPTIONAL:
-               params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_OPTIONAL;
-               break;
-       case IEEE80211W_REQUIRED:
-               params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_REQUIRED;
-               break;
-       }
-       if (ssid->ieee80211w != NO_IEEE80211W && bss) {
-               const u8 *rsn = wpa_scan_get_ie(bss, WLAN_EID_RSN);
+       params.mgmt_frame_protection = ssid->ieee80211w;
+       if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION && bss) {
+               const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
                struct wpa_ie_data ie;
                if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
                    ie.capabilities &
@@ -1241,7 +1244,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                wpa_supplicant_cancel_auth_timeout(wpa_s);
                wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 #ifdef CONFIG_IBSS_RSN
-       } else if (ssid->mode == IEEE80211_MODE_IBSS &&
+       } else if (ssid->mode == WPAS_MODE_IBSS &&
                   wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
                   wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
                ibss_rsn_set_psk(wpa_s->ibss_rsn, ssid->psk);
@@ -1250,7 +1253,6 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                 * per-BSSID authentication.
                 */
                wpa_supplicant_cancel_auth_timeout(wpa_s);
-               wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 #endif /* CONFIG_IBSS_RSN */
        } else {
                /* Timeout for IEEE 802.11 authentication and association */
@@ -1258,10 +1260,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 
                if (assoc_failed) {
                        /* give IBSS a bit more time */
-                       timeout = ssid->mode ? 10 : 5;
+                       timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
                } else if (wpa_s->conf->ap_scan == 1) {
                        /* give IBSS a bit more time */
-                       timeout = ssid->mode ? 20 : 10;
+                       timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
                }
                wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
        }
@@ -1281,6 +1283,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        }
        old_ssid = wpa_s->current_ssid;
        wpa_s->current_ssid = ssid;
+       wpa_s->current_bss = bss;
        wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
        wpa_supplicant_initiate_eapol(wpa_s);
        if (old_ssid != wpa_s->current_ssid)
@@ -1313,6 +1316,7 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s,
        wpa_supplicant_mark_disassoc(wpa_s);
        old_ssid = wpa_s->current_ssid;
        wpa_s->current_ssid = NULL;
+       wpa_s->current_bss = NULL;
        wpa_sm_set_config(wpa_s->wpa, NULL);
        eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
        if (old_ssid != wpa_s->current_ssid)
@@ -1346,6 +1350,7 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
        wpa_supplicant_mark_disassoc(wpa_s);
        old_ssid = wpa_s->current_ssid;
        wpa_s->current_ssid = NULL;
+       wpa_s->current_bss = NULL;
        wpa_sm_set_config(wpa_s->wpa, NULL);
        eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
        if (old_ssid != wpa_s->current_ssid)
@@ -1541,151 +1546,17 @@ int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
        wpa_debug_timestamp = debug_timestamp ? 1 : 0;
        wpa_debug_show_keys = debug_show_keys ? 1 : 0;
 
-       if (wpa_debug_level != old_level ||
-           wpa_debug_timestamp != old_timestamp ||
-           wpa_debug_show_keys != old_show_keys)
-               wpas_notify_debug_params_changed(global);
+       if (wpa_debug_level != old_level)
+               wpas_notify_debug_level_changed(global);
+       if (wpa_debug_timestamp != old_timestamp)
+               wpas_notify_debug_timestamp_changed(global);
+       if (wpa_debug_show_keys != old_show_keys)
+               wpas_notify_debug_show_keys_changed(global);
 
        return 0;
 }
 
 
-static struct wpa_scan_results * wpa_supplicant_get_scan_results_old(
-       struct wpa_supplicant *wpa_s)
-{
-#define SCAN_AP_LIMIT 128
-       struct wpa_scan_result *results;
-       int num, i;
-       struct wpa_scan_results *res;
-
-       results = os_malloc(SCAN_AP_LIMIT * sizeof(struct wpa_scan_result));
-       if (results == NULL) {
-               wpa_printf(MSG_WARNING, "Failed to allocate memory for scan "
-                          "results");
-               return NULL;
-       }
-
-       num = wpa_drv_get_scan_results(wpa_s, results, SCAN_AP_LIMIT);
-       wpa_printf(MSG_DEBUG, "Scan results: %d", num);
-       if (num < 0) {
-               wpa_printf(MSG_DEBUG, "Failed to get scan results");
-               os_free(results);
-               return NULL;
-       }
-       if (num > SCAN_AP_LIMIT) {
-               wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)",
-                          num, SCAN_AP_LIMIT);
-               num = SCAN_AP_LIMIT;
-       }
-
-       /* Convert old scan result data structure to the new one */
-       res = os_zalloc(sizeof(*res));
-       if (res == NULL) {
-               os_free(results);
-               return NULL;
-       }
-       res->res = os_zalloc(num * sizeof(struct wpa_scan_res *));
-       if (res->res == NULL) {
-               os_free(results);
-               os_free(res);
-               return NULL;
-       }
-
-       for (i = 0; i < num; i++) {
-               struct wpa_scan_result *bss = &results[i];
-               struct wpa_scan_res *r;
-               size_t ie_len;
-               u8 *pos;
-
-               ie_len = 2 + bss->ssid_len + bss->rsn_ie_len + bss->wpa_ie_len;
-               if (bss->maxrate)
-                       ie_len += 3;
-               if (bss->mdie_present)
-                       ie_len += 5;
-
-               r = os_zalloc(sizeof(*r) + ie_len);
-               if (r == NULL)
-                       break;
-
-               os_memcpy(r->bssid, bss->bssid, ETH_ALEN);
-               r->freq = bss->freq;
-               r->caps = bss->caps;
-               r->qual = bss->qual;
-               r->noise = bss->noise;
-               r->level = bss->level;
-               r->tsf = bss->tsf;
-               r->ie_len = ie_len;
-
-               pos = (u8 *) (r + 1);
-
-               /* SSID IE */
-               *pos++ = WLAN_EID_SSID;
-               *pos++ = bss->ssid_len;
-               os_memcpy(pos, bss->ssid, bss->ssid_len);
-               pos += bss->ssid_len;
-
-               if (bss->maxrate) {
-                       /* Fake Supported Rate IE to include max rate */
-                       *pos++ = WLAN_EID_SUPP_RATES;
-                       *pos++ = 1;
-                       *pos++ = bss->maxrate;
-               }
-
-               if (bss->rsn_ie_len) {
-                       os_memcpy(pos, bss->rsn_ie, bss->rsn_ie_len);
-                       pos += bss->rsn_ie_len;
-               }
-
-               if (bss->mdie_present) {
-                       os_memcpy(pos, bss->mdie, 5);
-                       pos += 5;
-               }
-
-               if (bss->wpa_ie_len) {
-                       os_memcpy(pos, bss->wpa_ie, bss->wpa_ie_len);
-                       pos += bss->wpa_ie_len;
-               }
-
-               res->res[res->num++] = r;
-       }
-
-       os_free(results);
-
-       return res;
-}
-
-
-/**
- * wpa_supplicant_get_scan_results - Get scan results
- * @wpa_s: Pointer to wpa_supplicant data
- * Returns: 0 on success, -1 on failure
- *
- * This function is request the current scan results from the driver and stores
- * a local copy of the results in wpa_s->scan_res.
- */
-int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
-{
-       int ret;
-
-       wpa_scan_results_free(wpa_s->scan_res);
-       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
-               wpa_s->scan_res = ieee80211_sta_get_scan_results(wpa_s);
-       else if (wpa_s->driver->get_scan_results2 == NULL)
-               wpa_s->scan_res = wpa_supplicant_get_scan_results_old(wpa_s);
-       else
-               wpa_s->scan_res = wpa_drv_get_scan_results2(wpa_s);
-       if (wpa_s->scan_res == NULL) {
-               wpa_printf(MSG_DEBUG, "Failed to get scan results");
-               ret = -1;
-       } else {
-               ret = 0;
-               wpa_scan_sort_results(wpa_s->scan_res);
-       }
-
-       return ret;
-}
-
-
 /**
  * wpa_supplicant_get_ssid - Get a pointer to the current network structure
  * @wpa_s: Pointer to wpa_supplicant data
@@ -1768,6 +1639,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;
        }
 
@@ -1781,6 +1653,7 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
                    os_strncmp(name, 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;
                }
        }
@@ -1790,6 +1663,20 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
 }
 
 
+/**
+ * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
+ * @ctx: Context pointer (wpa_s); this is the ctx variable registered
+ *     with struct wpa_driver_ops::init()
+ * @src_addr: Source address of the EAPOL frame
+ * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
+ * @len: Length of the EAPOL data
+ *
+ * This function is called for each received EAPOL frame. Most driver
+ * interfaces rely on more generic OS mechanism for receiving frames through
+ * l2_packet, but if such a mechanism is not available, the driver wrapper may
+ * take care of received EAPOL frames and deliver them to the core supplicant
+ * code by calling this function.
+ */
 void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
                             const u8 *buf, size_t len)
 {
@@ -1835,7 +1722,9 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
        if (wpa_s->eapol_received == 0 &&
            (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
             !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
-            wpa_s->wpa_state != WPA_COMPLETED)) {
+            wpa_s->wpa_state != WPA_COMPLETED) &&
+           (wpa_s->current_ssid == NULL ||
+            wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
                /* Timeout for completing IEEE 802.1X and WPA authentication */
                wpa_supplicant_req_auth_timeout(
                        wpa_s,
@@ -1854,7 +1743,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
 
 #ifdef CONFIG_IBSS_RSN
        if (wpa_s->current_ssid &&
-           wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS) {
+           wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
                ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
                return;
        }
@@ -1885,14 +1774,6 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
 }
 
 
-void wpa_supplicant_sta_rx(void *ctx, const u8 *buf, size_t len,
-                          struct ieee80211_rx_status *rx_status)
-{
-       struct wpa_supplicant *wpa_s = ctx;
-       ieee80211_sta_rx(wpa_s, buf, len, rx_status);
-}
-
-
 /**
  * wpa_supplicant_driver_init - Initialize driver interface parameters
  * @wpa_s: Pointer to wpa_supplicant data
@@ -1943,31 +1824,12 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
                }
        }
 
-       /* Backwards compatibility call to set_wpa() handler. This is called
-        * only just after init and just before deinit, so these handler can be
-        * used to implement same functionality. */
-       if (wpa_drv_set_wpa(wpa_s, 1) < 0) {
-               struct wpa_driver_capa capa;
-               if (wpa_drv_get_capa(wpa_s, &capa) < 0 ||
-                   !(capa.flags & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
-                                   WPA_DRIVER_CAPA_KEY_MGMT_WPA2))) {
-                       wpa_printf(MSG_DEBUG, "Driver does not support WPA.");
-                       /* Continue to allow non-WPA modes to be used. */
-               } else {
-                       wpa_printf(MSG_ERROR, "Failed to enable WPA in the "
-                               "driver.");
-                       return -1;
-               }
-       }
-
        wpa_clear_keys(wpa_s, NULL);
 
        /* Make sure that TKIP countermeasures are not left enabled (could
         * happen if wpa_supplicant is killed during countermeasures. */
        wpa_drv_set_countermeasures(wpa_s, 0);
 
-       wpa_drv_set_drop_unencrypted(wpa_s, 1);
-
        wpa_printf(MSG_DEBUG, "RSN: flushing PMKID list in the driver");
        wpa_drv_flush_pmkid(wpa_s);
 
@@ -1994,6 +1856,7 @@ static struct wpa_supplicant * wpa_supplicant_alloc(void)
        if (wpa_s == NULL)
                return NULL;
        wpa_s->scan_req = 1;
+       wpa_s->new_connection = 1;
 
        return wpa_s;
 }
@@ -2095,7 +1958,7 @@ next_driver:
        wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
        if (wpa_s->drv_priv == NULL) {
                const char *pos;
-               pos = os_strchr(driver, ',');
+               pos = driver ? os_strchr(driver, ',') : NULL;
                if (pos) {
                        wpa_printf(MSG_DEBUG, "Failed to initialize driver "
                                   "interface - try next driver wrapper");
@@ -2199,33 +2062,29 @@ next_driver:
        }
 #endif /* CONFIG_IBSS_RSN */
 
+       if (wpa_bss_init(wpa_s) < 0)
+               return -1;
+
        return 0;
 }
 
 
-static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s)
+static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
+                                       int notify)
 {
        if (wpa_s->drv_priv) {
                wpa_supplicant_deauthenticate(wpa_s,
                                              WLAN_REASON_DEAUTH_LEAVING);
 
-               /* Backwards compatibility call to set_wpa() handler. This is
-                * called only just after init and just before deinit, so these
-                * handler can be used to implement same functionality. */
-               if (wpa_drv_set_wpa(wpa_s, 0) < 0) {
-                       wpa_printf(MSG_ERROR, "Failed to disable WPA in the "
-                                  "driver.");
-               }
-
-               wpa_drv_set_drop_unencrypted(wpa_s, 0);
                wpa_drv_set_countermeasures(wpa_s, 0);
                wpa_clear_keys(wpa_s, NULL);
        }
 
-       wpas_notify_iface_removed(wpa_s);
-
        wpa_supplicant_cleanup(wpa_s);
 
+       if (notify)
+               wpas_notify_iface_removed(wpa_s);
+
        if (wpa_s->drv_priv)
                wpa_drv_deinit(wpa_s);
 }
@@ -2248,6 +2107,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
 {
        struct wpa_supplicant *wpa_s;
        struct wpa_interface t_iface;
+       struct wpa_ssid *ssid;
 
        if (global == NULL || iface == NULL)
                return NULL;
@@ -2256,6 +2116,8 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
        if (wpa_s == NULL)
                return NULL;
 
+       wpa_s->global = global;
+
        t_iface = *iface;
        if (global->params.override_driver) {
                wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
@@ -2274,20 +2136,21 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
        if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
                wpa_printf(MSG_DEBUG, "Failed to add interface %s",
                           iface->ifname);
-               wpa_supplicant_deinit_iface(wpa_s);
+               wpa_supplicant_deinit_iface(wpa_s, 0);
                os_free(wpa_s);
                return NULL;
        }
 
-       wpa_s->global = global;
-
        /* Notify the control interfaces about new iface */
        if (wpas_notify_iface_added(wpa_s)) {
-               wpa_supplicant_deinit_iface(wpa_s);
+               wpa_supplicant_deinit_iface(wpa_s, 1);
                os_free(wpa_s);
                return NULL;
        }
 
+       for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
+               wpas_notify_network_added(wpa_s, ssid);
+
        wpa_s->next = global->ifaces;
        global->ifaces = wpa_s;
 
@@ -2327,7 +2190,7 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
 
        wpa_printf(MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
 
-       wpa_supplicant_deinit_iface(wpa_s);
+       wpa_supplicant_deinit_iface(wpa_s, 1);
        os_free(wpa_s);
 
        return 0;
@@ -2374,7 +2237,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
        if (params->wpa_debug_syslog)
                wpa_debug_open_syslog();
 
-       ret = eap_peer_register_methods();
+       ret = eap_register_methods();
        if (ret) {
                wpa_printf(MSG_ERROR, "Failed to register EAP methods");
                if (ret == -2)
@@ -2383,17 +2246,6 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
                return NULL;
        }
 
-#ifdef CONFIG_AP
-       ret = eap_server_register_methods();
-       if (ret) {
-               wpa_printf(MSG_ERROR, "Failed to register EAP server methods");
-               if (ret == -2)
-                       wpa_printf(MSG_ERROR, "Two or more EAP methods used "
-                                  "the same EAP type.");
-               return NULL;
-       }
-#endif /* CONFIG_AP */
-
        global = os_zalloc(sizeof(*global));
        if (global == NULL)
                return NULL;
@@ -2418,7 +2270,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
        wpa_debug_timestamp = global->params.wpa_debug_timestamp =
                params->wpa_debug_timestamp;
 
-       if (eloop_init(global)) {
+       if (eloop_init()) {
                wpa_printf(MSG_ERROR, "Failed to initialize event loop");
                wpa_supplicant_deinit(global);
                return NULL;
@@ -2487,8 +2339,8 @@ int wpa_supplicant_run(struct wpa_global *global)
                                        wpa_s->ctrl_iface);
        }
 
-       eloop_register_signal_terminate(wpa_supplicant_terminate, NULL);
-       eloop_register_signal_reconfig(wpa_supplicant_reconfig, NULL);
+       eloop_register_signal_terminate(wpa_supplicant_terminate, global);
+       eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
 
        eloop_run();