X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=wpa_supplicant%2Fwpa_supplicant.c;h=45a0a760b5a2af99e8475131ae594ceeaa1d9494;hb=1581b38b6732e19a2f8fcfc049fdbdcc5183b10e;hp=00d20c92d4f27fcea0aa1110dd4a8b23d95956f2;hpb=0a40ec6a9059e7893970ff65554beac4782ecec4;p=wpasupplicant diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 00d20c9..45a0a76 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - * Copyright (c) 2003-2008, Jouni Malinen + * Copyright (c) 2003-2009, Jouni Malinen * * 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 @@ -38,12 +38,13 @@ #include "ieee802_11_defs.h" #include "blacklist.h" #include "wpas_glue.h" -#include "wps/wps.h" #include "wps_supplicant.h" +#include "ibss_rsn.h" +#include "sme.h" const char *wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" -"Copyright (c) 2003-2008, Jouni Malinen and contributors"; +"Copyright (c) 2003-2009, Jouni Malinen and contributors"; const char *wpa_supplicant_license = "This program is free software. You can distribute it and/or modify it\n" @@ -109,8 +110,6 @@ const char *wpa_supplicant_full_license5 = "\n"; #endif /* CONFIG_NO_STDOUT_DEBUG */ -extern struct wpa_driver_ops *wpa_supplicant_drivers[]; - extern int wpa_debug_level; extern int wpa_debug_show_keys; extern int wpa_debug_timestamp; @@ -214,7 +213,7 @@ void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, int sec, int usec) { if (wpa_s->conf && wpa_s->conf->ap_scan == 0 && - wpa_s->driver && IS_WIRED(wpa_s->driver)) + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) return; wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec " @@ -253,6 +252,21 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) struct eapol_config eapol_conf; struct wpa_ssid *ssid = wpa_s->current_ssid; +#ifdef CONFIG_IBSS_RSN + if (ssid->mode == IEEE80211_MODE_IBSS && + wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && + wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) { + /* + * RSN IBSS authentication is per-STA and we can disable the + * per-BSSID EAPOL authentication. + */ + eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); + eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); + return; + } +#endif /* CONFIG_IBSS_RSN */ + eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); @@ -274,9 +288,8 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) EAPOL_REQUIRE_KEY_BROADCAST; } - if (wpa_s->conf && wpa_s->driver && IS_WIRED(wpa_s->driver)) { + if (wpa_s->conf && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) eapol_conf.required_keys = 0; - } } if (wpa_s->conf) eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; @@ -388,6 +401,17 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) ieee80211_sta_deinit(wpa_s); wpas_wps_deinit(wpa_s); + +#ifdef CONFIG_IBSS_RSN + ibss_rsn_deinit(wpa_s->ibss_rsn); + wpa_s->ibss_rsn = NULL; +#endif /* CONFIG_IBSS_RSN */ + +#ifdef CONFIG_SME + os_free(wpa_s->sme.ft_ies); + wpa_s->sme.ft_ies = NULL; + wpa_s->sme.ft_ies_len = 0; +#endif /* CONFIG_SME */ } @@ -448,6 +472,8 @@ const char * wpa_supplicant_state_txt(int state) return "INACTIVE"; case WPA_SCANNING: return "SCANNING"; + case WPA_AUTHENTICATING: + return "AUTHENTICATING"; case WPA_ASSOCIATING: return "ASSOCIATING"; case WPA_ASSOCIATED: @@ -893,6 +919,31 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } +#ifdef CONFIG_AP +static void wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + struct wpa_driver_associate_params params; + + if (ssid->ssid == NULL || ssid->ssid_len == 0) { + wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); + return; + } + + wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + + os_memset(¶ms, 0, sizeof(params)); + params.ssid = ssid->ssid; + params.ssid_len = ssid->ssid_len; + params.mode = ssid->mode; + + if (wpa_drv_associate(wpa_s, ¶ms) < 0) + wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); +} +#endif /* CONFIG_AP */ + + /** * wpa_supplicant_associate - Request association * @wpa_s: Pointer to wpa_supplicant data @@ -914,6 +965,26 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, struct wpa_driver_capa capa; int assoc_failed = 0; + if (ssid->mode == 2) { +#ifdef CONFIG_AP + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) { + wpa_printf(MSG_INFO, "Driver does not support AP " + "mode"); + return; + } + wpa_supplicant_create_ap(wpa_s, ssid); +#else /* CONFIG_AP */ + wpa_printf(MSG_ERROR, "AP mode support not included in the " + "build"); +#endif /* CONFIG_AP */ + return; + } + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) { + sme_authenticate(wpa_s, bss, ssid); + return; + } + wpa_s->reassociate = 0; if (bss) { #ifdef CONFIG_IEEE80211R @@ -935,6 +1006,17 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wpa_ft_prepare_auth_request(wpa_s->wpa); } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_WPS + } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) && + wpa_s->conf->ap_scan == 2 && + (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { + /* Use ap_scan==1 style network selection to find the network + */ + wpa_s->scan_req = 2; + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + return; +#endif /* CONFIG_WPS */ } else { wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'", wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); @@ -1016,7 +1098,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) { wpa_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len); - } + } else + wpa_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ @@ -1091,7 +1174,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, } params.wep_tx_keyidx = ssid->wep_tx_keyidx; - if (wpa_s->driver_4way_handshake && + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && (params.key_mgmt_suite == KEY_MGMT_PSK || params.key_mgmt_suite == KEY_MGMT_FT_PSK)) { params.passphrase = ssid->passphrase; @@ -1099,6 +1182,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, params.psk = ssid->psk; } + params.drop_unencrypted = use_crypt; + #ifdef CONFIG_IEEE80211W switch (ssid->ieee80211w) { case NO_IEEE80211W: @@ -1111,9 +1196,21 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 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); + struct wpa_ie_data ie; + if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 && + ie.capabilities & + (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { + wpa_printf(MSG_DEBUG, "WPA: Selected AP supports MFP: " + "require MFP"); + params.mgmt_frame_protection = + MGMT_FRAME_PROTECTION_REQUIRED; + } + } #endif /* CONFIG_IEEE80211W */ - if (wpa_s->use_client_mlme) + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) ret = ieee80211_sta_associate(wpa_s, ¶ms); else ret = wpa_drv_associate(wpa_s, ¶ms); @@ -1133,6 +1230,18 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, * management. */ 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 && + 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); + /* + * RSN IBSS authentication is per-STA and we can disable the + * 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 */ int timeout = 60; @@ -1179,7 +1288,7 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, { u8 *addr = NULL; if (!is_zero_ether_addr(wpa_s->bssid)) { - if (wpa_s->use_client_mlme) + 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); @@ -1198,7 +1307,7 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, * @wpa_s: Pointer to wpa_supplicant data * @reason_code: IEEE 802.11 reason code for the deauthenticate frame * - * This function is used to request %wpa_supplicant to disassociate with the + * This function is used to request %wpa_supplicant to deauthenticate from the * current AP. */ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, @@ -1207,7 +1316,7 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, u8 *addr = NULL; wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); if (!is_zero_ether_addr(wpa_s->bssid)) { - if (wpa_s->use_client_mlme) + 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, @@ -1343,7 +1452,7 @@ int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s) { int ret; - if (wpa_s->use_client_mlme) { + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) { wpa_scan_results_free(wpa_s->scan_res); wpa_s->scan_res = ieee80211_sta_get_scan_results(wpa_s); if (wpa_s->scan_res == NULL) { @@ -1384,7 +1493,7 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) u8 bssid[ETH_ALEN]; int wired; - if (wpa_s->use_client_mlme) { + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) { if (ieee80211_sta_get_ssid(wpa_s, ssid, &ssid_len)) { wpa_printf(MSG_WARNING, "Could not read SSID from " "MLME."); @@ -1400,15 +1509,15 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) ssid_len = res; } - if (wpa_s->use_client_mlme) + 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) { wpa_printf(MSG_WARNING, "Could not read BSSID from driver."); return NULL; } - wired = wpa_s->conf->ap_scan == 0 && wpa_s->driver && - IS_WIRED(wpa_s->driver); + wired = wpa_s->conf->ap_scan == 0 && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED); entry = wpa_s->conf->ssid; while (entry) { @@ -1418,6 +1527,14 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) (!entry->bssid_set || os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) return entry; +#ifdef CONFIG_WPS + if (!entry->disabled && + (entry->key_mgmt & WPA_KEY_MGMT_WPS) && + (entry->ssid == NULL || entry->ssid_len == 0) && + (!entry->bssid_set || + os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) + return entry; +#endif /* CONFIG_WPS */ entry = entry->next; } @@ -1429,6 +1546,8 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, const char *name) { int i; + size_t len; + const char *pos; if (wpa_s == NULL) return -1; @@ -1445,14 +1564,21 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, return 0; } + pos = os_strchr(name, ','); + if (pos) + len = pos - name; + else + len = os_strlen(name); for (i = 0; wpa_supplicant_drivers[i]; i++) { - if (os_strcmp(name, wpa_supplicant_drivers[i]->name) == 0) { + if (os_strlen(wpa_supplicant_drivers[i]->name) == len && + os_strncmp(name, wpa_supplicant_drivers[i]->name, len) == + 0) { wpa_s->driver = wpa_supplicant_drivers[i]; return 0; } } - wpa_printf(MSG_ERROR, "Unsupported driver '%s'.\n", name); + wpa_printf(MSG_ERROR, "Unsupported driver '%s'.", name); return -1; } @@ -1472,14 +1598,15 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, } if (wpa_s->eapol_received == 0 && - (!wpa_s->driver_4way_handshake || + (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) || !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->wpa_state != WPA_COMPLETED)) { /* Timeout for completing IEEE 802.1X and WPA authentication */ wpa_supplicant_req_auth_timeout( wpa_s, (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) ? + wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA || + wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ? 70 : 10, 0); } wpa_s->eapol_received++; @@ -1490,6 +1617,14 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, return; } +#ifdef CONFIG_IBSS_RSN + if (wpa_s->current_ssid && + wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS) { + ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len); + return; + } +#endif /* CONFIG_IBSS_RSN */ + /* Source address of the incoming EAPOL frame could be compared to the * current BSSID. However, it is possible that a centralized * Authenticator could be using another MAC address than the BSSID of @@ -1501,7 +1636,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) return; wpa_drv_poll(wpa_s); - if (!wpa_s->driver_4way_handshake) + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* @@ -1608,7 +1743,7 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "RSN: flushing PMKID list in the driver"); wpa_drv_flush_pmkid(wpa_s); - wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; + wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; wpa_supplicant_req_scan(wpa_s, interface_count, 100000); interface_count++; @@ -1639,6 +1774,9 @@ static struct wpa_supplicant * wpa_supplicant_alloc(void) static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, struct wpa_interface *iface) { + const char *ifname, *driver; + struct wpa_driver_capa capa; + wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, iface->confname ? iface->confname : "N/A", @@ -1646,10 +1784,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, iface->ctrl_interface ? iface->ctrl_interface : "N/A", iface->bridge_ifname ? iface->bridge_ifname : "N/A"); - if (wpa_supplicant_set_driver(wpa_s, iface->driver) < 0) { - return -1; - } - if (iface->confname) { #ifdef CONFIG_BACKEND_FILE wpa_s->confname = os_rel2abs_path(iface->confname); @@ -1717,18 +1851,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, sizeof(wpa_s->bridge_ifname)); } - return 0; -} - - -static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s) -{ - const char *ifname; - struct wpa_driver_capa capa; - - wpa_printf(MSG_DEBUG, "Initializing interface (2) '%s'", - wpa_s->ifname); - /* RSNA Supplicant Key Management - INITIALIZE */ eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); @@ -1737,8 +1859,21 @@ static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s) * L2 receive handler so that association events are processed before * EAPOL-Key packets if both become available for the same select() * call. */ + driver = iface->driver; +next_driver: + if (wpa_supplicant_set_driver(wpa_s, driver) < 0) + return -1; + 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, ','); + if (pos) { + wpa_printf(MSG_DEBUG, "Failed to initialize driver " + "interface - try next driver wrapper"); + driver = pos + 1; + goto next_driver; + } wpa_printf(MSG_ERROR, "Failed to initialize driver interface"); return -1; } @@ -1790,6 +1925,12 @@ static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s) if (wpa_supplicant_driver_init(wpa_s) < 0) return -1; + if (wpa_s->conf->country[0] && wpa_s->conf->country[1] && + wpa_drv_set_country(wpa_s, wpa_s->conf->country)) { + wpa_printf(MSG_DEBUG, "Failed to set country"); + return -1; + } + wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); if (wpas_wps_init(wpa_s)) @@ -1814,14 +1955,21 @@ static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s) } if (wpa_drv_get_capa(wpa_s, &capa) == 0) { + wpa_s->drv_flags = capa.flags; if (capa.flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) { - wpa_s->use_client_mlme = 1; if (ieee80211_sta_init(wpa_s)) return -1; } - if (capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) - wpa_s->driver_4way_handshake = 1; + wpa_s->max_scan_ssids = capa.max_scan_ssids; + } + +#ifdef CONFIG_IBSS_RSN + wpa_s->ibss_rsn = ibss_rsn_init(wpa_s); + if (!wpa_s->ibss_rsn) { + wpa_printf(MSG_DEBUG, "Failed to init IBSS RSN"); + return -1; } +#endif /* CONFIG_IBSS_RSN */ return 0; } @@ -1879,8 +2027,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, if (wpa_s == NULL) return NULL; - if (wpa_supplicant_init_iface(wpa_s, iface) || - wpa_supplicant_init_iface2(wpa_s)) { + if (wpa_supplicant_init_iface(wpa_s, iface)) { wpa_printf(MSG_DEBUG, "Failed to add interface %s", iface->ifname); wpa_supplicant_deinit_iface(wpa_s); @@ -1974,12 +2121,14 @@ struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global, struct wpa_global * wpa_supplicant_init(struct wpa_params *params) { struct wpa_global *global; - int ret; + int ret, i; if (params == NULL) return NULL; wpa_debug_open_file(params->wpa_debug_file_path); + if (params->wpa_debug_syslog) + wpa_debug_open_syslog(); ret = eap_peer_register_methods(); if (ret) { @@ -2029,6 +2178,30 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) } } + for (i = 0; wpa_supplicant_drivers[i]; i++) + global->drv_count++; + if (global->drv_count == 0) { + wpa_printf(MSG_ERROR, "No drivers enabled"); + wpa_supplicant_deinit(global); + return NULL; + } + global->drv_priv = os_zalloc(global->drv_count * sizeof(void *)); + if (global->drv_priv == NULL) { + wpa_supplicant_deinit(global); + return NULL; + } + for (i = 0; wpa_supplicant_drivers[i]; i++) { + if (!wpa_supplicant_drivers[i]->global_init) + continue; + global->drv_priv[i] = wpa_supplicant_drivers[i]->global_init(); + if (global->drv_priv[i] == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize driver " + "'%s'", wpa_supplicant_drivers[i]->name); + wpa_supplicant_deinit(global); + return NULL; + } + } + return global; } @@ -2075,6 +2248,8 @@ int wpa_supplicant_run(struct wpa_global *global) */ void wpa_supplicant_deinit(struct wpa_global *global) { + int i; + if (global == NULL) return; @@ -2088,6 +2263,13 @@ void wpa_supplicant_deinit(struct wpa_global *global) eap_peer_unregister_methods(); + for (i = 0; wpa_supplicant_drivers[i] && global->drv_priv; i++) { + if (!global->drv_priv[i]) + continue; + wpa_supplicant_drivers[i]->global_deinit(global->drv_priv[i]); + } + os_free(global->drv_priv); + eloop_destroy(); if (global->params.pid_file) { @@ -2097,5 +2279,6 @@ void wpa_supplicant_deinit(struct wpa_global *global) os_free(global->params.ctrl_interface); os_free(global); + wpa_debug_close_syslog(); wpa_debug_close_file(); }