X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=wpa_supplicant%2Fwpa_supplicant.c;h=61d1c87e48d82a2e48eef242257f1a62b704f045;hb=HEAD;hp=3f05616ced54cf2290d2b718d2641e7f1bffb54c;hpb=8e56d1899360a3d372dfdc38126a3ccf7e1477ef;p=libeap.git diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 3f05616..61d1c87 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - * Copyright (c) 2003-2009, Jouni Malinen + * Copyright (c) 2003-2010, 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 @@ -36,19 +36,22 @@ #include "common/wpa_ctrl.h" #include "mlme.h" #include "common/ieee802_11_defs.h" +#include "p2p/p2p.h" #include "blacklist.h" #include "wpas_glue.h" #include "wps_supplicant.h" #include "ibss_rsn.h" #include "sme.h" #include "ap.h" +#include "p2p_supplicant.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 and contributors"; +"Copyright (c) 2003-2010, Jouni Malinen and contributors"; const char *wpa_supplicant_license = "This program is free software. You can distribute it and/or modify it\n" @@ -400,8 +403,6 @@ 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); @@ -428,6 +429,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) #ifdef CONFIG_AP wpa_supplicant_ap_deinit(wpa_s); #endif /* CONFIG_AP */ + +#ifdef CONFIG_P2P + wpas_p2p_deinit(wpa_s); +#endif /* CONFIG_P2P */ } @@ -490,6 +495,8 @@ const char * wpa_supplicant_state_txt(enum wpa_states state) return "DISCONNECTED"; case WPA_INACTIVE: return "INACTIVE"; + case WPA_INTERFACE_DISABLED: + return "INTERFACE_DISABLED"; case WPA_SCANNING: return "SCANNING"; case WPA_AUTHENTICATING: @@ -521,6 +528,8 @@ const char * wpa_supplicant_state_txt(enum 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)); @@ -528,8 +537,6 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, 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,12 +550,19 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_s->new_connection = 0; wpa_s->reassociated_connection = 1; wpa_drv_set_operstate(wpa_s, 1); + wpa_s->after_wps = 0; +#ifdef CONFIG_P2P + wpas_p2p_completed(wpa_s); +#endif /* CONFIG_P2P */ } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || state == WPA_ASSOCIATED) { wpa_s->new_connection = 1; 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); } @@ -581,15 +595,19 @@ static void wpa_supplicant_terminate(int sig, void *signal_ctx) } -static void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s) +void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s) { 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 != WPA_INTERFACE_DISABLED) + wpa_s->wpa_state = WPA_DISCONNECTED; + + if (wpa_s->wpa_state != old_state) + wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state); } @@ -619,6 +637,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) "file '%s' - exiting", wpa_s->confname); return -1; } + conf->changed_parameters = (unsigned int) -1; reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface || (conf->ctrl_interface && wpa_s->conf->ctrl_interface && @@ -661,9 +680,13 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) if (reconf_ctrl) wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); + wpa_supplicant_update_config(wpa_s); + wpa_supplicant_clear_status(wpa_s); - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); + if (wpa_supplicant_enabled_networks(wpa_s->conf)) { + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } wpa_msg(wpa_s, MSG_DEBUG, "Reconfiguration completed"); return 0; } @@ -682,7 +705,7 @@ static void wpa_supplicant_reconfig(int sig, void *signal_ctx) } -static enum wpa_cipher cipher_suite2driver(int cipher) +enum wpa_cipher cipher_suite2driver(int cipher) { switch (cipher) { case WPA_CIPHER_NONE: @@ -700,7 +723,7 @@ static enum wpa_cipher cipher_suite2driver(int cipher) } -static enum wpa_key_mgmt key_mgmt2driver(int key_mgmt) +enum wpa_key_mgmt key_mgmt2driver(int key_mgmt) { switch (key_mgmt) { case WPA_KEY_MGMT_NONE: @@ -764,7 +787,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"); @@ -791,8 +814,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; @@ -800,8 +822,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; @@ -834,7 +856,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 " @@ -941,7 +963,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) { @@ -954,6 +976,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, wpa_s->mgmt_group_cipher); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, ssid->ieee80211w); #endif /* CONFIG_IEEE80211W */ if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { @@ -980,12 +1003,12 @@ 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]; + u8 wpa_ie[200]; size_t wpa_ie_len; int use_crypt, ret, i, bssid_changed; - int algs = AUTH_ALG_OPEN_SYSTEM; + int algs = WPA_AUTH_ALG_OPEN; enum wpa_cipher cipher_pairwise, cipher_group; struct wpa_driver_associate_params params; int wep_keys_set = 0; @@ -993,7 +1016,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, int assoc_failed = 0; struct wpa_ssid *old_ssid; - if (ssid->mode == WPAS_MODE_AP) { + if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO || + ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) { #ifdef CONFIG_AP if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) { wpa_printf(MSG_INFO, "Driver does not support AP " @@ -1001,6 +1025,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"); @@ -1014,28 +1039,28 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, return; } + os_memset(¶ms, 0, sizeof(params)); 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); + wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(wpa_s->wpa); + wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_WPS @@ -1064,27 +1089,21 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 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); } - 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 | @@ -1128,12 +1147,46 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wpa_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); + if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY)) + params.wps = WPS_MODE_PRIVACY; + else + params.wps = WPS_MODE_OPEN; #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_ie_len = 0; } +#ifdef CONFIG_P2P + if (wpa_s->global->p2p) { + u8 *pos; + size_t len; + int res; + int p2p_group; + p2p_group = wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE; + pos = wpa_ie + wpa_ie_len; + len = sizeof(wpa_ie) - wpa_ie_len; + res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, p2p_group); + if (res >= 0) + wpa_ie_len += res; + } + + wpa_s->cross_connect_disallowed = 0; + if (bss) { + struct wpabuf *p2p; + p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE); + if (p2p) { + wpa_s->cross_connect_disallowed = + p2p_get_cross_connect_disallowed(p2p); + wpabuf_free(p2p); + wpa_printf(MSG_DEBUG, "P2P: WLAN AP %s cross " + "connection", + wpa_s->cross_connect_disallowed ? + "disallows" : "allows"); + } + } +#endif /* CONFIG_P2P */ + wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); use_crypt = 1; cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher); @@ -1172,12 +1225,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, } wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); - os_memset(¶ms, 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; @@ -1211,19 +1262,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 & @@ -1236,6 +1277,17 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_P2P + if (wpa_s->global->p2p && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)) + params.p2p = 1; +#endif /* CONFIG_P2P */ + + if (wpa_s->parent->set_sta_uapsd) + params.uapsd = wpa_s->parent->sta_uapsd; + else + params.uapsd = -1; + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) ret = ieee80211_sta_associate(wpa_s, ¶ms); else @@ -1296,6 +1348,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) @@ -1303,6 +1356,24 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, } +static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + struct wpa_ssid *old_ssid; + + wpa_clear_keys(wpa_s, addr); + 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) + wpas_notify_network_changed(wpa_s); + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); +} + + /** * wpa_supplicant_disassociate - Disassociate the current connection * @wpa_s: Pointer to wpa_supplicant data @@ -1314,7 +1385,6 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, int reason_code) { - struct wpa_ssid *old_ssid; u8 *addr = NULL; if (!is_zero_ether_addr(wpa_s->bssid)) { @@ -1324,14 +1394,8 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code); addr = wpa_s->bssid; } - wpa_clear_keys(wpa_s, addr); - wpa_supplicant_mark_disassoc(wpa_s); - old_ssid = wpa_s->current_ssid; - wpa_s->current_ssid = 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) - wpas_notify_network_changed(wpa_s); + + wpa_supplicant_clear_connection(wpa_s, addr); } @@ -1346,7 +1410,6 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, int reason_code) { - struct wpa_ssid *old_ssid; u8 *addr = NULL; if (!is_zero_ether_addr(wpa_s->bssid)) { @@ -1357,14 +1420,8 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, reason_code); addr = wpa_s->bssid; } - wpa_clear_keys(wpa_s, addr); - wpa_supplicant_mark_disassoc(wpa_s); - old_ssid = wpa_s->current_ssid; - wpa_s->current_ssid = 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) - wpas_notify_network_changed(wpa_s); + + wpa_supplicant_clear_connection(wpa_s, addr); } @@ -1382,8 +1439,11 @@ void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, int was_disabled; if (ssid == NULL) { - other_ssid = wpa_s->conf->ssid; - while (other_ssid) { + for (other_ssid = wpa_s->conf->ssid; other_ssid; + other_ssid = other_ssid->next) { + if (other_ssid->disabled == 2) + continue; /* do not change persistent P2P group + * data */ if (other_ssid == wpa_s->current_ssid && other_ssid->disabled) wpa_s->reassociate = 1; @@ -1395,18 +1455,18 @@ void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, if (was_disabled != other_ssid->disabled) wpas_notify_network_enabled_changed( wpa_s, other_ssid); - - other_ssid = other_ssid->next; } if (wpa_s->reassociate) wpa_supplicant_req_scan(wpa_s, 0, 0); - } else if (wpa_s->current_ssid == NULL && ssid->disabled) { - /* - * Try to reassociate since there is no current configuration - * and a new network was made available. - */ - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); + } else if (ssid->disabled && ssid->disabled != 2) { + if (wpa_s->current_ssid == NULL) { + /* + * Try to reassociate since there is no current + * configuration and a new network was made available. + */ + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } was_disabled = ssid->disabled; @@ -1432,22 +1492,23 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, int was_disabled; if (ssid == NULL) { - other_ssid = wpa_s->conf->ssid; - while (other_ssid) { + for (other_ssid = wpa_s->conf->ssid; other_ssid; + other_ssid = other_ssid->next) { was_disabled = other_ssid->disabled; + if (was_disabled == 2) + continue; /* do not change persistent P2P group + * data */ other_ssid->disabled = 1; if (was_disabled != other_ssid->disabled) wpas_notify_network_enabled_changed( wpa_s, other_ssid); - - other_ssid = other_ssid->next; } if (wpa_s->current_ssid) wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); - } else { + } else if (ssid->disabled != 2) { if (ssid == wpa_s->current_ssid) wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); @@ -1481,16 +1542,16 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, * Mark all other networks disabled or mark all networks enabled if no * network specified. */ - other_ssid = wpa_s->conf->ssid; - while (other_ssid) { + for (other_ssid = wpa_s->conf->ssid; other_ssid; + other_ssid = other_ssid->next) { int was_disabled = other_ssid->disabled; + if (was_disabled == 2) + continue; /* do not change persistent P2P group data */ other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0; if (was_disabled != other_ssid->disabled) wpas_notify_network_enabled_changed(wpa_s, other_ssid); - - other_ssid = other_ssid->next; } wpa_s->disconnected = 0; wpa_s->reassociate = 1; @@ -1556,43 +1617,12 @@ 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); - - return 0; -} - - -/** - * wpa_supplicant_get_scan_results - Get scan results - * @wpa_s: Pointer to wpa_supplicant data - * Returns: 0 on success, -1 on failure - * - * This function request the current scan results from the driver and updates - * the local BSS list wpa_s->bss. - */ -int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s) -{ - size_t i; - - 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 - 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"); - return -1; - } - - wpa_scan_sort_results(wpa_s->scan_res); - - wpa_bss_update_start(wpa_s); - for (i = 0; i < wpa_s->scan_res->num; i++) - wpa_bss_update_scan_res(wpa_s, wpa_s->scan_res->res[i]); - wpa_bss_update_end(wpa_s); + 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; } @@ -1704,6 +1734,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) { @@ -1801,14 +1845,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 @@ -1826,13 +1862,18 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) const u8 *addr = wpa_drv_get_mac_addr(wpa_s); if (addr) os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); - } else { + } else if (!(wpa_s->drv_flags & + WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) { wpa_s->l2 = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL, wpa_supplicant_rx_eapol, wpa_s, 0); if (wpa_s->l2 == NULL) return -1; + } else { + const u8 *addr = wpa_drv_get_mac_addr(wpa_s); + if (addr) + os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); } if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { @@ -1869,8 +1910,11 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) wpa_drv_flush_pmkid(wpa_s); wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; - wpa_supplicant_req_scan(wpa_s, interface_count, 100000); - interface_count++; + if (wpa_supplicant_enabled_networks(wpa_s->conf)) { + wpa_supplicant_req_scan(wpa_s, interface_count, 100000); + interface_count++; + } else + wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); return 0; } @@ -1892,6 +1936,7 @@ static struct wpa_supplicant * wpa_supplicant_alloc(void) return NULL; wpa_s->scan_req = 1; wpa_s->new_connection = 1; + wpa_s->parent = wpa_s; return wpa_s; } @@ -2048,6 +2093,19 @@ next_driver: return -1; } + if (wpa_drv_get_capa(wpa_s, &capa) == 0) { + 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_remain_on_chan = capa.max_remain_on_chan; + wpa_s->max_stations = capa.max_stations; + } + if (wpa_s->max_remain_on_chan == 0) + wpa_s->max_remain_on_chan = 1000; + if (wpa_supplicant_driver_init(wpa_s) < 0) return -1; @@ -2080,15 +2138,6 @@ next_driver: return -1; } - if (wpa_drv_get_capa(wpa_s, &capa) == 0) { - 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; - } - #ifdef CONFIG_IBSS_RSN wpa_s->ibss_rsn = ibss_rsn_init(wpa_s); if (!wpa_s->ibss_rsn) { @@ -2097,6 +2146,13 @@ next_driver: } #endif /* CONFIG_IBSS_RSN */ +#ifdef CONFIG_P2P + if (wpas_p2p_init(wpa_s->global, wpa_s) < 0) { + wpa_printf(MSG_ERROR, "Failed to init P2P"); + return -1; + } +#endif /* CONFIG_P2P */ + if (wpa_bss_init(wpa_s) < 0) return -1; @@ -2225,6 +2281,8 @@ int wpa_supplicant_remove_iface(struct wpa_global *global, wpa_printf(MSG_DEBUG, "Removing interface %s", wpa_s->ifname); + if (global->p2p_group_formation == wpa_s) + global->p2p_group_formation = NULL; wpa_supplicant_deinit_iface(wpa_s, 1); os_free(wpa_s); @@ -2284,6 +2342,8 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; + dl_list_init(&global->p2p_srv_bonjour); + dl_list_init(&global->p2p_srv_upnp); global->params.daemonize = params->daemonize; global->params.wait_for_monitor = params->wait_for_monitor; global->params.dbus_ctrl_interface = params->dbus_ctrl_interface; @@ -2397,6 +2457,10 @@ void wpa_supplicant_deinit(struct wpa_global *global) if (global == NULL) return; +#ifdef CONFIG_P2P + wpas_p2p_deinit_global(global); +#endif /* CONFIG_P2P */ + while (global->ifaces) wpa_supplicant_remove_iface(global, global->ifaces); @@ -2431,3 +2495,17 @@ void wpa_supplicant_deinit(struct wpa_global *global) wpa_debug_close_syslog(); wpa_debug_close_file(); } + + +void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_WPS + wpas_wps_update_config(wpa_s); +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P + wpas_p2p_update_config(wpa_s); +#endif /* CONFIG_P2P */ + + wpa_s->conf->changed_parameters = 0; +}