1189251Ssam/* 2189251Ssam * WPA Supplicant 3252726Srpaulo * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam * 8189251Ssam * This file implements functions for registering and unregistering 9189251Ssam * %wpa_supplicant interfaces. In addition, this file contains number of 10189251Ssam * functions for managing network connections. 11189251Ssam */ 12189251Ssam 13189251Ssam#include "includes.h" 14189251Ssam 15189251Ssam#include "common.h" 16252726Srpaulo#include "crypto/random.h" 17252726Srpaulo#include "crypto/sha1.h" 18189251Ssam#include "eapol_supp/eapol_supp_sm.h" 19189251Ssam#include "eap_peer/eap.h" 20214734Srpaulo#include "eap_server/eap_methods.h" 21214734Srpaulo#include "rsn_supp/wpa.h" 22189251Ssam#include "eloop.h" 23189251Ssam#include "config.h" 24252726Srpaulo#include "utils/ext_password.h" 25189251Ssam#include "l2_packet/l2_packet.h" 26189251Ssam#include "wpa_supplicant_i.h" 27214734Srpaulo#include "driver_i.h" 28189251Ssam#include "ctrl_iface.h" 29189251Ssam#include "pcsc_funcs.h" 30214734Srpaulo#include "common/version.h" 31214734Srpaulo#include "rsn_supp/preauth.h" 32214734Srpaulo#include "rsn_supp/pmksa_cache.h" 33214734Srpaulo#include "common/wpa_ctrl.h" 34214734Srpaulo#include "common/ieee802_11_defs.h" 35252726Srpaulo#include "p2p/p2p.h" 36189251Ssam#include "blacklist.h" 37189251Ssam#include "wpas_glue.h" 38189251Ssam#include "wps_supplicant.h" 39214734Srpaulo#include "ibss_rsn.h" 40214734Srpaulo#include "sme.h" 41252726Srpaulo#include "gas_query.h" 42214734Srpaulo#include "ap.h" 43252726Srpaulo#include "p2p_supplicant.h" 44252726Srpaulo#include "wifi_display.h" 45214734Srpaulo#include "notify.h" 46214734Srpaulo#include "bgscan.h" 47252726Srpaulo#include "autoscan.h" 48214734Srpaulo#include "bss.h" 49214734Srpaulo#include "scan.h" 50252726Srpaulo#include "offchannel.h" 51252726Srpaulo#include "hs20_supplicant.h" 52189251Ssam 53189251Ssamconst char *wpa_supplicant_version = 54189251Ssam"wpa_supplicant v" VERSION_STR "\n" 55252726Srpaulo"Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> and contributors"; 56189251Ssam 57189251Ssamconst char *wpa_supplicant_license = 58252726Srpaulo"This software may be distributed under the terms of the BSD license.\n" 59252726Srpaulo"See README for more details.\n" 60189251Ssam#ifdef EAP_TLS_OPENSSL 61189251Ssam"\nThis product includes software developed by the OpenSSL Project\n" 62189251Ssam"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n" 63189251Ssam#endif /* EAP_TLS_OPENSSL */ 64189251Ssam; 65189251Ssam 66189251Ssam#ifndef CONFIG_NO_STDOUT_DEBUG 67189251Ssam/* Long text divided into parts in order to fit in C89 strings size limits. */ 68189251Ssamconst char *wpa_supplicant_full_license1 = 69252726Srpaulo""; 70189251Ssamconst char *wpa_supplicant_full_license2 = 71252726Srpaulo"This software may be distributed under the terms of the BSD license.\n" 72189251Ssam"\n" 73189251Ssam"Redistribution and use in source and binary forms, with or without\n" 74189251Ssam"modification, are permitted provided that the following conditions are\n" 75189251Ssam"met:\n" 76189251Ssam"\n"; 77189251Ssamconst char *wpa_supplicant_full_license3 = 78189251Ssam"1. Redistributions of source code must retain the above copyright\n" 79189251Ssam" notice, this list of conditions and the following disclaimer.\n" 80189251Ssam"\n" 81189251Ssam"2. Redistributions in binary form must reproduce the above copyright\n" 82189251Ssam" notice, this list of conditions and the following disclaimer in the\n" 83189251Ssam" documentation and/or other materials provided with the distribution.\n" 84189251Ssam"\n"; 85189251Ssamconst char *wpa_supplicant_full_license4 = 86189251Ssam"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" 87189251Ssam" names of its contributors may be used to endorse or promote products\n" 88189251Ssam" derived from this software without specific prior written permission.\n" 89189251Ssam"\n" 90189251Ssam"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" 91189251Ssam"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" 92189251Ssam"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" 93189251Ssam"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"; 94189251Ssamconst char *wpa_supplicant_full_license5 = 95189251Ssam"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" 96189251Ssam"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" 97189251Ssam"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" 98189251Ssam"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" 99189251Ssam"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" 100189251Ssam"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" 101189251Ssam"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 102189251Ssam"\n"; 103189251Ssam#endif /* CONFIG_NO_STDOUT_DEBUG */ 104189251Ssam 105189251Ssamextern int wpa_debug_level; 106189251Ssamextern int wpa_debug_show_keys; 107189251Ssamextern int wpa_debug_timestamp; 108214734Srpauloextern struct wpa_driver_ops *wpa_drivers[]; 109189251Ssam 110189251Ssam/* Configure default/group WEP keys for static WEP */ 111214734Srpauloint wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) 112189251Ssam{ 113189251Ssam int i, set = 0; 114189251Ssam 115189251Ssam for (i = 0; i < NUM_WEP_KEYS; i++) { 116189251Ssam if (ssid->wep_key_len[i] == 0) 117189251Ssam continue; 118189251Ssam 119189251Ssam set = 1; 120252726Srpaulo wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL, 121252726Srpaulo i, i == ssid->wep_tx_keyidx, NULL, 0, 122189251Ssam ssid->wep_key[i], ssid->wep_key_len[i]); 123189251Ssam } 124189251Ssam 125189251Ssam return set; 126189251Ssam} 127189251Ssam 128189251Ssam 129189251Ssamstatic int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, 130189251Ssam struct wpa_ssid *ssid) 131189251Ssam{ 132189251Ssam u8 key[32]; 133189251Ssam size_t keylen; 134214734Srpaulo enum wpa_alg alg; 135189251Ssam u8 seq[6] = { 0 }; 136189251Ssam 137189251Ssam /* IBSS/WPA-None uses only one key (Group) for both receiving and 138189251Ssam * sending unicast and multicast packets. */ 139189251Ssam 140214734Srpaulo if (ssid->mode != WPAS_MODE_IBSS) { 141252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not " 142252726Srpaulo "IBSS/ad-hoc) for WPA-None", ssid->mode); 143189251Ssam return -1; 144189251Ssam } 145189251Ssam 146189251Ssam if (!ssid->psk_set) { 147252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for " 148252726Srpaulo "WPA-None"); 149189251Ssam return -1; 150189251Ssam } 151189251Ssam 152189251Ssam switch (wpa_s->group_cipher) { 153189251Ssam case WPA_CIPHER_CCMP: 154189251Ssam os_memcpy(key, ssid->psk, 16); 155189251Ssam keylen = 16; 156189251Ssam alg = WPA_ALG_CCMP; 157189251Ssam break; 158252726Srpaulo case WPA_CIPHER_GCMP: 159252726Srpaulo os_memcpy(key, ssid->psk, 16); 160252726Srpaulo keylen = 16; 161252726Srpaulo alg = WPA_ALG_GCMP; 162252726Srpaulo break; 163189251Ssam case WPA_CIPHER_TKIP: 164189251Ssam /* WPA-None uses the same Michael MIC key for both TX and RX */ 165189251Ssam os_memcpy(key, ssid->psk, 16 + 8); 166189251Ssam os_memcpy(key + 16 + 8, ssid->psk + 16, 8); 167189251Ssam keylen = 32; 168189251Ssam alg = WPA_ALG_TKIP; 169189251Ssam break; 170189251Ssam default: 171252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for " 172252726Srpaulo "WPA-None", wpa_s->group_cipher); 173189251Ssam return -1; 174189251Ssam } 175189251Ssam 176189251Ssam /* TODO: should actually remember the previously used seq#, both for TX 177189251Ssam * and RX from each STA.. */ 178189251Ssam 179252726Srpaulo return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen); 180189251Ssam} 181189251Ssam 182189251Ssam 183189251Ssamstatic void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) 184189251Ssam{ 185189251Ssam struct wpa_supplicant *wpa_s = eloop_ctx; 186189251Ssam const u8 *bssid = wpa_s->bssid; 187189251Ssam if (is_zero_ether_addr(bssid)) 188189251Ssam bssid = wpa_s->pending_bssid; 189189251Ssam wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.", 190189251Ssam MAC2STR(bssid)); 191189251Ssam wpa_blacklist_add(wpa_s, bssid); 192189251Ssam wpa_sm_notify_disassoc(wpa_s->wpa); 193252726Srpaulo wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 194189251Ssam wpa_s->reassociate = 1; 195252726Srpaulo 196252726Srpaulo /* 197252726Srpaulo * If we timed out, the AP or the local radio may be busy. 198252726Srpaulo * So, wait a second until scanning again. 199252726Srpaulo */ 200252726Srpaulo wpa_supplicant_req_scan(wpa_s, 1, 0); 201252726Srpaulo 202252726Srpaulo#ifdef CONFIG_P2P 203252726Srpaulo if (wpa_s->global->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled && 204252726Srpaulo wpa_s->global->p2p != NULL) { 205252726Srpaulo wpa_s->global->p2p_cb_on_scan_complete = 0; 206252726Srpaulo if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) { 207252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation " 208252726Srpaulo "continued after timed out authentication"); 209252726Srpaulo } 210252726Srpaulo } 211252726Srpaulo#endif /* CONFIG_P2P */ 212189251Ssam} 213189251Ssam 214189251Ssam 215189251Ssam/** 216189251Ssam * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication 217189251Ssam * @wpa_s: Pointer to wpa_supplicant data 218189251Ssam * @sec: Number of seconds after which to time out authentication 219189251Ssam * @usec: Number of microseconds after which to time out authentication 220189251Ssam * 221189251Ssam * This function is used to schedule a timeout for the current authentication 222189251Ssam * attempt. 223189251Ssam */ 224189251Ssamvoid wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, 225189251Ssam int sec, int usec) 226189251Ssam{ 227189251Ssam if (wpa_s->conf && wpa_s->conf->ap_scan == 0 && 228214734Srpaulo (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) 229189251Ssam return; 230189251Ssam 231252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec " 232189251Ssam "%d usec", sec, usec); 233189251Ssam eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 234189251Ssam eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL); 235189251Ssam} 236189251Ssam 237189251Ssam 238189251Ssam/** 239189251Ssam * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout 240189251Ssam * @wpa_s: Pointer to wpa_supplicant data 241189251Ssam * 242189251Ssam * This function is used to cancel authentication timeout scheduled with 243189251Ssam * wpa_supplicant_req_auth_timeout() and it is called when authentication has 244189251Ssam * been completed. 245189251Ssam */ 246189251Ssamvoid wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) 247189251Ssam{ 248252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout"); 249189251Ssam eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 250189251Ssam wpa_blacklist_del(wpa_s, wpa_s->bssid); 251189251Ssam} 252189251Ssam 253189251Ssam 254189251Ssam/** 255189251Ssam * wpa_supplicant_initiate_eapol - Configure EAPOL state machine 256189251Ssam * @wpa_s: Pointer to wpa_supplicant data 257189251Ssam * 258189251Ssam * This function is used to configure EAPOL state machine based on the selected 259189251Ssam * authentication mode. 260189251Ssam */ 261189251Ssamvoid wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) 262189251Ssam{ 263189251Ssam#ifdef IEEE8021X_EAPOL 264189251Ssam struct eapol_config eapol_conf; 265189251Ssam struct wpa_ssid *ssid = wpa_s->current_ssid; 266189251Ssam 267214734Srpaulo#ifdef CONFIG_IBSS_RSN 268214734Srpaulo if (ssid->mode == WPAS_MODE_IBSS && 269214734Srpaulo wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && 270214734Srpaulo wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) { 271214734Srpaulo /* 272214734Srpaulo * RSN IBSS authentication is per-STA and we can disable the 273214734Srpaulo * per-BSSID EAPOL authentication. 274214734Srpaulo */ 275214734Srpaulo eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); 276214734Srpaulo eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); 277214734Srpaulo eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); 278214734Srpaulo return; 279214734Srpaulo } 280214734Srpaulo#endif /* CONFIG_IBSS_RSN */ 281214734Srpaulo 282189251Ssam eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); 283189251Ssam eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); 284189251Ssam 285189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || 286189251Ssam wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) 287189251Ssam eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); 288189251Ssam else 289189251Ssam eapol_sm_notify_portControl(wpa_s->eapol, Auto); 290189251Ssam 291189251Ssam os_memset(&eapol_conf, 0, sizeof(eapol_conf)); 292189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 293189251Ssam eapol_conf.accept_802_1x_keys = 1; 294189251Ssam eapol_conf.required_keys = 0; 295189251Ssam if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) { 296189251Ssam eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST; 297189251Ssam } 298189251Ssam if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) { 299189251Ssam eapol_conf.required_keys |= 300189251Ssam EAPOL_REQUIRE_KEY_BROADCAST; 301189251Ssam } 302189251Ssam 303214734Srpaulo if (wpa_s->conf && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) 304189251Ssam eapol_conf.required_keys = 0; 305189251Ssam } 306189251Ssam if (wpa_s->conf) 307189251Ssam eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; 308189251Ssam eapol_conf.workaround = ssid->eap_workaround; 309189251Ssam eapol_conf.eap_disabled = 310189251Ssam !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && 311189251Ssam wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA && 312189251Ssam wpa_s->key_mgmt != WPA_KEY_MGMT_WPS; 313189251Ssam eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf); 314189251Ssam#endif /* IEEE8021X_EAPOL */ 315189251Ssam} 316189251Ssam 317189251Ssam 318189251Ssam/** 319189251Ssam * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode 320189251Ssam * @wpa_s: Pointer to wpa_supplicant data 321189251Ssam * @ssid: Configuration data for the network 322189251Ssam * 323189251Ssam * This function is used to configure WPA state machine and related parameters 324189251Ssam * to a mode where WPA is not enabled. This is called as part of the 325189251Ssam * authentication configuration when the selected network does not use WPA. 326189251Ssam */ 327189251Ssamvoid wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, 328189251Ssam struct wpa_ssid *ssid) 329189251Ssam{ 330189251Ssam int i; 331189251Ssam 332189251Ssam if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) 333189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_WPS; 334189251Ssam else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) 335189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; 336189251Ssam else 337189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; 338189251Ssam wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0); 339189251Ssam wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0); 340189251Ssam wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 341189251Ssam wpa_s->pairwise_cipher = WPA_CIPHER_NONE; 342189251Ssam wpa_s->group_cipher = WPA_CIPHER_NONE; 343189251Ssam wpa_s->mgmt_group_cipher = 0; 344189251Ssam 345189251Ssam for (i = 0; i < NUM_WEP_KEYS; i++) { 346189251Ssam if (ssid->wep_key_len[i] > 5) { 347189251Ssam wpa_s->pairwise_cipher = WPA_CIPHER_WEP104; 348189251Ssam wpa_s->group_cipher = WPA_CIPHER_WEP104; 349189251Ssam break; 350189251Ssam } else if (ssid->wep_key_len[i] > 0) { 351189251Ssam wpa_s->pairwise_cipher = WPA_CIPHER_WEP40; 352189251Ssam wpa_s->group_cipher = WPA_CIPHER_WEP40; 353189251Ssam break; 354189251Ssam } 355189251Ssam } 356189251Ssam 357189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0); 358189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); 359189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE, 360189251Ssam wpa_s->pairwise_cipher); 361189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher); 362189251Ssam#ifdef CONFIG_IEEE80211W 363189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, 364189251Ssam wpa_s->mgmt_group_cipher); 365189251Ssam#endif /* CONFIG_IEEE80211W */ 366189251Ssam 367189251Ssam pmksa_cache_clear_current(wpa_s->wpa); 368189251Ssam} 369189251Ssam 370189251Ssam 371252726Srpaulovoid free_hw_features(struct wpa_supplicant *wpa_s) 372252726Srpaulo{ 373252726Srpaulo int i; 374252726Srpaulo if (wpa_s->hw.modes == NULL) 375252726Srpaulo return; 376252726Srpaulo 377252726Srpaulo for (i = 0; i < wpa_s->hw.num_modes; i++) { 378252726Srpaulo os_free(wpa_s->hw.modes[i].channels); 379252726Srpaulo os_free(wpa_s->hw.modes[i].rates); 380252726Srpaulo } 381252726Srpaulo 382252726Srpaulo os_free(wpa_s->hw.modes); 383252726Srpaulo wpa_s->hw.modes = NULL; 384252726Srpaulo} 385252726Srpaulo 386252726Srpaulo 387189251Ssamstatic void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) 388189251Ssam{ 389214734Srpaulo bgscan_deinit(wpa_s); 390252726Srpaulo autoscan_deinit(wpa_s); 391189251Ssam scard_deinit(wpa_s->scard); 392189251Ssam wpa_s->scard = NULL; 393189251Ssam wpa_sm_set_scard_ctx(wpa_s->wpa, NULL); 394189251Ssam eapol_sm_register_scard_ctx(wpa_s->eapol, NULL); 395189251Ssam l2_packet_deinit(wpa_s->l2); 396189251Ssam wpa_s->l2 = NULL; 397189251Ssam if (wpa_s->l2_br) { 398189251Ssam l2_packet_deinit(wpa_s->l2_br); 399189251Ssam wpa_s->l2_br = NULL; 400189251Ssam } 401189251Ssam 402189251Ssam if (wpa_s->conf != NULL) { 403214734Srpaulo struct wpa_ssid *ssid; 404214734Srpaulo for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 405214734Srpaulo wpas_notify_network_removed(wpa_s, ssid); 406189251Ssam } 407189251Ssam 408189251Ssam os_free(wpa_s->confname); 409189251Ssam wpa_s->confname = NULL; 410189251Ssam 411189251Ssam wpa_sm_set_eapol(wpa_s->wpa, NULL); 412189251Ssam eapol_sm_deinit(wpa_s->eapol); 413189251Ssam wpa_s->eapol = NULL; 414189251Ssam 415189251Ssam rsn_preauth_deinit(wpa_s->wpa); 416189251Ssam 417252726Srpaulo#ifdef CONFIG_TDLS 418252726Srpaulo wpa_tdls_deinit(wpa_s->wpa); 419252726Srpaulo#endif /* CONFIG_TDLS */ 420252726Srpaulo 421189251Ssam pmksa_candidate_free(wpa_s->wpa); 422189251Ssam wpa_sm_deinit(wpa_s->wpa); 423189251Ssam wpa_s->wpa = NULL; 424189251Ssam wpa_blacklist_clear(wpa_s); 425189251Ssam 426214734Srpaulo wpa_bss_deinit(wpa_s); 427189251Ssam 428189251Ssam wpa_supplicant_cancel_scan(wpa_s); 429189251Ssam wpa_supplicant_cancel_auth_timeout(wpa_s); 430252726Srpaulo eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); 431252726Srpaulo#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT 432252726Srpaulo eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report, 433252726Srpaulo wpa_s, NULL); 434252726Srpaulo#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ 435189251Ssam 436189251Ssam wpas_wps_deinit(wpa_s); 437209158Srpaulo 438209158Srpaulo wpabuf_free(wpa_s->pending_eapol_rx); 439209158Srpaulo wpa_s->pending_eapol_rx = NULL; 440214734Srpaulo 441214734Srpaulo#ifdef CONFIG_IBSS_RSN 442214734Srpaulo ibss_rsn_deinit(wpa_s->ibss_rsn); 443214734Srpaulo wpa_s->ibss_rsn = NULL; 444214734Srpaulo#endif /* CONFIG_IBSS_RSN */ 445214734Srpaulo 446252726Srpaulo sme_deinit(wpa_s); 447214734Srpaulo 448214734Srpaulo#ifdef CONFIG_AP 449214734Srpaulo wpa_supplicant_ap_deinit(wpa_s); 450214734Srpaulo#endif /* CONFIG_AP */ 451252726Srpaulo 452252726Srpaulo#ifdef CONFIG_P2P 453252726Srpaulo wpas_p2p_deinit(wpa_s); 454252726Srpaulo#endif /* CONFIG_P2P */ 455252726Srpaulo 456252726Srpaulo#ifdef CONFIG_OFFCHANNEL 457252726Srpaulo offchannel_deinit(wpa_s); 458252726Srpaulo#endif /* CONFIG_OFFCHANNEL */ 459252726Srpaulo 460252726Srpaulo wpa_supplicant_cancel_sched_scan(wpa_s); 461252726Srpaulo 462252726Srpaulo os_free(wpa_s->next_scan_freqs); 463252726Srpaulo wpa_s->next_scan_freqs = NULL; 464252726Srpaulo 465252726Srpaulo gas_query_deinit(wpa_s->gas); 466252726Srpaulo wpa_s->gas = NULL; 467252726Srpaulo 468252726Srpaulo free_hw_features(wpa_s); 469252726Srpaulo 470252726Srpaulo os_free(wpa_s->bssid_filter); 471252726Srpaulo wpa_s->bssid_filter = NULL; 472252726Srpaulo 473252726Srpaulo os_free(wpa_s->disallow_aps_bssid); 474252726Srpaulo wpa_s->disallow_aps_bssid = NULL; 475252726Srpaulo os_free(wpa_s->disallow_aps_ssid); 476252726Srpaulo wpa_s->disallow_aps_ssid = NULL; 477252726Srpaulo 478252726Srpaulo wnm_bss_keep_alive_deinit(wpa_s); 479252726Srpaulo 480252726Srpaulo ext_password_deinit(wpa_s->ext_pw); 481252726Srpaulo wpa_s->ext_pw = NULL; 482252726Srpaulo 483252726Srpaulo wpabuf_free(wpa_s->last_gas_resp); 484252726Srpaulo 485252726Srpaulo os_free(wpa_s->last_scan_res); 486252726Srpaulo wpa_s->last_scan_res = NULL; 487189251Ssam} 488189251Ssam 489189251Ssam 490189251Ssam/** 491189251Ssam * wpa_clear_keys - Clear keys configured for the driver 492189251Ssam * @wpa_s: Pointer to wpa_supplicant data 493189251Ssam * @addr: Previously used BSSID or %NULL if not available 494189251Ssam * 495189251Ssam * This function clears the encryption keys that has been previously configured 496189251Ssam * for the driver. 497189251Ssam */ 498189251Ssamvoid wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) 499189251Ssam{ 500189251Ssam if (wpa_s->keys_cleared) { 501189251Ssam /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have 502189251Ssam * timing issues with keys being cleared just before new keys 503189251Ssam * are set or just after association or something similar. This 504189251Ssam * shows up in group key handshake failing often because of the 505189251Ssam * client not receiving the first encrypted packets correctly. 506189251Ssam * Skipping some of the extra key clearing steps seems to help 507189251Ssam * in completing group key handshake more reliably. */ 508252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - " 509252726Srpaulo "skip key clearing"); 510189251Ssam return; 511189251Ssam } 512189251Ssam 513189251Ssam /* MLME-DELETEKEYS.request */ 514252726Srpaulo wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 515252726Srpaulo wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 516252726Srpaulo wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 517252726Srpaulo wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 518209158Srpaulo#ifdef CONFIG_IEEE80211W 519252726Srpaulo wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 520252726Srpaulo wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 521209158Srpaulo#endif /* CONFIG_IEEE80211W */ 522189251Ssam if (addr) { 523189251Ssam wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, 524189251Ssam 0); 525189251Ssam /* MLME-SETPROTECTION.request(None) */ 526189251Ssam wpa_drv_mlme_setprotection( 527189251Ssam wpa_s, addr, 528189251Ssam MLME_SETPROTECTION_PROTECT_TYPE_NONE, 529189251Ssam MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 530189251Ssam } 531189251Ssam wpa_s->keys_cleared = 1; 532189251Ssam} 533189251Ssam 534189251Ssam 535189251Ssam/** 536189251Ssam * wpa_supplicant_state_txt - Get the connection state name as a text string 537189251Ssam * @state: State (wpa_state; WPA_*) 538189251Ssam * Returns: The state name as a printable text string 539189251Ssam */ 540214734Srpauloconst char * wpa_supplicant_state_txt(enum wpa_states state) 541189251Ssam{ 542189251Ssam switch (state) { 543189251Ssam case WPA_DISCONNECTED: 544189251Ssam return "DISCONNECTED"; 545189251Ssam case WPA_INACTIVE: 546189251Ssam return "INACTIVE"; 547252726Srpaulo case WPA_INTERFACE_DISABLED: 548252726Srpaulo return "INTERFACE_DISABLED"; 549189251Ssam case WPA_SCANNING: 550189251Ssam return "SCANNING"; 551214734Srpaulo case WPA_AUTHENTICATING: 552214734Srpaulo return "AUTHENTICATING"; 553189251Ssam case WPA_ASSOCIATING: 554189251Ssam return "ASSOCIATING"; 555189251Ssam case WPA_ASSOCIATED: 556189251Ssam return "ASSOCIATED"; 557189251Ssam case WPA_4WAY_HANDSHAKE: 558189251Ssam return "4WAY_HANDSHAKE"; 559189251Ssam case WPA_GROUP_HANDSHAKE: 560189251Ssam return "GROUP_HANDSHAKE"; 561189251Ssam case WPA_COMPLETED: 562189251Ssam return "COMPLETED"; 563189251Ssam default: 564189251Ssam return "UNKNOWN"; 565189251Ssam } 566189251Ssam} 567189251Ssam 568189251Ssam 569252726Srpaulo#ifdef CONFIG_BGSCAN 570252726Srpaulo 571252726Srpaulostatic void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) 572252726Srpaulo{ 573252726Srpaulo if (wpas_driver_bss_selection(wpa_s)) 574252726Srpaulo return; 575252726Srpaulo if (wpa_s->current_ssid == wpa_s->bgscan_ssid) 576252726Srpaulo return; 577252726Srpaulo 578252726Srpaulo bgscan_deinit(wpa_s); 579252726Srpaulo if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) { 580252726Srpaulo if (bgscan_init(wpa_s, wpa_s->current_ssid)) { 581252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize " 582252726Srpaulo "bgscan"); 583252726Srpaulo /* 584252726Srpaulo * Live without bgscan; it is only used as a roaming 585252726Srpaulo * optimization, so the initial connection is not 586252726Srpaulo * affected. 587252726Srpaulo */ 588252726Srpaulo } else { 589252726Srpaulo struct wpa_scan_results *scan_res; 590252726Srpaulo wpa_s->bgscan_ssid = wpa_s->current_ssid; 591252726Srpaulo scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 592252726Srpaulo 0); 593252726Srpaulo if (scan_res) { 594252726Srpaulo bgscan_notify_scan(wpa_s, scan_res); 595252726Srpaulo wpa_scan_results_free(scan_res); 596252726Srpaulo } 597252726Srpaulo } 598252726Srpaulo } else 599252726Srpaulo wpa_s->bgscan_ssid = NULL; 600252726Srpaulo} 601252726Srpaulo 602252726Srpaulo 603252726Srpaulostatic void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s) 604252726Srpaulo{ 605252726Srpaulo if (wpa_s->bgscan_ssid != NULL) { 606252726Srpaulo bgscan_deinit(wpa_s); 607252726Srpaulo wpa_s->bgscan_ssid = NULL; 608252726Srpaulo } 609252726Srpaulo} 610252726Srpaulo 611252726Srpaulo#endif /* CONFIG_BGSCAN */ 612252726Srpaulo 613252726Srpaulo 614252726Srpaulostatic void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s) 615252726Srpaulo{ 616252726Srpaulo if (autoscan_init(wpa_s, 0)) 617252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan"); 618252726Srpaulo} 619252726Srpaulo 620252726Srpaulo 621252726Srpaulostatic void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s) 622252726Srpaulo{ 623252726Srpaulo autoscan_deinit(wpa_s); 624252726Srpaulo} 625252726Srpaulo 626252726Srpaulo 627252726Srpaulovoid wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s) 628252726Srpaulo{ 629252726Srpaulo if (wpa_s->wpa_state == WPA_DISCONNECTED || 630252726Srpaulo wpa_s->wpa_state == WPA_SCANNING) { 631252726Srpaulo autoscan_deinit(wpa_s); 632252726Srpaulo wpa_supplicant_start_autoscan(wpa_s); 633252726Srpaulo } 634252726Srpaulo} 635252726Srpaulo 636252726Srpaulo 637189251Ssam/** 638189251Ssam * wpa_supplicant_set_state - Set current connection state 639189251Ssam * @wpa_s: Pointer to wpa_supplicant data 640189251Ssam * @state: The new connection state 641189251Ssam * 642189251Ssam * This function is called whenever the connection state changes, e.g., 643189251Ssam * association is completed for WPA/WPA2 4-Way Handshake is started. 644189251Ssam */ 645214734Srpaulovoid wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, 646214734Srpaulo enum wpa_states state) 647189251Ssam{ 648214734Srpaulo enum wpa_states old_state = wpa_s->wpa_state; 649214734Srpaulo 650252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s", 651252726Srpaulo wpa_supplicant_state_txt(wpa_s->wpa_state), 652252726Srpaulo wpa_supplicant_state_txt(state)); 653189251Ssam 654209158Srpaulo if (state != WPA_SCANNING) 655209158Srpaulo wpa_supplicant_notify_scanning(wpa_s, 0); 656209158Srpaulo 657189251Ssam if (state == WPA_COMPLETED && wpa_s->new_connection) { 658189251Ssam#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 659189251Ssam struct wpa_ssid *ssid = wpa_s->current_ssid; 660189251Ssam wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to " 661252726Srpaulo MACSTR " completed [id=%d id_str=%s]", 662252726Srpaulo MAC2STR(wpa_s->bssid), 663189251Ssam ssid ? ssid->id : -1, 664189251Ssam ssid && ssid->id_str ? ssid->id_str : ""); 665189251Ssam#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 666252726Srpaulo wpas_clear_temp_disabled(wpa_s, ssid, 1); 667252726Srpaulo wpa_s->extra_blacklist_count = 0; 668189251Ssam wpa_s->new_connection = 0; 669189251Ssam wpa_drv_set_operstate(wpa_s, 1); 670252726Srpaulo#ifndef IEEE8021X_EAPOL 671252726Srpaulo wpa_drv_set_supp_port(wpa_s, 1); 672252726Srpaulo#endif /* IEEE8021X_EAPOL */ 673214734Srpaulo wpa_s->after_wps = 0; 674252726Srpaulo#ifdef CONFIG_P2P 675252726Srpaulo wpas_p2p_completed(wpa_s); 676252726Srpaulo#endif /* CONFIG_P2P */ 677252726Srpaulo 678252726Srpaulo sme_sched_obss_scan(wpa_s, 1); 679189251Ssam } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || 680189251Ssam state == WPA_ASSOCIATED) { 681189251Ssam wpa_s->new_connection = 1; 682189251Ssam wpa_drv_set_operstate(wpa_s, 0); 683252726Srpaulo#ifndef IEEE8021X_EAPOL 684252726Srpaulo wpa_drv_set_supp_port(wpa_s, 0); 685252726Srpaulo#endif /* IEEE8021X_EAPOL */ 686252726Srpaulo sme_sched_obss_scan(wpa_s, 0); 687189251Ssam } 688189251Ssam wpa_s->wpa_state = state; 689214734Srpaulo 690252726Srpaulo#ifdef CONFIG_BGSCAN 691252726Srpaulo if (state == WPA_COMPLETED) 692252726Srpaulo wpa_supplicant_start_bgscan(wpa_s); 693252726Srpaulo else 694252726Srpaulo wpa_supplicant_stop_bgscan(wpa_s); 695252726Srpaulo#endif /* CONFIG_BGSCAN */ 696252726Srpaulo 697252726Srpaulo if (state == WPA_AUTHENTICATING) 698252726Srpaulo wpa_supplicant_stop_autoscan(wpa_s); 699252726Srpaulo 700252726Srpaulo if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 701252726Srpaulo wpa_supplicant_start_autoscan(wpa_s); 702252726Srpaulo 703252726Srpaulo if (wpa_s->wpa_state != old_state) { 704214734Srpaulo wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state); 705252726Srpaulo 706252726Srpaulo if (wpa_s->wpa_state == WPA_COMPLETED || 707252726Srpaulo old_state == WPA_COMPLETED) 708252726Srpaulo wpas_notify_auth_changed(wpa_s); 709252726Srpaulo } 710189251Ssam} 711189251Ssam 712189251Ssam 713214734Srpaulovoid wpa_supplicant_terminate_proc(struct wpa_global *global) 714189251Ssam{ 715214734Srpaulo int pending = 0; 716214734Srpaulo#ifdef CONFIG_WPS 717214734Srpaulo struct wpa_supplicant *wpa_s = global->ifaces; 718214734Srpaulo while (wpa_s) { 719214734Srpaulo if (wpas_wps_terminate_pending(wpa_s) == 1) 720214734Srpaulo pending = 1; 721214734Srpaulo wpa_s = wpa_s->next; 722214734Srpaulo } 723214734Srpaulo#endif /* CONFIG_WPS */ 724214734Srpaulo if (pending) 725214734Srpaulo return; 726214734Srpaulo eloop_terminate(); 727214734Srpaulo} 728214734Srpaulo 729214734Srpaulo 730214734Srpaulostatic void wpa_supplicant_terminate(int sig, void *signal_ctx) 731214734Srpaulo{ 732214734Srpaulo struct wpa_global *global = signal_ctx; 733214734Srpaulo wpa_supplicant_terminate_proc(global); 734189251Ssam} 735189251Ssam 736189251Ssam 737252726Srpaulovoid wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s) 738189251Ssam{ 739214734Srpaulo enum wpa_states old_state = wpa_s->wpa_state; 740214734Srpaulo 741189251Ssam wpa_s->pairwise_cipher = 0; 742189251Ssam wpa_s->group_cipher = 0; 743189251Ssam wpa_s->mgmt_group_cipher = 0; 744189251Ssam wpa_s->key_mgmt = 0; 745252726Srpaulo if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) 746252726Srpaulo wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 747214734Srpaulo 748214734Srpaulo if (wpa_s->wpa_state != old_state) 749214734Srpaulo wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state); 750189251Ssam} 751189251Ssam 752189251Ssam 753189251Ssam/** 754189251Ssam * wpa_supplicant_reload_configuration - Reload configuration data 755189251Ssam * @wpa_s: Pointer to wpa_supplicant data 756189251Ssam * Returns: 0 on success or -1 if configuration parsing failed 757189251Ssam * 758189251Ssam * This function can be used to request that the configuration data is reloaded 759189251Ssam * (e.g., after configuration file change). This function is reloading 760189251Ssam * configuration only for one interface, so this may need to be called multiple 761189251Ssam * times if %wpa_supplicant is controlling multiple interfaces and all 762189251Ssam * interfaces need reconfiguration. 763189251Ssam */ 764189251Ssamint wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) 765189251Ssam{ 766189251Ssam struct wpa_config *conf; 767189251Ssam int reconf_ctrl; 768214734Srpaulo int old_ap_scan; 769214734Srpaulo 770189251Ssam if (wpa_s->confname == NULL) 771189251Ssam return -1; 772189251Ssam conf = wpa_config_read(wpa_s->confname); 773189251Ssam if (conf == NULL) { 774189251Ssam wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration " 775189251Ssam "file '%s' - exiting", wpa_s->confname); 776189251Ssam return -1; 777189251Ssam } 778252726Srpaulo conf->changed_parameters = (unsigned int) -1; 779189251Ssam 780189251Ssam reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface 781189251Ssam || (conf->ctrl_interface && wpa_s->conf->ctrl_interface && 782189251Ssam os_strcmp(conf->ctrl_interface, 783189251Ssam wpa_s->conf->ctrl_interface) != 0); 784189251Ssam 785189251Ssam if (reconf_ctrl && wpa_s->ctrl_iface) { 786189251Ssam wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); 787189251Ssam wpa_s->ctrl_iface = NULL; 788189251Ssam } 789189251Ssam 790189251Ssam eapol_sm_invalidate_cached_session(wpa_s->eapol); 791252726Srpaulo if (wpa_s->current_ssid) { 792252726Srpaulo wpa_supplicant_deauthenticate(wpa_s, 793252726Srpaulo WLAN_REASON_DEAUTH_LEAVING); 794252726Srpaulo } 795214734Srpaulo 796189251Ssam /* 797189251Ssam * TODO: should notify EAPOL SM about changes in opensc_engine_path, 798189251Ssam * pkcs11_engine_path, pkcs11_module_path. 799189251Ssam */ 800189251Ssam if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { 801189251Ssam /* 802189251Ssam * Clear forced success to clear EAP state for next 803189251Ssam * authentication. 804189251Ssam */ 805189251Ssam eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); 806189251Ssam } 807189251Ssam eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 808189251Ssam wpa_sm_set_config(wpa_s->wpa, NULL); 809252726Srpaulo wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 810189251Ssam wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); 811189251Ssam rsn_preauth_deinit(wpa_s->wpa); 812214734Srpaulo 813214734Srpaulo old_ap_scan = wpa_s->conf->ap_scan; 814189251Ssam wpa_config_free(wpa_s->conf); 815189251Ssam wpa_s->conf = conf; 816214734Srpaulo if (old_ap_scan != wpa_s->conf->ap_scan) 817214734Srpaulo wpas_notify_ap_scan_changed(wpa_s); 818214734Srpaulo 819189251Ssam if (reconf_ctrl) 820189251Ssam wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); 821189251Ssam 822252726Srpaulo wpa_supplicant_update_config(wpa_s); 823252726Srpaulo 824189251Ssam wpa_supplicant_clear_status(wpa_s); 825252726Srpaulo if (wpa_supplicant_enabled_networks(wpa_s)) { 826252726Srpaulo wpa_s->reassociate = 1; 827252726Srpaulo wpa_supplicant_req_scan(wpa_s, 0, 0); 828252726Srpaulo } 829252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed"); 830189251Ssam return 0; 831189251Ssam} 832189251Ssam 833189251Ssam 834214734Srpaulostatic void wpa_supplicant_reconfig(int sig, void *signal_ctx) 835189251Ssam{ 836214734Srpaulo struct wpa_global *global = signal_ctx; 837189251Ssam struct wpa_supplicant *wpa_s; 838189251Ssam for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 839252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring", 840252726Srpaulo sig); 841189251Ssam if (wpa_supplicant_reload_configuration(wpa_s) < 0) { 842214734Srpaulo wpa_supplicant_terminate_proc(global); 843189251Ssam } 844189251Ssam } 845189251Ssam} 846189251Ssam 847189251Ssam 848214734Srpauloenum wpa_cipher cipher_suite2driver(int cipher) 849189251Ssam{ 850189251Ssam switch (cipher) { 851189251Ssam case WPA_CIPHER_NONE: 852189251Ssam return CIPHER_NONE; 853189251Ssam case WPA_CIPHER_WEP40: 854189251Ssam return CIPHER_WEP40; 855189251Ssam case WPA_CIPHER_WEP104: 856189251Ssam return CIPHER_WEP104; 857189251Ssam case WPA_CIPHER_CCMP: 858189251Ssam return CIPHER_CCMP; 859252726Srpaulo case WPA_CIPHER_GCMP: 860252726Srpaulo return CIPHER_GCMP; 861189251Ssam case WPA_CIPHER_TKIP: 862189251Ssam default: 863189251Ssam return CIPHER_TKIP; 864189251Ssam } 865189251Ssam} 866189251Ssam 867189251Ssam 868214734Srpauloenum wpa_key_mgmt key_mgmt2driver(int key_mgmt) 869189251Ssam{ 870189251Ssam switch (key_mgmt) { 871189251Ssam case WPA_KEY_MGMT_NONE: 872189251Ssam return KEY_MGMT_NONE; 873189251Ssam case WPA_KEY_MGMT_IEEE8021X_NO_WPA: 874189251Ssam return KEY_MGMT_802_1X_NO_WPA; 875189251Ssam case WPA_KEY_MGMT_IEEE8021X: 876189251Ssam return KEY_MGMT_802_1X; 877189251Ssam case WPA_KEY_MGMT_WPA_NONE: 878189251Ssam return KEY_MGMT_WPA_NONE; 879189251Ssam case WPA_KEY_MGMT_FT_IEEE8021X: 880189251Ssam return KEY_MGMT_FT_802_1X; 881189251Ssam case WPA_KEY_MGMT_FT_PSK: 882189251Ssam return KEY_MGMT_FT_PSK; 883189251Ssam case WPA_KEY_MGMT_IEEE8021X_SHA256: 884189251Ssam return KEY_MGMT_802_1X_SHA256; 885189251Ssam case WPA_KEY_MGMT_PSK_SHA256: 886189251Ssam return KEY_MGMT_PSK_SHA256; 887189251Ssam case WPA_KEY_MGMT_WPS: 888189251Ssam return KEY_MGMT_WPS; 889189251Ssam case WPA_KEY_MGMT_PSK: 890189251Ssam default: 891189251Ssam return KEY_MGMT_PSK; 892189251Ssam } 893189251Ssam} 894189251Ssam 895189251Ssam 896189251Ssamstatic int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s, 897189251Ssam struct wpa_ssid *ssid, 898189251Ssam struct wpa_ie_data *ie) 899189251Ssam{ 900189251Ssam int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie); 901189251Ssam if (ret) { 902189251Ssam if (ret == -2) { 903189251Ssam wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE " 904189251Ssam "from association info"); 905189251Ssam } 906189251Ssam return -1; 907189251Ssam } 908189251Ssam 909252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set " 910252726Srpaulo "cipher suites"); 911189251Ssam if (!(ie->group_cipher & ssid->group_cipher)) { 912189251Ssam wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group " 913189251Ssam "cipher 0x%x (mask 0x%x) - reject", 914189251Ssam ie->group_cipher, ssid->group_cipher); 915189251Ssam return -1; 916189251Ssam } 917189251Ssam if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) { 918189251Ssam wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise " 919189251Ssam "cipher 0x%x (mask 0x%x) - reject", 920189251Ssam ie->pairwise_cipher, ssid->pairwise_cipher); 921189251Ssam return -1; 922189251Ssam } 923189251Ssam if (!(ie->key_mgmt & ssid->key_mgmt)) { 924189251Ssam wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key " 925189251Ssam "management 0x%x (mask 0x%x) - reject", 926189251Ssam ie->key_mgmt, ssid->key_mgmt); 927189251Ssam return -1; 928189251Ssam } 929189251Ssam 930189251Ssam#ifdef CONFIG_IEEE80211W 931189251Ssam if (!(ie->capabilities & WPA_CAPABILITY_MFPC) && 932252726Srpaulo (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? 933252726Srpaulo wpa_s->conf->pmf : ssid->ieee80211w) == 934252726Srpaulo MGMT_FRAME_PROTECTION_REQUIRED) { 935189251Ssam wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP " 936189251Ssam "that does not support management frame protection - " 937189251Ssam "reject"); 938189251Ssam return -1; 939189251Ssam } 940189251Ssam#endif /* CONFIG_IEEE80211W */ 941189251Ssam 942189251Ssam return 0; 943189251Ssam} 944189251Ssam 945189251Ssam 946189251Ssam/** 947189251Ssam * wpa_supplicant_set_suites - Set authentication and encryption parameters 948189251Ssam * @wpa_s: Pointer to wpa_supplicant data 949189251Ssam * @bss: Scan results for the selected BSS, or %NULL if not available 950189251Ssam * @ssid: Configuration data for the selected network 951189251Ssam * @wpa_ie: Buffer for the WPA/RSN IE 952189251Ssam * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the 953189251Ssam * used buffer length in case the functions returns success. 954189251Ssam * Returns: 0 on success or -1 on failure 955189251Ssam * 956189251Ssam * This function is used to configure authentication and encryption parameters 957189251Ssam * based on the network configuration and scan result for the selected BSS (if 958189251Ssam * available). 959189251Ssam */ 960189251Ssamint wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, 961214734Srpaulo struct wpa_bss *bss, struct wpa_ssid *ssid, 962189251Ssam u8 *wpa_ie, size_t *wpa_ie_len) 963189251Ssam{ 964189251Ssam struct wpa_ie_data ie; 965189251Ssam int sel, proto; 966189251Ssam const u8 *bss_wpa, *bss_rsn; 967189251Ssam 968189251Ssam if (bss) { 969214734Srpaulo bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 970214734Srpaulo bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 971189251Ssam } else 972189251Ssam bss_wpa = bss_rsn = NULL; 973189251Ssam 974189251Ssam if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) && 975189251Ssam wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 && 976189251Ssam (ie.group_cipher & ssid->group_cipher) && 977189251Ssam (ie.pairwise_cipher & ssid->pairwise_cipher) && 978189251Ssam (ie.key_mgmt & ssid->key_mgmt)) { 979252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); 980189251Ssam proto = WPA_PROTO_RSN; 981189251Ssam } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) && 982189251Ssam wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 && 983189251Ssam (ie.group_cipher & ssid->group_cipher) && 984189251Ssam (ie.pairwise_cipher & ssid->pairwise_cipher) && 985189251Ssam (ie.key_mgmt & ssid->key_mgmt)) { 986252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); 987189251Ssam proto = WPA_PROTO_WPA; 988189251Ssam } else if (bss) { 989189251Ssam wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN"); 990189251Ssam return -1; 991189251Ssam } else { 992189251Ssam if (ssid->proto & WPA_PROTO_RSN) 993189251Ssam proto = WPA_PROTO_RSN; 994189251Ssam else 995189251Ssam proto = WPA_PROTO_WPA; 996189251Ssam if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) { 997189251Ssam os_memset(&ie, 0, sizeof(ie)); 998189251Ssam ie.group_cipher = ssid->group_cipher; 999189251Ssam ie.pairwise_cipher = ssid->pairwise_cipher; 1000189251Ssam ie.key_mgmt = ssid->key_mgmt; 1001189251Ssam#ifdef CONFIG_IEEE80211W 1002189251Ssam ie.mgmt_group_cipher = 1003214734Srpaulo ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ? 1004189251Ssam WPA_CIPHER_AES_128_CMAC : 0; 1005189251Ssam#endif /* CONFIG_IEEE80211W */ 1006252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites " 1007252726Srpaulo "based on configuration"); 1008189251Ssam } else 1009189251Ssam proto = ie.proto; 1010189251Ssam } 1011189251Ssam 1012252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d " 1013252726Srpaulo "pairwise %d key_mgmt %d proto %d", 1014252726Srpaulo ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto); 1015189251Ssam#ifdef CONFIG_IEEE80211W 1016189251Ssam if (ssid->ieee80211w) { 1017252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d", 1018252726Srpaulo ie.mgmt_group_cipher); 1019189251Ssam } 1020189251Ssam#endif /* CONFIG_IEEE80211W */ 1021189251Ssam 1022252726Srpaulo wpa_s->wpa_proto = proto; 1023189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto); 1024189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 1025189251Ssam !!(ssid->proto & WPA_PROTO_RSN)); 1026189251Ssam 1027189251Ssam if (bss || !wpa_s->ap_ies_from_associnfo) { 1028189251Ssam if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa, 1029189251Ssam bss_wpa ? 2 + bss_wpa[1] : 0) || 1030189251Ssam wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn, 1031189251Ssam bss_rsn ? 2 + bss_rsn[1] : 0)) 1032189251Ssam return -1; 1033189251Ssam } 1034189251Ssam 1035189251Ssam sel = ie.group_cipher & ssid->group_cipher; 1036189251Ssam if (sel & WPA_CIPHER_CCMP) { 1037189251Ssam wpa_s->group_cipher = WPA_CIPHER_CCMP; 1038252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK CCMP"); 1039252726Srpaulo } else if (sel & WPA_CIPHER_GCMP) { 1040252726Srpaulo wpa_s->group_cipher = WPA_CIPHER_GCMP; 1041252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK GCMP"); 1042189251Ssam } else if (sel & WPA_CIPHER_TKIP) { 1043189251Ssam wpa_s->group_cipher = WPA_CIPHER_TKIP; 1044252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK TKIP"); 1045189251Ssam } else if (sel & WPA_CIPHER_WEP104) { 1046189251Ssam wpa_s->group_cipher = WPA_CIPHER_WEP104; 1047252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP104"); 1048189251Ssam } else if (sel & WPA_CIPHER_WEP40) { 1049189251Ssam wpa_s->group_cipher = WPA_CIPHER_WEP40; 1050252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40"); 1051189251Ssam } else { 1052252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group " 1053252726Srpaulo "cipher"); 1054189251Ssam return -1; 1055189251Ssam } 1056189251Ssam 1057189251Ssam sel = ie.pairwise_cipher & ssid->pairwise_cipher; 1058189251Ssam if (sel & WPA_CIPHER_CCMP) { 1059189251Ssam wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; 1060252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK CCMP"); 1061252726Srpaulo } else if (sel & WPA_CIPHER_GCMP) { 1062252726Srpaulo wpa_s->pairwise_cipher = WPA_CIPHER_GCMP; 1063252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK GCMP"); 1064189251Ssam } else if (sel & WPA_CIPHER_TKIP) { 1065189251Ssam wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; 1066252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK TKIP"); 1067189251Ssam } else if (sel & WPA_CIPHER_NONE) { 1068189251Ssam wpa_s->pairwise_cipher = WPA_CIPHER_NONE; 1069252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE"); 1070189251Ssam } else { 1071252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise " 1072252726Srpaulo "cipher"); 1073189251Ssam return -1; 1074189251Ssam } 1075189251Ssam 1076189251Ssam sel = ie.key_mgmt & ssid->key_mgmt; 1077252726Srpaulo#ifdef CONFIG_SAE 1078252726Srpaulo if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) 1079252726Srpaulo sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); 1080252726Srpaulo#endif /* CONFIG_SAE */ 1081189251Ssam if (0) { 1082189251Ssam#ifdef CONFIG_IEEE80211R 1083189251Ssam } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) { 1084189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; 1085252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X"); 1086189251Ssam } else if (sel & WPA_KEY_MGMT_FT_PSK) { 1087189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK; 1088252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK"); 1089189251Ssam#endif /* CONFIG_IEEE80211R */ 1090252726Srpaulo#ifdef CONFIG_SAE 1091252726Srpaulo } else if (sel & WPA_KEY_MGMT_SAE) { 1092252726Srpaulo wpa_s->key_mgmt = WPA_KEY_MGMT_SAE; 1093252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE"); 1094252726Srpaulo } else if (sel & WPA_KEY_MGMT_FT_SAE) { 1095252726Srpaulo wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE; 1096252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE"); 1097252726Srpaulo#endif /* CONFIG_SAE */ 1098189251Ssam#ifdef CONFIG_IEEE80211W 1099189251Ssam } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1100189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; 1101252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, 1102189251Ssam "WPA: using KEY_MGMT 802.1X with SHA256"); 1103189251Ssam } else if (sel & WPA_KEY_MGMT_PSK_SHA256) { 1104189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256; 1105252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, 1106189251Ssam "WPA: using KEY_MGMT PSK with SHA256"); 1107189251Ssam#endif /* CONFIG_IEEE80211W */ 1108189251Ssam } else if (sel & WPA_KEY_MGMT_IEEE8021X) { 1109189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 1110252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X"); 1111189251Ssam } else if (sel & WPA_KEY_MGMT_PSK) { 1112189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; 1113252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK"); 1114189251Ssam } else if (sel & WPA_KEY_MGMT_WPA_NONE) { 1115189251Ssam wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE; 1116252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE"); 1117189251Ssam } else { 1118252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select " 1119252726Srpaulo "authenticated key management type"); 1120189251Ssam return -1; 1121189251Ssam } 1122189251Ssam 1123189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); 1124189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE, 1125189251Ssam wpa_s->pairwise_cipher); 1126189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher); 1127189251Ssam 1128189251Ssam#ifdef CONFIG_IEEE80211W 1129189251Ssam sel = ie.mgmt_group_cipher; 1130252726Srpaulo if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? 1131252726Srpaulo wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION || 1132189251Ssam !(ie.capabilities & WPA_CAPABILITY_MFPC)) 1133189251Ssam sel = 0; 1134189251Ssam if (sel & WPA_CIPHER_AES_128_CMAC) { 1135189251Ssam wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; 1136252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher " 1137189251Ssam "AES-128-CMAC"); 1138189251Ssam } else { 1139189251Ssam wpa_s->mgmt_group_cipher = 0; 1140252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher"); 1141189251Ssam } 1142189251Ssam wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, 1143189251Ssam wpa_s->mgmt_group_cipher); 1144252726Srpaulo wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, 1145252726Srpaulo (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? 1146252726Srpaulo wpa_s->conf->pmf : ssid->ieee80211w)); 1147189251Ssam#endif /* CONFIG_IEEE80211W */ 1148189251Ssam 1149189251Ssam if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { 1150252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE"); 1151189251Ssam return -1; 1152189251Ssam } 1153189251Ssam 1154252726Srpaulo if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { 1155189251Ssam wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN); 1156252726Srpaulo#ifndef CONFIG_NO_PBKDF2 1157252726Srpaulo if (bss && ssid->bssid_set && ssid->ssid_len == 0 && 1158252726Srpaulo ssid->passphrase) { 1159252726Srpaulo u8 psk[PMK_LEN]; 1160252726Srpaulo pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len, 1161252726Srpaulo 4096, psk, PMK_LEN); 1162252726Srpaulo wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", 1163252726Srpaulo psk, PMK_LEN); 1164252726Srpaulo wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); 1165252726Srpaulo } 1166252726Srpaulo#endif /* CONFIG_NO_PBKDF2 */ 1167252726Srpaulo#ifdef CONFIG_EXT_PASSWORD 1168252726Srpaulo if (ssid->ext_psk) { 1169252726Srpaulo struct wpabuf *pw = ext_password_get(wpa_s->ext_pw, 1170252726Srpaulo ssid->ext_psk); 1171252726Srpaulo char pw_str[64 + 1]; 1172252726Srpaulo u8 psk[PMK_LEN]; 1173252726Srpaulo 1174252726Srpaulo if (pw == NULL) { 1175252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK " 1176252726Srpaulo "found from external storage"); 1177252726Srpaulo return -1; 1178252726Srpaulo } 1179252726Srpaulo 1180252726Srpaulo if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) { 1181252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected " 1182252726Srpaulo "PSK length %d in external storage", 1183252726Srpaulo (int) wpabuf_len(pw)); 1184252726Srpaulo ext_password_free(pw); 1185252726Srpaulo return -1; 1186252726Srpaulo } 1187252726Srpaulo 1188252726Srpaulo os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw)); 1189252726Srpaulo pw_str[wpabuf_len(pw)] = '\0'; 1190252726Srpaulo 1191252726Srpaulo#ifndef CONFIG_NO_PBKDF2 1192252726Srpaulo if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss) 1193252726Srpaulo { 1194252726Srpaulo pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len, 1195252726Srpaulo 4096, psk, PMK_LEN); 1196252726Srpaulo os_memset(pw_str, 0, sizeof(pw_str)); 1197252726Srpaulo wpa_hexdump_key(MSG_MSGDUMP, "PSK (from " 1198252726Srpaulo "external passphrase)", 1199252726Srpaulo psk, PMK_LEN); 1200252726Srpaulo wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); 1201252726Srpaulo } else 1202252726Srpaulo#endif /* CONFIG_NO_PBKDF2 */ 1203252726Srpaulo if (wpabuf_len(pw) == 2 * PMK_LEN) { 1204252726Srpaulo if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) { 1205252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "EXT PW: " 1206252726Srpaulo "Invalid PSK hex string"); 1207252726Srpaulo os_memset(pw_str, 0, sizeof(pw_str)); 1208252726Srpaulo ext_password_free(pw); 1209252726Srpaulo return -1; 1210252726Srpaulo } 1211252726Srpaulo wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); 1212252726Srpaulo } else { 1213252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable " 1214252726Srpaulo "PSK available"); 1215252726Srpaulo os_memset(pw_str, 0, sizeof(pw_str)); 1216252726Srpaulo ext_password_free(pw); 1217252726Srpaulo return -1; 1218252726Srpaulo } 1219252726Srpaulo 1220252726Srpaulo os_memset(pw_str, 0, sizeof(pw_str)); 1221252726Srpaulo ext_password_free(pw); 1222252726Srpaulo } 1223252726Srpaulo#endif /* CONFIG_EXT_PASSWORD */ 1224252726Srpaulo } else 1225189251Ssam wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); 1226189251Ssam 1227189251Ssam return 0; 1228189251Ssam} 1229189251Ssam 1230189251Ssam 1231252726Srpauloint wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf) 1232252726Srpaulo{ 1233252726Srpaulo u32 ext_capab = 0; 1234252726Srpaulo u8 *pos = buf; 1235252726Srpaulo 1236252726Srpaulo#ifdef CONFIG_INTERWORKING 1237252726Srpaulo if (wpa_s->conf->interworking) 1238252726Srpaulo ext_capab |= BIT(31); /* Interworking */ 1239252726Srpaulo#endif /* CONFIG_INTERWORKING */ 1240252726Srpaulo 1241252726Srpaulo#ifdef CONFIG_WNM 1242252726Srpaulo ext_capab |= BIT(17); /* WNM-Sleep Mode */ 1243252726Srpaulo ext_capab |= BIT(19); /* BSS Transition */ 1244252726Srpaulo#endif /* CONFIG_WNM */ 1245252726Srpaulo 1246252726Srpaulo if (!ext_capab) 1247252726Srpaulo return 0; 1248252726Srpaulo 1249252726Srpaulo *pos++ = WLAN_EID_EXT_CAPAB; 1250252726Srpaulo *pos++ = 4; 1251252726Srpaulo WPA_PUT_LE32(pos, ext_capab); 1252252726Srpaulo pos += 4; 1253252726Srpaulo 1254252726Srpaulo return pos - buf; 1255252726Srpaulo} 1256252726Srpaulo 1257252726Srpaulo 1258189251Ssam/** 1259189251Ssam * wpa_supplicant_associate - Request association 1260189251Ssam * @wpa_s: Pointer to wpa_supplicant data 1261189251Ssam * @bss: Scan results for the selected BSS, or %NULL if not available 1262189251Ssam * @ssid: Configuration data for the selected network 1263189251Ssam * 1264189251Ssam * This function is used to request %wpa_supplicant to associate with a BSS. 1265189251Ssam */ 1266189251Ssamvoid wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 1267214734Srpaulo struct wpa_bss *bss, struct wpa_ssid *ssid) 1268189251Ssam{ 1269252726Srpaulo u8 wpa_ie[200]; 1270189251Ssam size_t wpa_ie_len; 1271214734Srpaulo int use_crypt, ret, i, bssid_changed; 1272214734Srpaulo int algs = WPA_AUTH_ALG_OPEN; 1273214734Srpaulo enum wpa_cipher cipher_pairwise, cipher_group; 1274189251Ssam struct wpa_driver_associate_params params; 1275189251Ssam int wep_keys_set = 0; 1276189251Ssam struct wpa_driver_capa capa; 1277189251Ssam int assoc_failed = 0; 1278214734Srpaulo struct wpa_ssid *old_ssid; 1279252726Srpaulo u8 ext_capab[10]; 1280252726Srpaulo int ext_capab_len; 1281252726Srpaulo#ifdef CONFIG_HT_OVERRIDES 1282252726Srpaulo struct ieee80211_ht_capabilities htcaps; 1283252726Srpaulo struct ieee80211_ht_capabilities htcaps_mask; 1284252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */ 1285189251Ssam 1286252726Srpaulo#ifdef CONFIG_IBSS_RSN 1287252726Srpaulo ibss_rsn_deinit(wpa_s->ibss_rsn); 1288252726Srpaulo wpa_s->ibss_rsn = NULL; 1289252726Srpaulo#endif /* CONFIG_IBSS_RSN */ 1290252726Srpaulo 1291252726Srpaulo if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO || 1292252726Srpaulo ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) { 1293214734Srpaulo#ifdef CONFIG_AP 1294214734Srpaulo if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) { 1295252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP " 1296252726Srpaulo "mode"); 1297214734Srpaulo return; 1298214734Srpaulo } 1299252726Srpaulo if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) { 1300252726Srpaulo wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 1301252726Srpaulo return; 1302252726Srpaulo } 1303214734Srpaulo wpa_s->current_bss = bss; 1304214734Srpaulo#else /* CONFIG_AP */ 1305252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in " 1306252726Srpaulo "the build"); 1307214734Srpaulo#endif /* CONFIG_AP */ 1308214734Srpaulo return; 1309214734Srpaulo } 1310214734Srpaulo 1311252726Srpaulo#ifdef CONFIG_TDLS 1312252726Srpaulo if (bss) 1313252726Srpaulo wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1), 1314252726Srpaulo bss->ie_len); 1315252726Srpaulo#endif /* CONFIG_TDLS */ 1316252726Srpaulo 1317214734Srpaulo if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && 1318214734Srpaulo ssid->mode == IEEE80211_MODE_INFRA) { 1319214734Srpaulo sme_authenticate(wpa_s, bss, ssid); 1320214734Srpaulo return; 1321214734Srpaulo } 1322214734Srpaulo 1323252726Srpaulo os_memset(¶ms, 0, sizeof(params)); 1324189251Ssam wpa_s->reassociate = 0; 1325252726Srpaulo if (bss && !wpas_driver_bss_selection(wpa_s)) { 1326189251Ssam#ifdef CONFIG_IEEE80211R 1327214734Srpaulo const u8 *ie, *md = NULL; 1328189251Ssam#endif /* CONFIG_IEEE80211R */ 1329189251Ssam wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR 1330189251Ssam " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid), 1331214734Srpaulo wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq); 1332214734Srpaulo bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 1333189251Ssam os_memset(wpa_s->bssid, 0, ETH_ALEN); 1334189251Ssam os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); 1335214734Srpaulo if (bssid_changed) 1336214734Srpaulo wpas_notify_bssid_changed(wpa_s); 1337189251Ssam#ifdef CONFIG_IEEE80211R 1338214734Srpaulo ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 1339189251Ssam if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) 1340189251Ssam md = ie + 2; 1341214734Srpaulo wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); 1342189251Ssam if (md) { 1343189251Ssam /* Prepare for the next transition */ 1344214734Srpaulo wpa_ft_prepare_auth_request(wpa_s->wpa, ie); 1345189251Ssam } 1346189251Ssam#endif /* CONFIG_IEEE80211R */ 1347189251Ssam#ifdef CONFIG_WPS 1348189251Ssam } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) && 1349189251Ssam wpa_s->conf->ap_scan == 2 && 1350189251Ssam (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { 1351189251Ssam /* Use ap_scan==1 style network selection to find the network 1352189251Ssam */ 1353252726Srpaulo wpa_s->scan_req = MANUAL_SCAN_REQ; 1354189251Ssam wpa_s->reassociate = 1; 1355189251Ssam wpa_supplicant_req_scan(wpa_s, 0, 0); 1356189251Ssam return; 1357189251Ssam#endif /* CONFIG_WPS */ 1358189251Ssam } else { 1359189251Ssam wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'", 1360189251Ssam wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 1361189251Ssam os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 1362189251Ssam } 1363252726Srpaulo wpa_supplicant_cancel_sched_scan(wpa_s); 1364189251Ssam wpa_supplicant_cancel_scan(wpa_s); 1365189251Ssam 1366189251Ssam /* Starting new association, so clear the possibly used WPA IE from the 1367189251Ssam * previous association. */ 1368189251Ssam wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 1369189251Ssam 1370189251Ssam#ifdef IEEE8021X_EAPOL 1371189251Ssam if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1372189251Ssam if (ssid->leap) { 1373189251Ssam if (ssid->non_leap == 0) 1374214734Srpaulo algs = WPA_AUTH_ALG_LEAP; 1375189251Ssam else 1376214734Srpaulo algs |= WPA_AUTH_ALG_LEAP; 1377189251Ssam } 1378189251Ssam } 1379189251Ssam#endif /* IEEE8021X_EAPOL */ 1380252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs); 1381189251Ssam if (ssid->auth_alg) { 1382214734Srpaulo algs = ssid->auth_alg; 1383252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " 1384252726Srpaulo "0x%x", algs); 1385189251Ssam } 1386189251Ssam 1387214734Srpaulo if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || 1388214734Srpaulo wpa_bss_get_ie(bss, WLAN_EID_RSN)) && 1389252726Srpaulo wpa_key_mgmt_wpa(ssid->key_mgmt)) { 1390189251Ssam int try_opportunistic; 1391252726Srpaulo try_opportunistic = (ssid->proactive_key_caching < 0 ? 1392252726Srpaulo wpa_s->conf->okc : 1393252726Srpaulo ssid->proactive_key_caching) && 1394189251Ssam (ssid->proto & WPA_PROTO_RSN); 1395189251Ssam if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, 1396189251Ssam wpa_s->current_ssid, 1397189251Ssam try_opportunistic) == 0) 1398189251Ssam eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); 1399189251Ssam wpa_ie_len = sizeof(wpa_ie); 1400189251Ssam if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 1401189251Ssam wpa_ie, &wpa_ie_len)) { 1402252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA " 1403252726Srpaulo "key management and encryption suites"); 1404189251Ssam return; 1405189251Ssam } 1406252726Srpaulo } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss && 1407252726Srpaulo wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { 1408252726Srpaulo /* 1409252726Srpaulo * Both WPA and non-WPA IEEE 802.1X enabled in configuration - 1410252726Srpaulo * use non-WPA since the scan results did not indicate that the 1411252726Srpaulo * AP is using WPA or WPA2. 1412252726Srpaulo */ 1413252726Srpaulo wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 1414252726Srpaulo wpa_ie_len = 0; 1415252726Srpaulo wpa_s->wpa_proto = 0; 1416252726Srpaulo } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { 1417189251Ssam wpa_ie_len = sizeof(wpa_ie); 1418189251Ssam if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, 1419189251Ssam wpa_ie, &wpa_ie_len)) { 1420252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA " 1421252726Srpaulo "key management and encryption suites (no " 1422252726Srpaulo "scan results)"); 1423189251Ssam return; 1424189251Ssam } 1425189251Ssam#ifdef CONFIG_WPS 1426189251Ssam } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 1427189251Ssam struct wpabuf *wps_ie; 1428189251Ssam wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); 1429189251Ssam if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) { 1430189251Ssam wpa_ie_len = wpabuf_len(wps_ie); 1431189251Ssam os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len); 1432189251Ssam } else 1433189251Ssam wpa_ie_len = 0; 1434189251Ssam wpabuf_free(wps_ie); 1435189251Ssam wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 1436252726Srpaulo if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY)) 1437252726Srpaulo params.wps = WPS_MODE_PRIVACY; 1438252726Srpaulo else 1439252726Srpaulo params.wps = WPS_MODE_OPEN; 1440252726Srpaulo wpa_s->wpa_proto = 0; 1441189251Ssam#endif /* CONFIG_WPS */ 1442189251Ssam } else { 1443189251Ssam wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 1444189251Ssam wpa_ie_len = 0; 1445252726Srpaulo wpa_s->wpa_proto = 0; 1446189251Ssam } 1447189251Ssam 1448252726Srpaulo#ifdef CONFIG_P2P 1449252726Srpaulo if (wpa_s->global->p2p) { 1450252726Srpaulo u8 *pos; 1451252726Srpaulo size_t len; 1452252726Srpaulo int res; 1453252726Srpaulo pos = wpa_ie + wpa_ie_len; 1454252726Srpaulo len = sizeof(wpa_ie) - wpa_ie_len; 1455252726Srpaulo res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, 1456252726Srpaulo ssid->p2p_group); 1457252726Srpaulo if (res >= 0) 1458252726Srpaulo wpa_ie_len += res; 1459252726Srpaulo } 1460252726Srpaulo 1461252726Srpaulo wpa_s->cross_connect_disallowed = 0; 1462252726Srpaulo if (bss) { 1463252726Srpaulo struct wpabuf *p2p; 1464252726Srpaulo p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE); 1465252726Srpaulo if (p2p) { 1466252726Srpaulo wpa_s->cross_connect_disallowed = 1467252726Srpaulo p2p_get_cross_connect_disallowed(p2p); 1468252726Srpaulo wpabuf_free(p2p); 1469252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross " 1470252726Srpaulo "connection", 1471252726Srpaulo wpa_s->cross_connect_disallowed ? 1472252726Srpaulo "disallows" : "allows"); 1473252726Srpaulo } 1474252726Srpaulo } 1475252726Srpaulo#endif /* CONFIG_P2P */ 1476252726Srpaulo 1477252726Srpaulo#ifdef CONFIG_HS20 1478252726Srpaulo if (wpa_s->conf->hs20) { 1479252726Srpaulo struct wpabuf *hs20; 1480252726Srpaulo hs20 = wpabuf_alloc(20); 1481252726Srpaulo if (hs20) { 1482252726Srpaulo wpas_hs20_add_indication(hs20); 1483252726Srpaulo os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20), 1484252726Srpaulo wpabuf_len(hs20)); 1485252726Srpaulo wpa_ie_len += wpabuf_len(hs20); 1486252726Srpaulo wpabuf_free(hs20); 1487252726Srpaulo } 1488252726Srpaulo } 1489252726Srpaulo#endif /* CONFIG_HS20 */ 1490252726Srpaulo 1491252726Srpaulo ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab); 1492252726Srpaulo if (ext_capab_len > 0) { 1493252726Srpaulo u8 *pos = wpa_ie; 1494252726Srpaulo if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN) 1495252726Srpaulo pos += 2 + pos[1]; 1496252726Srpaulo os_memmove(pos + ext_capab_len, pos, 1497252726Srpaulo wpa_ie_len - (pos - wpa_ie)); 1498252726Srpaulo wpa_ie_len += ext_capab_len; 1499252726Srpaulo os_memcpy(pos, ext_capab, ext_capab_len); 1500252726Srpaulo } 1501252726Srpaulo 1502189251Ssam wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); 1503189251Ssam use_crypt = 1; 1504189251Ssam cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher); 1505189251Ssam cipher_group = cipher_suite2driver(wpa_s->group_cipher); 1506189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || 1507189251Ssam wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1508189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) 1509189251Ssam use_crypt = 0; 1510189251Ssam if (wpa_set_wep_keys(wpa_s, ssid)) { 1511189251Ssam use_crypt = 1; 1512189251Ssam wep_keys_set = 1; 1513189251Ssam } 1514189251Ssam } 1515189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) 1516189251Ssam use_crypt = 0; 1517189251Ssam 1518189251Ssam#ifdef IEEE8021X_EAPOL 1519189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1520189251Ssam if ((ssid->eapol_flags & 1521189251Ssam (EAPOL_FLAG_REQUIRE_KEY_UNICAST | 1522189251Ssam EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 && 1523189251Ssam !wep_keys_set) { 1524189251Ssam use_crypt = 0; 1525189251Ssam } else { 1526189251Ssam /* Assume that dynamic WEP-104 keys will be used and 1527189251Ssam * set cipher suites in order for drivers to expect 1528189251Ssam * encryption. */ 1529189251Ssam cipher_pairwise = cipher_group = CIPHER_WEP104; 1530189251Ssam } 1531189251Ssam } 1532189251Ssam#endif /* IEEE8021X_EAPOL */ 1533189251Ssam 1534189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { 1535189251Ssam /* Set the key before (and later after) association */ 1536189251Ssam wpa_supplicant_set_wpa_none_key(wpa_s, ssid); 1537189251Ssam } 1538189251Ssam 1539189251Ssam wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); 1540189251Ssam if (bss) { 1541214734Srpaulo params.ssid = bss->ssid; 1542214734Srpaulo params.ssid_len = bss->ssid_len; 1543252726Srpaulo if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) { 1544252726Srpaulo wpa_printf(MSG_DEBUG, "Limit connection to BSSID " 1545252726Srpaulo MACSTR " freq=%u MHz based on scan results " 1546252726Srpaulo "(bssid_set=%d)", 1547252726Srpaulo MAC2STR(bss->bssid), bss->freq, 1548252726Srpaulo ssid->bssid_set); 1549252726Srpaulo params.bssid = bss->bssid; 1550252726Srpaulo params.freq = bss->freq; 1551252726Srpaulo } 1552189251Ssam } else { 1553189251Ssam params.ssid = ssid->ssid; 1554189251Ssam params.ssid_len = ssid->ssid_len; 1555189251Ssam } 1556252726Srpaulo 1557252726Srpaulo if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set && 1558252726Srpaulo wpa_s->conf->ap_scan == 2) { 1559252726Srpaulo params.bssid = ssid->bssid; 1560252726Srpaulo params.fixed_bssid = 1; 1561252726Srpaulo } 1562252726Srpaulo 1563214734Srpaulo if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 && 1564214734Srpaulo params.freq == 0) 1565189251Ssam params.freq = ssid->frequency; /* Initial channel for IBSS */ 1566189251Ssam params.wpa_ie = wpa_ie; 1567189251Ssam params.wpa_ie_len = wpa_ie_len; 1568189251Ssam params.pairwise_suite = cipher_pairwise; 1569189251Ssam params.group_suite = cipher_group; 1570189251Ssam params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt); 1571252726Srpaulo params.wpa_proto = wpa_s->wpa_proto; 1572189251Ssam params.auth_alg = algs; 1573189251Ssam params.mode = ssid->mode; 1574252726Srpaulo params.bg_scan_period = ssid->bg_scan_period; 1575189251Ssam for (i = 0; i < NUM_WEP_KEYS; i++) { 1576189251Ssam if (ssid->wep_key_len[i]) 1577189251Ssam params.wep_key[i] = ssid->wep_key[i]; 1578189251Ssam params.wep_key_len[i] = ssid->wep_key_len[i]; 1579189251Ssam } 1580189251Ssam params.wep_tx_keyidx = ssid->wep_tx_keyidx; 1581189251Ssam 1582214734Srpaulo if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && 1583189251Ssam (params.key_mgmt_suite == KEY_MGMT_PSK || 1584189251Ssam params.key_mgmt_suite == KEY_MGMT_FT_PSK)) { 1585189251Ssam params.passphrase = ssid->passphrase; 1586189251Ssam if (ssid->psk_set) 1587189251Ssam params.psk = ssid->psk; 1588189251Ssam } 1589189251Ssam 1590214734Srpaulo params.drop_unencrypted = use_crypt; 1591214734Srpaulo 1592189251Ssam#ifdef CONFIG_IEEE80211W 1593252726Srpaulo params.mgmt_frame_protection = 1594252726Srpaulo ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? 1595252726Srpaulo wpa_s->conf->pmf : ssid->ieee80211w; 1596252726Srpaulo if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) { 1597214734Srpaulo const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 1598189251Ssam struct wpa_ie_data ie; 1599189251Ssam if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 && 1600189251Ssam ie.capabilities & 1601189251Ssam (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { 1602252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports " 1603252726Srpaulo "MFP: require MFP"); 1604189251Ssam params.mgmt_frame_protection = 1605189251Ssam MGMT_FRAME_PROTECTION_REQUIRED; 1606189251Ssam } 1607189251Ssam } 1608189251Ssam#endif /* CONFIG_IEEE80211W */ 1609189251Ssam 1610252726Srpaulo params.p2p = ssid->p2p_group; 1611252726Srpaulo 1612252726Srpaulo if (wpa_s->parent->set_sta_uapsd) 1613252726Srpaulo params.uapsd = wpa_s->parent->sta_uapsd; 1614189251Ssam else 1615252726Srpaulo params.uapsd = -1; 1616252726Srpaulo 1617252726Srpaulo#ifdef CONFIG_HT_OVERRIDES 1618252726Srpaulo os_memset(&htcaps, 0, sizeof(htcaps)); 1619252726Srpaulo os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); 1620252726Srpaulo params.htcaps = (u8 *) &htcaps; 1621252726Srpaulo params.htcaps_mask = (u8 *) &htcaps_mask; 1622252726Srpaulo wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms); 1623252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */ 1624252726Srpaulo 1625252726Srpaulo ret = wpa_drv_associate(wpa_s, ¶ms); 1626189251Ssam if (ret < 0) { 1627189251Ssam wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " 1628189251Ssam "failed"); 1629252726Srpaulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) { 1630252726Srpaulo /* 1631252726Srpaulo * The driver is known to mean what is saying, so we 1632252726Srpaulo * can stop right here; the association will not 1633252726Srpaulo * succeed. 1634252726Srpaulo */ 1635252726Srpaulo wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 1636252726Srpaulo wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 1637252726Srpaulo os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 1638252726Srpaulo return; 1639252726Srpaulo } 1640189251Ssam /* try to continue anyway; new association will be tried again 1641189251Ssam * after timeout */ 1642189251Ssam assoc_failed = 1; 1643189251Ssam } 1644189251Ssam 1645189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { 1646189251Ssam /* Set the key after the association just in case association 1647189251Ssam * cleared the previously configured key. */ 1648189251Ssam wpa_supplicant_set_wpa_none_key(wpa_s, ssid); 1649189251Ssam /* No need to timeout authentication since there is no key 1650189251Ssam * management. */ 1651189251Ssam wpa_supplicant_cancel_auth_timeout(wpa_s); 1652189251Ssam wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 1653214734Srpaulo#ifdef CONFIG_IBSS_RSN 1654214734Srpaulo } else if (ssid->mode == WPAS_MODE_IBSS && 1655214734Srpaulo wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && 1656214734Srpaulo wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) { 1657214734Srpaulo /* 1658214734Srpaulo * RSN IBSS authentication is per-STA and we can disable the 1659214734Srpaulo * per-BSSID authentication. 1660214734Srpaulo */ 1661214734Srpaulo wpa_supplicant_cancel_auth_timeout(wpa_s); 1662214734Srpaulo#endif /* CONFIG_IBSS_RSN */ 1663189251Ssam } else { 1664189251Ssam /* Timeout for IEEE 802.11 authentication and association */ 1665189251Ssam int timeout = 60; 1666189251Ssam 1667189251Ssam if (assoc_failed) { 1668189251Ssam /* give IBSS a bit more time */ 1669214734Srpaulo timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5; 1670189251Ssam } else if (wpa_s->conf->ap_scan == 1) { 1671189251Ssam /* give IBSS a bit more time */ 1672214734Srpaulo timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10; 1673189251Ssam } 1674189251Ssam wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0); 1675189251Ssam } 1676189251Ssam 1677189251Ssam if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 && 1678189251Ssam capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) { 1679189251Ssam /* Set static WEP keys again */ 1680189251Ssam wpa_set_wep_keys(wpa_s, ssid); 1681189251Ssam } 1682189251Ssam 1683189251Ssam if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) { 1684189251Ssam /* 1685189251Ssam * Do not allow EAP session resumption between different 1686189251Ssam * network configurations. 1687189251Ssam */ 1688189251Ssam eapol_sm_invalidate_cached_session(wpa_s->eapol); 1689189251Ssam } 1690214734Srpaulo old_ssid = wpa_s->current_ssid; 1691189251Ssam wpa_s->current_ssid = ssid; 1692214734Srpaulo wpa_s->current_bss = bss; 1693189251Ssam wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); 1694189251Ssam wpa_supplicant_initiate_eapol(wpa_s); 1695214734Srpaulo if (old_ssid != wpa_s->current_ssid) 1696214734Srpaulo wpas_notify_network_changed(wpa_s); 1697189251Ssam} 1698189251Ssam 1699189251Ssam 1700252726Srpaulostatic void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s, 1701252726Srpaulo const u8 *addr) 1702189251Ssam{ 1703214734Srpaulo struct wpa_ssid *old_ssid; 1704214734Srpaulo 1705189251Ssam wpa_clear_keys(wpa_s, addr); 1706252726Srpaulo old_ssid = wpa_s->current_ssid; 1707189251Ssam wpa_supplicant_mark_disassoc(wpa_s); 1708189251Ssam wpa_sm_set_config(wpa_s->wpa, NULL); 1709189251Ssam eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 1710214734Srpaulo if (old_ssid != wpa_s->current_ssid) 1711214734Srpaulo wpas_notify_network_changed(wpa_s); 1712214734Srpaulo eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 1713189251Ssam} 1714189251Ssam 1715189251Ssam 1716189251Ssam/** 1717189251Ssam * wpa_supplicant_deauthenticate - Deauthenticate the current connection 1718189251Ssam * @wpa_s: Pointer to wpa_supplicant data 1719189251Ssam * @reason_code: IEEE 802.11 reason code for the deauthenticate frame 1720189251Ssam * 1721189251Ssam * This function is used to request %wpa_supplicant to deauthenticate from the 1722189251Ssam * current AP. 1723189251Ssam */ 1724189251Ssamvoid wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, 1725189251Ssam int reason_code) 1726189251Ssam{ 1727189251Ssam u8 *addr = NULL; 1728252726Srpaulo union wpa_event_data event; 1729252726Srpaulo int zero_addr = 0; 1730214734Srpaulo 1731252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR 1732252726Srpaulo " pending_bssid=" MACSTR " reason=%d state=%s", 1733252726Srpaulo MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid), 1734252726Srpaulo reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state)); 1735252726Srpaulo 1736252726Srpaulo if (!is_zero_ether_addr(wpa_s->bssid)) 1737189251Ssam addr = wpa_s->bssid; 1738252726Srpaulo else if (!is_zero_ether_addr(wpa_s->pending_bssid) && 1739252726Srpaulo (wpa_s->wpa_state == WPA_AUTHENTICATING || 1740252726Srpaulo wpa_s->wpa_state == WPA_ASSOCIATING)) 1741252726Srpaulo addr = wpa_s->pending_bssid; 1742252726Srpaulo else if (wpa_s->wpa_state == WPA_ASSOCIATING) { 1743252726Srpaulo /* 1744252726Srpaulo * When using driver-based BSS selection, we may not know the 1745252726Srpaulo * BSSID with which we are currently trying to associate. We 1746252726Srpaulo * need to notify the driver of this disconnection even in such 1747252726Srpaulo * a case, so use the all zeros address here. 1748252726Srpaulo */ 1749252726Srpaulo addr = wpa_s->bssid; 1750252726Srpaulo zero_addr = 1; 1751189251Ssam } 1752252726Srpaulo 1753252726Srpaulo if (addr) { 1754252726Srpaulo wpa_drv_deauthenticate(wpa_s, addr, reason_code); 1755252726Srpaulo os_memset(&event, 0, sizeof(event)); 1756252726Srpaulo event.deauth_info.reason_code = (u16) reason_code; 1757252726Srpaulo event.deauth_info.locally_generated = 1; 1758252726Srpaulo wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event); 1759252726Srpaulo if (zero_addr) 1760252726Srpaulo addr = NULL; 1761252726Srpaulo } 1762252726Srpaulo 1763252726Srpaulo wpa_supplicant_clear_connection(wpa_s, addr); 1764189251Ssam} 1765189251Ssam 1766189251Ssam 1767214734Srpaulo/** 1768214734Srpaulo * wpa_supplicant_enable_network - Mark a configured network as enabled 1769214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1770214734Srpaulo * @ssid: wpa_ssid structure for a configured network or %NULL 1771214734Srpaulo * 1772214734Srpaulo * Enables the specified network or all networks if no network specified. 1773214734Srpaulo */ 1774214734Srpaulovoid wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, 1775214734Srpaulo struct wpa_ssid *ssid) 1776189251Ssam{ 1777214734Srpaulo struct wpa_ssid *other_ssid; 1778214734Srpaulo int was_disabled; 1779189251Ssam 1780214734Srpaulo if (ssid == NULL) { 1781252726Srpaulo for (other_ssid = wpa_s->conf->ssid; other_ssid; 1782252726Srpaulo other_ssid = other_ssid->next) { 1783252726Srpaulo if (other_ssid->disabled == 2) 1784252726Srpaulo continue; /* do not change persistent P2P group 1785252726Srpaulo * data */ 1786214734Srpaulo if (other_ssid == wpa_s->current_ssid && 1787214734Srpaulo other_ssid->disabled) 1788214734Srpaulo wpa_s->reassociate = 1; 1789189251Ssam 1790214734Srpaulo was_disabled = other_ssid->disabled; 1791189251Ssam 1792214734Srpaulo other_ssid->disabled = 0; 1793252726Srpaulo if (was_disabled) 1794252726Srpaulo wpas_clear_temp_disabled(wpa_s, other_ssid, 0); 1795189251Ssam 1796214734Srpaulo if (was_disabled != other_ssid->disabled) 1797214734Srpaulo wpas_notify_network_enabled_changed( 1798214734Srpaulo wpa_s, other_ssid); 1799214734Srpaulo } 1800214734Srpaulo if (wpa_s->reassociate) 1801214734Srpaulo wpa_supplicant_req_scan(wpa_s, 0, 0); 1802252726Srpaulo } else if (ssid->disabled && ssid->disabled != 2) { 1803214734Srpaulo if (wpa_s->current_ssid == NULL) { 1804214734Srpaulo /* 1805214734Srpaulo * Try to reassociate since there is no current 1806214734Srpaulo * configuration and a new network was made available. 1807214734Srpaulo */ 1808214734Srpaulo wpa_s->reassociate = 1; 1809214734Srpaulo wpa_supplicant_req_scan(wpa_s, 0, 0); 1810214734Srpaulo } 1811189251Ssam 1812214734Srpaulo was_disabled = ssid->disabled; 1813189251Ssam 1814214734Srpaulo ssid->disabled = 0; 1815252726Srpaulo wpas_clear_temp_disabled(wpa_s, ssid, 1); 1816189251Ssam 1817214734Srpaulo if (was_disabled != ssid->disabled) 1818214734Srpaulo wpas_notify_network_enabled_changed(wpa_s, ssid); 1819214734Srpaulo } 1820214734Srpaulo} 1821189251Ssam 1822189251Ssam 1823214734Srpaulo/** 1824214734Srpaulo * wpa_supplicant_disable_network - Mark a configured network as disabled 1825214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1826214734Srpaulo * @ssid: wpa_ssid structure for a configured network or %NULL 1827214734Srpaulo * 1828214734Srpaulo * Disables the specified network or all networks if no network specified. 1829214734Srpaulo */ 1830214734Srpaulovoid wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, 1831214734Srpaulo struct wpa_ssid *ssid) 1832214734Srpaulo{ 1833214734Srpaulo struct wpa_ssid *other_ssid; 1834214734Srpaulo int was_disabled; 1835189251Ssam 1836214734Srpaulo if (ssid == NULL) { 1837252726Srpaulo for (other_ssid = wpa_s->conf->ssid; other_ssid; 1838252726Srpaulo other_ssid = other_ssid->next) { 1839214734Srpaulo was_disabled = other_ssid->disabled; 1840252726Srpaulo if (was_disabled == 2) 1841252726Srpaulo continue; /* do not change persistent P2P group 1842252726Srpaulo * data */ 1843189251Ssam 1844214734Srpaulo other_ssid->disabled = 1; 1845189251Ssam 1846214734Srpaulo if (was_disabled != other_ssid->disabled) 1847214734Srpaulo wpas_notify_network_enabled_changed( 1848214734Srpaulo wpa_s, other_ssid); 1849189251Ssam } 1850214734Srpaulo if (wpa_s->current_ssid) 1851252726Srpaulo wpa_supplicant_deauthenticate( 1852214734Srpaulo wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1853252726Srpaulo } else if (ssid->disabled != 2) { 1854214734Srpaulo if (ssid == wpa_s->current_ssid) 1855252726Srpaulo wpa_supplicant_deauthenticate( 1856214734Srpaulo wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1857189251Ssam 1858214734Srpaulo was_disabled = ssid->disabled; 1859214734Srpaulo 1860214734Srpaulo ssid->disabled = 1; 1861214734Srpaulo 1862214734Srpaulo if (was_disabled != ssid->disabled) 1863214734Srpaulo wpas_notify_network_enabled_changed(wpa_s, ssid); 1864189251Ssam } 1865214734Srpaulo} 1866189251Ssam 1867189251Ssam 1868214734Srpaulo/** 1869214734Srpaulo * wpa_supplicant_select_network - Attempt association with a network 1870214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1871214734Srpaulo * @ssid: wpa_ssid structure for a configured network or %NULL for any network 1872214734Srpaulo */ 1873214734Srpaulovoid wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, 1874214734Srpaulo struct wpa_ssid *ssid) 1875214734Srpaulo{ 1876214734Srpaulo 1877214734Srpaulo struct wpa_ssid *other_ssid; 1878252726Srpaulo int disconnected = 0; 1879214734Srpaulo 1880252726Srpaulo if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) { 1881252726Srpaulo wpa_supplicant_deauthenticate( 1882214734Srpaulo wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1883252726Srpaulo disconnected = 1; 1884252726Srpaulo } 1885214734Srpaulo 1886252726Srpaulo if (ssid) 1887252726Srpaulo wpas_clear_temp_disabled(wpa_s, ssid, 1); 1888252726Srpaulo 1889214734Srpaulo /* 1890214734Srpaulo * Mark all other networks disabled or mark all networks enabled if no 1891214734Srpaulo * network specified. 1892214734Srpaulo */ 1893252726Srpaulo for (other_ssid = wpa_s->conf->ssid; other_ssid; 1894252726Srpaulo other_ssid = other_ssid->next) { 1895214734Srpaulo int was_disabled = other_ssid->disabled; 1896252726Srpaulo if (was_disabled == 2) 1897252726Srpaulo continue; /* do not change persistent P2P group data */ 1898214734Srpaulo 1899214734Srpaulo other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0; 1900252726Srpaulo if (was_disabled && !other_ssid->disabled) 1901252726Srpaulo wpas_clear_temp_disabled(wpa_s, other_ssid, 0); 1902214734Srpaulo 1903214734Srpaulo if (was_disabled != other_ssid->disabled) 1904214734Srpaulo wpas_notify_network_enabled_changed(wpa_s, other_ssid); 1905252726Srpaulo } 1906214734Srpaulo 1907252726Srpaulo if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) { 1908252726Srpaulo /* We are already associated with the selected network */ 1909252726Srpaulo wpa_printf(MSG_DEBUG, "Already associated with the " 1910252726Srpaulo "selected network - do nothing"); 1911252726Srpaulo return; 1912214734Srpaulo } 1913252726Srpaulo 1914252726Srpaulo if (ssid) 1915252726Srpaulo wpa_s->current_ssid = ssid; 1916252726Srpaulo wpa_s->connect_without_scan = NULL; 1917214734Srpaulo wpa_s->disconnected = 0; 1918214734Srpaulo wpa_s->reassociate = 1; 1919252726Srpaulo wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0); 1920214734Srpaulo 1921214734Srpaulo if (ssid) 1922214734Srpaulo wpas_notify_network_selected(wpa_s, ssid); 1923189251Ssam} 1924189251Ssam 1925189251Ssam 1926189251Ssam/** 1927214734Srpaulo * wpa_supplicant_set_ap_scan - Set AP scan mode for interface 1928214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1929214734Srpaulo * @ap_scan: AP scan mode 1930214734Srpaulo * Returns: 0 if succeed or -1 if ap_scan has an invalid value 1931189251Ssam * 1932189251Ssam */ 1933214734Srpauloint wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan) 1934189251Ssam{ 1935189251Ssam 1936214734Srpaulo int old_ap_scan; 1937189251Ssam 1938214734Srpaulo if (ap_scan < 0 || ap_scan > 2) 1939214734Srpaulo return -1; 1940189251Ssam 1941252726Srpaulo#ifdef ANDROID 1942252726Srpaulo if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan && 1943252726Srpaulo wpa_s->wpa_state >= WPA_ASSOCIATING && 1944252726Srpaulo wpa_s->wpa_state < WPA_COMPLETED) { 1945252726Srpaulo wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while " 1946252726Srpaulo "associating", wpa_s->conf->ap_scan, ap_scan); 1947252726Srpaulo return 0; 1948252726Srpaulo } 1949252726Srpaulo#endif /* ANDROID */ 1950252726Srpaulo 1951214734Srpaulo old_ap_scan = wpa_s->conf->ap_scan; 1952214734Srpaulo wpa_s->conf->ap_scan = ap_scan; 1953214734Srpaulo 1954214734Srpaulo if (old_ap_scan != wpa_s->conf->ap_scan) 1955214734Srpaulo wpas_notify_ap_scan_changed(wpa_s); 1956214734Srpaulo 1957214734Srpaulo return 0; 1958189251Ssam} 1959189251Ssam 1960189251Ssam 1961189251Ssam/** 1962252726Srpaulo * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age 1963252726Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1964252726Srpaulo * @expire_age: Expiration age in seconds 1965252726Srpaulo * Returns: 0 if succeed or -1 if expire_age has an invalid value 1966252726Srpaulo * 1967252726Srpaulo */ 1968252726Srpauloint wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s, 1969252726Srpaulo unsigned int bss_expire_age) 1970252726Srpaulo{ 1971252726Srpaulo if (bss_expire_age < 10) { 1972252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u", 1973252726Srpaulo bss_expire_age); 1974252726Srpaulo return -1; 1975252726Srpaulo } 1976252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec", 1977252726Srpaulo bss_expire_age); 1978252726Srpaulo wpa_s->conf->bss_expiration_age = bss_expire_age; 1979252726Srpaulo 1980252726Srpaulo return 0; 1981252726Srpaulo} 1982252726Srpaulo 1983252726Srpaulo 1984252726Srpaulo/** 1985252726Srpaulo * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count 1986252726Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1987252726Srpaulo * @expire_count: number of scans after which an unseen BSS is reclaimed 1988252726Srpaulo * Returns: 0 if succeed or -1 if expire_count has an invalid value 1989252726Srpaulo * 1990252726Srpaulo */ 1991252726Srpauloint wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s, 1992252726Srpaulo unsigned int bss_expire_count) 1993252726Srpaulo{ 1994252726Srpaulo if (bss_expire_count < 1) { 1995252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u", 1996252726Srpaulo bss_expire_count); 1997252726Srpaulo return -1; 1998252726Srpaulo } 1999252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u", 2000252726Srpaulo bss_expire_count); 2001252726Srpaulo wpa_s->conf->bss_expiration_scan_count = bss_expire_count; 2002252726Srpaulo 2003252726Srpaulo return 0; 2004252726Srpaulo} 2005252726Srpaulo 2006252726Srpaulo 2007252726Srpaulo/** 2008252726Srpaulo * wpa_supplicant_set_scan_interval - Set scan interval 2009252726Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 2010252726Srpaulo * @scan_interval: scan interval in seconds 2011252726Srpaulo * Returns: 0 if succeed or -1 if scan_interval has an invalid value 2012252726Srpaulo * 2013252726Srpaulo */ 2014252726Srpauloint wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s, 2015252726Srpaulo int scan_interval) 2016252726Srpaulo{ 2017252726Srpaulo if (scan_interval < 0) { 2018252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d", 2019252726Srpaulo scan_interval); 2020252726Srpaulo return -1; 2021252726Srpaulo } 2022252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec", 2023252726Srpaulo scan_interval); 2024252726Srpaulo wpa_s->scan_interval = scan_interval; 2025252726Srpaulo 2026252726Srpaulo return 0; 2027252726Srpaulo} 2028252726Srpaulo 2029252726Srpaulo 2030252726Srpaulo/** 2031214734Srpaulo * wpa_supplicant_set_debug_params - Set global debug params 2032214734Srpaulo * @global: wpa_global structure 2033214734Srpaulo * @debug_level: debug level 2034214734Srpaulo * @debug_timestamp: determines if show timestamp in debug data 2035214734Srpaulo * @debug_show_keys: determines if show keys in debug data 2036214734Srpaulo * Returns: 0 if succeed or -1 if debug_level has wrong value 2037214734Srpaulo */ 2038214734Srpauloint wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level, 2039214734Srpaulo int debug_timestamp, int debug_show_keys) 2040214734Srpaulo{ 2041214734Srpaulo 2042214734Srpaulo int old_level, old_timestamp, old_show_keys; 2043214734Srpaulo 2044214734Srpaulo /* check for allowed debuglevels */ 2045252726Srpaulo if (debug_level != MSG_EXCESSIVE && 2046252726Srpaulo debug_level != MSG_MSGDUMP && 2047214734Srpaulo debug_level != MSG_DEBUG && 2048214734Srpaulo debug_level != MSG_INFO && 2049214734Srpaulo debug_level != MSG_WARNING && 2050214734Srpaulo debug_level != MSG_ERROR) 2051214734Srpaulo return -1; 2052214734Srpaulo 2053214734Srpaulo old_level = wpa_debug_level; 2054214734Srpaulo old_timestamp = wpa_debug_timestamp; 2055214734Srpaulo old_show_keys = wpa_debug_show_keys; 2056214734Srpaulo 2057214734Srpaulo wpa_debug_level = debug_level; 2058214734Srpaulo wpa_debug_timestamp = debug_timestamp ? 1 : 0; 2059214734Srpaulo wpa_debug_show_keys = debug_show_keys ? 1 : 0; 2060214734Srpaulo 2061214734Srpaulo if (wpa_debug_level != old_level) 2062214734Srpaulo wpas_notify_debug_level_changed(global); 2063214734Srpaulo if (wpa_debug_timestamp != old_timestamp) 2064214734Srpaulo wpas_notify_debug_timestamp_changed(global); 2065214734Srpaulo if (wpa_debug_show_keys != old_show_keys) 2066214734Srpaulo wpas_notify_debug_show_keys_changed(global); 2067214734Srpaulo 2068214734Srpaulo return 0; 2069214734Srpaulo} 2070214734Srpaulo 2071214734Srpaulo 2072214734Srpaulo/** 2073189251Ssam * wpa_supplicant_get_ssid - Get a pointer to the current network structure 2074189251Ssam * @wpa_s: Pointer to wpa_supplicant data 2075189251Ssam * Returns: A pointer to the current network structure or %NULL on failure 2076189251Ssam */ 2077189251Ssamstruct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) 2078189251Ssam{ 2079189251Ssam struct wpa_ssid *entry; 2080189251Ssam u8 ssid[MAX_SSID_LEN]; 2081189251Ssam int res; 2082189251Ssam size_t ssid_len; 2083189251Ssam u8 bssid[ETH_ALEN]; 2084189251Ssam int wired; 2085189251Ssam 2086252726Srpaulo res = wpa_drv_get_ssid(wpa_s, ssid); 2087252726Srpaulo if (res < 0) { 2088252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from " 2089252726Srpaulo "driver"); 2090252726Srpaulo return NULL; 2091189251Ssam } 2092252726Srpaulo ssid_len = res; 2093189251Ssam 2094252726Srpaulo if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { 2095252726Srpaulo wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from " 2096252726Srpaulo "driver"); 2097189251Ssam return NULL; 2098189251Ssam } 2099189251Ssam 2100214734Srpaulo wired = wpa_s->conf->ap_scan == 0 && 2101214734Srpaulo (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED); 2102189251Ssam 2103189251Ssam entry = wpa_s->conf->ssid; 2104189251Ssam while (entry) { 2105252726Srpaulo if (!wpas_network_disabled(wpa_s, entry) && 2106189251Ssam ((ssid_len == entry->ssid_len && 2107189251Ssam os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) && 2108189251Ssam (!entry->bssid_set || 2109189251Ssam os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) 2110189251Ssam return entry; 2111189251Ssam#ifdef CONFIG_WPS 2112252726Srpaulo if (!wpas_network_disabled(wpa_s, entry) && 2113189251Ssam (entry->key_mgmt & WPA_KEY_MGMT_WPS) && 2114189251Ssam (entry->ssid == NULL || entry->ssid_len == 0) && 2115189251Ssam (!entry->bssid_set || 2116189251Ssam os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) 2117189251Ssam return entry; 2118189251Ssam#endif /* CONFIG_WPS */ 2119252726Srpaulo 2120252726Srpaulo if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set && 2121252726Srpaulo entry->ssid_len == 0 && 2122252726Srpaulo os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0) 2123252726Srpaulo return entry; 2124252726Srpaulo 2125189251Ssam entry = entry->next; 2126189251Ssam } 2127189251Ssam 2128189251Ssam return NULL; 2129189251Ssam} 2130189251Ssam 2131189251Ssam 2132252726Srpaulostatic int select_driver(struct wpa_supplicant *wpa_s, int i) 2133252726Srpaulo{ 2134252726Srpaulo struct wpa_global *global = wpa_s->global; 2135252726Srpaulo 2136252726Srpaulo if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) { 2137252726Srpaulo global->drv_priv[i] = wpa_drivers[i]->global_init(); 2138252726Srpaulo if (global->drv_priv[i] == NULL) { 2139252726Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize driver " 2140252726Srpaulo "'%s'", wpa_drivers[i]->name); 2141252726Srpaulo return -1; 2142252726Srpaulo } 2143252726Srpaulo } 2144252726Srpaulo 2145252726Srpaulo wpa_s->driver = wpa_drivers[i]; 2146252726Srpaulo wpa_s->global_drv_priv = global->drv_priv[i]; 2147252726Srpaulo 2148252726Srpaulo return 0; 2149252726Srpaulo} 2150252726Srpaulo 2151252726Srpaulo 2152189251Ssamstatic int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, 2153189251Ssam const char *name) 2154189251Ssam{ 2155189251Ssam int i; 2156214734Srpaulo size_t len; 2157252726Srpaulo const char *pos, *driver = name; 2158189251Ssam 2159189251Ssam if (wpa_s == NULL) 2160189251Ssam return -1; 2161189251Ssam 2162214734Srpaulo if (wpa_drivers[0] == NULL) { 2163252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into " 2164252726Srpaulo "wpa_supplicant"); 2165189251Ssam return -1; 2166189251Ssam } 2167189251Ssam 2168189251Ssam if (name == NULL) { 2169189251Ssam /* default to first driver in the list */ 2170252726Srpaulo return select_driver(wpa_s, 0); 2171189251Ssam } 2172189251Ssam 2173252726Srpaulo do { 2174252726Srpaulo pos = os_strchr(driver, ','); 2175252726Srpaulo if (pos) 2176252726Srpaulo len = pos - driver; 2177252726Srpaulo else 2178252726Srpaulo len = os_strlen(driver); 2179252726Srpaulo 2180252726Srpaulo for (i = 0; wpa_drivers[i]; i++) { 2181252726Srpaulo if (os_strlen(wpa_drivers[i]->name) == len && 2182252726Srpaulo os_strncmp(driver, wpa_drivers[i]->name, len) == 2183252726Srpaulo 0) { 2184252726Srpaulo /* First driver that succeeds wins */ 2185252726Srpaulo if (select_driver(wpa_s, i) == 0) 2186252726Srpaulo return 0; 2187252726Srpaulo } 2188189251Ssam } 2189189251Ssam 2190252726Srpaulo driver = pos + 1; 2191252726Srpaulo } while (pos); 2192252726Srpaulo 2193252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name); 2194189251Ssam return -1; 2195189251Ssam} 2196189251Ssam 2197189251Ssam 2198214734Srpaulo/** 2199214734Srpaulo * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant 2200214734Srpaulo * @ctx: Context pointer (wpa_s); this is the ctx variable registered 2201214734Srpaulo * with struct wpa_driver_ops::init() 2202214734Srpaulo * @src_addr: Source address of the EAPOL frame 2203214734Srpaulo * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header) 2204214734Srpaulo * @len: Length of the EAPOL data 2205214734Srpaulo * 2206214734Srpaulo * This function is called for each received EAPOL frame. Most driver 2207214734Srpaulo * interfaces rely on more generic OS mechanism for receiving frames through 2208214734Srpaulo * l2_packet, but if such a mechanism is not available, the driver wrapper may 2209214734Srpaulo * take care of received EAPOL frames and deliver them to the core supplicant 2210214734Srpaulo * code by calling this function. 2211214734Srpaulo */ 2212189251Ssamvoid wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, 2213189251Ssam const u8 *buf, size_t len) 2214189251Ssam{ 2215189251Ssam struct wpa_supplicant *wpa_s = ctx; 2216189251Ssam 2217252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr)); 2218189251Ssam wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len); 2219189251Ssam 2220252726Srpaulo if (wpa_s->wpa_state < WPA_ASSOCIATED || 2221252726Srpaulo (wpa_s->last_eapol_matches_bssid && 2222252726Srpaulo#ifdef CONFIG_AP 2223252726Srpaulo !wpa_s->ap_iface && 2224252726Srpaulo#endif /* CONFIG_AP */ 2225252726Srpaulo os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) { 2226209158Srpaulo /* 2227209158Srpaulo * There is possible race condition between receiving the 2228209158Srpaulo * association event and the EAPOL frame since they are coming 2229209158Srpaulo * through different paths from the driver. In order to avoid 2230209158Srpaulo * issues in trying to process the EAPOL frame before receiving 2231209158Srpaulo * association information, lets queue it for processing until 2232252726Srpaulo * the association event is received. This may also be needed in 2233252726Srpaulo * driver-based roaming case, so also use src_addr != BSSID as a 2234252726Srpaulo * trigger if we have previously confirmed that the 2235252726Srpaulo * Authenticator uses BSSID as the src_addr (which is not the 2236252726Srpaulo * case with wired IEEE 802.1X). 2237209158Srpaulo */ 2238252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing " 2239252726Srpaulo "of received EAPOL frame (state=%s bssid=" MACSTR ")", 2240252726Srpaulo wpa_supplicant_state_txt(wpa_s->wpa_state), 2241252726Srpaulo MAC2STR(wpa_s->bssid)); 2242209158Srpaulo wpabuf_free(wpa_s->pending_eapol_rx); 2243209158Srpaulo wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len); 2244209158Srpaulo if (wpa_s->pending_eapol_rx) { 2245209158Srpaulo os_get_time(&wpa_s->pending_eapol_rx_time); 2246209158Srpaulo os_memcpy(wpa_s->pending_eapol_rx_src, src_addr, 2247209158Srpaulo ETH_ALEN); 2248209158Srpaulo } 2249209158Srpaulo return; 2250209158Srpaulo } 2251209158Srpaulo 2252252726Srpaulo wpa_s->last_eapol_matches_bssid = 2253252726Srpaulo os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0; 2254252726Srpaulo 2255214734Srpaulo#ifdef CONFIG_AP 2256214734Srpaulo if (wpa_s->ap_iface) { 2257214734Srpaulo wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len); 2258214734Srpaulo return; 2259214734Srpaulo } 2260214734Srpaulo#endif /* CONFIG_AP */ 2261214734Srpaulo 2262189251Ssam if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { 2263252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since " 2264252726Srpaulo "no key management is configured"); 2265189251Ssam return; 2266189251Ssam } 2267189251Ssam 2268189251Ssam if (wpa_s->eapol_received == 0 && 2269214734Srpaulo (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) || 2270189251Ssam !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || 2271214734Srpaulo wpa_s->wpa_state != WPA_COMPLETED) && 2272214734Srpaulo (wpa_s->current_ssid == NULL || 2273214734Srpaulo wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) { 2274189251Ssam /* Timeout for completing IEEE 802.1X and WPA authentication */ 2275189251Ssam wpa_supplicant_req_auth_timeout( 2276189251Ssam wpa_s, 2277189251Ssam (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 2278189251Ssam wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA || 2279189251Ssam wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ? 2280189251Ssam 70 : 10, 0); 2281189251Ssam } 2282189251Ssam wpa_s->eapol_received++; 2283189251Ssam 2284189251Ssam if (wpa_s->countermeasures) { 2285252726Srpaulo wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped " 2286252726Srpaulo "EAPOL packet"); 2287189251Ssam return; 2288189251Ssam } 2289189251Ssam 2290214734Srpaulo#ifdef CONFIG_IBSS_RSN 2291214734Srpaulo if (wpa_s->current_ssid && 2292214734Srpaulo wpa_s->current_ssid->mode == WPAS_MODE_IBSS) { 2293214734Srpaulo ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len); 2294214734Srpaulo return; 2295214734Srpaulo } 2296214734Srpaulo#endif /* CONFIG_IBSS_RSN */ 2297214734Srpaulo 2298189251Ssam /* Source address of the incoming EAPOL frame could be compared to the 2299189251Ssam * current BSSID. However, it is possible that a centralized 2300189251Ssam * Authenticator could be using another MAC address than the BSSID of 2301189251Ssam * an AP, so just allow any address to be used for now. The replies are 2302189251Ssam * still sent to the current BSSID (if available), though. */ 2303189251Ssam 2304189251Ssam os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN); 2305189251Ssam if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) && 2306189251Ssam eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) 2307189251Ssam return; 2308189251Ssam wpa_drv_poll(wpa_s); 2309214734Srpaulo if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) 2310189251Ssam wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); 2311189251Ssam else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 2312189251Ssam /* 2313189251Ssam * Set portValid = TRUE here since we are going to skip 4-way 2314189251Ssam * handshake processing which would normally set portValid. We 2315189251Ssam * need this to allow the EAPOL state machines to be completed 2316189251Ssam * without going through EAPOL-Key handshake. 2317189251Ssam */ 2318189251Ssam eapol_sm_notify_portValid(wpa_s->eapol, TRUE); 2319189251Ssam } 2320189251Ssam} 2321189251Ssam 2322189251Ssam 2323252726Srpauloint wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) 2324189251Ssam{ 2325189251Ssam if (wpa_s->driver->send_eapol) { 2326189251Ssam const u8 *addr = wpa_drv_get_mac_addr(wpa_s); 2327189251Ssam if (addr) 2328189251Ssam os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); 2329252726Srpaulo } else if (!(wpa_s->drv_flags & 2330252726Srpaulo WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) { 2331252726Srpaulo l2_packet_deinit(wpa_s->l2); 2332189251Ssam wpa_s->l2 = l2_packet_init(wpa_s->ifname, 2333189251Ssam wpa_drv_get_mac_addr(wpa_s), 2334189251Ssam ETH_P_EAPOL, 2335189251Ssam wpa_supplicant_rx_eapol, wpa_s, 0); 2336189251Ssam if (wpa_s->l2 == NULL) 2337189251Ssam return -1; 2338252726Srpaulo } else { 2339252726Srpaulo const u8 *addr = wpa_drv_get_mac_addr(wpa_s); 2340252726Srpaulo if (addr) 2341252726Srpaulo os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); 2342189251Ssam } 2343189251Ssam 2344189251Ssam if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { 2345252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address"); 2346189251Ssam return -1; 2347189251Ssam } 2348189251Ssam 2349252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR, 2350252726Srpaulo MAC2STR(wpa_s->own_addr)); 2351252726Srpaulo wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); 2352189251Ssam 2353252726Srpaulo return 0; 2354252726Srpaulo} 2355252726Srpaulo 2356252726Srpaulo 2357252726Srpaulostatic void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr, 2358252726Srpaulo const u8 *buf, size_t len) 2359252726Srpaulo{ 2360252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 2361252726Srpaulo const struct l2_ethhdr *eth; 2362252726Srpaulo 2363252726Srpaulo if (len < sizeof(*eth)) 2364252726Srpaulo return; 2365252726Srpaulo eth = (const struct l2_ethhdr *) buf; 2366252726Srpaulo 2367252726Srpaulo if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 && 2368252726Srpaulo !(eth->h_dest[0] & 0x01)) { 2369252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR 2370252726Srpaulo " (bridge - not for this interface - ignore)", 2371252726Srpaulo MAC2STR(src_addr), MAC2STR(eth->h_dest)); 2372252726Srpaulo return; 2373252726Srpaulo } 2374252726Srpaulo 2375252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR 2376252726Srpaulo " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest)); 2377252726Srpaulo wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth), 2378252726Srpaulo len - sizeof(*eth)); 2379252726Srpaulo} 2380252726Srpaulo 2381252726Srpaulo 2382252726Srpaulo/** 2383252726Srpaulo * wpa_supplicant_driver_init - Initialize driver interface parameters 2384252726Srpaulo * @wpa_s: Pointer to wpa_supplicant data 2385252726Srpaulo * Returns: 0 on success, -1 on failure 2386252726Srpaulo * 2387252726Srpaulo * This function is called to initialize driver interface parameters. 2388252726Srpaulo * wpa_drv_init() must have been called before this function to initialize the 2389252726Srpaulo * driver interface. 2390252726Srpaulo */ 2391252726Srpauloint wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) 2392252726Srpaulo{ 2393252726Srpaulo static int interface_count = 0; 2394252726Srpaulo 2395252726Srpaulo if (wpa_supplicant_update_mac_addr(wpa_s) < 0) 2396252726Srpaulo return -1; 2397252726Srpaulo 2398189251Ssam if (wpa_s->bridge_ifname[0]) { 2399252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge " 2400252726Srpaulo "interface '%s'", wpa_s->bridge_ifname); 2401189251Ssam wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname, 2402189251Ssam wpa_s->own_addr, 2403189251Ssam ETH_P_EAPOL, 2404252726Srpaulo wpa_supplicant_rx_eapol_bridge, 2405252726Srpaulo wpa_s, 1); 2406189251Ssam if (wpa_s->l2_br == NULL) { 2407252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet " 2408252726Srpaulo "connection for the bridge interface '%s'", 2409252726Srpaulo wpa_s->bridge_ifname); 2410189251Ssam return -1; 2411189251Ssam } 2412189251Ssam } 2413189251Ssam 2414189251Ssam wpa_clear_keys(wpa_s, NULL); 2415189251Ssam 2416189251Ssam /* Make sure that TKIP countermeasures are not left enabled (could 2417189251Ssam * happen if wpa_supplicant is killed during countermeasures. */ 2418189251Ssam wpa_drv_set_countermeasures(wpa_s, 0); 2419189251Ssam 2420252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver"); 2421189251Ssam wpa_drv_flush_pmkid(wpa_s); 2422189251Ssam 2423214734Srpaulo wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 2424252726Srpaulo wpa_s->prev_scan_wildcard = 0; 2425252726Srpaulo 2426252726Srpaulo if (wpa_supplicant_enabled_networks(wpa_s)) { 2427252726Srpaulo if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count, 2428252726Srpaulo 100000)) 2429252726Srpaulo wpa_supplicant_req_scan(wpa_s, interface_count, 2430252726Srpaulo 100000); 2431214734Srpaulo interface_count++; 2432214734Srpaulo } else 2433214734Srpaulo wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 2434189251Ssam 2435189251Ssam return 0; 2436189251Ssam} 2437189251Ssam 2438189251Ssam 2439189251Ssamstatic int wpa_supplicant_daemon(const char *pid_file) 2440189251Ssam{ 2441189251Ssam wpa_printf(MSG_DEBUG, "Daemonize.."); 2442189251Ssam return os_daemonize(pid_file); 2443189251Ssam} 2444189251Ssam 2445189251Ssam 2446189251Ssamstatic struct wpa_supplicant * wpa_supplicant_alloc(void) 2447189251Ssam{ 2448189251Ssam struct wpa_supplicant *wpa_s; 2449189251Ssam 2450189251Ssam wpa_s = os_zalloc(sizeof(*wpa_s)); 2451189251Ssam if (wpa_s == NULL) 2452189251Ssam return NULL; 2453252726Srpaulo wpa_s->scan_req = INITIAL_SCAN_REQ; 2454252726Srpaulo wpa_s->scan_interval = 5; 2455214734Srpaulo wpa_s->new_connection = 1; 2456252726Srpaulo wpa_s->parent = wpa_s; 2457252726Srpaulo wpa_s->sched_scanning = 0; 2458189251Ssam 2459189251Ssam return wpa_s; 2460189251Ssam} 2461189251Ssam 2462189251Ssam 2463252726Srpaulo#ifdef CONFIG_HT_OVERRIDES 2464252726Srpaulo 2465252726Srpaulostatic int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s, 2466252726Srpaulo struct ieee80211_ht_capabilities *htcaps, 2467252726Srpaulo struct ieee80211_ht_capabilities *htcaps_mask, 2468252726Srpaulo const char *ht_mcs) 2469252726Srpaulo{ 2470252726Srpaulo /* parse ht_mcs into hex array */ 2471252726Srpaulo int i; 2472252726Srpaulo const char *tmp = ht_mcs; 2473252726Srpaulo char *end = NULL; 2474252726Srpaulo 2475252726Srpaulo /* If ht_mcs is null, do not set anything */ 2476252726Srpaulo if (!ht_mcs) 2477252726Srpaulo return 0; 2478252726Srpaulo 2479252726Srpaulo /* This is what we are setting in the kernel */ 2480252726Srpaulo os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN); 2481252726Srpaulo 2482252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs); 2483252726Srpaulo 2484252726Srpaulo for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { 2485252726Srpaulo errno = 0; 2486252726Srpaulo long v = strtol(tmp, &end, 16); 2487252726Srpaulo if (errno == 0) { 2488252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, 2489252726Srpaulo "htcap value[%i]: %ld end: %p tmp: %p", 2490252726Srpaulo i, v, end, tmp); 2491252726Srpaulo if (end == tmp) 2492252726Srpaulo break; 2493252726Srpaulo 2494252726Srpaulo htcaps->supported_mcs_set[i] = v; 2495252726Srpaulo tmp = end; 2496252726Srpaulo } else { 2497252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, 2498252726Srpaulo "Failed to parse ht-mcs: %s, error: %s\n", 2499252726Srpaulo ht_mcs, strerror(errno)); 2500252726Srpaulo return -1; 2501252726Srpaulo } 2502252726Srpaulo } 2503252726Srpaulo 2504252726Srpaulo /* 2505252726Srpaulo * If we were able to parse any values, then set mask for the MCS set. 2506252726Srpaulo */ 2507252726Srpaulo if (i) { 2508252726Srpaulo os_memset(&htcaps_mask->supported_mcs_set, 0xff, 2509252726Srpaulo IEEE80211_HT_MCS_MASK_LEN - 1); 2510252726Srpaulo /* skip the 3 reserved bits */ 2511252726Srpaulo htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] = 2512252726Srpaulo 0x1f; 2513252726Srpaulo } 2514252726Srpaulo 2515252726Srpaulo return 0; 2516252726Srpaulo} 2517252726Srpaulo 2518252726Srpaulo 2519252726Srpaulostatic int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s, 2520252726Srpaulo struct ieee80211_ht_capabilities *htcaps, 2521252726Srpaulo struct ieee80211_ht_capabilities *htcaps_mask, 2522252726Srpaulo int disabled) 2523252726Srpaulo{ 2524252726Srpaulo u16 msk; 2525252726Srpaulo 2526252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled); 2527252726Srpaulo 2528252726Srpaulo if (disabled == -1) 2529252726Srpaulo return 0; 2530252726Srpaulo 2531252726Srpaulo msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE); 2532252726Srpaulo htcaps_mask->ht_capabilities_info |= msk; 2533252726Srpaulo if (disabled) 2534252726Srpaulo htcaps->ht_capabilities_info &= msk; 2535252726Srpaulo else 2536252726Srpaulo htcaps->ht_capabilities_info |= msk; 2537252726Srpaulo 2538252726Srpaulo return 0; 2539252726Srpaulo} 2540252726Srpaulo 2541252726Srpaulo 2542252726Srpaulostatic int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s, 2543252726Srpaulo struct ieee80211_ht_capabilities *htcaps, 2544252726Srpaulo struct ieee80211_ht_capabilities *htcaps_mask, 2545252726Srpaulo int factor) 2546252726Srpaulo{ 2547252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor); 2548252726Srpaulo 2549252726Srpaulo if (factor == -1) 2550252726Srpaulo return 0; 2551252726Srpaulo 2552252726Srpaulo if (factor < 0 || factor > 3) { 2553252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. " 2554252726Srpaulo "Must be 0-3 or -1", factor); 2555252726Srpaulo return -EINVAL; 2556252726Srpaulo } 2557252726Srpaulo 2558252726Srpaulo htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */ 2559252726Srpaulo htcaps->a_mpdu_params &= ~0x3; 2560252726Srpaulo htcaps->a_mpdu_params |= factor & 0x3; 2561252726Srpaulo 2562252726Srpaulo return 0; 2563252726Srpaulo} 2564252726Srpaulo 2565252726Srpaulo 2566252726Srpaulostatic int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s, 2567252726Srpaulo struct ieee80211_ht_capabilities *htcaps, 2568252726Srpaulo struct ieee80211_ht_capabilities *htcaps_mask, 2569252726Srpaulo int density) 2570252726Srpaulo{ 2571252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density); 2572252726Srpaulo 2573252726Srpaulo if (density == -1) 2574252726Srpaulo return 0; 2575252726Srpaulo 2576252726Srpaulo if (density < 0 || density > 7) { 2577252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, 2578252726Srpaulo "ampdu_density: %d out of range. Must be 0-7 or -1.", 2579252726Srpaulo density); 2580252726Srpaulo return -EINVAL; 2581252726Srpaulo } 2582252726Srpaulo 2583252726Srpaulo htcaps_mask->a_mpdu_params |= 0x1C; 2584252726Srpaulo htcaps->a_mpdu_params &= ~(0x1C); 2585252726Srpaulo htcaps->a_mpdu_params |= (density << 2) & 0x1C; 2586252726Srpaulo 2587252726Srpaulo return 0; 2588252726Srpaulo} 2589252726Srpaulo 2590252726Srpaulo 2591252726Srpaulostatic int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s, 2592252726Srpaulo struct ieee80211_ht_capabilities *htcaps, 2593252726Srpaulo struct ieee80211_ht_capabilities *htcaps_mask, 2594252726Srpaulo int disabled) 2595252726Srpaulo{ 2596252726Srpaulo /* Masking these out disables HT40 */ 2597252726Srpaulo u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET | 2598252726Srpaulo HT_CAP_INFO_SHORT_GI40MHZ); 2599252726Srpaulo 2600252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled); 2601252726Srpaulo 2602252726Srpaulo if (disabled) 2603252726Srpaulo htcaps->ht_capabilities_info &= ~msk; 2604252726Srpaulo else 2605252726Srpaulo htcaps->ht_capabilities_info |= msk; 2606252726Srpaulo 2607252726Srpaulo htcaps_mask->ht_capabilities_info |= msk; 2608252726Srpaulo 2609252726Srpaulo return 0; 2610252726Srpaulo} 2611252726Srpaulo 2612252726Srpaulo 2613252726Srpaulostatic int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s, 2614252726Srpaulo struct ieee80211_ht_capabilities *htcaps, 2615252726Srpaulo struct ieee80211_ht_capabilities *htcaps_mask, 2616252726Srpaulo int disabled) 2617252726Srpaulo{ 2618252726Srpaulo /* Masking these out disables SGI */ 2619252726Srpaulo u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ | 2620252726Srpaulo HT_CAP_INFO_SHORT_GI40MHZ); 2621252726Srpaulo 2622252726Srpaulo wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled); 2623252726Srpaulo 2624252726Srpaulo if (disabled) 2625252726Srpaulo htcaps->ht_capabilities_info &= ~msk; 2626252726Srpaulo else 2627252726Srpaulo htcaps->ht_capabilities_info |= msk; 2628252726Srpaulo 2629252726Srpaulo htcaps_mask->ht_capabilities_info |= msk; 2630252726Srpaulo 2631252726Srpaulo return 0; 2632252726Srpaulo} 2633252726Srpaulo 2634252726Srpaulo 2635252726Srpaulovoid wpa_supplicant_apply_ht_overrides( 2636252726Srpaulo struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 2637252726Srpaulo struct wpa_driver_associate_params *params) 2638252726Srpaulo{ 2639252726Srpaulo struct ieee80211_ht_capabilities *htcaps; 2640252726Srpaulo struct ieee80211_ht_capabilities *htcaps_mask; 2641252726Srpaulo 2642252726Srpaulo if (!ssid) 2643252726Srpaulo return; 2644252726Srpaulo 2645252726Srpaulo params->disable_ht = ssid->disable_ht; 2646252726Srpaulo if (!params->htcaps || !params->htcaps_mask) 2647252726Srpaulo return; 2648252726Srpaulo 2649252726Srpaulo htcaps = (struct ieee80211_ht_capabilities *) params->htcaps; 2650252726Srpaulo htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask; 2651252726Srpaulo wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs); 2652252726Srpaulo wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask, 2653252726Srpaulo ssid->disable_max_amsdu); 2654252726Srpaulo wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor); 2655252726Srpaulo wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density); 2656252726Srpaulo wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40); 2657252726Srpaulo wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi); 2658252726Srpaulo} 2659252726Srpaulo 2660252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */ 2661252726Srpaulo 2662252726Srpaulo 2663252726Srpaulostatic int pcsc_reader_init(struct wpa_supplicant *wpa_s) 2664252726Srpaulo{ 2665252726Srpaulo#ifdef PCSC_FUNCS 2666252726Srpaulo size_t len; 2667252726Srpaulo 2668252726Srpaulo if (!wpa_s->conf->pcsc_reader) 2669252726Srpaulo return 0; 2670252726Srpaulo 2671252726Srpaulo wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader); 2672252726Srpaulo if (!wpa_s->scard) 2673252726Srpaulo return 1; 2674252726Srpaulo 2675252726Srpaulo if (wpa_s->conf->pcsc_pin && 2676252726Srpaulo scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) { 2677252726Srpaulo scard_deinit(wpa_s->scard); 2678252726Srpaulo wpa_s->scard = NULL; 2679252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed"); 2680252726Srpaulo return -1; 2681252726Srpaulo } 2682252726Srpaulo 2683252726Srpaulo len = sizeof(wpa_s->imsi) - 1; 2684252726Srpaulo if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) { 2685252726Srpaulo scard_deinit(wpa_s->scard); 2686252726Srpaulo wpa_s->scard = NULL; 2687252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI"); 2688252726Srpaulo return -1; 2689252726Srpaulo } 2690252726Srpaulo wpa_s->imsi[len] = '\0'; 2691252726Srpaulo 2692252726Srpaulo wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard); 2693252726Srpaulo 2694252726Srpaulo wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)", 2695252726Srpaulo wpa_s->imsi, wpa_s->mnc_len); 2696252726Srpaulo 2697252726Srpaulo wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard); 2698252726Srpaulo eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); 2699252726Srpaulo#endif /* PCSC_FUNCS */ 2700252726Srpaulo 2701252726Srpaulo return 0; 2702252726Srpaulo} 2703252726Srpaulo 2704252726Srpaulo 2705252726Srpauloint wpas_init_ext_pw(struct wpa_supplicant *wpa_s) 2706252726Srpaulo{ 2707252726Srpaulo char *val, *pos; 2708252726Srpaulo 2709252726Srpaulo ext_password_deinit(wpa_s->ext_pw); 2710252726Srpaulo wpa_s->ext_pw = NULL; 2711252726Srpaulo eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL); 2712252726Srpaulo 2713252726Srpaulo if (!wpa_s->conf->ext_password_backend) 2714252726Srpaulo return 0; 2715252726Srpaulo 2716252726Srpaulo val = os_strdup(wpa_s->conf->ext_password_backend); 2717252726Srpaulo if (val == NULL) 2718252726Srpaulo return -1; 2719252726Srpaulo pos = os_strchr(val, ':'); 2720252726Srpaulo if (pos) 2721252726Srpaulo *pos++ = '\0'; 2722252726Srpaulo 2723252726Srpaulo wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val); 2724252726Srpaulo 2725252726Srpaulo wpa_s->ext_pw = ext_password_init(val, pos); 2726252726Srpaulo os_free(val); 2727252726Srpaulo if (wpa_s->ext_pw == NULL) { 2728252726Srpaulo wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend"); 2729252726Srpaulo return -1; 2730252726Srpaulo } 2731252726Srpaulo eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw); 2732252726Srpaulo 2733252726Srpaulo return 0; 2734252726Srpaulo} 2735252726Srpaulo 2736252726Srpaulo 2737189251Ssamstatic int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, 2738189251Ssam struct wpa_interface *iface) 2739189251Ssam{ 2740214734Srpaulo const char *ifname, *driver; 2741214734Srpaulo struct wpa_driver_capa capa; 2742214734Srpaulo 2743189251Ssam wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " 2744189251Ssam "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, 2745189251Ssam iface->confname ? iface->confname : "N/A", 2746189251Ssam iface->driver ? iface->driver : "default", 2747189251Ssam iface->ctrl_interface ? iface->ctrl_interface : "N/A", 2748189251Ssam iface->bridge_ifname ? iface->bridge_ifname : "N/A"); 2749189251Ssam 2750189251Ssam if (iface->confname) { 2751189251Ssam#ifdef CONFIG_BACKEND_FILE 2752189251Ssam wpa_s->confname = os_rel2abs_path(iface->confname); 2753189251Ssam if (wpa_s->confname == NULL) { 2754189251Ssam wpa_printf(MSG_ERROR, "Failed to get absolute path " 2755189251Ssam "for configuration file '%s'.", 2756189251Ssam iface->confname); 2757189251Ssam return -1; 2758189251Ssam } 2759189251Ssam wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'", 2760189251Ssam iface->confname, wpa_s->confname); 2761189251Ssam#else /* CONFIG_BACKEND_FILE */ 2762189251Ssam wpa_s->confname = os_strdup(iface->confname); 2763189251Ssam#endif /* CONFIG_BACKEND_FILE */ 2764189251Ssam wpa_s->conf = wpa_config_read(wpa_s->confname); 2765189251Ssam if (wpa_s->conf == NULL) { 2766189251Ssam wpa_printf(MSG_ERROR, "Failed to read or parse " 2767189251Ssam "configuration '%s'.", wpa_s->confname); 2768189251Ssam return -1; 2769189251Ssam } 2770189251Ssam 2771189251Ssam /* 2772189251Ssam * Override ctrl_interface and driver_param if set on command 2773189251Ssam * line. 2774189251Ssam */ 2775189251Ssam if (iface->ctrl_interface) { 2776189251Ssam os_free(wpa_s->conf->ctrl_interface); 2777189251Ssam wpa_s->conf->ctrl_interface = 2778189251Ssam os_strdup(iface->ctrl_interface); 2779189251Ssam } 2780189251Ssam 2781189251Ssam if (iface->driver_param) { 2782189251Ssam os_free(wpa_s->conf->driver_param); 2783189251Ssam wpa_s->conf->driver_param = 2784189251Ssam os_strdup(iface->driver_param); 2785189251Ssam } 2786189251Ssam } else 2787189251Ssam wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface, 2788189251Ssam iface->driver_param); 2789189251Ssam 2790189251Ssam if (wpa_s->conf == NULL) { 2791189251Ssam wpa_printf(MSG_ERROR, "\nNo configuration found."); 2792189251Ssam return -1; 2793189251Ssam } 2794189251Ssam 2795189251Ssam if (iface->ifname == NULL) { 2796189251Ssam wpa_printf(MSG_ERROR, "\nInterface name is required."); 2797189251Ssam return -1; 2798189251Ssam } 2799189251Ssam if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) { 2800189251Ssam wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.", 2801189251Ssam iface->ifname); 2802189251Ssam return -1; 2803189251Ssam } 2804189251Ssam os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname)); 2805189251Ssam 2806189251Ssam if (iface->bridge_ifname) { 2807189251Ssam if (os_strlen(iface->bridge_ifname) >= 2808189251Ssam sizeof(wpa_s->bridge_ifname)) { 2809189251Ssam wpa_printf(MSG_ERROR, "\nToo long bridge interface " 2810189251Ssam "name '%s'.", iface->bridge_ifname); 2811189251Ssam return -1; 2812189251Ssam } 2813189251Ssam os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname, 2814189251Ssam sizeof(wpa_s->bridge_ifname)); 2815189251Ssam } 2816189251Ssam 2817189251Ssam /* RSNA Supplicant Key Management - INITIALIZE */ 2818189251Ssam eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); 2819189251Ssam eapol_sm_notify_portValid(wpa_s->eapol, FALSE); 2820189251Ssam 2821189251Ssam /* Initialize driver interface and register driver event handler before 2822189251Ssam * L2 receive handler so that association events are processed before 2823189251Ssam * EAPOL-Key packets if both become available for the same select() 2824189251Ssam * call. */ 2825214734Srpaulo driver = iface->driver; 2826214734Srpaulonext_driver: 2827214734Srpaulo if (wpa_supplicant_set_driver(wpa_s, driver) < 0) 2828214734Srpaulo return -1; 2829214734Srpaulo 2830189251Ssam wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); 2831189251Ssam if (wpa_s->drv_priv == NULL) { 2832214734Srpaulo const char *pos; 2833214734Srpaulo pos = driver ? os_strchr(driver, ',') : NULL; 2834214734Srpaulo if (pos) { 2835252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize " 2836252726Srpaulo "driver interface - try next driver wrapper"); 2837214734Srpaulo driver = pos + 1; 2838214734Srpaulo goto next_driver; 2839214734Srpaulo } 2840252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver " 2841252726Srpaulo "interface"); 2842189251Ssam return -1; 2843189251Ssam } 2844189251Ssam if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) { 2845252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected " 2846252726Srpaulo "driver_param '%s'", wpa_s->conf->driver_param); 2847189251Ssam return -1; 2848189251Ssam } 2849189251Ssam 2850189251Ssam ifname = wpa_drv_get_ifname(wpa_s); 2851189251Ssam if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) { 2852252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced " 2853252726Srpaulo "interface name with '%s'", ifname); 2854189251Ssam os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); 2855189251Ssam } 2856189251Ssam 2857189251Ssam if (wpa_supplicant_init_wpa(wpa_s) < 0) 2858189251Ssam return -1; 2859189251Ssam 2860189251Ssam wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname, 2861189251Ssam wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname : 2862189251Ssam NULL); 2863189251Ssam wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); 2864189251Ssam 2865189251Ssam if (wpa_s->conf->dot11RSNAConfigPMKLifetime && 2866189251Ssam wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 2867189251Ssam wpa_s->conf->dot11RSNAConfigPMKLifetime)) { 2868252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " 2869252726Srpaulo "dot11RSNAConfigPMKLifetime"); 2870189251Ssam return -1; 2871189251Ssam } 2872189251Ssam 2873189251Ssam if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold && 2874189251Ssam wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 2875189251Ssam wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) { 2876252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " 2877189251Ssam "dot11RSNAConfigPMKReauthThreshold"); 2878189251Ssam return -1; 2879189251Ssam } 2880189251Ssam 2881189251Ssam if (wpa_s->conf->dot11RSNAConfigSATimeout && 2882189251Ssam wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 2883189251Ssam wpa_s->conf->dot11RSNAConfigSATimeout)) { 2884252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " 2885252726Srpaulo "dot11RSNAConfigSATimeout"); 2886189251Ssam return -1; 2887189251Ssam } 2888189251Ssam 2889252726Srpaulo wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s, 2890252726Srpaulo &wpa_s->hw.num_modes, 2891252726Srpaulo &wpa_s->hw.flags); 2892252726Srpaulo 2893214734Srpaulo if (wpa_drv_get_capa(wpa_s, &capa) == 0) { 2894252726Srpaulo wpa_s->drv_capa_known = 1; 2895214734Srpaulo wpa_s->drv_flags = capa.flags; 2896252726Srpaulo wpa_s->drv_enc = capa.enc; 2897252726Srpaulo wpa_s->probe_resp_offloads = capa.probe_resp_offloads; 2898214734Srpaulo wpa_s->max_scan_ssids = capa.max_scan_ssids; 2899252726Srpaulo wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids; 2900252726Srpaulo wpa_s->sched_scan_supported = capa.sched_scan_supported; 2901252726Srpaulo wpa_s->max_match_sets = capa.max_match_sets; 2902214734Srpaulo wpa_s->max_remain_on_chan = capa.max_remain_on_chan; 2903252726Srpaulo wpa_s->max_stations = capa.max_stations; 2904214734Srpaulo } 2905214734Srpaulo if (wpa_s->max_remain_on_chan == 0) 2906214734Srpaulo wpa_s->max_remain_on_chan = 1000; 2907214734Srpaulo 2908189251Ssam if (wpa_supplicant_driver_init(wpa_s) < 0) 2909189251Ssam return -1; 2910189251Ssam 2911252726Srpaulo#ifdef CONFIG_TDLS 2912252726Srpaulo if (wpa_tdls_init(wpa_s->wpa)) 2913252726Srpaulo return -1; 2914252726Srpaulo#endif /* CONFIG_TDLS */ 2915252726Srpaulo 2916189251Ssam if (wpa_s->conf->country[0] && wpa_s->conf->country[1] && 2917189251Ssam wpa_drv_set_country(wpa_s, wpa_s->conf->country)) { 2918252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country"); 2919189251Ssam return -1; 2920189251Ssam } 2921189251Ssam 2922189251Ssam if (wpas_wps_init(wpa_s)) 2923189251Ssam return -1; 2924189251Ssam 2925189251Ssam if (wpa_supplicant_init_eapol(wpa_s) < 0) 2926189251Ssam return -1; 2927189251Ssam wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); 2928189251Ssam 2929189251Ssam wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); 2930189251Ssam if (wpa_s->ctrl_iface == NULL) { 2931189251Ssam wpa_printf(MSG_ERROR, 2932189251Ssam "Failed to initialize control interface '%s'.\n" 2933189251Ssam "You may have another wpa_supplicant process " 2934189251Ssam "already running or the file was\n" 2935189251Ssam "left by an unclean termination of wpa_supplicant " 2936189251Ssam "in which case you will need\n" 2937189251Ssam "to manually remove this file before starting " 2938189251Ssam "wpa_supplicant again.\n", 2939189251Ssam wpa_s->conf->ctrl_interface); 2940189251Ssam return -1; 2941189251Ssam } 2942189251Ssam 2943252726Srpaulo wpa_s->gas = gas_query_init(wpa_s); 2944252726Srpaulo if (wpa_s->gas == NULL) { 2945252726Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize GAS query"); 2946214734Srpaulo return -1; 2947189251Ssam } 2948189251Ssam 2949252726Srpaulo#ifdef CONFIG_P2P 2950252726Srpaulo if (wpas_p2p_init(wpa_s->global, wpa_s) < 0) { 2951252726Srpaulo wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P"); 2952252726Srpaulo return -1; 2953252726Srpaulo } 2954252726Srpaulo#endif /* CONFIG_P2P */ 2955252726Srpaulo 2956214734Srpaulo if (wpa_bss_init(wpa_s) < 0) 2957214734Srpaulo return -1; 2958214734Srpaulo 2959252726Srpaulo if (pcsc_reader_init(wpa_s) < 0) 2960252726Srpaulo return -1; 2961252726Srpaulo 2962252726Srpaulo if (wpas_init_ext_pw(wpa_s) < 0) 2963252726Srpaulo return -1; 2964252726Srpaulo 2965189251Ssam return 0; 2966189251Ssam} 2967189251Ssam 2968189251Ssam 2969214734Srpaulostatic void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, 2970252726Srpaulo int notify, int terminate) 2971189251Ssam{ 2972189251Ssam if (wpa_s->drv_priv) { 2973189251Ssam wpa_supplicant_deauthenticate(wpa_s, 2974189251Ssam WLAN_REASON_DEAUTH_LEAVING); 2975189251Ssam 2976189251Ssam wpa_drv_set_countermeasures(wpa_s, 0); 2977189251Ssam wpa_clear_keys(wpa_s, NULL); 2978189251Ssam } 2979189251Ssam 2980189251Ssam wpa_supplicant_cleanup(wpa_s); 2981189251Ssam 2982252726Srpaulo#ifdef CONFIG_P2P 2983252726Srpaulo if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) { 2984252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing " 2985252726Srpaulo "the management interface is being removed"); 2986252726Srpaulo wpas_p2p_deinit_global(wpa_s->global); 2987252726Srpaulo } 2988252726Srpaulo#endif /* CONFIG_P2P */ 2989252726Srpaulo 2990252726Srpaulo if (wpa_s->drv_priv) 2991252726Srpaulo wpa_drv_deinit(wpa_s); 2992252726Srpaulo 2993214734Srpaulo if (notify) 2994214734Srpaulo wpas_notify_iface_removed(wpa_s); 2995214734Srpaulo 2996252726Srpaulo if (terminate) 2997252726Srpaulo wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING); 2998252726Srpaulo 2999252726Srpaulo if (wpa_s->ctrl_iface) { 3000252726Srpaulo wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); 3001252726Srpaulo wpa_s->ctrl_iface = NULL; 3002252726Srpaulo } 3003252726Srpaulo 3004252726Srpaulo if (wpa_s->conf != NULL) { 3005252726Srpaulo wpa_config_free(wpa_s->conf); 3006252726Srpaulo wpa_s->conf = NULL; 3007252726Srpaulo } 3008189251Ssam} 3009189251Ssam 3010189251Ssam 3011189251Ssam/** 3012189251Ssam * wpa_supplicant_add_iface - Add a new network interface 3013189251Ssam * @global: Pointer to global data from wpa_supplicant_init() 3014189251Ssam * @iface: Interface configuration options 3015189251Ssam * Returns: Pointer to the created interface or %NULL on failure 3016189251Ssam * 3017189251Ssam * This function is used to add new network interfaces for %wpa_supplicant. 3018189251Ssam * This can be called before wpa_supplicant_run() to add interfaces before the 3019189251Ssam * main event loop has been started. In addition, new interfaces can be added 3020189251Ssam * dynamically while %wpa_supplicant is already running. This could happen, 3021189251Ssam * e.g., when a hotplug network adapter is inserted. 3022189251Ssam */ 3023189251Ssamstruct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, 3024189251Ssam struct wpa_interface *iface) 3025189251Ssam{ 3026189251Ssam struct wpa_supplicant *wpa_s; 3027214734Srpaulo struct wpa_interface t_iface; 3028214734Srpaulo struct wpa_ssid *ssid; 3029189251Ssam 3030189251Ssam if (global == NULL || iface == NULL) 3031189251Ssam return NULL; 3032189251Ssam 3033189251Ssam wpa_s = wpa_supplicant_alloc(); 3034189251Ssam if (wpa_s == NULL) 3035189251Ssam return NULL; 3036189251Ssam 3037209158Srpaulo wpa_s->global = global; 3038209158Srpaulo 3039214734Srpaulo t_iface = *iface; 3040214734Srpaulo if (global->params.override_driver) { 3041214734Srpaulo wpa_printf(MSG_DEBUG, "Override interface parameter: driver " 3042214734Srpaulo "('%s' -> '%s')", 3043214734Srpaulo iface->driver, global->params.override_driver); 3044214734Srpaulo t_iface.driver = global->params.override_driver; 3045214734Srpaulo } 3046214734Srpaulo if (global->params.override_ctrl_interface) { 3047214734Srpaulo wpa_printf(MSG_DEBUG, "Override interface parameter: " 3048214734Srpaulo "ctrl_interface ('%s' -> '%s')", 3049214734Srpaulo iface->ctrl_interface, 3050214734Srpaulo global->params.override_ctrl_interface); 3051214734Srpaulo t_iface.ctrl_interface = 3052214734Srpaulo global->params.override_ctrl_interface; 3053214734Srpaulo } 3054214734Srpaulo if (wpa_supplicant_init_iface(wpa_s, &t_iface)) { 3055189251Ssam wpa_printf(MSG_DEBUG, "Failed to add interface %s", 3056189251Ssam iface->ifname); 3057252726Srpaulo wpa_supplicant_deinit_iface(wpa_s, 0, 0); 3058189251Ssam os_free(wpa_s); 3059189251Ssam return NULL; 3060189251Ssam } 3061189251Ssam 3062214734Srpaulo /* Notify the control interfaces about new iface */ 3063214734Srpaulo if (wpas_notify_iface_added(wpa_s)) { 3064252726Srpaulo wpa_supplicant_deinit_iface(wpa_s, 1, 0); 3065189251Ssam os_free(wpa_s); 3066189251Ssam return NULL; 3067189251Ssam } 3068209158Srpaulo 3069214734Srpaulo for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 3070214734Srpaulo wpas_notify_network_added(wpa_s, ssid); 3071214734Srpaulo 3072189251Ssam wpa_s->next = global->ifaces; 3073189251Ssam global->ifaces = wpa_s; 3074189251Ssam 3075252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname); 3076252726Srpaulo wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 3077189251Ssam 3078189251Ssam return wpa_s; 3079189251Ssam} 3080189251Ssam 3081189251Ssam 3082189251Ssam/** 3083189251Ssam * wpa_supplicant_remove_iface - Remove a network interface 3084189251Ssam * @global: Pointer to global data from wpa_supplicant_init() 3085189251Ssam * @wpa_s: Pointer to the network interface to be removed 3086189251Ssam * Returns: 0 if interface was removed, -1 if interface was not found 3087189251Ssam * 3088189251Ssam * This function can be used to dynamically remove network interfaces from 3089189251Ssam * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In 3090189251Ssam * addition, this function is used to remove all remaining interfaces when 3091189251Ssam * %wpa_supplicant is terminated. 3092189251Ssam */ 3093189251Ssamint wpa_supplicant_remove_iface(struct wpa_global *global, 3094252726Srpaulo struct wpa_supplicant *wpa_s, 3095252726Srpaulo int terminate) 3096189251Ssam{ 3097189251Ssam struct wpa_supplicant *prev; 3098189251Ssam 3099189251Ssam /* Remove interface from the global list of interfaces */ 3100189251Ssam prev = global->ifaces; 3101189251Ssam if (prev == wpa_s) { 3102189251Ssam global->ifaces = wpa_s->next; 3103189251Ssam } else { 3104189251Ssam while (prev && prev->next != wpa_s) 3105189251Ssam prev = prev->next; 3106189251Ssam if (prev == NULL) 3107189251Ssam return -1; 3108189251Ssam prev->next = wpa_s->next; 3109189251Ssam } 3110189251Ssam 3111252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname); 3112189251Ssam 3113252726Srpaulo if (global->p2p_group_formation == wpa_s) 3114252726Srpaulo global->p2p_group_formation = NULL; 3115252726Srpaulo wpa_supplicant_deinit_iface(wpa_s, 1, terminate); 3116189251Ssam os_free(wpa_s); 3117189251Ssam 3118189251Ssam return 0; 3119189251Ssam} 3120189251Ssam 3121189251Ssam 3122189251Ssam/** 3123252726Srpaulo * wpa_supplicant_get_eap_mode - Get the current EAP mode 3124252726Srpaulo * @wpa_s: Pointer to the network interface 3125252726Srpaulo * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found 3126252726Srpaulo */ 3127252726Srpauloconst char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s) 3128252726Srpaulo{ 3129252726Srpaulo const char *eapol_method; 3130252726Srpaulo 3131252726Srpaulo if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 && 3132252726Srpaulo wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 3133252726Srpaulo return "NO-EAP"; 3134252726Srpaulo } 3135252726Srpaulo 3136252726Srpaulo eapol_method = eapol_sm_get_method_name(wpa_s->eapol); 3137252726Srpaulo if (eapol_method == NULL) 3138252726Srpaulo return "UNKNOWN-EAP"; 3139252726Srpaulo 3140252726Srpaulo return eapol_method; 3141252726Srpaulo} 3142252726Srpaulo 3143252726Srpaulo 3144252726Srpaulo/** 3145189251Ssam * wpa_supplicant_get_iface - Get a new network interface 3146189251Ssam * @global: Pointer to global data from wpa_supplicant_init() 3147189251Ssam * @ifname: Interface name 3148189251Ssam * Returns: Pointer to the interface or %NULL if not found 3149189251Ssam */ 3150189251Ssamstruct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global, 3151189251Ssam const char *ifname) 3152189251Ssam{ 3153189251Ssam struct wpa_supplicant *wpa_s; 3154189251Ssam 3155189251Ssam for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 3156189251Ssam if (os_strcmp(wpa_s->ifname, ifname) == 0) 3157189251Ssam return wpa_s; 3158189251Ssam } 3159189251Ssam return NULL; 3160189251Ssam} 3161189251Ssam 3162189251Ssam 3163252726Srpaulo#ifndef CONFIG_NO_WPA_MSG 3164252726Srpaulostatic const char * wpa_supplicant_msg_ifname_cb(void *ctx) 3165252726Srpaulo{ 3166252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 3167252726Srpaulo if (wpa_s == NULL) 3168252726Srpaulo return NULL; 3169252726Srpaulo return wpa_s->ifname; 3170252726Srpaulo} 3171252726Srpaulo#endif /* CONFIG_NO_WPA_MSG */ 3172252726Srpaulo 3173252726Srpaulo 3174189251Ssam/** 3175189251Ssam * wpa_supplicant_init - Initialize %wpa_supplicant 3176189251Ssam * @params: Parameters for %wpa_supplicant 3177189251Ssam * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure 3178189251Ssam * 3179189251Ssam * This function is used to initialize %wpa_supplicant. After successful 3180189251Ssam * initialization, the returned data pointer can be used to add and remove 3181189251Ssam * network interfaces, and eventually, to deinitialize %wpa_supplicant. 3182189251Ssam */ 3183189251Ssamstruct wpa_global * wpa_supplicant_init(struct wpa_params *params) 3184189251Ssam{ 3185189251Ssam struct wpa_global *global; 3186189251Ssam int ret, i; 3187189251Ssam 3188189251Ssam if (params == NULL) 3189189251Ssam return NULL; 3190189251Ssam 3191252726Srpaulo#ifdef CONFIG_DRIVER_NDIS 3192252726Srpaulo { 3193252726Srpaulo void driver_ndis_init_ops(void); 3194252726Srpaulo driver_ndis_init_ops(); 3195252726Srpaulo } 3196252726Srpaulo#endif /* CONFIG_DRIVER_NDIS */ 3197252726Srpaulo 3198252726Srpaulo#ifndef CONFIG_NO_WPA_MSG 3199252726Srpaulo wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb); 3200252726Srpaulo#endif /* CONFIG_NO_WPA_MSG */ 3201252726Srpaulo 3202189251Ssam wpa_debug_open_file(params->wpa_debug_file_path); 3203189262Ssam if (params->wpa_debug_syslog) 3204189262Ssam wpa_debug_open_syslog(); 3205252726Srpaulo if (params->wpa_debug_tracing) { 3206252726Srpaulo ret = wpa_debug_open_linux_tracing(); 3207252726Srpaulo if (ret) { 3208252726Srpaulo wpa_printf(MSG_ERROR, 3209252726Srpaulo "Failed to enable trace logging"); 3210252726Srpaulo return NULL; 3211252726Srpaulo } 3212252726Srpaulo } 3213189251Ssam 3214214734Srpaulo ret = eap_register_methods(); 3215189251Ssam if (ret) { 3216189251Ssam wpa_printf(MSG_ERROR, "Failed to register EAP methods"); 3217189251Ssam if (ret == -2) 3218189251Ssam wpa_printf(MSG_ERROR, "Two or more EAP methods used " 3219189251Ssam "the same EAP type."); 3220189251Ssam return NULL; 3221189251Ssam } 3222189251Ssam 3223189251Ssam global = os_zalloc(sizeof(*global)); 3224189251Ssam if (global == NULL) 3225189251Ssam return NULL; 3226252726Srpaulo dl_list_init(&global->p2p_srv_bonjour); 3227252726Srpaulo dl_list_init(&global->p2p_srv_upnp); 3228189251Ssam global->params.daemonize = params->daemonize; 3229189251Ssam global->params.wait_for_monitor = params->wait_for_monitor; 3230189251Ssam global->params.dbus_ctrl_interface = params->dbus_ctrl_interface; 3231189251Ssam if (params->pid_file) 3232189251Ssam global->params.pid_file = os_strdup(params->pid_file); 3233189251Ssam if (params->ctrl_interface) 3234189251Ssam global->params.ctrl_interface = 3235189251Ssam os_strdup(params->ctrl_interface); 3236214734Srpaulo if (params->override_driver) 3237214734Srpaulo global->params.override_driver = 3238214734Srpaulo os_strdup(params->override_driver); 3239214734Srpaulo if (params->override_ctrl_interface) 3240214734Srpaulo global->params.override_ctrl_interface = 3241214734Srpaulo os_strdup(params->override_ctrl_interface); 3242189251Ssam wpa_debug_level = global->params.wpa_debug_level = 3243189251Ssam params->wpa_debug_level; 3244189251Ssam wpa_debug_show_keys = global->params.wpa_debug_show_keys = 3245189251Ssam params->wpa_debug_show_keys; 3246189251Ssam wpa_debug_timestamp = global->params.wpa_debug_timestamp = 3247189251Ssam params->wpa_debug_timestamp; 3248189251Ssam 3249252726Srpaulo wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR); 3250252726Srpaulo 3251214734Srpaulo if (eloop_init()) { 3252189251Ssam wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 3253189251Ssam wpa_supplicant_deinit(global); 3254189251Ssam return NULL; 3255189251Ssam } 3256189251Ssam 3257252726Srpaulo random_init(params->entropy_file); 3258252726Srpaulo 3259189251Ssam global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global); 3260189251Ssam if (global->ctrl_iface == NULL) { 3261189251Ssam wpa_supplicant_deinit(global); 3262189251Ssam return NULL; 3263189251Ssam } 3264189251Ssam 3265214734Srpaulo if (wpas_notify_supplicant_initialized(global)) { 3266214734Srpaulo wpa_supplicant_deinit(global); 3267214734Srpaulo return NULL; 3268189251Ssam } 3269189251Ssam 3270214734Srpaulo for (i = 0; wpa_drivers[i]; i++) 3271189251Ssam global->drv_count++; 3272189251Ssam if (global->drv_count == 0) { 3273189251Ssam wpa_printf(MSG_ERROR, "No drivers enabled"); 3274189251Ssam wpa_supplicant_deinit(global); 3275189251Ssam return NULL; 3276189251Ssam } 3277189251Ssam global->drv_priv = os_zalloc(global->drv_count * sizeof(void *)); 3278189251Ssam if (global->drv_priv == NULL) { 3279189251Ssam wpa_supplicant_deinit(global); 3280189251Ssam return NULL; 3281189251Ssam } 3282252726Srpaulo 3283252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY 3284252726Srpaulo if (wifi_display_init(global) < 0) { 3285252726Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display"); 3286252726Srpaulo wpa_supplicant_deinit(global); 3287252726Srpaulo return NULL; 3288189251Ssam } 3289252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */ 3290189251Ssam 3291189251Ssam return global; 3292189251Ssam} 3293189251Ssam 3294189251Ssam 3295189251Ssam/** 3296189251Ssam * wpa_supplicant_run - Run the %wpa_supplicant main event loop 3297189251Ssam * @global: Pointer to global data from wpa_supplicant_init() 3298189251Ssam * Returns: 0 after successful event loop run, -1 on failure 3299189251Ssam * 3300189251Ssam * This function starts the main event loop and continues running as long as 3301189251Ssam * there are any remaining events. In most cases, this function is running as 3302189251Ssam * long as the %wpa_supplicant process in still in use. 3303189251Ssam */ 3304189251Ssamint wpa_supplicant_run(struct wpa_global *global) 3305189251Ssam{ 3306189251Ssam struct wpa_supplicant *wpa_s; 3307189251Ssam 3308189251Ssam if (global->params.daemonize && 3309189251Ssam wpa_supplicant_daemon(global->params.pid_file)) 3310189251Ssam return -1; 3311189251Ssam 3312189251Ssam if (global->params.wait_for_monitor) { 3313189251Ssam for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) 3314189251Ssam if (wpa_s->ctrl_iface) 3315189251Ssam wpa_supplicant_ctrl_iface_wait( 3316189251Ssam wpa_s->ctrl_iface); 3317189251Ssam } 3318189251Ssam 3319214734Srpaulo eloop_register_signal_terminate(wpa_supplicant_terminate, global); 3320214734Srpaulo eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); 3321189251Ssam 3322189251Ssam eloop_run(); 3323189251Ssam 3324189251Ssam return 0; 3325189251Ssam} 3326189251Ssam 3327189251Ssam 3328189251Ssam/** 3329189251Ssam * wpa_supplicant_deinit - Deinitialize %wpa_supplicant 3330189251Ssam * @global: Pointer to global data from wpa_supplicant_init() 3331189251Ssam * 3332189251Ssam * This function is called to deinitialize %wpa_supplicant and to free all 3333189251Ssam * allocated resources. Remaining network interfaces will also be removed. 3334189251Ssam */ 3335189251Ssamvoid wpa_supplicant_deinit(struct wpa_global *global) 3336189251Ssam{ 3337189251Ssam int i; 3338189251Ssam 3339189251Ssam if (global == NULL) 3340189251Ssam return; 3341189251Ssam 3342252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY 3343252726Srpaulo wifi_display_deinit(global); 3344252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */ 3345252726Srpaulo#ifdef CONFIG_P2P 3346252726Srpaulo wpas_p2p_deinit_global(global); 3347252726Srpaulo#endif /* CONFIG_P2P */ 3348252726Srpaulo 3349189251Ssam while (global->ifaces) 3350252726Srpaulo wpa_supplicant_remove_iface(global, global->ifaces, 1); 3351189251Ssam 3352189251Ssam if (global->ctrl_iface) 3353189251Ssam wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface); 3354189251Ssam 3355214734Srpaulo wpas_notify_supplicant_deinitialized(global); 3356214734Srpaulo 3357189251Ssam eap_peer_unregister_methods(); 3358214734Srpaulo#ifdef CONFIG_AP 3359214734Srpaulo eap_server_unregister_methods(); 3360214734Srpaulo#endif /* CONFIG_AP */ 3361189251Ssam 3362214734Srpaulo for (i = 0; wpa_drivers[i] && global->drv_priv; i++) { 3363189251Ssam if (!global->drv_priv[i]) 3364189251Ssam continue; 3365214734Srpaulo wpa_drivers[i]->global_deinit(global->drv_priv[i]); 3366189251Ssam } 3367189251Ssam os_free(global->drv_priv); 3368189251Ssam 3369252726Srpaulo random_deinit(); 3370252726Srpaulo 3371189251Ssam eloop_destroy(); 3372189251Ssam 3373189251Ssam if (global->params.pid_file) { 3374189251Ssam os_daemonize_terminate(global->params.pid_file); 3375189251Ssam os_free(global->params.pid_file); 3376189251Ssam } 3377189251Ssam os_free(global->params.ctrl_interface); 3378214734Srpaulo os_free(global->params.override_driver); 3379214734Srpaulo os_free(global->params.override_ctrl_interface); 3380189251Ssam 3381252726Srpaulo os_free(global->p2p_disallow_freq); 3382252726Srpaulo 3383189251Ssam os_free(global); 3384189262Ssam wpa_debug_close_syslog(); 3385189251Ssam wpa_debug_close_file(); 3386252726Srpaulo wpa_debug_close_linux_tracing(); 3387189251Ssam} 3388252726Srpaulo 3389252726Srpaulo 3390252726Srpaulovoid wpa_supplicant_update_config(struct wpa_supplicant *wpa_s) 3391252726Srpaulo{ 3392252726Srpaulo if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) && 3393252726Srpaulo wpa_s->conf->country[0] && wpa_s->conf->country[1]) { 3394252726Srpaulo char country[3]; 3395252726Srpaulo country[0] = wpa_s->conf->country[0]; 3396252726Srpaulo country[1] = wpa_s->conf->country[1]; 3397252726Srpaulo country[2] = '\0'; 3398252726Srpaulo if (wpa_drv_set_country(wpa_s, country) < 0) { 3399252726Srpaulo wpa_printf(MSG_ERROR, "Failed to set country code " 3400252726Srpaulo "'%s'", country); 3401252726Srpaulo } 3402252726Srpaulo } 3403252726Srpaulo 3404252726Srpaulo if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND) 3405252726Srpaulo wpas_init_ext_pw(wpa_s); 3406252726Srpaulo 3407252726Srpaulo#ifdef CONFIG_WPS 3408252726Srpaulo wpas_wps_update_config(wpa_s); 3409252726Srpaulo#endif /* CONFIG_WPS */ 3410252726Srpaulo 3411252726Srpaulo#ifdef CONFIG_P2P 3412252726Srpaulo wpas_p2p_update_config(wpa_s); 3413252726Srpaulo#endif /* CONFIG_P2P */ 3414252726Srpaulo 3415252726Srpaulo wpa_s->conf->changed_parameters = 0; 3416252726Srpaulo} 3417252726Srpaulo 3418252726Srpaulo 3419252726Srpaulostatic void add_freq(int *freqs, int *num_freqs, int freq) 3420252726Srpaulo{ 3421252726Srpaulo int i; 3422252726Srpaulo 3423252726Srpaulo for (i = 0; i < *num_freqs; i++) { 3424252726Srpaulo if (freqs[i] == freq) 3425252726Srpaulo return; 3426252726Srpaulo } 3427252726Srpaulo 3428252726Srpaulo freqs[*num_freqs] = freq; 3429252726Srpaulo (*num_freqs)++; 3430252726Srpaulo} 3431252726Srpaulo 3432252726Srpaulo 3433252726Srpaulostatic int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s) 3434252726Srpaulo{ 3435252726Srpaulo struct wpa_bss *bss, *cbss; 3436252726Srpaulo const int max_freqs = 10; 3437252726Srpaulo int *freqs; 3438252726Srpaulo int num_freqs = 0; 3439252726Srpaulo 3440252726Srpaulo freqs = os_zalloc(sizeof(int) * (max_freqs + 1)); 3441252726Srpaulo if (freqs == NULL) 3442252726Srpaulo return NULL; 3443252726Srpaulo 3444252726Srpaulo cbss = wpa_s->current_bss; 3445252726Srpaulo 3446252726Srpaulo dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 3447252726Srpaulo if (bss == cbss) 3448252726Srpaulo continue; 3449252726Srpaulo if (bss->ssid_len == cbss->ssid_len && 3450252726Srpaulo os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 && 3451252726Srpaulo wpa_blacklist_get(wpa_s, bss->bssid) == NULL) { 3452252726Srpaulo add_freq(freqs, &num_freqs, bss->freq); 3453252726Srpaulo if (num_freqs == max_freqs) 3454252726Srpaulo break; 3455252726Srpaulo } 3456252726Srpaulo } 3457252726Srpaulo 3458252726Srpaulo if (num_freqs == 0) { 3459252726Srpaulo os_free(freqs); 3460252726Srpaulo freqs = NULL; 3461252726Srpaulo } 3462252726Srpaulo 3463252726Srpaulo return freqs; 3464252726Srpaulo} 3465252726Srpaulo 3466252726Srpaulo 3467252726Srpaulovoid wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) 3468252726Srpaulo{ 3469252726Srpaulo int timeout; 3470252726Srpaulo int count; 3471252726Srpaulo int *freqs = NULL; 3472252726Srpaulo 3473252726Srpaulo /* 3474252726Srpaulo * Remove possible authentication timeout since the connection failed. 3475252726Srpaulo */ 3476252726Srpaulo eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 3477252726Srpaulo 3478252726Srpaulo /* 3479252726Srpaulo * Add the failed BSSID into the blacklist and speed up next scan 3480252726Srpaulo * attempt if there could be other APs that could accept association. 3481252726Srpaulo * The current blacklist count indicates how many times we have tried 3482252726Srpaulo * connecting to this AP and multiple attempts mean that other APs are 3483252726Srpaulo * either not available or has already been tried, so that we can start 3484252726Srpaulo * increasing the delay here to avoid constant scanning. 3485252726Srpaulo */ 3486252726Srpaulo count = wpa_blacklist_add(wpa_s, bssid); 3487252726Srpaulo if (count == 1 && wpa_s->current_bss) { 3488252726Srpaulo /* 3489252726Srpaulo * This BSS was not in the blacklist before. If there is 3490252726Srpaulo * another BSS available for the same ESS, we should try that 3491252726Srpaulo * next. Otherwise, we may as well try this one once more 3492252726Srpaulo * before allowing other, likely worse, ESSes to be considered. 3493252726Srpaulo */ 3494252726Srpaulo freqs = get_bss_freqs_in_ess(wpa_s); 3495252726Srpaulo if (freqs) { 3496252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS " 3497252726Srpaulo "has been seen; try it next"); 3498252726Srpaulo wpa_blacklist_add(wpa_s, bssid); 3499252726Srpaulo /* 3500252726Srpaulo * On the next scan, go through only the known channels 3501252726Srpaulo * used in this ESS based on previous scans to speed up 3502252726Srpaulo * common load balancing use case. 3503252726Srpaulo */ 3504252726Srpaulo os_free(wpa_s->next_scan_freqs); 3505252726Srpaulo wpa_s->next_scan_freqs = freqs; 3506252726Srpaulo } 3507252726Srpaulo } 3508252726Srpaulo 3509252726Srpaulo /* 3510252726Srpaulo * Add previous failure count in case the temporary blacklist was 3511252726Srpaulo * cleared due to no other BSSes being available. 3512252726Srpaulo */ 3513252726Srpaulo count += wpa_s->extra_blacklist_count; 3514252726Srpaulo 3515252726Srpaulo switch (count) { 3516252726Srpaulo case 1: 3517252726Srpaulo timeout = 100; 3518252726Srpaulo break; 3519252726Srpaulo case 2: 3520252726Srpaulo timeout = 500; 3521252726Srpaulo break; 3522252726Srpaulo case 3: 3523252726Srpaulo timeout = 1000; 3524252726Srpaulo break; 3525252726Srpaulo case 4: 3526252726Srpaulo timeout = 5000; 3527252726Srpaulo break; 3528252726Srpaulo default: 3529252726Srpaulo timeout = 10000; 3530252726Srpaulo break; 3531252726Srpaulo } 3532252726Srpaulo 3533252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d " 3534252726Srpaulo "ms", count, timeout); 3535252726Srpaulo 3536252726Srpaulo /* 3537252726Srpaulo * TODO: if more than one possible AP is available in scan results, 3538252726Srpaulo * could try the other ones before requesting a new scan. 3539252726Srpaulo */ 3540252726Srpaulo wpa_supplicant_req_scan(wpa_s, timeout / 1000, 3541252726Srpaulo 1000 * (timeout % 1000)); 3542252726Srpaulo 3543252726Srpaulo#ifdef CONFIG_P2P 3544252726Srpaulo if (wpa_s->global->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled && 3545252726Srpaulo wpa_s->global->p2p != NULL) { 3546252726Srpaulo wpa_s->global->p2p_cb_on_scan_complete = 0; 3547252726Srpaulo if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) { 3548252726Srpaulo wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation " 3549252726Srpaulo "continued after failed association"); 3550252726Srpaulo } 3551252726Srpaulo } 3552252726Srpaulo#endif /* CONFIG_P2P */ 3553252726Srpaulo} 3554252726Srpaulo 3555252726Srpaulo 3556252726Srpauloint wpas_driver_bss_selection(struct wpa_supplicant *wpa_s) 3557252726Srpaulo{ 3558252726Srpaulo return wpa_s->conf->ap_scan == 2 || 3559252726Srpaulo (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION); 3560252726Srpaulo} 3561252726Srpaulo 3562252726Srpaulo 3563252726Srpaulo#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) 3564252726Srpauloint wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s, 3565252726Srpaulo struct wpa_ssid *ssid, 3566252726Srpaulo const char *field, 3567252726Srpaulo const char *value) 3568252726Srpaulo{ 3569252726Srpaulo#ifdef IEEE8021X_EAPOL 3570252726Srpaulo struct eap_peer_config *eap = &ssid->eap; 3571252726Srpaulo 3572252726Srpaulo wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field); 3573252726Srpaulo wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value", 3574252726Srpaulo (const u8 *) value, os_strlen(value)); 3575252726Srpaulo 3576252726Srpaulo switch (wpa_supplicant_ctrl_req_from_string(field)) { 3577252726Srpaulo case WPA_CTRL_REQ_EAP_IDENTITY: 3578252726Srpaulo os_free(eap->identity); 3579252726Srpaulo eap->identity = (u8 *) os_strdup(value); 3580252726Srpaulo eap->identity_len = os_strlen(value); 3581252726Srpaulo eap->pending_req_identity = 0; 3582252726Srpaulo if (ssid == wpa_s->current_ssid) 3583252726Srpaulo wpa_s->reassociate = 1; 3584252726Srpaulo break; 3585252726Srpaulo case WPA_CTRL_REQ_EAP_PASSWORD: 3586252726Srpaulo os_free(eap->password); 3587252726Srpaulo eap->password = (u8 *) os_strdup(value); 3588252726Srpaulo eap->password_len = os_strlen(value); 3589252726Srpaulo eap->pending_req_password = 0; 3590252726Srpaulo if (ssid == wpa_s->current_ssid) 3591252726Srpaulo wpa_s->reassociate = 1; 3592252726Srpaulo break; 3593252726Srpaulo case WPA_CTRL_REQ_EAP_NEW_PASSWORD: 3594252726Srpaulo os_free(eap->new_password); 3595252726Srpaulo eap->new_password = (u8 *) os_strdup(value); 3596252726Srpaulo eap->new_password_len = os_strlen(value); 3597252726Srpaulo eap->pending_req_new_password = 0; 3598252726Srpaulo if (ssid == wpa_s->current_ssid) 3599252726Srpaulo wpa_s->reassociate = 1; 3600252726Srpaulo break; 3601252726Srpaulo case WPA_CTRL_REQ_EAP_PIN: 3602252726Srpaulo os_free(eap->pin); 3603252726Srpaulo eap->pin = os_strdup(value); 3604252726Srpaulo eap->pending_req_pin = 0; 3605252726Srpaulo if (ssid == wpa_s->current_ssid) 3606252726Srpaulo wpa_s->reassociate = 1; 3607252726Srpaulo break; 3608252726Srpaulo case WPA_CTRL_REQ_EAP_OTP: 3609252726Srpaulo os_free(eap->otp); 3610252726Srpaulo eap->otp = (u8 *) os_strdup(value); 3611252726Srpaulo eap->otp_len = os_strlen(value); 3612252726Srpaulo os_free(eap->pending_req_otp); 3613252726Srpaulo eap->pending_req_otp = NULL; 3614252726Srpaulo eap->pending_req_otp_len = 0; 3615252726Srpaulo break; 3616252726Srpaulo case WPA_CTRL_REQ_EAP_PASSPHRASE: 3617252726Srpaulo os_free(eap->private_key_passwd); 3618252726Srpaulo eap->private_key_passwd = (u8 *) os_strdup(value); 3619252726Srpaulo eap->pending_req_passphrase = 0; 3620252726Srpaulo if (ssid == wpa_s->current_ssid) 3621252726Srpaulo wpa_s->reassociate = 1; 3622252726Srpaulo break; 3623252726Srpaulo default: 3624252726Srpaulo wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field); 3625252726Srpaulo return -1; 3626252726Srpaulo } 3627252726Srpaulo 3628252726Srpaulo return 0; 3629252726Srpaulo#else /* IEEE8021X_EAPOL */ 3630252726Srpaulo wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included"); 3631252726Srpaulo return -1; 3632252726Srpaulo#endif /* IEEE8021X_EAPOL */ 3633252726Srpaulo} 3634252726Srpaulo#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */ 3635252726Srpaulo 3636252726Srpaulo 3637252726Srpauloint wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) 3638252726Srpaulo{ 3639252726Srpaulo int i; 3640252726Srpaulo unsigned int drv_enc; 3641252726Srpaulo 3642252726Srpaulo if (ssid == NULL) 3643252726Srpaulo return 1; 3644252726Srpaulo 3645252726Srpaulo if (ssid->disabled) 3646252726Srpaulo return 1; 3647252726Srpaulo 3648252726Srpaulo if (wpa_s && wpa_s->drv_capa_known) 3649252726Srpaulo drv_enc = wpa_s->drv_enc; 3650252726Srpaulo else 3651252726Srpaulo drv_enc = (unsigned int) -1; 3652252726Srpaulo 3653252726Srpaulo for (i = 0; i < NUM_WEP_KEYS; i++) { 3654252726Srpaulo size_t len = ssid->wep_key_len[i]; 3655252726Srpaulo if (len == 0) 3656252726Srpaulo continue; 3657252726Srpaulo if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40)) 3658252726Srpaulo continue; 3659252726Srpaulo if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104)) 3660252726Srpaulo continue; 3661252726Srpaulo if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128)) 3662252726Srpaulo continue; 3663252726Srpaulo return 1; /* invalid WEP key */ 3664252726Srpaulo } 3665252726Srpaulo 3666252726Srpaulo if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && 3667252726Srpaulo !ssid->ext_psk) 3668252726Srpaulo return 1; 3669252726Srpaulo 3670252726Srpaulo return 0; 3671252726Srpaulo} 3672252726Srpaulo 3673252726Srpaulo 3674252726Srpauloint wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s) 3675252726Srpaulo{ 3676252726Srpaulo if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P) 3677252726Srpaulo return 1; 3678252726Srpaulo if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA) 3679252726Srpaulo return 0; 3680252726Srpaulo return -1; 3681252726Srpaulo} 3682252726Srpaulo 3683252726Srpaulo 3684252726Srpaulovoid wpas_auth_failed(struct wpa_supplicant *wpa_s) 3685252726Srpaulo{ 3686252726Srpaulo struct wpa_ssid *ssid = wpa_s->current_ssid; 3687252726Srpaulo int dur; 3688252726Srpaulo struct os_time now; 3689252726Srpaulo 3690252726Srpaulo if (ssid == NULL) { 3691252726Srpaulo wpa_printf(MSG_DEBUG, "Authentication failure but no known " 3692252726Srpaulo "SSID block"); 3693252726Srpaulo return; 3694252726Srpaulo } 3695252726Srpaulo 3696252726Srpaulo if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) 3697252726Srpaulo return; 3698252726Srpaulo 3699252726Srpaulo ssid->auth_failures++; 3700252726Srpaulo if (ssid->auth_failures > 50) 3701252726Srpaulo dur = 300; 3702252726Srpaulo else if (ssid->auth_failures > 20) 3703252726Srpaulo dur = 120; 3704252726Srpaulo else if (ssid->auth_failures > 10) 3705252726Srpaulo dur = 60; 3706252726Srpaulo else if (ssid->auth_failures > 5) 3707252726Srpaulo dur = 30; 3708252726Srpaulo else if (ssid->auth_failures > 1) 3709252726Srpaulo dur = 20; 3710252726Srpaulo else 3711252726Srpaulo dur = 10; 3712252726Srpaulo 3713252726Srpaulo os_get_time(&now); 3714252726Srpaulo if (now.sec + dur <= ssid->disabled_until.sec) 3715252726Srpaulo return; 3716252726Srpaulo 3717252726Srpaulo ssid->disabled_until.sec = now.sec + dur; 3718252726Srpaulo 3719252726Srpaulo wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED 3720252726Srpaulo "id=%d ssid=\"%s\" auth_failures=%u duration=%d", 3721252726Srpaulo ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len), 3722252726Srpaulo ssid->auth_failures, dur); 3723252726Srpaulo} 3724252726Srpaulo 3725252726Srpaulo 3726252726Srpaulovoid wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s, 3727252726Srpaulo struct wpa_ssid *ssid, int clear_failures) 3728252726Srpaulo{ 3729252726Srpaulo if (ssid == NULL) 3730252726Srpaulo return; 3731252726Srpaulo 3732252726Srpaulo if (ssid->disabled_until.sec) { 3733252726Srpaulo wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED 3734252726Srpaulo "id=%d ssid=\"%s\"", 3735252726Srpaulo ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 3736252726Srpaulo } 3737252726Srpaulo ssid->disabled_until.sec = 0; 3738252726Srpaulo ssid->disabled_until.usec = 0; 3739252726Srpaulo if (clear_failures) 3740252726Srpaulo ssid->auth_failures = 0; 3741252726Srpaulo} 3742252726Srpaulo 3743252726Srpaulo 3744252726Srpauloint disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid) 3745252726Srpaulo{ 3746252726Srpaulo size_t i; 3747252726Srpaulo 3748252726Srpaulo if (wpa_s->disallow_aps_bssid == NULL) 3749252726Srpaulo return 0; 3750252726Srpaulo 3751252726Srpaulo for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) { 3752252726Srpaulo if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN, 3753252726Srpaulo bssid, ETH_ALEN) == 0) 3754252726Srpaulo return 1; 3755252726Srpaulo } 3756252726Srpaulo 3757252726Srpaulo return 0; 3758252726Srpaulo} 3759252726Srpaulo 3760252726Srpaulo 3761252726Srpauloint disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid, 3762252726Srpaulo size_t ssid_len) 3763252726Srpaulo{ 3764252726Srpaulo size_t i; 3765252726Srpaulo 3766252726Srpaulo if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL) 3767252726Srpaulo return 0; 3768252726Srpaulo 3769252726Srpaulo for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) { 3770252726Srpaulo struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i]; 3771252726Srpaulo if (ssid_len == s->ssid_len && 3772252726Srpaulo os_memcmp(ssid, s->ssid, ssid_len) == 0) 3773252726Srpaulo return 1; 3774252726Srpaulo } 3775252726Srpaulo 3776252726Srpaulo return 0; 3777252726Srpaulo} 3778252726Srpaulo 3779252726Srpaulo 3780252726Srpaulo/** 3781252726Srpaulo * wpas_request_connection - Request a new connection 3782252726Srpaulo * @wpa_s: Pointer to the network interface 3783252726Srpaulo * 3784252726Srpaulo * This function is used to request a new connection to be found. It will mark 3785252726Srpaulo * the interface to allow reassociation and request a new scan to find a 3786252726Srpaulo * suitable network to connect to. 3787252726Srpaulo */ 3788252726Srpaulovoid wpas_request_connection(struct wpa_supplicant *wpa_s) 3789252726Srpaulo{ 3790252726Srpaulo wpa_s->normal_scans = 0; 3791252726Srpaulo wpa_supplicant_reinit_autoscan(wpa_s); 3792252726Srpaulo wpa_s->extra_blacklist_count = 0; 3793252726Srpaulo wpa_s->disconnected = 0; 3794252726Srpaulo wpa_s->reassociate = 1; 3795252726Srpaulo wpa_supplicant_req_scan(wpa_s, 0, 0); 3796252726Srpaulo} 3797