Branch data Line data Source code
1 : : /*
2 : : * WPA Supplicant
3 : : * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : *
8 : : * This file implements functions for registering and unregistering
9 : : * %wpa_supplicant interfaces. In addition, this file contains number of
10 : : * functions for managing network connections.
11 : : */
12 : :
13 : : #include "includes.h"
14 : :
15 : : #include "common.h"
16 : : #include "crypto/random.h"
17 : : #include "crypto/sha1.h"
18 : : #include "eapol_supp/eapol_supp_sm.h"
19 : : #include "eap_peer/eap.h"
20 : : #include "eap_peer/eap_proxy.h"
21 : : #include "eap_server/eap_methods.h"
22 : : #include "rsn_supp/wpa.h"
23 : : #include "eloop.h"
24 : : #include "config.h"
25 : : #include "utils/ext_password.h"
26 : : #include "l2_packet/l2_packet.h"
27 : : #include "wpa_supplicant_i.h"
28 : : #include "driver_i.h"
29 : : #include "ctrl_iface.h"
30 : : #include "pcsc_funcs.h"
31 : : #include "common/version.h"
32 : : #include "rsn_supp/preauth.h"
33 : : #include "rsn_supp/pmksa_cache.h"
34 : : #include "common/wpa_ctrl.h"
35 : : #include "common/ieee802_11_defs.h"
36 : : #include "p2p/p2p.h"
37 : : #include "blacklist.h"
38 : : #include "wpas_glue.h"
39 : : #include "wps_supplicant.h"
40 : : #include "ibss_rsn.h"
41 : : #include "sme.h"
42 : : #include "gas_query.h"
43 : : #include "ap.h"
44 : : #include "p2p_supplicant.h"
45 : : #include "wifi_display.h"
46 : : #include "notify.h"
47 : : #include "bgscan.h"
48 : : #include "autoscan.h"
49 : : #include "bss.h"
50 : : #include "scan.h"
51 : : #include "offchannel.h"
52 : : #include "hs20_supplicant.h"
53 : : #include "wnm_sta.h"
54 : :
55 : : const char *wpa_supplicant_version =
56 : : "wpa_supplicant v" VERSION_STR "\n"
57 : : "Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> and contributors";
58 : :
59 : : const char *wpa_supplicant_license =
60 : : "This software may be distributed under the terms of the BSD license.\n"
61 : : "See README for more details.\n"
62 : : #ifdef EAP_TLS_OPENSSL
63 : : "\nThis product includes software developed by the OpenSSL Project\n"
64 : : "for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
65 : : #endif /* EAP_TLS_OPENSSL */
66 : : ;
67 : :
68 : : #ifndef CONFIG_NO_STDOUT_DEBUG
69 : : /* Long text divided into parts in order to fit in C89 strings size limits. */
70 : : const char *wpa_supplicant_full_license1 =
71 : : "";
72 : : const char *wpa_supplicant_full_license2 =
73 : : "This software may be distributed under the terms of the BSD license.\n"
74 : : "\n"
75 : : "Redistribution and use in source and binary forms, with or without\n"
76 : : "modification, are permitted provided that the following conditions are\n"
77 : : "met:\n"
78 : : "\n";
79 : : const char *wpa_supplicant_full_license3 =
80 : : "1. Redistributions of source code must retain the above copyright\n"
81 : : " notice, this list of conditions and the following disclaimer.\n"
82 : : "\n"
83 : : "2. Redistributions in binary form must reproduce the above copyright\n"
84 : : " notice, this list of conditions and the following disclaimer in the\n"
85 : : " documentation and/or other materials provided with the distribution.\n"
86 : : "\n";
87 : : const char *wpa_supplicant_full_license4 =
88 : : "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
89 : : " names of its contributors may be used to endorse or promote products\n"
90 : : " derived from this software without specific prior written permission.\n"
91 : : "\n"
92 : : "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
93 : : "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
94 : : "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
95 : : "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
96 : : const char *wpa_supplicant_full_license5 =
97 : : "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
98 : : "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
99 : : "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
100 : : "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
101 : : "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
102 : : "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
103 : : "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
104 : : "\n";
105 : : #endif /* CONFIG_NO_STDOUT_DEBUG */
106 : :
107 : : /* Configure default/group WEP keys for static WEP */
108 : 89 : int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
109 : : {
110 : 89 : int i, set = 0;
111 : :
112 [ + + ]: 445 : for (i = 0; i < NUM_WEP_KEYS; i++) {
113 [ + + ]: 356 : if (ssid->wep_key_len[i] == 0)
114 : 354 : continue;
115 : :
116 : 2 : set = 1;
117 : 2 : wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
118 : 2 : i, i == ssid->wep_tx_keyidx, NULL, 0,
119 : 4 : ssid->wep_key[i], ssid->wep_key_len[i]);
120 : : }
121 : :
122 : 89 : return set;
123 : : }
124 : :
125 : :
126 : 9 : int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
127 : : struct wpa_ssid *ssid)
128 : : {
129 : : u8 key[32];
130 : : size_t keylen;
131 : : enum wpa_alg alg;
132 : 9 : u8 seq[6] = { 0 };
133 : :
134 : : /* IBSS/WPA-None uses only one key (Group) for both receiving and
135 : : * sending unicast and multicast packets. */
136 : :
137 [ - + ]: 9 : if (ssid->mode != WPAS_MODE_IBSS) {
138 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
139 : 0 : "IBSS/ad-hoc) for WPA-None", ssid->mode);
140 : 0 : return -1;
141 : : }
142 : :
143 [ - + ]: 9 : if (!ssid->psk_set) {
144 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
145 : : "WPA-None");
146 : 0 : return -1;
147 : : }
148 : :
149 [ - - + - ]: 9 : switch (wpa_s->group_cipher) {
150 : : case WPA_CIPHER_CCMP:
151 : 0 : os_memcpy(key, ssid->psk, 16);
152 : 0 : keylen = 16;
153 : 0 : alg = WPA_ALG_CCMP;
154 : 0 : break;
155 : : case WPA_CIPHER_GCMP:
156 : 0 : os_memcpy(key, ssid->psk, 16);
157 : 0 : keylen = 16;
158 : 0 : alg = WPA_ALG_GCMP;
159 : 0 : break;
160 : : case WPA_CIPHER_TKIP:
161 : : /* WPA-None uses the same Michael MIC key for both TX and RX */
162 : 9 : os_memcpy(key, ssid->psk, 16 + 8);
163 : 9 : os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
164 : 9 : keylen = 32;
165 : 9 : alg = WPA_ALG_TKIP;
166 : 9 : break;
167 : : default:
168 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
169 : : "WPA-None", wpa_s->group_cipher);
170 : 0 : return -1;
171 : : }
172 : :
173 : : /* TODO: should actually remember the previously used seq#, both for TX
174 : : * and RX from each STA.. */
175 : :
176 : 9 : return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
177 : : }
178 : :
179 : :
180 : 0 : static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
181 : : {
182 : 0 : struct wpa_supplicant *wpa_s = eloop_ctx;
183 : 0 : const u8 *bssid = wpa_s->bssid;
184 [ # # ]: 0 : if (is_zero_ether_addr(bssid))
185 : 0 : bssid = wpa_s->pending_bssid;
186 : 0 : wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
187 : 0 : MAC2STR(bssid));
188 : 0 : wpa_blacklist_add(wpa_s, bssid);
189 : 0 : wpa_sm_notify_disassoc(wpa_s->wpa);
190 : 0 : wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
191 : 0 : wpa_s->reassociate = 1;
192 : :
193 : : /*
194 : : * If we timed out, the AP or the local radio may be busy.
195 : : * So, wait a second until scanning again.
196 : : */
197 : 0 : wpa_supplicant_req_scan(wpa_s, 1, 0);
198 : :
199 : 0 : wpas_p2p_continue_after_scan(wpa_s);
200 : 0 : }
201 : :
202 : :
203 : : /**
204 : : * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
205 : : * @wpa_s: Pointer to wpa_supplicant data
206 : : * @sec: Number of seconds after which to time out authentication
207 : : * @usec: Number of microseconds after which to time out authentication
208 : : *
209 : : * This function is used to schedule a timeout for the current authentication
210 : : * attempt.
211 : : */
212 : 682 : void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
213 : : int sec, int usec)
214 : : {
215 [ - + ][ # # ]: 682 : if (wpa_s->conf->ap_scan == 0 &&
216 : 0 : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
217 : 682 : return;
218 : :
219 : 682 : wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
220 : : "%d usec", sec, usec);
221 : 682 : eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
222 : 682 : eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
223 : : }
224 : :
225 : :
226 : : /**
227 : : * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
228 : : * @wpa_s: Pointer to wpa_supplicant data
229 : : *
230 : : * This function is used to cancel authentication timeout scheduled with
231 : : * wpa_supplicant_req_auth_timeout() and it is called when authentication has
232 : : * been completed.
233 : : */
234 : 418 : void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
235 : : {
236 : 418 : wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
237 : 418 : eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
238 : 418 : wpa_blacklist_del(wpa_s, wpa_s->bssid);
239 : 418 : }
240 : :
241 : :
242 : : /**
243 : : * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
244 : : * @wpa_s: Pointer to wpa_supplicant data
245 : : *
246 : : * This function is used to configure EAPOL state machine based on the selected
247 : : * authentication mode.
248 : : */
249 : 460 : void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
250 : : {
251 : : #ifdef IEEE8021X_EAPOL
252 : : struct eapol_config eapol_conf;
253 : 460 : struct wpa_ssid *ssid = wpa_s->current_ssid;
254 : :
255 : : #ifdef CONFIG_IBSS_RSN
256 [ + + ][ + - ]: 460 : if (ssid->mode == WPAS_MODE_IBSS &&
257 [ + + ]: 6 : wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
258 : 6 : wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
259 : : /*
260 : : * RSN IBSS authentication is per-STA and we can disable the
261 : : * per-BSSID EAPOL authentication.
262 : : */
263 : 3 : eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
264 : 3 : eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
265 : 3 : eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
266 : 460 : return;
267 : : }
268 : : #endif /* CONFIG_IBSS_RSN */
269 : :
270 : 457 : eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
271 : 457 : eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
272 : :
273 [ + + ][ + + ]: 457 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
274 : 374 : wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
275 : 86 : eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
276 : : else
277 : 371 : eapol_sm_notify_portControl(wpa_s->eapol, Auto);
278 : :
279 : 457 : os_memset(&eapol_conf, 0, sizeof(eapol_conf));
280 [ + + ]: 457 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
281 : 4 : eapol_conf.accept_802_1x_keys = 1;
282 : 4 : eapol_conf.required_keys = 0;
283 [ + + ]: 4 : if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
284 : 2 : eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
285 : : }
286 [ + + ]: 4 : if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
287 : 2 : eapol_conf.required_keys |=
288 : : EAPOL_REQUIRE_KEY_BROADCAST;
289 : : }
290 : :
291 [ - + ]: 4 : if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
292 : 0 : eapol_conf.required_keys = 0;
293 : : }
294 : 457 : eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
295 : 457 : eapol_conf.workaround = ssid->eap_workaround;
296 [ + + ]: 842 : eapol_conf.eap_disabled =
297 [ + + ]: 842 : !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
298 [ + + ]: 381 : wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
299 : 381 : wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
300 : 457 : eapol_conf.external_sim = wpa_s->conf->external_sim;
301 : 457 : eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
302 : : #endif /* IEEE8021X_EAPOL */
303 : : }
304 : :
305 : :
306 : : /**
307 : : * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
308 : : * @wpa_s: Pointer to wpa_supplicant data
309 : : * @ssid: Configuration data for the network
310 : : *
311 : : * This function is used to configure WPA state machine and related parameters
312 : : * to a mode where WPA is not enabled. This is called as part of the
313 : : * authentication configuration when the selected network does not use WPA.
314 : : */
315 : 179 : void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
316 : : struct wpa_ssid *ssid)
317 : : {
318 : : int i;
319 : :
320 [ + + ]: 179 : if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
321 : 92 : wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
322 [ + + ]: 87 : else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
323 : 4 : wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
324 : : else
325 : 83 : wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
326 : 179 : wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
327 : 179 : wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
328 : 179 : wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
329 : 179 : wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
330 : 179 : wpa_s->group_cipher = WPA_CIPHER_NONE;
331 : 179 : wpa_s->mgmt_group_cipher = 0;
332 : :
333 [ + + ]: 887 : for (i = 0; i < NUM_WEP_KEYS; i++) {
334 [ - + ]: 710 : if (ssid->wep_key_len[i] > 5) {
335 : 0 : wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
336 : 0 : wpa_s->group_cipher = WPA_CIPHER_WEP104;
337 : 0 : break;
338 [ + + ]: 710 : } else if (ssid->wep_key_len[i] > 0) {
339 : 2 : wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
340 : 2 : wpa_s->group_cipher = WPA_CIPHER_WEP40;
341 : 2 : break;
342 : : }
343 : : }
344 : :
345 : 179 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
346 : 179 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
347 : 179 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
348 : 179 : wpa_s->pairwise_cipher);
349 : 179 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
350 : : #ifdef CONFIG_IEEE80211W
351 : 179 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
352 : 179 : wpa_s->mgmt_group_cipher);
353 : : #endif /* CONFIG_IEEE80211W */
354 : :
355 : 179 : pmksa_cache_clear_current(wpa_s->wpa);
356 : 179 : }
357 : :
358 : :
359 : 1112 : void free_hw_features(struct wpa_supplicant *wpa_s)
360 : : {
361 : : int i;
362 [ - + ]: 1112 : if (wpa_s->hw.modes == NULL)
363 : 1112 : return;
364 : :
365 [ + + ]: 4448 : for (i = 0; i < wpa_s->hw.num_modes; i++) {
366 : 3336 : os_free(wpa_s->hw.modes[i].channels);
367 : 3336 : os_free(wpa_s->hw.modes[i].rates);
368 : : }
369 : :
370 : 1112 : os_free(wpa_s->hw.modes);
371 : 1112 : wpa_s->hw.modes = NULL;
372 : : }
373 : :
374 : :
375 : 31 : static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
376 : : {
377 : 31 : bgscan_deinit(wpa_s);
378 : 31 : autoscan_deinit(wpa_s);
379 : 31 : scard_deinit(wpa_s->scard);
380 : 31 : wpa_s->scard = NULL;
381 : 31 : wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
382 : 31 : eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
383 : 31 : l2_packet_deinit(wpa_s->l2);
384 : 31 : wpa_s->l2 = NULL;
385 [ - + ]: 31 : if (wpa_s->l2_br) {
386 : 0 : l2_packet_deinit(wpa_s->l2_br);
387 : 0 : wpa_s->l2_br = NULL;
388 : : }
389 : :
390 [ + - ]: 31 : if (wpa_s->conf != NULL) {
391 : : struct wpa_ssid *ssid;
392 [ + + ]: 57 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
393 : 26 : wpas_notify_network_removed(wpa_s, ssid);
394 : : }
395 : :
396 : 31 : os_free(wpa_s->confname);
397 : 31 : wpa_s->confname = NULL;
398 : :
399 : 31 : os_free(wpa_s->confanother);
400 : 31 : wpa_s->confanother = NULL;
401 : :
402 : 31 : wpa_sm_set_eapol(wpa_s->wpa, NULL);
403 : 31 : eapol_sm_deinit(wpa_s->eapol);
404 : 31 : wpa_s->eapol = NULL;
405 : :
406 : 31 : rsn_preauth_deinit(wpa_s->wpa);
407 : :
408 : : #ifdef CONFIG_TDLS
409 : 31 : wpa_tdls_deinit(wpa_s->wpa);
410 : : #endif /* CONFIG_TDLS */
411 : :
412 : 31 : pmksa_candidate_free(wpa_s->wpa);
413 : 31 : wpa_sm_deinit(wpa_s->wpa);
414 : 31 : wpa_s->wpa = NULL;
415 : 31 : wpa_blacklist_clear(wpa_s);
416 : :
417 : 31 : wpa_bss_deinit(wpa_s);
418 : :
419 : 31 : wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
420 : 31 : wpa_supplicant_cancel_scan(wpa_s);
421 : 31 : wpa_supplicant_cancel_auth_timeout(wpa_s);
422 : 31 : eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
423 : : #ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
424 : 31 : eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
425 : : wpa_s, NULL);
426 : : #endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
427 : :
428 : 31 : wpas_wps_deinit(wpa_s);
429 : :
430 : 31 : wpabuf_free(wpa_s->pending_eapol_rx);
431 : 31 : wpa_s->pending_eapol_rx = NULL;
432 : :
433 : : #ifdef CONFIG_IBSS_RSN
434 : 31 : ibss_rsn_deinit(wpa_s->ibss_rsn);
435 : 31 : wpa_s->ibss_rsn = NULL;
436 : : #endif /* CONFIG_IBSS_RSN */
437 : :
438 : 31 : sme_deinit(wpa_s);
439 : :
440 : : #ifdef CONFIG_AP
441 : 31 : wpa_supplicant_ap_deinit(wpa_s);
442 : : #endif /* CONFIG_AP */
443 : :
444 : : #ifdef CONFIG_P2P
445 : 31 : wpas_p2p_deinit(wpa_s);
446 : : #endif /* CONFIG_P2P */
447 : :
448 : : #ifdef CONFIG_OFFCHANNEL
449 : 31 : offchannel_deinit(wpa_s);
450 : : #endif /* CONFIG_OFFCHANNEL */
451 : :
452 : 31 : wpa_supplicant_cancel_sched_scan(wpa_s);
453 : :
454 : 31 : os_free(wpa_s->next_scan_freqs);
455 : 31 : wpa_s->next_scan_freqs = NULL;
456 : :
457 : 31 : os_free(wpa_s->manual_scan_freqs);
458 : 31 : wpa_s->manual_scan_freqs = NULL;
459 : :
460 : 31 : gas_query_deinit(wpa_s->gas);
461 : 31 : wpa_s->gas = NULL;
462 : :
463 : 31 : free_hw_features(wpa_s);
464 : :
465 : 31 : os_free(wpa_s->bssid_filter);
466 : 31 : wpa_s->bssid_filter = NULL;
467 : :
468 : 31 : os_free(wpa_s->disallow_aps_bssid);
469 : 31 : wpa_s->disallow_aps_bssid = NULL;
470 : 31 : os_free(wpa_s->disallow_aps_ssid);
471 : 31 : wpa_s->disallow_aps_ssid = NULL;
472 : :
473 : 31 : wnm_bss_keep_alive_deinit(wpa_s);
474 : : #ifdef CONFIG_WNM
475 : 31 : wnm_deallocate_memory(wpa_s);
476 : : #endif /* CONFIG_WNM */
477 : :
478 : 31 : ext_password_deinit(wpa_s->ext_pw);
479 : 31 : wpa_s->ext_pw = NULL;
480 : :
481 : 31 : wpabuf_free(wpa_s->last_gas_resp);
482 : :
483 : 31 : os_free(wpa_s->last_scan_res);
484 : 31 : wpa_s->last_scan_res = NULL;
485 : 31 : }
486 : :
487 : :
488 : : /**
489 : : * wpa_clear_keys - Clear keys configured for the driver
490 : : * @wpa_s: Pointer to wpa_supplicant data
491 : : * @addr: Previously used BSSID or %NULL if not available
492 : : *
493 : : * This function clears the encryption keys that has been previously configured
494 : : * for the driver.
495 : : */
496 : 2064 : void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
497 : : {
498 [ + + ]: 2064 : if (wpa_s->keys_cleared) {
499 : : /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have
500 : : * timing issues with keys being cleared just before new keys
501 : : * are set or just after association or something similar. This
502 : : * shows up in group key handshake failing often because of the
503 : : * client not receiving the first encrypted packets correctly.
504 : : * Skipping some of the extra key clearing steps seems to help
505 : : * in completing group key handshake more reliably. */
506 : 1289 : wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - "
507 : : "skip key clearing");
508 : 2064 : return;
509 : : }
510 : :
511 : : /* MLME-DELETEKEYS.request */
512 : 775 : wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
513 : 775 : wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
514 : 775 : wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
515 : 775 : wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
516 : : #ifdef CONFIG_IEEE80211W
517 : 775 : wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
518 : 775 : wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
519 : : #endif /* CONFIG_IEEE80211W */
520 [ + + ]: 775 : if (addr) {
521 : 744 : wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
522 : : 0);
523 : : /* MLME-SETPROTECTION.request(None) */
524 : 744 : wpa_drv_mlme_setprotection(
525 : : wpa_s, addr,
526 : : MLME_SETPROTECTION_PROTECT_TYPE_NONE,
527 : : MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
528 : : }
529 : 775 : wpa_s->keys_cleared = 1;
530 : : }
531 : :
532 : :
533 : : /**
534 : : * wpa_supplicant_state_txt - Get the connection state name as a text string
535 : : * @state: State (wpa_state; WPA_*)
536 : : * Returns: The state name as a printable text string
537 : : */
538 : 11002 : const char * wpa_supplicant_state_txt(enum wpa_states state)
539 : : {
540 [ + + - + : 11002 : switch (state) {
+ + + + +
+ - ]
541 : : case WPA_DISCONNECTED:
542 : 3059 : return "DISCONNECTED";
543 : : case WPA_INACTIVE:
544 : 615 : return "INACTIVE";
545 : : case WPA_INTERFACE_DISABLED:
546 : 0 : return "INTERFACE_DISABLED";
547 : : case WPA_SCANNING:
548 : 1300 : return "SCANNING";
549 : : case WPA_AUTHENTICATING:
550 : 1048 : return "AUTHENTICATING";
551 : : case WPA_ASSOCIATING:
552 : 886 : return "ASSOCIATING";
553 : : case WPA_ASSOCIATED:
554 : 983 : return "ASSOCIATED";
555 : : case WPA_4WAY_HANDSHAKE:
556 : 1066 : return "4WAY_HANDSHAKE";
557 : : case WPA_GROUP_HANDSHAKE:
558 : 526 : return "GROUP_HANDSHAKE";
559 : : case WPA_COMPLETED:
560 : 1519 : return "COMPLETED";
561 : : default:
562 : 11002 : return "UNKNOWN";
563 : : }
564 : : }
565 : :
566 : :
567 : : #ifdef CONFIG_BGSCAN
568 : :
569 : 443 : static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
570 : : {
571 : : const char *name;
572 : :
573 [ + - ][ - + ]: 443 : if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
574 : 0 : name = wpa_s->current_ssid->bgscan;
575 : : else
576 : 443 : name = wpa_s->conf->bgscan;
577 [ + - ]: 443 : if (name == NULL)
578 : 443 : return;
579 [ # # ]: 0 : if (wpas_driver_bss_selection(wpa_s))
580 : 0 : return;
581 [ # # ]: 0 : if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
582 : 0 : return;
583 : :
584 : 0 : bgscan_deinit(wpa_s);
585 [ # # ]: 0 : if (wpa_s->current_ssid) {
586 [ # # ]: 0 : if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
587 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
588 : : "bgscan");
589 : : /*
590 : : * Live without bgscan; it is only used as a roaming
591 : : * optimization, so the initial connection is not
592 : : * affected.
593 : : */
594 : : } else {
595 : : struct wpa_scan_results *scan_res;
596 : 0 : wpa_s->bgscan_ssid = wpa_s->current_ssid;
597 : 0 : scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
598 : : 0);
599 [ # # ]: 0 : if (scan_res) {
600 : 0 : bgscan_notify_scan(wpa_s, scan_res);
601 : 0 : wpa_scan_results_free(scan_res);
602 : : }
603 : : }
604 : : } else
605 : 443 : wpa_s->bgscan_ssid = NULL;
606 : : }
607 : :
608 : :
609 : 3145 : static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
610 : : {
611 [ - + ]: 3145 : if (wpa_s->bgscan_ssid != NULL) {
612 : 0 : bgscan_deinit(wpa_s);
613 : 0 : wpa_s->bgscan_ssid = NULL;
614 : : }
615 : 3145 : }
616 : :
617 : : #endif /* CONFIG_BGSCAN */
618 : :
619 : :
620 : 1716 : static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
621 : : {
622 [ - + ]: 1716 : if (autoscan_init(wpa_s, 0))
623 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
624 : 1716 : }
625 : :
626 : :
627 : 524 : static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
628 : : {
629 : 524 : autoscan_deinit(wpa_s);
630 : 524 : }
631 : :
632 : :
633 : 5 : void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
634 : : {
635 [ + + ][ - + ]: 5 : if (wpa_s->wpa_state == WPA_DISCONNECTED ||
636 : 2 : wpa_s->wpa_state == WPA_SCANNING) {
637 : 3 : autoscan_deinit(wpa_s);
638 : 3 : wpa_supplicant_start_autoscan(wpa_s);
639 : : }
640 : 5 : }
641 : :
642 : :
643 : : /**
644 : : * wpa_supplicant_set_state - Set current connection state
645 : : * @wpa_s: Pointer to wpa_supplicant data
646 : : * @state: The new connection state
647 : : *
648 : : * This function is called whenever the connection state changes, e.g.,
649 : : * association is completed for WPA/WPA2 4-Way Handshake is started.
650 : : */
651 : 4828 : void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
652 : : enum wpa_states state)
653 : : {
654 : 4828 : enum wpa_states old_state = wpa_s->wpa_state;
655 : :
656 : 4828 : wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
657 : : wpa_supplicant_state_txt(wpa_s->wpa_state),
658 : : wpa_supplicant_state_txt(state));
659 : :
660 [ + + ]: 4828 : if (state != WPA_SCANNING)
661 : 4363 : wpa_supplicant_notify_scanning(wpa_s, 0);
662 : :
663 [ + + ][ + + ]: 5232 : if (state == WPA_COMPLETED && wpa_s->new_connection) {
664 : 404 : struct wpa_ssid *ssid = wpa_s->current_ssid;
665 : : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
666 [ + - ][ + - ]: 808 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
667 : : MACSTR " completed [id=%d id_str=%s]",
668 : 2424 : MAC2STR(wpa_s->bssid),
669 : : ssid ? ssid->id : -1,
670 [ - + ]: 404 : ssid && ssid->id_str ? ssid->id_str : "");
671 : : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
672 : 404 : wpas_clear_temp_disabled(wpa_s, ssid, 1);
673 : 404 : wpa_s->extra_blacklist_count = 0;
674 : 404 : wpa_s->new_connection = 0;
675 : 404 : wpa_drv_set_operstate(wpa_s, 1);
676 : : #ifndef IEEE8021X_EAPOL
677 : : wpa_drv_set_supp_port(wpa_s, 1);
678 : : #endif /* IEEE8021X_EAPOL */
679 : 404 : wpa_s->after_wps = 0;
680 : 404 : wpa_s->known_wps_freq = 0;
681 : : #ifdef CONFIG_P2P
682 : 404 : wpas_p2p_completed(wpa_s);
683 : : #endif /* CONFIG_P2P */
684 : :
685 : 404 : sme_sched_obss_scan(wpa_s, 1);
686 [ + + ][ + + ]: 4424 : } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
[ + + ]
687 : : state == WPA_ASSOCIATED) {
688 : 2314 : wpa_s->new_connection = 1;
689 : 2314 : wpa_drv_set_operstate(wpa_s, 0);
690 : : #ifndef IEEE8021X_EAPOL
691 : : wpa_drv_set_supp_port(wpa_s, 0);
692 : : #endif /* IEEE8021X_EAPOL */
693 : 2314 : sme_sched_obss_scan(wpa_s, 0);
694 : : }
695 : 4828 : wpa_s->wpa_state = state;
696 : :
697 : : #ifdef CONFIG_BGSCAN
698 [ + + ]: 4828 : if (state == WPA_COMPLETED)
699 : 443 : wpa_supplicant_start_bgscan(wpa_s);
700 [ + + ]: 4385 : else if (state < WPA_ASSOCIATED)
701 : 3145 : wpa_supplicant_stop_bgscan(wpa_s);
702 : : #endif /* CONFIG_BGSCAN */
703 : :
704 [ + + ]: 4828 : if (state == WPA_AUTHENTICATING)
705 : 524 : wpa_supplicant_stop_autoscan(wpa_s);
706 : :
707 [ + + ][ + + ]: 4828 : if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
708 : 1713 : wpa_supplicant_start_autoscan(wpa_s);
709 : :
710 [ + + ]: 4828 : if (wpa_s->wpa_state != old_state) {
711 : 3721 : wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
712 : :
713 [ + + ][ + + ]: 3721 : if (wpa_s->wpa_state == WPA_COMPLETED ||
714 : : old_state == WPA_COMPLETED)
715 : 854 : wpas_notify_auth_changed(wpa_s);
716 : : }
717 : 4828 : }
718 : :
719 : :
720 : 4 : void wpa_supplicant_terminate_proc(struct wpa_global *global)
721 : : {
722 : 4 : int pending = 0;
723 : : #ifdef CONFIG_WPS
724 : 4 : struct wpa_supplicant *wpa_s = global->ifaces;
725 [ + + ]: 7 : while (wpa_s) {
726 : 3 : struct wpa_supplicant *next = wpa_s->next;
727 : : #ifdef CONFIG_P2P
728 [ + - ][ - + ]: 3 : if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
729 [ # # ]: 0 : (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
730 : 0 : wpas_p2p_disconnect(wpa_s);
731 : : #endif /* CONFIG_P2P */
732 [ + + ]: 3 : if (wpas_wps_terminate_pending(wpa_s) == 1)
733 : 1 : pending = 1;
734 : 3 : wpa_s = next;
735 : : }
736 : : #endif /* CONFIG_WPS */
737 [ + + ]: 4 : if (pending)
738 : 4 : return;
739 : 3 : eloop_terminate();
740 : : }
741 : :
742 : :
743 : 4 : static void wpa_supplicant_terminate(int sig, void *signal_ctx)
744 : : {
745 : 4 : struct wpa_global *global = signal_ctx;
746 : 4 : wpa_supplicant_terminate_proc(global);
747 : 4 : }
748 : :
749 : :
750 : 97 : void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
751 : : {
752 : 97 : enum wpa_states old_state = wpa_s->wpa_state;
753 : :
754 : 97 : wpa_s->pairwise_cipher = 0;
755 : 97 : wpa_s->group_cipher = 0;
756 : 97 : wpa_s->mgmt_group_cipher = 0;
757 : 97 : wpa_s->key_mgmt = 0;
758 [ + - ]: 97 : if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
759 : 97 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
760 : :
761 [ + + ]: 97 : if (wpa_s->wpa_state != old_state)
762 : 46 : wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
763 : 97 : }
764 : :
765 : :
766 : : /**
767 : : * wpa_supplicant_reload_configuration - Reload configuration data
768 : : * @wpa_s: Pointer to wpa_supplicant data
769 : : * Returns: 0 on success or -1 if configuration parsing failed
770 : : *
771 : : * This function can be used to request that the configuration data is reloaded
772 : : * (e.g., after configuration file change). This function is reloading
773 : : * configuration only for one interface, so this may need to be called multiple
774 : : * times if %wpa_supplicant is controlling multiple interfaces and all
775 : : * interfaces need reconfiguration.
776 : : */
777 : 0 : int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
778 : : {
779 : : struct wpa_config *conf;
780 : : int reconf_ctrl;
781 : : int old_ap_scan;
782 : :
783 [ # # ]: 0 : if (wpa_s->confname == NULL)
784 : 0 : return -1;
785 : 0 : conf = wpa_config_read(wpa_s->confname, NULL);
786 [ # # ]: 0 : if (conf == NULL) {
787 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
788 : : "file '%s' - exiting", wpa_s->confname);
789 : 0 : return -1;
790 : : }
791 : 0 : wpa_config_read(wpa_s->confanother, conf);
792 : :
793 : 0 : conf->changed_parameters = (unsigned int) -1;
794 : :
795 [ # # ]: 0 : reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
796 [ # # ][ # # ]: 0 : || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
[ # # ]
797 : 0 : os_strcmp(conf->ctrl_interface,
798 : : wpa_s->conf->ctrl_interface) != 0);
799 : :
800 [ # # ][ # # ]: 0 : if (reconf_ctrl && wpa_s->ctrl_iface) {
801 : 0 : wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
802 : 0 : wpa_s->ctrl_iface = NULL;
803 : : }
804 : :
805 : 0 : eapol_sm_invalidate_cached_session(wpa_s->eapol);
806 [ # # ]: 0 : if (wpa_s->current_ssid) {
807 : 0 : wpa_supplicant_deauthenticate(wpa_s,
808 : : WLAN_REASON_DEAUTH_LEAVING);
809 : : }
810 : :
811 : : /*
812 : : * TODO: should notify EAPOL SM about changes in opensc_engine_path,
813 : : * pkcs11_engine_path, pkcs11_module_path.
814 : : */
815 [ # # ]: 0 : if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
816 : : /*
817 : : * Clear forced success to clear EAP state for next
818 : : * authentication.
819 : : */
820 : 0 : eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
821 : : }
822 : 0 : eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
823 : 0 : wpa_sm_set_config(wpa_s->wpa, NULL);
824 : 0 : wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
825 : 0 : wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
826 : 0 : rsn_preauth_deinit(wpa_s->wpa);
827 : :
828 : 0 : old_ap_scan = wpa_s->conf->ap_scan;
829 : 0 : wpa_config_free(wpa_s->conf);
830 : 0 : wpa_s->conf = conf;
831 [ # # ]: 0 : if (old_ap_scan != wpa_s->conf->ap_scan)
832 : 0 : wpas_notify_ap_scan_changed(wpa_s);
833 : :
834 [ # # ]: 0 : if (reconf_ctrl)
835 : 0 : wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
836 : :
837 : 0 : wpa_supplicant_update_config(wpa_s);
838 : :
839 : 0 : wpa_supplicant_clear_status(wpa_s);
840 [ # # ]: 0 : if (wpa_supplicant_enabled_networks(wpa_s)) {
841 : 0 : wpa_s->reassociate = 1;
842 : 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
843 : : }
844 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
845 : 0 : return 0;
846 : : }
847 : :
848 : :
849 : 0 : static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
850 : : {
851 : 0 : struct wpa_global *global = signal_ctx;
852 : : struct wpa_supplicant *wpa_s;
853 [ # # ]: 0 : for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
854 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
855 : : sig);
856 [ # # ]: 0 : if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
857 : 0 : wpa_supplicant_terminate_proc(global);
858 : : }
859 : : }
860 : 0 : }
861 : :
862 : :
863 : 6 : static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
864 : : struct wpa_ssid *ssid,
865 : : struct wpa_ie_data *ie)
866 : : {
867 : 6 : int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
868 [ + - ]: 6 : if (ret) {
869 [ - + ]: 6 : if (ret == -2) {
870 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
871 : : "from association info");
872 : : }
873 : 6 : return -1;
874 : : }
875 : :
876 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
877 : : "cipher suites");
878 [ # # ]: 0 : if (!(ie->group_cipher & ssid->group_cipher)) {
879 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
880 : : "cipher 0x%x (mask 0x%x) - reject",
881 : : ie->group_cipher, ssid->group_cipher);
882 : 0 : return -1;
883 : : }
884 [ # # ]: 0 : if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
885 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
886 : : "cipher 0x%x (mask 0x%x) - reject",
887 : : ie->pairwise_cipher, ssid->pairwise_cipher);
888 : 0 : return -1;
889 : : }
890 [ # # ]: 0 : if (!(ie->key_mgmt & ssid->key_mgmt)) {
891 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
892 : : "management 0x%x (mask 0x%x) - reject",
893 : : ie->key_mgmt, ssid->key_mgmt);
894 : 0 : return -1;
895 : : }
896 : :
897 : : #ifdef CONFIG_IEEE80211W
898 [ # # ][ # # ]: 0 : if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
899 : 0 : (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
900 [ # # ]: 0 : wpa_s->conf->pmf : ssid->ieee80211w) ==
901 : : MGMT_FRAME_PROTECTION_REQUIRED) {
902 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
903 : : "that does not support management frame protection - "
904 : : "reject");
905 : 0 : return -1;
906 : : }
907 : : #endif /* CONFIG_IEEE80211W */
908 : :
909 : 6 : return 0;
910 : : }
911 : :
912 : :
913 : : /**
914 : : * wpa_supplicant_set_suites - Set authentication and encryption parameters
915 : : * @wpa_s: Pointer to wpa_supplicant data
916 : : * @bss: Scan results for the selected BSS, or %NULL if not available
917 : : * @ssid: Configuration data for the selected network
918 : : * @wpa_ie: Buffer for the WPA/RSN IE
919 : : * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
920 : : * used buffer length in case the functions returns success.
921 : : * Returns: 0 on success or -1 on failure
922 : : *
923 : : * This function is used to configure authentication and encryption parameters
924 : : * based on the network configuration and scan result for the selected BSS (if
925 : : * available).
926 : : */
927 : 281 : int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
928 : : struct wpa_bss *bss, struct wpa_ssid *ssid,
929 : : u8 *wpa_ie, size_t *wpa_ie_len)
930 : : {
931 : : struct wpa_ie_data ie;
932 : : int sel, proto;
933 : : const u8 *bss_wpa, *bss_rsn;
934 : :
935 [ + + ]: 281 : if (bss) {
936 : 275 : bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
937 : 275 : bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
938 : : } else
939 : 6 : bss_wpa = bss_rsn = NULL;
940 : :
941 [ + + ]: 549 : if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
[ + + + - ]
942 [ + - ]: 536 : wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
943 [ + - ]: 268 : (ie.group_cipher & ssid->group_cipher) &&
944 [ + - ]: 268 : (ie.pairwise_cipher & ssid->pairwise_cipher) &&
945 : 268 : (ie.key_mgmt & ssid->key_mgmt)) {
946 : 268 : wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
947 : 268 : proto = WPA_PROTO_RSN;
948 [ + + ]: 20 : } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
[ + - + - ]
949 [ + - ]: 14 : wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
950 [ + - ]: 7 : (ie.group_cipher & ssid->group_cipher) &&
951 [ + - ]: 7 : (ie.pairwise_cipher & ssid->pairwise_cipher) &&
952 : 7 : (ie.key_mgmt & ssid->key_mgmt)) {
953 : 7 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
954 : 7 : proto = WPA_PROTO_WPA;
955 [ - + ]: 6 : } else if (bss) {
956 : 0 : wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
957 : 0 : return -1;
958 : : } else {
959 [ + + ]: 6 : if (ssid->proto & WPA_PROTO_RSN)
960 : 3 : proto = WPA_PROTO_RSN;
961 : : else
962 : 3 : proto = WPA_PROTO_WPA;
963 [ + - ]: 6 : if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
964 : 6 : os_memset(&ie, 0, sizeof(ie));
965 : 6 : ie.group_cipher = ssid->group_cipher;
966 : 6 : ie.pairwise_cipher = ssid->pairwise_cipher;
967 : 6 : ie.key_mgmt = ssid->key_mgmt;
968 : : #ifdef CONFIG_IEEE80211W
969 : 6 : ie.mgmt_group_cipher =
970 : 6 : ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
971 [ + - ]: 6 : WPA_CIPHER_AES_128_CMAC : 0;
972 : : #endif /* CONFIG_IEEE80211W */
973 : 6 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
974 : : "based on configuration");
975 : : } else
976 : 0 : proto = ie.proto;
977 : : }
978 : :
979 : 281 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
980 : : "pairwise %d key_mgmt %d proto %d",
981 : : ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
982 : : #ifdef CONFIG_IEEE80211W
983 [ + - ]: 281 : if (ssid->ieee80211w) {
984 : 281 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
985 : : ie.mgmt_group_cipher);
986 : : }
987 : : #endif /* CONFIG_IEEE80211W */
988 : :
989 : 281 : wpa_s->wpa_proto = proto;
990 : 281 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
991 : 281 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
992 : 281 : !!(ssid->proto & WPA_PROTO_RSN));
993 : :
994 [ + + ][ + - ]: 281 : if (bss || !wpa_s->ap_ies_from_associnfo) {
995 [ + + ][ + - ]: 281 : if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
996 [ - + ]: 281 : bss_wpa ? 2 + bss_wpa[1] : 0) ||
997 [ + + ]: 281 : wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
998 : 271 : bss_rsn ? 2 + bss_rsn[1] : 0))
999 : 0 : return -1;
1000 : : }
1001 : :
1002 : 281 : sel = ie.group_cipher & ssid->group_cipher;
1003 : 281 : wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1004 [ - + ]: 281 : if (wpa_s->group_cipher < 0) {
1005 : 0 : wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1006 : : "cipher");
1007 : 0 : return -1;
1008 : : }
1009 : 281 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1010 : : wpa_cipher_txt(wpa_s->group_cipher));
1011 : :
1012 : 281 : sel = ie.pairwise_cipher & ssid->pairwise_cipher;
1013 : 281 : wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1014 [ - + ]: 281 : if (wpa_s->pairwise_cipher < 0) {
1015 : 0 : wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1016 : : "cipher");
1017 : 0 : return -1;
1018 : : }
1019 : 281 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1020 : : wpa_cipher_txt(wpa_s->pairwise_cipher));
1021 : :
1022 : 281 : sel = ie.key_mgmt & ssid->key_mgmt;
1023 : : #ifdef CONFIG_SAE
1024 [ - + ]: 281 : if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1025 : 0 : sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1026 : : #endif /* CONFIG_SAE */
1027 : : if (0) {
1028 : : #ifdef CONFIG_IEEE80211R
1029 [ + + ]: 281 : } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1030 : 3 : wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1031 : 3 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1032 [ + + ]: 278 : } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1033 : 11 : wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1034 : 11 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1035 : : #endif /* CONFIG_IEEE80211R */
1036 : : #ifdef CONFIG_SAE
1037 [ + + ]: 267 : } else if (sel & WPA_KEY_MGMT_SAE) {
1038 : 32 : wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1039 : 32 : wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1040 [ + + ]: 235 : } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1041 : 6 : wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1042 : 6 : wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1043 : : #endif /* CONFIG_SAE */
1044 : : #ifdef CONFIG_IEEE80211W
1045 [ + + ]: 229 : } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1046 : 1 : wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1047 : 1 : wpa_dbg(wpa_s, MSG_DEBUG,
1048 : : "WPA: using KEY_MGMT 802.1X with SHA256");
1049 [ + + ]: 228 : } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1050 : 6 : wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1051 : 6 : wpa_dbg(wpa_s, MSG_DEBUG,
1052 : : "WPA: using KEY_MGMT PSK with SHA256");
1053 : : #endif /* CONFIG_IEEE80211W */
1054 [ + + ]: 222 : } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1055 : 68 : wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1056 : 68 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1057 [ + + ]: 154 : } else if (sel & WPA_KEY_MGMT_PSK) {
1058 : 151 : wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1059 : 151 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1060 [ + - ]: 3 : } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1061 : 3 : wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1062 : 3 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1063 : : } else {
1064 : 0 : wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1065 : : "authenticated key management type");
1066 : 0 : return -1;
1067 : : }
1068 : :
1069 : 281 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1070 : 281 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1071 : 281 : wpa_s->pairwise_cipher);
1072 : 281 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1073 : :
1074 : : #ifdef CONFIG_IEEE80211W
1075 : 281 : sel = ie.mgmt_group_cipher;
1076 [ + + ][ - + ]: 281 : if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1077 [ + - ][ + + ]: 54 : wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
1078 : 54 : !(ie.capabilities & WPA_CAPABILITY_MFPC))
1079 : 268 : sel = 0;
1080 [ + + ]: 281 : if (sel & WPA_CIPHER_AES_128_CMAC) {
1081 : 13 : wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1082 : 13 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1083 : : "AES-128-CMAC");
1084 : : } else {
1085 : 268 : wpa_s->mgmt_group_cipher = 0;
1086 : 268 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1087 : : }
1088 : 281 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1089 : 281 : wpa_s->mgmt_group_cipher);
1090 [ + + ]: 281 : wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1091 : 281 : (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1092 : 227 : wpa_s->conf->pmf : ssid->ieee80211w));
1093 : : #endif /* CONFIG_IEEE80211W */
1094 : :
1095 [ - + ]: 281 : if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1096 : 0 : wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1097 : 0 : return -1;
1098 : : }
1099 : :
1100 [ + + ]: 281 : if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
1101 : 206 : wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
1102 : : #ifndef CONFIG_NO_PBKDF2
1103 [ + + ][ + + ]: 206 : if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
[ - + ][ # # ]
1104 : 0 : ssid->passphrase) {
1105 : : u8 psk[PMK_LEN];
1106 : 0 : pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1107 : : 4096, psk, PMK_LEN);
1108 : 0 : wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1109 : : psk, PMK_LEN);
1110 : 0 : wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1111 : : }
1112 : : #endif /* CONFIG_NO_PBKDF2 */
1113 : : #ifdef CONFIG_EXT_PASSWORD
1114 [ - + ]: 206 : if (ssid->ext_psk) {
1115 : 0 : struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1116 : 0 : ssid->ext_psk);
1117 : : char pw_str[64 + 1];
1118 : : u8 psk[PMK_LEN];
1119 : :
1120 [ # # ]: 0 : if (pw == NULL) {
1121 : 0 : wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1122 : : "found from external storage");
1123 : 0 : return -1;
1124 : : }
1125 : :
1126 [ # # ][ # # ]: 0 : if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1127 : 0 : wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1128 : : "PSK length %d in external storage",
1129 : 0 : (int) wpabuf_len(pw));
1130 : 0 : ext_password_free(pw);
1131 : 0 : return -1;
1132 : : }
1133 : :
1134 : 0 : os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1135 : 0 : pw_str[wpabuf_len(pw)] = '\0';
1136 : :
1137 : : #ifndef CONFIG_NO_PBKDF2
1138 [ # # ][ # # ]: 0 : if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
[ # # ]
1139 : : {
1140 : 0 : pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1141 : : 4096, psk, PMK_LEN);
1142 : 0 : os_memset(pw_str, 0, sizeof(pw_str));
1143 : 0 : wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1144 : : "external passphrase)",
1145 : : psk, PMK_LEN);
1146 : 0 : wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1147 : : } else
1148 : : #endif /* CONFIG_NO_PBKDF2 */
1149 [ # # ]: 0 : if (wpabuf_len(pw) == 2 * PMK_LEN) {
1150 [ # # ]: 0 : if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1151 : 0 : wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1152 : : "Invalid PSK hex string");
1153 : 0 : os_memset(pw_str, 0, sizeof(pw_str));
1154 : 0 : ext_password_free(pw);
1155 : 0 : return -1;
1156 : : }
1157 : 0 : wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1158 : : } else {
1159 : 0 : wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1160 : : "PSK available");
1161 : 0 : os_memset(pw_str, 0, sizeof(pw_str));
1162 : 0 : ext_password_free(pw);
1163 : 0 : return -1;
1164 : : }
1165 : :
1166 : 0 : os_memset(pw_str, 0, sizeof(pw_str));
1167 : 0 : ext_password_free(pw);
1168 : : }
1169 : : #endif /* CONFIG_EXT_PASSWORD */
1170 : : } else
1171 : 75 : wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1172 : :
1173 : 281 : return 0;
1174 : : }
1175 : :
1176 : :
1177 : 3680 : static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1178 : : {
1179 : 3680 : *pos = 0x00;
1180 : :
1181 [ + + + + : 3680 : switch (idx) {
+ + + + ]
1182 : : case 0: /* Bits 0-7 */
1183 : 460 : break;
1184 : : case 1: /* Bits 8-15 */
1185 : 460 : break;
1186 : : case 2: /* Bits 16-23 */
1187 : : #ifdef CONFIG_WNM
1188 : 460 : *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1189 : 460 : *pos |= 0x08; /* Bit 19 - BSS Transition */
1190 : : #endif /* CONFIG_WNM */
1191 : 460 : break;
1192 : : case 3: /* Bits 24-31 */
1193 : : #ifdef CONFIG_WNM
1194 : 460 : *pos |= 0x02; /* Bit 25 - SSID List */
1195 : : #endif /* CONFIG_WNM */
1196 : : #ifdef CONFIG_INTERWORKING
1197 [ + + ]: 460 : if (wpa_s->conf->interworking)
1198 : 90 : *pos |= 0x80; /* Bit 31 - Interworking */
1199 : : #endif /* CONFIG_INTERWORKING */
1200 : 460 : break;
1201 : : case 4: /* Bits 32-39 */
1202 : : #ifdef CONFIG_INTERWORKING
1203 [ + - ]: 460 : if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1204 : 460 : *pos |= 0x01; /* Bit 32 - QoS Map */
1205 : : #endif /* CONFIG_INTERWORKING */
1206 : 460 : break;
1207 : : case 5: /* Bits 40-47 */
1208 : 460 : break;
1209 : : case 6: /* Bits 48-55 */
1210 : 460 : break;
1211 : : }
1212 : 3680 : }
1213 : :
1214 : :
1215 : 460 : int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1216 : : {
1217 : 460 : u8 *pos = buf;
1218 : 460 : u8 len = 4, i;
1219 : :
1220 [ + - ]: 460 : if (len < wpa_s->extended_capa_len)
1221 : 460 : len = wpa_s->extended_capa_len;
1222 : :
1223 : 460 : *pos++ = WLAN_EID_EXT_CAPAB;
1224 : 460 : *pos++ = len;
1225 [ + + ]: 4140 : for (i = 0; i < len; i++, pos++) {
1226 : 3680 : wpas_ext_capab_byte(wpa_s, pos, i);
1227 : :
1228 [ + - ]: 3680 : if (i < wpa_s->extended_capa_len) {
1229 : 3680 : *pos &= ~wpa_s->extended_capa_mask[i];
1230 : 3680 : *pos |= wpa_s->extended_capa[i];
1231 : : }
1232 : : }
1233 : :
1234 [ + - ][ - + ]: 460 : while (len > 0 && buf[1 + len] == 0) {
1235 : 0 : len--;
1236 : 0 : buf[1] = len;
1237 : : }
1238 [ - + ]: 460 : if (len == 0)
1239 : 0 : return 0;
1240 : :
1241 : 460 : return 2 + len;
1242 : : }
1243 : :
1244 : :
1245 : : /**
1246 : : * wpa_supplicant_associate - Request association
1247 : : * @wpa_s: Pointer to wpa_supplicant data
1248 : : * @bss: Scan results for the selected BSS, or %NULL if not available
1249 : : * @ssid: Configuration data for the selected network
1250 : : *
1251 : : * This function is used to request %wpa_supplicant to associate with a BSS.
1252 : : */
1253 : 499 : void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1254 : : struct wpa_bss *bss, struct wpa_ssid *ssid)
1255 : : {
1256 : : u8 wpa_ie[200];
1257 : : size_t wpa_ie_len;
1258 : : int use_crypt, ret, i, bssid_changed;
1259 : 499 : int algs = WPA_AUTH_ALG_OPEN;
1260 : : unsigned int cipher_pairwise, cipher_group;
1261 : : struct wpa_driver_associate_params params;
1262 : 499 : int wep_keys_set = 0;
1263 : 499 : int assoc_failed = 0;
1264 : : struct wpa_ssid *old_ssid;
1265 : : #ifdef CONFIG_HT_OVERRIDES
1266 : : struct ieee80211_ht_capabilities htcaps;
1267 : : struct ieee80211_ht_capabilities htcaps_mask;
1268 : : #endif /* CONFIG_HT_OVERRIDES */
1269 : :
1270 : : #ifdef CONFIG_IBSS_RSN
1271 : 499 : ibss_rsn_deinit(wpa_s->ibss_rsn);
1272 : 499 : wpa_s->ibss_rsn = NULL;
1273 : : #endif /* CONFIG_IBSS_RSN */
1274 : :
1275 [ + + ][ + + ]: 499 : if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
[ + + ]
1276 : 474 : ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1277 : : #ifdef CONFIG_AP
1278 [ - + ]: 59 : if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1279 : 0 : wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1280 : : "mode");
1281 : 0 : return;
1282 : : }
1283 [ - + ]: 59 : if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1284 : 0 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1285 [ # # ]: 0 : if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1286 : 0 : wpas_p2p_ap_setup_failed(wpa_s);
1287 : 0 : return;
1288 : : }
1289 : 59 : wpa_s->current_bss = bss;
1290 : : #else /* CONFIG_AP */
1291 : : wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1292 : : "the build");
1293 : : #endif /* CONFIG_AP */
1294 : 59 : return;
1295 : : }
1296 : :
1297 : : #ifdef CONFIG_TDLS
1298 [ + + ]: 440 : if (bss)
1299 : 434 : wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1300 : : bss->ie_len);
1301 : : #endif /* CONFIG_TDLS */
1302 : :
1303 [ + + ][ + + ]: 440 : if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1304 : 438 : ssid->mode == IEEE80211_MODE_INFRA) {
1305 : 432 : sme_authenticate(wpa_s, bss, ssid);
1306 : 432 : return;
1307 : : }
1308 : :
1309 : 8 : os_memset(¶ms, 0, sizeof(params));
1310 : 8 : wpa_s->reassociate = 0;
1311 [ + + ][ + - ]: 10 : if (bss && !wpas_driver_bss_selection(wpa_s)) {
1312 : : #ifdef CONFIG_IEEE80211R
1313 : 2 : const u8 *ie, *md = NULL;
1314 : : #endif /* CONFIG_IEEE80211R */
1315 : 2 : wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1316 : 12 : " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1317 : 2 : wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1318 : 2 : bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1319 : 2 : os_memset(wpa_s->bssid, 0, ETH_ALEN);
1320 : 2 : os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1321 [ - + ]: 2 : if (bssid_changed)
1322 : 0 : wpas_notify_bssid_changed(wpa_s);
1323 : : #ifdef CONFIG_IEEE80211R
1324 : 2 : ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1325 [ - + ][ # # ]: 2 : if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1326 : 0 : md = ie + 2;
1327 [ - + ]: 2 : wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1328 [ - + ]: 2 : if (md) {
1329 : : /* Prepare for the next transition */
1330 : 0 : wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1331 : : }
1332 : : #endif /* CONFIG_IEEE80211R */
1333 : : #ifdef CONFIG_WPS
1334 [ + - ][ - + ]: 6 : } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
[ # # ]
1335 [ # # ]: 0 : wpa_s->conf->ap_scan == 2 &&
1336 : 0 : (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1337 : : /* Use ap_scan==1 style network selection to find the network
1338 : : */
1339 : 0 : wpa_s->scan_req = MANUAL_SCAN_REQ;
1340 : 0 : wpa_s->reassociate = 1;
1341 : 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
1342 : 0 : return;
1343 : : #endif /* CONFIG_WPS */
1344 : : } else {
1345 : 6 : wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1346 : 6 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1347 : 6 : os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1348 : : }
1349 : 8 : wpa_supplicant_cancel_sched_scan(wpa_s);
1350 : 8 : wpa_supplicant_cancel_scan(wpa_s);
1351 : :
1352 : : /* Starting new association, so clear the possibly used WPA IE from the
1353 : : * previous association. */
1354 : 8 : wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1355 : :
1356 : : #ifdef IEEE8021X_EAPOL
1357 [ - + ]: 8 : if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1358 [ # # ]: 0 : if (ssid->leap) {
1359 [ # # ]: 0 : if (ssid->non_leap == 0)
1360 : 0 : algs = WPA_AUTH_ALG_LEAP;
1361 : : else
1362 : 0 : algs |= WPA_AUTH_ALG_LEAP;
1363 : : }
1364 : : }
1365 : : #endif /* IEEE8021X_EAPOL */
1366 : 8 : wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1367 [ - + ]: 8 : if (ssid->auth_alg) {
1368 : 0 : algs = ssid->auth_alg;
1369 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1370 : : "0x%x", algs);
1371 : : }
1372 : :
1373 [ + + ]: 10 : if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
[ + - + + ]
1374 [ + - ]: 3 : wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
1375 : 2 : wpa_key_mgmt_wpa(ssid->key_mgmt)) {
1376 : : int try_opportunistic;
1377 [ + - ][ - + ]: 1 : try_opportunistic = (ssid->proactive_key_caching < 0 ?
1378 : 1 : wpa_s->conf->okc :
1379 [ # # ][ # # ]: 0 : ssid->proactive_key_caching) &&
1380 : 0 : (ssid->proto & WPA_PROTO_RSN);
1381 [ - + ]: 1 : if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
1382 : : ssid, try_opportunistic) == 0)
1383 : 0 : eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1384 : 1 : wpa_ie_len = sizeof(wpa_ie);
1385 [ - + ]: 1 : if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1386 : : wpa_ie, &wpa_ie_len)) {
1387 : 0 : wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1388 : : "key management and encryption suites");
1389 : 0 : return;
1390 : : }
1391 [ - + ]: 7 : } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
[ # # # # ]
1392 : 0 : wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1393 : : /*
1394 : : * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1395 : : * use non-WPA since the scan results did not indicate that the
1396 : : * AP is using WPA or WPA2.
1397 : : */
1398 : 0 : wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1399 : 0 : wpa_ie_len = 0;
1400 : 0 : wpa_s->wpa_proto = 0;
1401 [ + + ]: 7 : } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
1402 : 6 : wpa_ie_len = sizeof(wpa_ie);
1403 [ - + ]: 6 : if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1404 : : wpa_ie, &wpa_ie_len)) {
1405 : 0 : wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1406 : : "key management and encryption suites (no "
1407 : : "scan results)");
1408 : 0 : return;
1409 : : }
1410 : : #ifdef CONFIG_WPS
1411 [ - + ]: 1 : } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1412 : : struct wpabuf *wps_ie;
1413 : 0 : wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1414 [ # # ][ # # ]: 0 : if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1415 : 0 : wpa_ie_len = wpabuf_len(wps_ie);
1416 : 0 : os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1417 : : } else
1418 : 0 : wpa_ie_len = 0;
1419 : 0 : wpabuf_free(wps_ie);
1420 : 0 : wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1421 [ # # ][ # # ]: 0 : if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1422 : 0 : params.wps = WPS_MODE_PRIVACY;
1423 : : else
1424 : 0 : params.wps = WPS_MODE_OPEN;
1425 : 0 : wpa_s->wpa_proto = 0;
1426 : : #endif /* CONFIG_WPS */
1427 : : } else {
1428 : 1 : wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1429 : 1 : wpa_ie_len = 0;
1430 : 1 : wpa_s->wpa_proto = 0;
1431 : : }
1432 : :
1433 : : #ifdef CONFIG_P2P
1434 [ + - ]: 8 : if (wpa_s->global->p2p) {
1435 : : u8 *pos;
1436 : : size_t len;
1437 : : int res;
1438 : 8 : pos = wpa_ie + wpa_ie_len;
1439 : 8 : len = sizeof(wpa_ie) - wpa_ie_len;
1440 : 8 : res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1441 : : ssid->p2p_group);
1442 [ + + ]: 8 : if (res >= 0)
1443 : 2 : wpa_ie_len += res;
1444 : : }
1445 : :
1446 : 8 : wpa_s->cross_connect_disallowed = 0;
1447 [ + + ]: 8 : if (bss) {
1448 : : struct wpabuf *p2p;
1449 : 2 : p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1450 [ - + ]: 2 : if (p2p) {
1451 : 0 : wpa_s->cross_connect_disallowed =
1452 : 0 : p2p_get_cross_connect_disallowed(p2p);
1453 : 0 : wpabuf_free(p2p);
1454 [ # # ]: 0 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1455 : : "connection",
1456 : : wpa_s->cross_connect_disallowed ?
1457 : : "disallows" : "allows");
1458 : : }
1459 : : }
1460 : : #endif /* CONFIG_P2P */
1461 : :
1462 : : #ifdef CONFIG_HS20
1463 [ - + ]: 8 : if (is_hs20_network(wpa_s, ssid, bss)) {
1464 : : struct wpabuf *hs20;
1465 : 0 : hs20 = wpabuf_alloc(20);
1466 [ # # ]: 0 : if (hs20) {
1467 : 0 : wpas_hs20_add_indication(hs20);
1468 : 0 : os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1469 : : wpabuf_len(hs20));
1470 : 0 : wpa_ie_len += wpabuf_len(hs20);
1471 : 0 : wpabuf_free(hs20);
1472 : : }
1473 : : }
1474 : : #endif /* CONFIG_HS20 */
1475 : :
1476 : : /*
1477 : : * Workaround: Add Extended Capabilities element only if the AP
1478 : : * included this element in Beacon/Probe Response frames. Some older
1479 : : * APs seem to have interoperability issues if this element is
1480 : : * included, so while the standard may require us to include the
1481 : : * element in all cases, it is justifiable to skip it to avoid
1482 : : * interoperability issues.
1483 : : */
1484 [ + + ][ + - ]: 8 : if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
1485 : : u8 ext_capab[10];
1486 : : int ext_capab_len;
1487 : 8 : ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1488 [ + - ]: 8 : if (ext_capab_len > 0) {
1489 : 8 : u8 *pos = wpa_ie;
1490 [ + + ][ + + ]: 8 : if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1491 : 4 : pos += 2 + pos[1];
1492 : 8 : os_memmove(pos + ext_capab_len, pos,
1493 : : wpa_ie_len - (pos - wpa_ie));
1494 : 8 : wpa_ie_len += ext_capab_len;
1495 : 8 : os_memcpy(pos, ext_capab, ext_capab_len);
1496 : : }
1497 : : }
1498 : :
1499 [ + + ]: 8 : wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1500 : 8 : use_crypt = 1;
1501 : 8 : cipher_pairwise = wpa_s->pairwise_cipher;
1502 : 8 : cipher_group = wpa_s->group_cipher;
1503 [ + + ][ - + ]: 8 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1504 : 7 : wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1505 [ + - ]: 1 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1506 : 1 : use_crypt = 0;
1507 [ - + ]: 1 : if (wpa_set_wep_keys(wpa_s, ssid)) {
1508 : 0 : use_crypt = 1;
1509 : 0 : wep_keys_set = 1;
1510 : : }
1511 : : }
1512 [ - + ]: 8 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1513 : 0 : use_crypt = 0;
1514 : :
1515 : : #ifdef IEEE8021X_EAPOL
1516 [ - + ]: 8 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1517 [ # # ]: 0 : if ((ssid->eapol_flags &
1518 : : (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1519 [ # # ]: 0 : EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1520 : : !wep_keys_set) {
1521 : 0 : use_crypt = 0;
1522 : : } else {
1523 : : /* Assume that dynamic WEP-104 keys will be used and
1524 : : * set cipher suites in order for drivers to expect
1525 : : * encryption. */
1526 : 0 : cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
1527 : : }
1528 : : }
1529 : : #endif /* IEEE8021X_EAPOL */
1530 : :
1531 [ + + ]: 8 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1532 : : /* Set the key before (and later after) association */
1533 : 3 : wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1534 : : }
1535 : :
1536 : 8 : wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1537 [ + + ]: 8 : if (bss) {
1538 : 2 : params.ssid = bss->ssid;
1539 : 2 : params.ssid_len = bss->ssid_len;
1540 [ - + ][ # # ]: 2 : if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1541 : 2 : wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1542 : : MACSTR " freq=%u MHz based on scan results "
1543 : : "(bssid_set=%d)",
1544 : 12 : MAC2STR(bss->bssid), bss->freq,
1545 : : ssid->bssid_set);
1546 : 2 : params.bssid = bss->bssid;
1547 : 2 : params.freq = bss->freq;
1548 : : }
1549 : : } else {
1550 : 6 : params.ssid = ssid->ssid;
1551 : 6 : params.ssid_len = ssid->ssid_len;
1552 : : }
1553 : :
1554 [ + + ][ - + ]: 8 : if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
[ # # ]
1555 : 0 : wpa_s->conf->ap_scan == 2) {
1556 : 0 : params.bssid = ssid->bssid;
1557 : 0 : params.fixed_bssid = 1;
1558 : : }
1559 : :
1560 [ + + ][ + - ]: 8 : if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
[ + - ]
1561 : 6 : params.freq == 0)
1562 : 6 : params.freq = ssid->frequency; /* Initial channel for IBSS */
1563 : 8 : params.wpa_ie = wpa_ie;
1564 : 8 : params.wpa_ie_len = wpa_ie_len;
1565 : 8 : params.pairwise_suite = cipher_pairwise;
1566 : 8 : params.group_suite = cipher_group;
1567 : 8 : params.key_mgmt_suite = wpa_s->key_mgmt;
1568 : 8 : params.wpa_proto = wpa_s->wpa_proto;
1569 : 8 : params.auth_alg = algs;
1570 : 8 : params.mode = ssid->mode;
1571 : 8 : params.bg_scan_period = ssid->bg_scan_period;
1572 [ + + ]: 40 : for (i = 0; i < NUM_WEP_KEYS; i++) {
1573 [ - + ]: 32 : if (ssid->wep_key_len[i])
1574 : 0 : params.wep_key[i] = ssid->wep_key[i];
1575 : 32 : params.wep_key_len[i] = ssid->wep_key_len[i];
1576 : : }
1577 : 8 : params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1578 : :
1579 [ - + ][ # # ]: 8 : if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
1580 [ # # ]: 0 : (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1581 : 0 : params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
1582 : 0 : params.passphrase = ssid->passphrase;
1583 [ # # ]: 0 : if (ssid->psk_set)
1584 : 0 : params.psk = ssid->psk;
1585 : : }
1586 : :
1587 : 8 : params.drop_unencrypted = use_crypt;
1588 : :
1589 : : #ifdef CONFIG_IEEE80211W
1590 [ + - ]: 8 : params.mgmt_frame_protection =
1591 : 8 : ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1592 : 8 : wpa_s->conf->pmf : ssid->ieee80211w;
1593 [ - + ][ # # ]: 8 : if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
1594 : 0 : const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1595 : : struct wpa_ie_data ie;
1596 [ # # ][ # # ]: 0 : if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
[ # # ]
1597 : 0 : ie.capabilities &
1598 : : (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1599 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1600 : : "MFP: require MFP");
1601 : 0 : params.mgmt_frame_protection =
1602 : : MGMT_FRAME_PROTECTION_REQUIRED;
1603 : : }
1604 : : }
1605 : : #endif /* CONFIG_IEEE80211W */
1606 : :
1607 : 8 : params.p2p = ssid->p2p_group;
1608 : :
1609 [ - + ]: 8 : if (wpa_s->parent->set_sta_uapsd)
1610 : 0 : params.uapsd = wpa_s->parent->sta_uapsd;
1611 : : else
1612 : 8 : params.uapsd = -1;
1613 : :
1614 : : #ifdef CONFIG_HT_OVERRIDES
1615 : : os_memset(&htcaps, 0, sizeof(htcaps));
1616 : : os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1617 : : params.htcaps = (u8 *) &htcaps;
1618 : : params.htcaps_mask = (u8 *) &htcaps_mask;
1619 : : wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms);
1620 : : #endif /* CONFIG_HT_OVERRIDES */
1621 : :
1622 : : #ifdef CONFIG_P2P
1623 : : /*
1624 : : * If multi-channel concurrency is not supported, check for any
1625 : : * frequency conflict. In case of any frequency conflict, remove the
1626 : : * least prioritized connection.
1627 : : */
1628 [ + - ]: 8 : if (wpa_s->num_multichan_concurrent < 2) {
1629 : 8 : int freq = wpa_drv_shared_freq(wpa_s);
1630 [ - + ][ # # ]: 8 : if (freq > 0 && freq != params.freq) {
1631 : 0 : wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1632 : : freq, params.freq);
1633 [ # # ]: 0 : if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1634 : : params.freq,
1635 : : ssid) < 0)
1636 : 0 : return;
1637 : : }
1638 : : }
1639 : : #endif /* CONFIG_P2P */
1640 : :
1641 : 8 : ret = wpa_drv_associate(wpa_s, ¶ms);
1642 [ - + ]: 8 : if (ret < 0) {
1643 : 0 : wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1644 : : "failed");
1645 [ # # ]: 0 : if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1646 : : /*
1647 : : * The driver is known to mean what is saying, so we
1648 : : * can stop right here; the association will not
1649 : : * succeed.
1650 : : */
1651 : 0 : wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1652 : 0 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1653 : 0 : os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1654 : 0 : return;
1655 : : }
1656 : : /* try to continue anyway; new association will be tried again
1657 : : * after timeout */
1658 : 0 : assoc_failed = 1;
1659 : : }
1660 : :
1661 [ + + ]: 8 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1662 : : /* Set the key after the association just in case association
1663 : : * cleared the previously configured key. */
1664 : 3 : wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1665 : : /* No need to timeout authentication since there is no key
1666 : : * management. */
1667 : 3 : wpa_supplicant_cancel_auth_timeout(wpa_s);
1668 : 3 : wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1669 : : #ifdef CONFIG_IBSS_RSN
1670 [ + + ][ + - ]: 5 : } else if (ssid->mode == WPAS_MODE_IBSS &&
1671 [ + - ]: 3 : wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1672 : 3 : wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1673 : : /*
1674 : : * RSN IBSS authentication is per-STA and we can disable the
1675 : : * per-BSSID authentication.
1676 : : */
1677 : 3 : wpa_supplicant_cancel_auth_timeout(wpa_s);
1678 : : #endif /* CONFIG_IBSS_RSN */
1679 : : } else {
1680 : : /* Timeout for IEEE 802.11 authentication and association */
1681 : 2 : int timeout = 60;
1682 : :
1683 [ - + ]: 2 : if (assoc_failed) {
1684 : : /* give IBSS a bit more time */
1685 [ # # ]: 0 : timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1686 [ + - ]: 2 : } else if (wpa_s->conf->ap_scan == 1) {
1687 : : /* give IBSS a bit more time */
1688 [ - + ]: 2 : timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1689 : : }
1690 : 2 : wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1691 : : }
1692 : :
1693 [ - + ][ # # ]: 8 : if (wep_keys_set &&
1694 : 0 : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
1695 : : /* Set static WEP keys again */
1696 : 0 : wpa_set_wep_keys(wpa_s, ssid);
1697 : : }
1698 : :
1699 [ + - ][ - + ]: 8 : if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1700 : : /*
1701 : : * Do not allow EAP session resumption between different
1702 : : * network configurations.
1703 : : */
1704 : 0 : eapol_sm_invalidate_cached_session(wpa_s->eapol);
1705 : : }
1706 : 8 : old_ssid = wpa_s->current_ssid;
1707 : 8 : wpa_s->current_ssid = ssid;
1708 : 8 : wpa_s->current_bss = bss;
1709 : 8 : wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1710 : 8 : wpa_supplicant_initiate_eapol(wpa_s);
1711 [ - + ]: 8 : if (old_ssid != wpa_s->current_ssid)
1712 : 499 : wpas_notify_network_changed(wpa_s);
1713 : : }
1714 : :
1715 : :
1716 : 482 : static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1717 : : const u8 *addr)
1718 : : {
1719 : : struct wpa_ssid *old_ssid;
1720 : :
1721 : 482 : wpa_clear_keys(wpa_s, addr);
1722 : 482 : old_ssid = wpa_s->current_ssid;
1723 : 482 : wpa_supplicant_mark_disassoc(wpa_s);
1724 : 482 : wpa_sm_set_config(wpa_s->wpa, NULL);
1725 : 482 : eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1726 [ + + ]: 482 : if (old_ssid != wpa_s->current_ssid)
1727 : 49 : wpas_notify_network_changed(wpa_s);
1728 : 482 : eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1729 : 482 : }
1730 : :
1731 : :
1732 : : /**
1733 : : * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1734 : : * @wpa_s: Pointer to wpa_supplicant data
1735 : : * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1736 : : *
1737 : : * This function is used to request %wpa_supplicant to deauthenticate from the
1738 : : * current AP.
1739 : : */
1740 : 482 : void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1741 : : int reason_code)
1742 : : {
1743 : 482 : u8 *addr = NULL;
1744 : : union wpa_event_data event;
1745 : 482 : int zero_addr = 0;
1746 : :
1747 : 482 : wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1748 : : " pending_bssid=" MACSTR " reason=%d state=%s",
1749 : : MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1750 : : reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1751 : :
1752 [ + + ]: 482 : if (!is_zero_ether_addr(wpa_s->bssid))
1753 : 422 : addr = wpa_s->bssid;
1754 [ - + ][ # # ]: 60 : else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1755 [ # # ]: 0 : (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1756 : 0 : wpa_s->wpa_state == WPA_ASSOCIATING))
1757 : 0 : addr = wpa_s->pending_bssid;
1758 [ - + ]: 60 : else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1759 : : /*
1760 : : * When using driver-based BSS selection, we may not know the
1761 : : * BSSID with which we are currently trying to associate. We
1762 : : * need to notify the driver of this disconnection even in such
1763 : : * a case, so use the all zeros address here.
1764 : : */
1765 : 0 : addr = wpa_s->bssid;
1766 : 0 : zero_addr = 1;
1767 : : }
1768 : :
1769 : : #ifdef CONFIG_TDLS
1770 : 482 : wpa_tdls_teardown_peers(wpa_s->wpa);
1771 : : #endif /* CONFIG_TDLS */
1772 : :
1773 [ + + ]: 482 : if (addr) {
1774 : 422 : wpa_drv_deauthenticate(wpa_s, addr, reason_code);
1775 : 422 : os_memset(&event, 0, sizeof(event));
1776 : 422 : event.deauth_info.reason_code = (u16) reason_code;
1777 : 422 : event.deauth_info.locally_generated = 1;
1778 : 422 : wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
1779 [ - + ]: 422 : if (zero_addr)
1780 : 0 : addr = NULL;
1781 : : }
1782 : :
1783 : 482 : wpa_supplicant_clear_connection(wpa_s, addr);
1784 : 482 : }
1785 : :
1786 : 0 : static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1787 : : struct wpa_ssid *ssid)
1788 : : {
1789 [ # # ][ # # ]: 0 : if (!ssid || !ssid->disabled || ssid->disabled == 2)
[ # # ]
1790 : 0 : return;
1791 : :
1792 : 0 : ssid->disabled = 0;
1793 : 0 : wpas_clear_temp_disabled(wpa_s, ssid, 1);
1794 : 0 : wpas_notify_network_enabled_changed(wpa_s, ssid);
1795 : :
1796 : : /*
1797 : : * Try to reassociate since there is no current configuration and a new
1798 : : * network was made available.
1799 : : */
1800 [ # # ][ # # ]: 0 : if (!wpa_s->current_ssid && !wpa_s->disconnected)
1801 : 0 : wpa_s->reassociate = 1;
1802 : : }
1803 : :
1804 : :
1805 : : /**
1806 : : * wpa_supplicant_enable_network - Mark a configured network as enabled
1807 : : * @wpa_s: wpa_supplicant structure for a network interface
1808 : : * @ssid: wpa_ssid structure for a configured network or %NULL
1809 : : *
1810 : : * Enables the specified network or all networks if no network specified.
1811 : : */
1812 : 0 : void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1813 : : struct wpa_ssid *ssid)
1814 : : {
1815 [ # # ]: 0 : if (ssid == NULL) {
1816 [ # # ]: 0 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1817 : 0 : wpa_supplicant_enable_one_network(wpa_s, ssid);
1818 : : } else
1819 : 0 : wpa_supplicant_enable_one_network(wpa_s, ssid);
1820 : :
1821 [ # # ][ # # ]: 0 : if (wpa_s->reassociate && !wpa_s->disconnected) {
1822 [ # # ]: 0 : if (wpa_s->sched_scanning) {
1823 : 0 : wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1824 : : "new network to scan filters");
1825 : 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
1826 : : }
1827 : :
1828 [ # # ]: 0 : if (wpa_supplicant_fast_associate(wpa_s) != 1)
1829 : 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
1830 : : }
1831 : 0 : }
1832 : :
1833 : :
1834 : : /**
1835 : : * wpa_supplicant_disable_network - Mark a configured network as disabled
1836 : : * @wpa_s: wpa_supplicant structure for a network interface
1837 : : * @ssid: wpa_ssid structure for a configured network or %NULL
1838 : : *
1839 : : * Disables the specified network or all networks if no network specified.
1840 : : */
1841 : 0 : void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1842 : : struct wpa_ssid *ssid)
1843 : : {
1844 : : struct wpa_ssid *other_ssid;
1845 : : int was_disabled;
1846 : :
1847 [ # # ]: 0 : if (ssid == NULL) {
1848 [ # # ]: 0 : if (wpa_s->sched_scanning)
1849 : 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
1850 : :
1851 [ # # ]: 0 : for (other_ssid = wpa_s->conf->ssid; other_ssid;
1852 : 0 : other_ssid = other_ssid->next) {
1853 : 0 : was_disabled = other_ssid->disabled;
1854 [ # # ]: 0 : if (was_disabled == 2)
1855 : 0 : continue; /* do not change persistent P2P group
1856 : : * data */
1857 : :
1858 : 0 : other_ssid->disabled = 1;
1859 : :
1860 [ # # ]: 0 : if (was_disabled != other_ssid->disabled)
1861 : 0 : wpas_notify_network_enabled_changed(
1862 : : wpa_s, other_ssid);
1863 : : }
1864 [ # # ]: 0 : if (wpa_s->current_ssid)
1865 : 0 : wpa_supplicant_deauthenticate(
1866 : : wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1867 [ # # ]: 0 : } else if (ssid->disabled != 2) {
1868 [ # # ]: 0 : if (ssid == wpa_s->current_ssid)
1869 : 0 : wpa_supplicant_deauthenticate(
1870 : : wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1871 : :
1872 : 0 : was_disabled = ssid->disabled;
1873 : :
1874 : 0 : ssid->disabled = 1;
1875 : :
1876 [ # # ]: 0 : if (was_disabled != ssid->disabled) {
1877 : 0 : wpas_notify_network_enabled_changed(wpa_s, ssid);
1878 [ # # ]: 0 : if (wpa_s->sched_scanning) {
1879 : 0 : wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1880 : : "to remove network from filters");
1881 : 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
1882 : 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
1883 : : }
1884 : : }
1885 : : }
1886 : 0 : }
1887 : :
1888 : :
1889 : : /**
1890 : : * wpa_supplicant_select_network - Attempt association with a network
1891 : : * @wpa_s: wpa_supplicant structure for a network interface
1892 : : * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1893 : : */
1894 : 241 : void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1895 : : struct wpa_ssid *ssid)
1896 : : {
1897 : :
1898 : : struct wpa_ssid *other_ssid;
1899 : 241 : int disconnected = 0;
1900 : :
1901 [ + - ][ + - ]: 241 : if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
[ + + ]
1902 : 1 : wpa_supplicant_deauthenticate(
1903 : : wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1904 : 1 : disconnected = 1;
1905 : : }
1906 : :
1907 [ + - ]: 241 : if (ssid)
1908 : 241 : wpas_clear_temp_disabled(wpa_s, ssid, 1);
1909 : :
1910 : : /*
1911 : : * Mark all other networks disabled or mark all networks enabled if no
1912 : : * network specified.
1913 : : */
1914 [ + + ]: 494 : for (other_ssid = wpa_s->conf->ssid; other_ssid;
1915 : 253 : other_ssid = other_ssid->next) {
1916 : 253 : int was_disabled = other_ssid->disabled;
1917 [ + + ]: 253 : if (was_disabled == 2)
1918 : 10 : continue; /* do not change persistent P2P group data */
1919 : :
1920 [ + - ][ + + ]: 243 : other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
1921 [ + + ][ + - ]: 243 : if (was_disabled && !other_ssid->disabled)
1922 : 228 : wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
1923 : :
1924 [ + + ]: 243 : if (was_disabled != other_ssid->disabled)
1925 : 230 : wpas_notify_network_enabled_changed(wpa_s, other_ssid);
1926 : : }
1927 : :
1928 [ + - ][ - + ]: 241 : if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
[ # # ]
1929 : : /* We are already associated with the selected network */
1930 : 0 : wpa_printf(MSG_DEBUG, "Already associated with the "
1931 : : "selected network - do nothing");
1932 : 241 : return;
1933 : : }
1934 : :
1935 [ + - ]: 241 : if (ssid) {
1936 : 241 : wpa_s->current_ssid = ssid;
1937 : 241 : eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1938 : : }
1939 : 241 : wpa_s->connect_without_scan = NULL;
1940 : 241 : wpa_s->disconnected = 0;
1941 : 241 : wpa_s->reassociate = 1;
1942 : :
1943 [ + + ]: 241 : if (wpa_supplicant_fast_associate(wpa_s) != 1)
1944 [ - + ]: 217 : wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
1945 : :
1946 [ + - ]: 241 : if (ssid)
1947 : 241 : wpas_notify_network_selected(wpa_s, ssid);
1948 : : }
1949 : :
1950 : :
1951 : : /**
1952 : : * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
1953 : : * @wpa_s: wpa_supplicant structure for a network interface
1954 : : * @pkcs11_engine_path: PKCS #11 engine path or NULL
1955 : : * @pkcs11_module_path: PKCS #11 module path or NULL
1956 : : * Returns: 0 on success; -1 on failure
1957 : : *
1958 : : * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
1959 : : * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
1960 : : * module path fails the paths will be reset to the default value (NULL).
1961 : : */
1962 : 0 : int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
1963 : : const char *pkcs11_engine_path,
1964 : : const char *pkcs11_module_path)
1965 : : {
1966 : 0 : char *pkcs11_engine_path_copy = NULL;
1967 : 0 : char *pkcs11_module_path_copy = NULL;
1968 : :
1969 [ # # ]: 0 : if (pkcs11_engine_path != NULL) {
1970 : 0 : pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
1971 [ # # ]: 0 : if (pkcs11_engine_path_copy == NULL)
1972 : 0 : return -1;
1973 : : }
1974 [ # # ]: 0 : if (pkcs11_module_path != NULL) {
1975 : 0 : pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
1976 [ # # ]: 0 : if (pkcs11_engine_path_copy == NULL) {
1977 : 0 : os_free(pkcs11_engine_path_copy);
1978 : 0 : return -1;
1979 : : }
1980 : : }
1981 : :
1982 : 0 : os_free(wpa_s->conf->pkcs11_engine_path);
1983 : 0 : os_free(wpa_s->conf->pkcs11_module_path);
1984 : 0 : wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
1985 : 0 : wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
1986 : :
1987 : 0 : wpa_sm_set_eapol(wpa_s->wpa, NULL);
1988 : 0 : eapol_sm_deinit(wpa_s->eapol);
1989 : 0 : wpa_s->eapol = NULL;
1990 [ # # ]: 0 : if (wpa_supplicant_init_eapol(wpa_s)) {
1991 : : /* Error -> Reset paths to the default value (NULL) once. */
1992 [ # # ][ # # ]: 0 : if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
1993 : 0 : wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
1994 : : NULL);
1995 : :
1996 : 0 : return -1;
1997 : : }
1998 : 0 : wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
1999 : :
2000 : 0 : return 0;
2001 : : }
2002 : :
2003 : :
2004 : : /**
2005 : : * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2006 : : * @wpa_s: wpa_supplicant structure for a network interface
2007 : : * @ap_scan: AP scan mode
2008 : : * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2009 : : *
2010 : : */
2011 : 0 : int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2012 : : {
2013 : :
2014 : : int old_ap_scan;
2015 : :
2016 [ # # ][ # # ]: 0 : if (ap_scan < 0 || ap_scan > 2)
2017 : 0 : return -1;
2018 : :
2019 : : #ifdef ANDROID
2020 : : if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2021 : : wpa_s->wpa_state >= WPA_ASSOCIATING &&
2022 : : wpa_s->wpa_state < WPA_COMPLETED) {
2023 : : wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2024 : : "associating", wpa_s->conf->ap_scan, ap_scan);
2025 : : return 0;
2026 : : }
2027 : : #endif /* ANDROID */
2028 : :
2029 : 0 : old_ap_scan = wpa_s->conf->ap_scan;
2030 : 0 : wpa_s->conf->ap_scan = ap_scan;
2031 : :
2032 [ # # ]: 0 : if (old_ap_scan != wpa_s->conf->ap_scan)
2033 : 0 : wpas_notify_ap_scan_changed(wpa_s);
2034 : :
2035 : 0 : return 0;
2036 : : }
2037 : :
2038 : :
2039 : : /**
2040 : : * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2041 : : * @wpa_s: wpa_supplicant structure for a network interface
2042 : : * @expire_age: Expiration age in seconds
2043 : : * Returns: 0 if succeed or -1 if expire_age has an invalid value
2044 : : *
2045 : : */
2046 : 0 : int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2047 : : unsigned int bss_expire_age)
2048 : : {
2049 [ # # ]: 0 : if (bss_expire_age < 10) {
2050 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2051 : : bss_expire_age);
2052 : 0 : return -1;
2053 : : }
2054 : 0 : wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2055 : : bss_expire_age);
2056 : 0 : wpa_s->conf->bss_expiration_age = bss_expire_age;
2057 : :
2058 : 0 : return 0;
2059 : : }
2060 : :
2061 : :
2062 : : /**
2063 : : * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2064 : : * @wpa_s: wpa_supplicant structure for a network interface
2065 : : * @expire_count: number of scans after which an unseen BSS is reclaimed
2066 : : * Returns: 0 if succeed or -1 if expire_count has an invalid value
2067 : : *
2068 : : */
2069 : 0 : int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2070 : : unsigned int bss_expire_count)
2071 : : {
2072 [ # # ]: 0 : if (bss_expire_count < 1) {
2073 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2074 : : bss_expire_count);
2075 : 0 : return -1;
2076 : : }
2077 : 0 : wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2078 : : bss_expire_count);
2079 : 0 : wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2080 : :
2081 : 0 : return 0;
2082 : : }
2083 : :
2084 : :
2085 : : /**
2086 : : * wpa_supplicant_set_scan_interval - Set scan interval
2087 : : * @wpa_s: wpa_supplicant structure for a network interface
2088 : : * @scan_interval: scan interval in seconds
2089 : : * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2090 : : *
2091 : : */
2092 : 0 : int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2093 : : int scan_interval)
2094 : : {
2095 [ # # ]: 0 : if (scan_interval < 0) {
2096 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2097 : : scan_interval);
2098 : 0 : return -1;
2099 : : }
2100 : 0 : wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2101 : : scan_interval);
2102 : 0 : wpa_supplicant_update_scan_int(wpa_s, scan_interval);
2103 : :
2104 : 0 : return 0;
2105 : : }
2106 : :
2107 : :
2108 : : /**
2109 : : * wpa_supplicant_set_debug_params - Set global debug params
2110 : : * @global: wpa_global structure
2111 : : * @debug_level: debug level
2112 : : * @debug_timestamp: determines if show timestamp in debug data
2113 : : * @debug_show_keys: determines if show keys in debug data
2114 : : * Returns: 0 if succeed or -1 if debug_level has wrong value
2115 : : */
2116 : 0 : int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2117 : : int debug_timestamp, int debug_show_keys)
2118 : : {
2119 : :
2120 : : int old_level, old_timestamp, old_show_keys;
2121 : :
2122 : : /* check for allowed debuglevels */
2123 [ # # ][ # # ]: 0 : if (debug_level != MSG_EXCESSIVE &&
2124 [ # # ]: 0 : debug_level != MSG_MSGDUMP &&
2125 [ # # ]: 0 : debug_level != MSG_DEBUG &&
2126 [ # # ]: 0 : debug_level != MSG_INFO &&
2127 [ # # ]: 0 : debug_level != MSG_WARNING &&
2128 : : debug_level != MSG_ERROR)
2129 : 0 : return -1;
2130 : :
2131 : 0 : old_level = wpa_debug_level;
2132 : 0 : old_timestamp = wpa_debug_timestamp;
2133 : 0 : old_show_keys = wpa_debug_show_keys;
2134 : :
2135 : 0 : wpa_debug_level = debug_level;
2136 : 0 : wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2137 : 0 : wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2138 : :
2139 [ # # ]: 0 : if (wpa_debug_level != old_level)
2140 : 0 : wpas_notify_debug_level_changed(global);
2141 [ # # ]: 0 : if (wpa_debug_timestamp != old_timestamp)
2142 : 0 : wpas_notify_debug_timestamp_changed(global);
2143 [ # # ]: 0 : if (wpa_debug_show_keys != old_show_keys)
2144 : 0 : wpas_notify_debug_show_keys_changed(global);
2145 : :
2146 : 0 : return 0;
2147 : : }
2148 : :
2149 : :
2150 : : /**
2151 : : * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2152 : : * @wpa_s: Pointer to wpa_supplicant data
2153 : : * Returns: A pointer to the current network structure or %NULL on failure
2154 : : */
2155 : 284 : struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2156 : : {
2157 : : struct wpa_ssid *entry;
2158 : : u8 ssid[MAX_SSID_LEN];
2159 : : int res;
2160 : : size_t ssid_len;
2161 : : u8 bssid[ETH_ALEN];
2162 : : int wired;
2163 : :
2164 : 284 : res = wpa_drv_get_ssid(wpa_s, ssid);
2165 [ - + ]: 284 : if (res < 0) {
2166 : 0 : wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2167 : : "driver");
2168 : 0 : return NULL;
2169 : : }
2170 : 284 : ssid_len = res;
2171 : :
2172 [ - + ]: 284 : if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
2173 : 0 : wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2174 : : "driver");
2175 : 0 : return NULL;
2176 : : }
2177 : :
2178 [ - + ][ # # ]: 284 : wired = wpa_s->conf->ap_scan == 0 &&
2179 : 0 : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2180 : :
2181 : 284 : entry = wpa_s->conf->ssid;
2182 [ + - ]: 313 : while (entry) {
2183 [ + + ][ + - ]: 313 : if (!wpas_network_disabled(wpa_s, entry) &&
2184 [ - + ]: 284 : ((ssid_len == entry->ssid_len &&
2185 [ # # ][ + + ]: 284 : os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2186 [ + - ]: 53 : (!entry->bssid_set ||
2187 : 53 : os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2188 : 284 : return entry;
2189 : : #ifdef CONFIG_WPS
2190 [ - + ][ # # ]: 29 : if (!wpas_network_disabled(wpa_s, entry) &&
2191 [ # # ]: 0 : (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2192 [ # # ][ # # ]: 0 : (entry->ssid == NULL || entry->ssid_len == 0) &&
2193 [ # # ]: 0 : (!entry->bssid_set ||
2194 : 0 : os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2195 : 0 : return entry;
2196 : : #endif /* CONFIG_WPS */
2197 : :
2198 [ - + ][ # # ]: 29 : if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
[ # # ]
2199 [ # # ]: 0 : entry->ssid_len == 0 &&
2200 : 0 : os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2201 : 0 : return entry;
2202 : :
2203 : 29 : entry = entry->next;
2204 : : }
2205 : :
2206 : 284 : return NULL;
2207 : : }
2208 : :
2209 : :
2210 : 31 : static int select_driver(struct wpa_supplicant *wpa_s, int i)
2211 : : {
2212 : 31 : struct wpa_global *global = wpa_s->global;
2213 : :
2214 [ + - ][ + + ]: 31 : if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2215 : 4 : global->drv_priv[i] = wpa_drivers[i]->global_init();
2216 [ - + ]: 4 : if (global->drv_priv[i] == NULL) {
2217 : 0 : wpa_printf(MSG_ERROR, "Failed to initialize driver "
2218 : 0 : "'%s'", wpa_drivers[i]->name);
2219 : 0 : return -1;
2220 : : }
2221 : : }
2222 : :
2223 : 31 : wpa_s->driver = wpa_drivers[i];
2224 : 31 : wpa_s->global_drv_priv = global->drv_priv[i];
2225 : :
2226 : 31 : return 0;
2227 : : }
2228 : :
2229 : :
2230 : 31 : static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2231 : : const char *name)
2232 : : {
2233 : : int i;
2234 : : size_t len;
2235 : 31 : const char *pos, *driver = name;
2236 : :
2237 [ - + ]: 31 : if (wpa_s == NULL)
2238 : 0 : return -1;
2239 : :
2240 [ - + ]: 31 : if (wpa_drivers[0] == NULL) {
2241 : 0 : wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2242 : : "wpa_supplicant");
2243 : 0 : return -1;
2244 : : }
2245 : :
2246 [ - + ]: 31 : if (name == NULL) {
2247 : : /* default to first driver in the list */
2248 : 0 : return select_driver(wpa_s, 0);
2249 : : }
2250 : :
2251 : : do {
2252 : 31 : pos = os_strchr(driver, ',');
2253 [ - + ]: 31 : if (pos)
2254 : 0 : len = pos - driver;
2255 : : else
2256 : 31 : len = os_strlen(driver);
2257 : :
2258 [ + - ]: 31 : for (i = 0; wpa_drivers[i]; i++) {
2259 [ + - ][ + - ]: 31 : if (os_strlen(wpa_drivers[i]->name) == len &&
2260 : 31 : os_strncmp(driver, wpa_drivers[i]->name, len) ==
2261 : : 0) {
2262 : : /* First driver that succeeds wins */
2263 [ + - ]: 31 : if (select_driver(wpa_s, i) == 0)
2264 : 31 : return 0;
2265 : : }
2266 : : }
2267 : :
2268 : 0 : driver = pos + 1;
2269 [ # # ]: 0 : } while (pos);
2270 : :
2271 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2272 : 31 : return -1;
2273 : : }
2274 : :
2275 : :
2276 : : /**
2277 : : * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2278 : : * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2279 : : * with struct wpa_driver_ops::init()
2280 : : * @src_addr: Source address of the EAPOL frame
2281 : : * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2282 : : * @len: Length of the EAPOL data
2283 : : *
2284 : : * This function is called for each received EAPOL frame. Most driver
2285 : : * interfaces rely on more generic OS mechanism for receiving frames through
2286 : : * l2_packet, but if such a mechanism is not available, the driver wrapper may
2287 : : * take care of received EAPOL frames and deliver them to the core supplicant
2288 : : * code by calling this function.
2289 : : */
2290 : 2236 : void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2291 : : const u8 *buf, size_t len)
2292 : : {
2293 : 2236 : struct wpa_supplicant *wpa_s = ctx;
2294 : :
2295 : 2236 : wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2296 : 2236 : wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2297 : :
2298 : : #ifdef CONFIG_PEERKEY
2299 [ + + ][ + - ]: 2236 : if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
[ + + ]
2300 [ + - ]: 9 : wpa_s->current_ssid->peerkey &&
2301 [ + + ]: 9 : !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2302 : 9 : wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2303 : 4 : wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2304 : 4 : return;
2305 : : }
2306 : : #endif /* CONFIG_PEERKEY */
2307 : :
2308 [ + - ][ + + ]: 2232 : if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2309 [ + + ]: 1414 : (wpa_s->last_eapol_matches_bssid &&
2310 : : #ifdef CONFIG_AP
2311 [ - + ]: 1397 : !wpa_s->ap_iface &&
2312 : : #endif /* CONFIG_AP */
2313 : 1397 : os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
2314 : : /*
2315 : : * There is possible race condition between receiving the
2316 : : * association event and the EAPOL frame since they are coming
2317 : : * through different paths from the driver. In order to avoid
2318 : : * issues in trying to process the EAPOL frame before receiving
2319 : : * association information, lets queue it for processing until
2320 : : * the association event is received. This may also be needed in
2321 : : * driver-based roaming case, so also use src_addr != BSSID as a
2322 : : * trigger if we have previously confirmed that the
2323 : : * Authenticator uses BSSID as the src_addr (which is not the
2324 : : * case with wired IEEE 802.1X).
2325 : : */
2326 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
2327 : : "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2328 : : wpa_supplicant_state_txt(wpa_s->wpa_state),
2329 : : MAC2STR(wpa_s->bssid));
2330 : 0 : wpabuf_free(wpa_s->pending_eapol_rx);
2331 : 0 : wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2332 [ # # ]: 0 : if (wpa_s->pending_eapol_rx) {
2333 : 0 : os_get_reltime(&wpa_s->pending_eapol_rx_time);
2334 : 0 : os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2335 : : ETH_ALEN);
2336 : : }
2337 : 0 : return;
2338 : : }
2339 : :
2340 : 2232 : wpa_s->last_eapol_matches_bssid =
2341 : 2232 : os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2342 : :
2343 : : #ifdef CONFIG_AP
2344 [ + + ]: 2232 : if (wpa_s->ap_iface) {
2345 : 473 : wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2346 : 473 : return;
2347 : : }
2348 : : #endif /* CONFIG_AP */
2349 : :
2350 [ - + ]: 1759 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2351 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2352 : : "no key management is configured");
2353 : 0 : return;
2354 : : }
2355 : :
2356 [ + + ][ - + ]: 1759 : if (wpa_s->eapol_received == 0 &&
2357 [ # # ]: 0 : (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2358 [ # # ]: 0 : !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2359 [ + - ]: 341 : wpa_s->wpa_state != WPA_COMPLETED) &&
2360 [ + + ]: 341 : (wpa_s->current_ssid == NULL ||
2361 : 341 : wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2362 : : /* Timeout for completing IEEE 802.1X and WPA authentication */
2363 [ + + ]: 606 : wpa_supplicant_req_auth_timeout(
2364 : : wpa_s,
2365 [ + + ]: 606 : (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2366 [ + + ]: 264 : wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2367 : 264 : wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2368 : : 70 : 10, 0);
2369 : : }
2370 : 1759 : wpa_s->eapol_received++;
2371 : :
2372 [ - + ]: 1759 : if (wpa_s->countermeasures) {
2373 : 0 : wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2374 : : "EAPOL packet");
2375 : 0 : return;
2376 : : }
2377 : :
2378 : : #ifdef CONFIG_IBSS_RSN
2379 [ + - ][ + + ]: 1759 : if (wpa_s->current_ssid &&
2380 : 1759 : wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2381 : 24 : ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2382 : 24 : return;
2383 : : }
2384 : : #endif /* CONFIG_IBSS_RSN */
2385 : :
2386 : : /* Source address of the incoming EAPOL frame could be compared to the
2387 : : * current BSSID. However, it is possible that a centralized
2388 : : * Authenticator could be using another MAC address than the BSSID of
2389 : : * an AP, so just allow any address to be used for now. The replies are
2390 : : * still sent to the current BSSID (if available), though. */
2391 : :
2392 : 1735 : os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2393 [ + + + + ]: 3248 : if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2394 : 1513 : eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2395 : 1191 : return;
2396 : 544 : wpa_drv_poll(wpa_s);
2397 [ + - ]: 544 : if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2398 : 544 : wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2399 [ # # ]: 0 : else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2400 : : /*
2401 : : * Set portValid = TRUE here since we are going to skip 4-way
2402 : : * handshake processing which would normally set portValid. We
2403 : : * need this to allow the EAPOL state machines to be completed
2404 : : * without going through EAPOL-Key handshake.
2405 : : */
2406 : 2236 : eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2407 : : }
2408 : : }
2409 : :
2410 : :
2411 : 31 : int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
2412 : : {
2413 [ - + ]: 31 : if (wpa_s->driver->send_eapol) {
2414 : 0 : const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2415 [ # # ]: 0 : if (addr)
2416 : 0 : os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2417 [ - + ][ # # ]: 31 : } else if ((!wpa_s->p2p_mgmt ||
2418 : 0 : !(wpa_s->drv_flags &
2419 [ + - ]: 31 : WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2420 : 31 : !(wpa_s->drv_flags &
2421 : : WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
2422 : 31 : l2_packet_deinit(wpa_s->l2);
2423 : 31 : wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2424 : : wpa_drv_get_mac_addr(wpa_s),
2425 : : ETH_P_EAPOL,
2426 : : wpa_supplicant_rx_eapol, wpa_s, 0);
2427 [ - + ]: 31 : if (wpa_s->l2 == NULL)
2428 : 0 : return -1;
2429 : : } else {
2430 : 0 : const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2431 [ # # ]: 0 : if (addr)
2432 : 0 : os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2433 : : }
2434 : :
2435 [ + - ][ - + ]: 31 : if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2436 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2437 : 0 : return -1;
2438 : : }
2439 : :
2440 : 31 : return 0;
2441 : : }
2442 : :
2443 : :
2444 : 0 : static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2445 : : const u8 *buf, size_t len)
2446 : : {
2447 : 0 : struct wpa_supplicant *wpa_s = ctx;
2448 : : const struct l2_ethhdr *eth;
2449 : :
2450 [ # # ]: 0 : if (len < sizeof(*eth))
2451 : 0 : return;
2452 : 0 : eth = (const struct l2_ethhdr *) buf;
2453 : :
2454 [ # # ][ # # ]: 0 : if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2455 : 0 : !(eth->h_dest[0] & 0x01)) {
2456 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2457 : : " (bridge - not for this interface - ignore)",
2458 : : MAC2STR(src_addr), MAC2STR(eth->h_dest));
2459 : 0 : return;
2460 : : }
2461 : :
2462 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2463 : : " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2464 : 0 : wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2465 : : len - sizeof(*eth));
2466 : : }
2467 : :
2468 : :
2469 : : /**
2470 : : * wpa_supplicant_driver_init - Initialize driver interface parameters
2471 : : * @wpa_s: Pointer to wpa_supplicant data
2472 : : * Returns: 0 on success, -1 on failure
2473 : : *
2474 : : * This function is called to initialize driver interface parameters.
2475 : : * wpa_drv_init() must have been called before this function to initialize the
2476 : : * driver interface.
2477 : : */
2478 : 31 : int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2479 : : {
2480 : : static int interface_count = 0;
2481 : :
2482 [ - + ]: 31 : if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2483 : 0 : return -1;
2484 : :
2485 : 31 : wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2486 : : MAC2STR(wpa_s->own_addr));
2487 : 31 : wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2488 : :
2489 [ - + ]: 31 : if (wpa_s->bridge_ifname[0]) {
2490 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2491 : : "interface '%s'", wpa_s->bridge_ifname);
2492 : 0 : wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2493 : 0 : wpa_s->own_addr,
2494 : : ETH_P_EAPOL,
2495 : : wpa_supplicant_rx_eapol_bridge,
2496 : : wpa_s, 1);
2497 [ # # ]: 0 : if (wpa_s->l2_br == NULL) {
2498 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2499 : : "connection for the bridge interface '%s'",
2500 : 0 : wpa_s->bridge_ifname);
2501 : 0 : return -1;
2502 : : }
2503 : : }
2504 : :
2505 : 31 : wpa_clear_keys(wpa_s, NULL);
2506 : :
2507 : : /* Make sure that TKIP countermeasures are not left enabled (could
2508 : : * happen if wpa_supplicant is killed during countermeasures. */
2509 : 31 : wpa_drv_set_countermeasures(wpa_s, 0);
2510 : :
2511 : 31 : wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2512 : 31 : wpa_drv_flush_pmkid(wpa_s);
2513 : :
2514 : 31 : wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
2515 : 31 : wpa_s->prev_scan_wildcard = 0;
2516 : :
2517 [ - + ]: 31 : if (wpa_supplicant_enabled_networks(wpa_s)) {
2518 [ # # ]: 0 : if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2519 : : 100000))
2520 : 0 : wpa_supplicant_req_scan(wpa_s, interface_count,
2521 : : 100000);
2522 : 0 : interface_count++;
2523 : : } else
2524 : 31 : wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2525 : :
2526 : 31 : return 0;
2527 : : }
2528 : :
2529 : :
2530 : 0 : static int wpa_supplicant_daemon(const char *pid_file)
2531 : : {
2532 : 0 : wpa_printf(MSG_DEBUG, "Daemonize..");
2533 : 0 : return os_daemonize(pid_file);
2534 : : }
2535 : :
2536 : :
2537 : 31 : static struct wpa_supplicant * wpa_supplicant_alloc(void)
2538 : : {
2539 : : struct wpa_supplicant *wpa_s;
2540 : :
2541 : 31 : wpa_s = os_zalloc(sizeof(*wpa_s));
2542 [ - + ]: 31 : if (wpa_s == NULL)
2543 : 0 : return NULL;
2544 : 31 : wpa_s->scan_req = INITIAL_SCAN_REQ;
2545 : 31 : wpa_s->scan_interval = 5;
2546 : 31 : wpa_s->new_connection = 1;
2547 : 31 : wpa_s->parent = wpa_s;
2548 : 31 : wpa_s->sched_scanning = 0;
2549 : :
2550 : 31 : return wpa_s;
2551 : : }
2552 : :
2553 : :
2554 : : #ifdef CONFIG_HT_OVERRIDES
2555 : :
2556 : : static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2557 : : struct ieee80211_ht_capabilities *htcaps,
2558 : : struct ieee80211_ht_capabilities *htcaps_mask,
2559 : : const char *ht_mcs)
2560 : : {
2561 : : /* parse ht_mcs into hex array */
2562 : : int i;
2563 : : const char *tmp = ht_mcs;
2564 : : char *end = NULL;
2565 : :
2566 : : /* If ht_mcs is null, do not set anything */
2567 : : if (!ht_mcs)
2568 : : return 0;
2569 : :
2570 : : /* This is what we are setting in the kernel */
2571 : : os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2572 : :
2573 : : wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2574 : :
2575 : : for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2576 : : errno = 0;
2577 : : long v = strtol(tmp, &end, 16);
2578 : : if (errno == 0) {
2579 : : wpa_msg(wpa_s, MSG_DEBUG,
2580 : : "htcap value[%i]: %ld end: %p tmp: %p",
2581 : : i, v, end, tmp);
2582 : : if (end == tmp)
2583 : : break;
2584 : :
2585 : : htcaps->supported_mcs_set[i] = v;
2586 : : tmp = end;
2587 : : } else {
2588 : : wpa_msg(wpa_s, MSG_ERROR,
2589 : : "Failed to parse ht-mcs: %s, error: %s\n",
2590 : : ht_mcs, strerror(errno));
2591 : : return -1;
2592 : : }
2593 : : }
2594 : :
2595 : : /*
2596 : : * If we were able to parse any values, then set mask for the MCS set.
2597 : : */
2598 : : if (i) {
2599 : : os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2600 : : IEEE80211_HT_MCS_MASK_LEN - 1);
2601 : : /* skip the 3 reserved bits */
2602 : : htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2603 : : 0x1f;
2604 : : }
2605 : :
2606 : : return 0;
2607 : : }
2608 : :
2609 : :
2610 : : static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2611 : : struct ieee80211_ht_capabilities *htcaps,
2612 : : struct ieee80211_ht_capabilities *htcaps_mask,
2613 : : int disabled)
2614 : : {
2615 : : u16 msk;
2616 : :
2617 : : wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2618 : :
2619 : : if (disabled == -1)
2620 : : return 0;
2621 : :
2622 : : msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2623 : : htcaps_mask->ht_capabilities_info |= msk;
2624 : : if (disabled)
2625 : : htcaps->ht_capabilities_info &= msk;
2626 : : else
2627 : : htcaps->ht_capabilities_info |= msk;
2628 : :
2629 : : return 0;
2630 : : }
2631 : :
2632 : :
2633 : : static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2634 : : struct ieee80211_ht_capabilities *htcaps,
2635 : : struct ieee80211_ht_capabilities *htcaps_mask,
2636 : : int factor)
2637 : : {
2638 : : wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2639 : :
2640 : : if (factor == -1)
2641 : : return 0;
2642 : :
2643 : : if (factor < 0 || factor > 3) {
2644 : : wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2645 : : "Must be 0-3 or -1", factor);
2646 : : return -EINVAL;
2647 : : }
2648 : :
2649 : : htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2650 : : htcaps->a_mpdu_params &= ~0x3;
2651 : : htcaps->a_mpdu_params |= factor & 0x3;
2652 : :
2653 : : return 0;
2654 : : }
2655 : :
2656 : :
2657 : : static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2658 : : struct ieee80211_ht_capabilities *htcaps,
2659 : : struct ieee80211_ht_capabilities *htcaps_mask,
2660 : : int density)
2661 : : {
2662 : : wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2663 : :
2664 : : if (density == -1)
2665 : : return 0;
2666 : :
2667 : : if (density < 0 || density > 7) {
2668 : : wpa_msg(wpa_s, MSG_ERROR,
2669 : : "ampdu_density: %d out of range. Must be 0-7 or -1.",
2670 : : density);
2671 : : return -EINVAL;
2672 : : }
2673 : :
2674 : : htcaps_mask->a_mpdu_params |= 0x1C;
2675 : : htcaps->a_mpdu_params &= ~(0x1C);
2676 : : htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2677 : :
2678 : : return 0;
2679 : : }
2680 : :
2681 : :
2682 : : static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2683 : : struct ieee80211_ht_capabilities *htcaps,
2684 : : struct ieee80211_ht_capabilities *htcaps_mask,
2685 : : int disabled)
2686 : : {
2687 : : /* Masking these out disables HT40 */
2688 : : u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2689 : : HT_CAP_INFO_SHORT_GI40MHZ);
2690 : :
2691 : : wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2692 : :
2693 : : if (disabled)
2694 : : htcaps->ht_capabilities_info &= ~msk;
2695 : : else
2696 : : htcaps->ht_capabilities_info |= msk;
2697 : :
2698 : : htcaps_mask->ht_capabilities_info |= msk;
2699 : :
2700 : : return 0;
2701 : : }
2702 : :
2703 : :
2704 : : static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2705 : : struct ieee80211_ht_capabilities *htcaps,
2706 : : struct ieee80211_ht_capabilities *htcaps_mask,
2707 : : int disabled)
2708 : : {
2709 : : /* Masking these out disables SGI */
2710 : : u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2711 : : HT_CAP_INFO_SHORT_GI40MHZ);
2712 : :
2713 : : wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2714 : :
2715 : : if (disabled)
2716 : : htcaps->ht_capabilities_info &= ~msk;
2717 : : else
2718 : : htcaps->ht_capabilities_info |= msk;
2719 : :
2720 : : htcaps_mask->ht_capabilities_info |= msk;
2721 : :
2722 : : return 0;
2723 : : }
2724 : :
2725 : :
2726 : : void wpa_supplicant_apply_ht_overrides(
2727 : : struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2728 : : struct wpa_driver_associate_params *params)
2729 : : {
2730 : : struct ieee80211_ht_capabilities *htcaps;
2731 : : struct ieee80211_ht_capabilities *htcaps_mask;
2732 : :
2733 : : if (!ssid)
2734 : : return;
2735 : :
2736 : : params->disable_ht = ssid->disable_ht;
2737 : : if (!params->htcaps || !params->htcaps_mask)
2738 : : return;
2739 : :
2740 : : htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2741 : : htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2742 : : wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2743 : : wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2744 : : ssid->disable_max_amsdu);
2745 : : wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2746 : : wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2747 : : wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
2748 : : wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
2749 : : }
2750 : :
2751 : : #endif /* CONFIG_HT_OVERRIDES */
2752 : :
2753 : :
2754 : : #ifdef CONFIG_VHT_OVERRIDES
2755 : : void wpa_supplicant_apply_vht_overrides(
2756 : : struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2757 : : struct wpa_driver_associate_params *params)
2758 : : {
2759 : : struct ieee80211_vht_capabilities *vhtcaps;
2760 : : struct ieee80211_vht_capabilities *vhtcaps_mask;
2761 : :
2762 : : if (!ssid)
2763 : : return;
2764 : :
2765 : : params->disable_vht = ssid->disable_vht;
2766 : :
2767 : : vhtcaps = (void *) params->vhtcaps;
2768 : : vhtcaps_mask = (void *) params->vhtcaps_mask;
2769 : :
2770 : : if (!vhtcaps || !vhtcaps_mask)
2771 : : return;
2772 : :
2773 : : vhtcaps->vht_capabilities_info = ssid->vht_capa;
2774 : : vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2775 : :
2776 : : #define OVERRIDE_MCS(i) \
2777 : : if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2778 : : vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2779 : : 3 << 2 * (i - 1); \
2780 : : vhtcaps->vht_supported_mcs_set.tx_map |= \
2781 : : ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2782 : : } \
2783 : : if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2784 : : vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2785 : : 3 << 2 * (i - 1); \
2786 : : vhtcaps->vht_supported_mcs_set.rx_map |= \
2787 : : ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2788 : : }
2789 : :
2790 : : OVERRIDE_MCS(1);
2791 : : OVERRIDE_MCS(2);
2792 : : OVERRIDE_MCS(3);
2793 : : OVERRIDE_MCS(4);
2794 : : OVERRIDE_MCS(5);
2795 : : OVERRIDE_MCS(6);
2796 : : OVERRIDE_MCS(7);
2797 : : OVERRIDE_MCS(8);
2798 : : }
2799 : : #endif /* CONFIG_VHT_OVERRIDES */
2800 : :
2801 : :
2802 : 31 : static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2803 : : {
2804 : : #ifdef PCSC_FUNCS
2805 : : size_t len;
2806 : :
2807 [ + - ]: 31 : if (!wpa_s->conf->pcsc_reader)
2808 : 31 : return 0;
2809 : :
2810 : 0 : wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
2811 [ # # ]: 0 : if (!wpa_s->scard)
2812 : 0 : return 1;
2813 : :
2814 [ # # # # ]: 0 : if (wpa_s->conf->pcsc_pin &&
2815 : 0 : scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2816 : 0 : scard_deinit(wpa_s->scard);
2817 : 0 : wpa_s->scard = NULL;
2818 : 0 : wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2819 : 0 : return -1;
2820 : : }
2821 : :
2822 : 0 : len = sizeof(wpa_s->imsi) - 1;
2823 [ # # ]: 0 : if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2824 : 0 : scard_deinit(wpa_s->scard);
2825 : 0 : wpa_s->scard = NULL;
2826 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2827 : 0 : return -1;
2828 : : }
2829 : 0 : wpa_s->imsi[len] = '\0';
2830 : :
2831 : 0 : wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2832 : :
2833 : 0 : wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2834 : 0 : wpa_s->imsi, wpa_s->mnc_len);
2835 : :
2836 : 0 : wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2837 : 0 : eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2838 : : #endif /* PCSC_FUNCS */
2839 : :
2840 : 31 : return 0;
2841 : : }
2842 : :
2843 : :
2844 : 31 : int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2845 : : {
2846 : : char *val, *pos;
2847 : :
2848 : 31 : ext_password_deinit(wpa_s->ext_pw);
2849 : 31 : wpa_s->ext_pw = NULL;
2850 : 31 : eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2851 : :
2852 [ + - ]: 31 : if (!wpa_s->conf->ext_password_backend)
2853 : 31 : return 0;
2854 : :
2855 : 0 : val = os_strdup(wpa_s->conf->ext_password_backend);
2856 [ # # ]: 0 : if (val == NULL)
2857 : 0 : return -1;
2858 : 0 : pos = os_strchr(val, ':');
2859 [ # # ]: 0 : if (pos)
2860 : 0 : *pos++ = '\0';
2861 : :
2862 : 0 : wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2863 : :
2864 : 0 : wpa_s->ext_pw = ext_password_init(val, pos);
2865 : 0 : os_free(val);
2866 [ # # ]: 0 : if (wpa_s->ext_pw == NULL) {
2867 : 0 : wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2868 : 0 : return -1;
2869 : : }
2870 : 0 : eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2871 : :
2872 : 31 : return 0;
2873 : : }
2874 : :
2875 : :
2876 : 31 : static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
2877 : : const char *rn)
2878 : : {
2879 : 31 : struct wpa_supplicant *iface = wpa_s->global->ifaces;
2880 : : struct wpa_radio *radio;
2881 : :
2882 [ + - ][ + + ]: 31 : while (rn && iface) {
2883 : 21 : radio = iface->radio;
2884 [ + - ][ + - ]: 21 : if (radio && os_strcmp(rn, radio->name) == 0) {
2885 : 21 : wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
2886 : 21 : wpa_s->ifname, rn);
2887 : 21 : dl_list_add(&radio->ifaces, &wpa_s->radio_list);
2888 : 21 : return radio;
2889 : : }
2890 : :
2891 : 0 : iface = iface->next;
2892 : : }
2893 : :
2894 [ + - ]: 10 : wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
2895 : 10 : wpa_s->ifname, rn ? rn : "N/A");
2896 : 10 : radio = os_zalloc(sizeof(*radio));
2897 [ - + ]: 10 : if (radio == NULL)
2898 : 0 : return NULL;
2899 : :
2900 [ + - ]: 10 : if (rn)
2901 : 10 : os_strlcpy(radio->name, rn, sizeof(radio->name));
2902 : 10 : dl_list_init(&radio->ifaces);
2903 : 10 : dl_list_add(&radio->ifaces, &wpa_s->radio_list);
2904 : :
2905 : 31 : return radio;
2906 : : }
2907 : :
2908 : :
2909 : 31 : static void radio_remove_interface(struct wpa_supplicant *wpa_s)
2910 : : {
2911 : 31 : struct wpa_radio *radio = wpa_s->radio;
2912 : :
2913 [ - + ]: 31 : if (!radio)
2914 : 0 : return;
2915 : :
2916 : 31 : wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
2917 : 31 : wpa_s->ifname, radio->name);
2918 : 31 : dl_list_del(&wpa_s->radio_list);
2919 : 31 : wpa_s->radio = NULL;
2920 : :
2921 [ + + ]: 31 : if (!dl_list_empty(&radio->ifaces))
2922 : 21 : return; /* Interfaces remain for this radio */
2923 : :
2924 : 10 : wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
2925 : 31 : os_free(radio);
2926 : : }
2927 : :
2928 : :
2929 : 31 : static int wpas_init_driver(struct wpa_supplicant *wpa_s,
2930 : : struct wpa_interface *iface)
2931 : : {
2932 : : const char *ifname, *driver, *rn;
2933 : :
2934 : 31 : driver = iface->driver;
2935 : : next_driver:
2936 [ - + ]: 31 : if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
2937 : 0 : return -1;
2938 : :
2939 : 31 : wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
2940 [ - + ]: 31 : if (wpa_s->drv_priv == NULL) {
2941 : : const char *pos;
2942 [ # # ]: 0 : pos = driver ? os_strchr(driver, ',') : NULL;
2943 [ # # ]: 0 : if (pos) {
2944 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
2945 : : "driver interface - try next driver wrapper");
2946 : 0 : driver = pos + 1;
2947 : 0 : goto next_driver;
2948 : : }
2949 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
2950 : : "interface");
2951 : 0 : return -1;
2952 : : }
2953 [ - + ]: 31 : if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
2954 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
2955 : 0 : "driver_param '%s'", wpa_s->conf->driver_param);
2956 : 0 : return -1;
2957 : : }
2958 : :
2959 : 31 : ifname = wpa_drv_get_ifname(wpa_s);
2960 [ - + ][ # # ]: 31 : if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
2961 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
2962 : : "interface name with '%s'", ifname);
2963 : 0 : os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
2964 : : }
2965 : :
2966 [ + - ]: 31 : if (wpa_s->driver->get_radio_name)
2967 : 31 : rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
2968 : : else
2969 : 0 : rn = NULL;
2970 [ + - ][ - + ]: 31 : if (rn && rn[0] == '\0')
2971 : 0 : rn = NULL;
2972 : :
2973 : 31 : wpa_s->radio = radio_add_interface(wpa_s, rn);
2974 [ - + ]: 31 : if (wpa_s->radio == NULL)
2975 : 0 : return -1;
2976 : :
2977 : 31 : return 0;
2978 : : }
2979 : :
2980 : :
2981 : 31 : static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
2982 : : struct wpa_interface *iface)
2983 : : {
2984 : : struct wpa_driver_capa capa;
2985 : :
2986 [ - + ][ + + ]: 31 : wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
[ + - ][ + + ]
2987 : : "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
2988 : 31 : iface->confname ? iface->confname : "N/A",
2989 : 31 : iface->driver ? iface->driver : "default",
2990 : 31 : iface->ctrl_interface ? iface->ctrl_interface : "N/A",
2991 : 31 : iface->bridge_ifname ? iface->bridge_ifname : "N/A");
2992 : :
2993 [ + + ]: 31 : if (iface->confname) {
2994 : : #ifdef CONFIG_BACKEND_FILE
2995 : 3 : wpa_s->confname = os_rel2abs_path(iface->confname);
2996 [ - + ]: 3 : if (wpa_s->confname == NULL) {
2997 : 0 : wpa_printf(MSG_ERROR, "Failed to get absolute path "
2998 : : "for configuration file '%s'.",
2999 : : iface->confname);
3000 : 0 : return -1;
3001 : : }
3002 : 3 : wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3003 : : iface->confname, wpa_s->confname);
3004 : : #else /* CONFIG_BACKEND_FILE */
3005 : : wpa_s->confname = os_strdup(iface->confname);
3006 : : #endif /* CONFIG_BACKEND_FILE */
3007 : 3 : wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
3008 [ - + ]: 3 : if (wpa_s->conf == NULL) {
3009 : 0 : wpa_printf(MSG_ERROR, "Failed to read or parse "
3010 : : "configuration '%s'.", wpa_s->confname);
3011 : 0 : return -1;
3012 : : }
3013 : 3 : wpa_s->confanother = os_rel2abs_path(iface->confanother);
3014 : 3 : wpa_config_read(wpa_s->confanother, wpa_s->conf);
3015 : :
3016 : : /*
3017 : : * Override ctrl_interface and driver_param if set on command
3018 : : * line.
3019 : : */
3020 [ - + ]: 3 : if (iface->ctrl_interface) {
3021 : 0 : os_free(wpa_s->conf->ctrl_interface);
3022 : 0 : wpa_s->conf->ctrl_interface =
3023 : 0 : os_strdup(iface->ctrl_interface);
3024 : : }
3025 : :
3026 [ - + ]: 3 : if (iface->driver_param) {
3027 : 0 : os_free(wpa_s->conf->driver_param);
3028 : 0 : wpa_s->conf->driver_param =
3029 : 0 : os_strdup(iface->driver_param);
3030 : : }
3031 : :
3032 [ - + ][ # # ]: 3 : if (iface->p2p_mgmt && !iface->ctrl_interface) {
3033 : 0 : os_free(wpa_s->conf->ctrl_interface);
3034 : 0 : wpa_s->conf->ctrl_interface = NULL;
3035 : : }
3036 : : } else
3037 : 28 : wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3038 : : iface->driver_param);
3039 : :
3040 [ - + ]: 31 : if (wpa_s->conf == NULL) {
3041 : 0 : wpa_printf(MSG_ERROR, "\nNo configuration found.");
3042 : 0 : return -1;
3043 : : }
3044 : :
3045 [ - + ]: 31 : if (iface->ifname == NULL) {
3046 : 0 : wpa_printf(MSG_ERROR, "\nInterface name is required.");
3047 : 0 : return -1;
3048 : : }
3049 [ - + ]: 31 : if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3050 : 0 : wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3051 : : iface->ifname);
3052 : 0 : return -1;
3053 : : }
3054 : 31 : os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3055 : :
3056 [ - + ]: 31 : if (iface->bridge_ifname) {
3057 [ # # ]: 0 : if (os_strlen(iface->bridge_ifname) >=
3058 : : sizeof(wpa_s->bridge_ifname)) {
3059 : 0 : wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3060 : : "name '%s'.", iface->bridge_ifname);
3061 : 0 : return -1;
3062 : : }
3063 : 0 : os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3064 : : sizeof(wpa_s->bridge_ifname));
3065 : : }
3066 : :
3067 : : /* RSNA Supplicant Key Management - INITIALIZE */
3068 : 31 : eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3069 : 31 : eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3070 : :
3071 : : /* Initialize driver interface and register driver event handler before
3072 : : * L2 receive handler so that association events are processed before
3073 : : * EAPOL-Key packets if both become available for the same select()
3074 : : * call. */
3075 [ - + ]: 31 : if (wpas_init_driver(wpa_s, iface) < 0)
3076 : 0 : return -1;
3077 : :
3078 [ - + ]: 31 : if (wpa_supplicant_init_wpa(wpa_s) < 0)
3079 : 0 : return -1;
3080 : :
3081 [ - + ]: 31 : wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3082 : 31 : wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3083 : : NULL);
3084 : 31 : wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3085 : :
3086 [ - + # # ]: 31 : if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3087 : 0 : wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3088 : 0 : wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3089 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3090 : : "dot11RSNAConfigPMKLifetime");
3091 : 0 : return -1;
3092 : : }
3093 : :
3094 [ - + # # ]: 31 : if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3095 : 0 : wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3096 : 0 : wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3097 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3098 : : "dot11RSNAConfigPMKReauthThreshold");
3099 : 0 : return -1;
3100 : : }
3101 : :
3102 [ - + # # ]: 31 : if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3103 : 0 : wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3104 : 0 : wpa_s->conf->dot11RSNAConfigSATimeout)) {
3105 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3106 : : "dot11RSNAConfigSATimeout");
3107 : 0 : return -1;
3108 : : }
3109 : :
3110 : 31 : wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3111 : : &wpa_s->hw.num_modes,
3112 : : &wpa_s->hw.flags);
3113 : :
3114 [ + - ]: 31 : if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
3115 : 31 : wpa_s->drv_capa_known = 1;
3116 : 31 : wpa_s->drv_flags = capa.flags;
3117 : 31 : wpa_s->drv_enc = capa.enc;
3118 : 31 : wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
3119 : 31 : wpa_s->max_scan_ssids = capa.max_scan_ssids;
3120 : 31 : wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3121 : 31 : wpa_s->sched_scan_supported = capa.sched_scan_supported;
3122 : 31 : wpa_s->max_match_sets = capa.max_match_sets;
3123 : 31 : wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3124 : 31 : wpa_s->max_stations = capa.max_stations;
3125 : 31 : wpa_s->extended_capa = capa.extended_capa;
3126 : 31 : wpa_s->extended_capa_mask = capa.extended_capa_mask;
3127 : 31 : wpa_s->extended_capa_len = capa.extended_capa_len;
3128 : 31 : wpa_s->num_multichan_concurrent =
3129 : 31 : capa.num_multichan_concurrent;
3130 : : }
3131 [ - + ]: 31 : if (wpa_s->max_remain_on_chan == 0)
3132 : 0 : wpa_s->max_remain_on_chan = 1000;
3133 : :
3134 : : /*
3135 : : * Only take p2p_mgmt parameters when P2P Device is supported.
3136 : : * Doing it here as it determines whether l2_packet_init() will be done
3137 : : * during wpa_supplicant_driver_init().
3138 : : */
3139 [ - + ]: 31 : if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3140 : 0 : wpa_s->p2p_mgmt = iface->p2p_mgmt;
3141 : : else
3142 : 31 : iface->p2p_mgmt = 1;
3143 : :
3144 [ + - ]: 31 : if (wpa_s->num_multichan_concurrent == 0)
3145 : 31 : wpa_s->num_multichan_concurrent = 1;
3146 : :
3147 [ - + ]: 31 : if (wpa_supplicant_driver_init(wpa_s) < 0)
3148 : 0 : return -1;
3149 : :
3150 : : #ifdef CONFIG_TDLS
3151 [ + - ][ + - ]: 31 : if ((!iface->p2p_mgmt ||
3152 : 31 : !(wpa_s->drv_flags &
3153 [ - + ]: 31 : WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3154 : 31 : wpa_tdls_init(wpa_s->wpa))
3155 : 0 : return -1;
3156 : : #endif /* CONFIG_TDLS */
3157 : :
3158 [ - + ]: 31 : if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
[ # # # # ]
3159 : 0 : wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3160 : 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3161 : 0 : return -1;
3162 : : }
3163 : :
3164 [ - + ]: 31 : if (wpas_wps_init(wpa_s))
3165 : 0 : return -1;
3166 : :
3167 [ - + ]: 31 : if (wpa_supplicant_init_eapol(wpa_s) < 0)
3168 : 0 : return -1;
3169 : 31 : wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3170 : :
3171 : 31 : wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3172 [ - + ]: 31 : if (wpa_s->ctrl_iface == NULL) {
3173 : 0 : wpa_printf(MSG_ERROR,
3174 : : "Failed to initialize control interface '%s'.\n"
3175 : : "You may have another wpa_supplicant process "
3176 : : "already running or the file was\n"
3177 : : "left by an unclean termination of wpa_supplicant "
3178 : : "in which case you will need\n"
3179 : : "to manually remove this file before starting "
3180 : : "wpa_supplicant again.\n",
3181 : 0 : wpa_s->conf->ctrl_interface);
3182 : 0 : return -1;
3183 : : }
3184 : :
3185 : 31 : wpa_s->gas = gas_query_init(wpa_s);
3186 [ - + ]: 31 : if (wpa_s->gas == NULL) {
3187 : 0 : wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3188 : 0 : return -1;
3189 : : }
3190 : :
3191 : : #ifdef CONFIG_P2P
3192 [ + - ][ - + ]: 31 : if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
3193 : 0 : wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3194 : 0 : return -1;
3195 : : }
3196 : : #endif /* CONFIG_P2P */
3197 : :
3198 [ - + ]: 31 : if (wpa_bss_init(wpa_s) < 0)
3199 : 0 : return -1;
3200 : :
3201 : : #ifdef CONFIG_EAP_PROXY
3202 : : {
3203 : : size_t len;
3204 : : wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3205 : : &len);
3206 : : if (wpa_s->mnc_len > 0) {
3207 : : wpa_s->imsi[len] = '\0';
3208 : : wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3209 : : wpa_s->imsi, wpa_s->mnc_len);
3210 : : } else {
3211 : : wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3212 : : }
3213 : : }
3214 : : #endif /* CONFIG_EAP_PROXY */
3215 : :
3216 [ - + ]: 31 : if (pcsc_reader_init(wpa_s) < 0)
3217 : 0 : return -1;
3218 : :
3219 [ - + ]: 31 : if (wpas_init_ext_pw(wpa_s) < 0)
3220 : 0 : return -1;
3221 : :
3222 : 31 : return 0;
3223 : : }
3224 : :
3225 : :
3226 : 31 : static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
3227 : : int notify, int terminate)
3228 : : {
3229 : 31 : wpa_s->disconnected = 1;
3230 [ + - ]: 31 : if (wpa_s->drv_priv) {
3231 : 31 : wpa_supplicant_deauthenticate(wpa_s,
3232 : : WLAN_REASON_DEAUTH_LEAVING);
3233 : :
3234 : 31 : wpa_drv_set_countermeasures(wpa_s, 0);
3235 : 31 : wpa_clear_keys(wpa_s, NULL);
3236 : : }
3237 : :
3238 : 31 : wpa_supplicant_cleanup(wpa_s);
3239 : :
3240 : : #ifdef CONFIG_P2P
3241 [ + + ][ + - ]: 31 : if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3242 : 10 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3243 : : "the management interface is being removed");
3244 : 10 : wpas_p2p_deinit_global(wpa_s->global);
3245 : : }
3246 : : #endif /* CONFIG_P2P */
3247 : :
3248 : 31 : radio_remove_interface(wpa_s);
3249 : :
3250 [ + - ]: 31 : if (wpa_s->drv_priv)
3251 : 31 : wpa_drv_deinit(wpa_s);
3252 : :
3253 [ + - ]: 31 : if (notify)
3254 : 31 : wpas_notify_iface_removed(wpa_s);
3255 : :
3256 [ + + ]: 31 : if (terminate)
3257 : 3 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
3258 : :
3259 [ + - ]: 31 : if (wpa_s->ctrl_iface) {
3260 : 31 : wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3261 : 31 : wpa_s->ctrl_iface = NULL;
3262 : : }
3263 : :
3264 [ + - ]: 31 : if (wpa_s->conf != NULL) {
3265 : 31 : wpa_config_free(wpa_s->conf);
3266 : 31 : wpa_s->conf = NULL;
3267 : : }
3268 : :
3269 : 31 : os_free(wpa_s);
3270 : 31 : }
3271 : :
3272 : :
3273 : : /**
3274 : : * wpa_supplicant_add_iface - Add a new network interface
3275 : : * @global: Pointer to global data from wpa_supplicant_init()
3276 : : * @iface: Interface configuration options
3277 : : * Returns: Pointer to the created interface or %NULL on failure
3278 : : *
3279 : : * This function is used to add new network interfaces for %wpa_supplicant.
3280 : : * This can be called before wpa_supplicant_run() to add interfaces before the
3281 : : * main event loop has been started. In addition, new interfaces can be added
3282 : : * dynamically while %wpa_supplicant is already running. This could happen,
3283 : : * e.g., when a hotplug network adapter is inserted.
3284 : : */
3285 : 31 : struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3286 : : struct wpa_interface *iface)
3287 : : {
3288 : : struct wpa_supplicant *wpa_s;
3289 : : struct wpa_interface t_iface;
3290 : : struct wpa_ssid *ssid;
3291 : :
3292 [ + - ][ - + ]: 31 : if (global == NULL || iface == NULL)
3293 : 0 : return NULL;
3294 : :
3295 : 31 : wpa_s = wpa_supplicant_alloc();
3296 [ - + ]: 31 : if (wpa_s == NULL)
3297 : 0 : return NULL;
3298 : :
3299 : 31 : wpa_s->global = global;
3300 : :
3301 : 31 : t_iface = *iface;
3302 [ - + ]: 31 : if (global->params.override_driver) {
3303 : 0 : wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3304 : : "('%s' -> '%s')",
3305 : : iface->driver, global->params.override_driver);
3306 : 0 : t_iface.driver = global->params.override_driver;
3307 : : }
3308 [ - + ]: 31 : if (global->params.override_ctrl_interface) {
3309 : 0 : wpa_printf(MSG_DEBUG, "Override interface parameter: "
3310 : : "ctrl_interface ('%s' -> '%s')",
3311 : : iface->ctrl_interface,
3312 : : global->params.override_ctrl_interface);
3313 : 0 : t_iface.ctrl_interface =
3314 : 0 : global->params.override_ctrl_interface;
3315 : : }
3316 [ - + ]: 31 : if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3317 : 0 : wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3318 : : iface->ifname);
3319 : 0 : wpa_supplicant_deinit_iface(wpa_s, 0, 0);
3320 : 0 : return NULL;
3321 : : }
3322 : :
3323 : : /* Notify the control interfaces about new iface */
3324 [ - + ]: 31 : if (wpas_notify_iface_added(wpa_s)) {
3325 : 0 : wpa_supplicant_deinit_iface(wpa_s, 1, 0);
3326 : 0 : return NULL;
3327 : : }
3328 : :
3329 [ - + ]: 31 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3330 : 0 : wpas_notify_network_added(wpa_s, ssid);
3331 : :
3332 : 31 : wpa_s->next = global->ifaces;
3333 : 31 : global->ifaces = wpa_s;
3334 : :
3335 : 31 : wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
3336 : 31 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3337 : :
3338 : 31 : return wpa_s;
3339 : : }
3340 : :
3341 : :
3342 : : /**
3343 : : * wpa_supplicant_remove_iface - Remove a network interface
3344 : : * @global: Pointer to global data from wpa_supplicant_init()
3345 : : * @wpa_s: Pointer to the network interface to be removed
3346 : : * Returns: 0 if interface was removed, -1 if interface was not found
3347 : : *
3348 : : * This function can be used to dynamically remove network interfaces from
3349 : : * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3350 : : * addition, this function is used to remove all remaining interfaces when
3351 : : * %wpa_supplicant is terminated.
3352 : : */
3353 : 31 : int wpa_supplicant_remove_iface(struct wpa_global *global,
3354 : : struct wpa_supplicant *wpa_s,
3355 : : int terminate)
3356 : : {
3357 : : struct wpa_supplicant *prev;
3358 : :
3359 : : /* Remove interface from the global list of interfaces */
3360 : 31 : prev = global->ifaces;
3361 [ + - ]: 31 : if (prev == wpa_s) {
3362 : 31 : global->ifaces = wpa_s->next;
3363 : : } else {
3364 [ # # ][ # # ]: 0 : while (prev && prev->next != wpa_s)
3365 : 0 : prev = prev->next;
3366 [ # # ]: 0 : if (prev == NULL)
3367 : 0 : return -1;
3368 : 0 : prev->next = wpa_s->next;
3369 : : }
3370 : :
3371 : 31 : wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3372 : :
3373 [ - + ]: 31 : if (global->p2p_group_formation == wpa_s)
3374 : 0 : global->p2p_group_formation = NULL;
3375 [ + + ]: 31 : if (global->p2p_invite_group == wpa_s)
3376 : 1 : global->p2p_invite_group = NULL;
3377 : 31 : wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
3378 : :
3379 : 31 : return 0;
3380 : : }
3381 : :
3382 : :
3383 : : /**
3384 : : * wpa_supplicant_get_eap_mode - Get the current EAP mode
3385 : : * @wpa_s: Pointer to the network interface
3386 : : * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3387 : : */
3388 : 0 : const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3389 : : {
3390 : : const char *eapol_method;
3391 : :
3392 [ # # ][ # # ]: 0 : if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3393 : 0 : wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3394 : 0 : return "NO-EAP";
3395 : : }
3396 : :
3397 : 0 : eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3398 [ # # ]: 0 : if (eapol_method == NULL)
3399 : 0 : return "UNKNOWN-EAP";
3400 : :
3401 : 0 : return eapol_method;
3402 : : }
3403 : :
3404 : :
3405 : : /**
3406 : : * wpa_supplicant_get_iface - Get a new network interface
3407 : : * @global: Pointer to global data from wpa_supplicant_init()
3408 : : * @ifname: Interface name
3409 : : * Returns: Pointer to the interface or %NULL if not found
3410 : : */
3411 : 248 : struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3412 : : const char *ifname)
3413 : : {
3414 : : struct wpa_supplicant *wpa_s;
3415 : :
3416 [ + + ]: 248 : for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3417 [ + - ]: 7 : if (os_strcmp(wpa_s->ifname, ifname) == 0)
3418 : 7 : return wpa_s;
3419 : : }
3420 : 248 : return NULL;
3421 : : }
3422 : :
3423 : :
3424 : : #ifndef CONFIG_NO_WPA_MSG
3425 : 79355 : static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3426 : : {
3427 : 79355 : struct wpa_supplicant *wpa_s = ctx;
3428 [ - + ]: 79355 : if (wpa_s == NULL)
3429 : 0 : return NULL;
3430 : 79355 : return wpa_s->ifname;
3431 : : }
3432 : : #endif /* CONFIG_NO_WPA_MSG */
3433 : :
3434 : :
3435 : : /**
3436 : : * wpa_supplicant_init - Initialize %wpa_supplicant
3437 : : * @params: Parameters for %wpa_supplicant
3438 : : * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3439 : : *
3440 : : * This function is used to initialize %wpa_supplicant. After successful
3441 : : * initialization, the returned data pointer can be used to add and remove
3442 : : * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3443 : : */
3444 : 4 : struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3445 : : {
3446 : : struct wpa_global *global;
3447 : : int ret, i;
3448 : :
3449 [ - + ]: 4 : if (params == NULL)
3450 : 0 : return NULL;
3451 : :
3452 : : #ifdef CONFIG_DRIVER_NDIS
3453 : : {
3454 : : void driver_ndis_init_ops(void);
3455 : : driver_ndis_init_ops();
3456 : : }
3457 : : #endif /* CONFIG_DRIVER_NDIS */
3458 : :
3459 : : #ifndef CONFIG_NO_WPA_MSG
3460 : 4 : wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3461 : : #endif /* CONFIG_NO_WPA_MSG */
3462 : :
3463 : 4 : wpa_debug_open_file(params->wpa_debug_file_path);
3464 [ - + ]: 4 : if (params->wpa_debug_syslog)
3465 : 0 : wpa_debug_open_syslog();
3466 [ - + ]: 4 : if (params->wpa_debug_tracing) {
3467 : 0 : ret = wpa_debug_open_linux_tracing();
3468 [ # # ]: 0 : if (ret) {
3469 : 0 : wpa_printf(MSG_ERROR,
3470 : : "Failed to enable trace logging");
3471 : 0 : return NULL;
3472 : : }
3473 : : }
3474 : :
3475 : 4 : ret = eap_register_methods();
3476 [ - + ]: 4 : if (ret) {
3477 : 0 : wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3478 [ # # ]: 0 : if (ret == -2)
3479 : 0 : wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3480 : : "the same EAP type.");
3481 : 0 : return NULL;
3482 : : }
3483 : :
3484 : 4 : global = os_zalloc(sizeof(*global));
3485 [ - + ]: 4 : if (global == NULL)
3486 : 0 : return NULL;
3487 : 4 : dl_list_init(&global->p2p_srv_bonjour);
3488 : 4 : dl_list_init(&global->p2p_srv_upnp);
3489 : 4 : global->params.daemonize = params->daemonize;
3490 : 4 : global->params.wait_for_monitor = params->wait_for_monitor;
3491 : 4 : global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3492 [ - + ]: 4 : if (params->pid_file)
3493 : 0 : global->params.pid_file = os_strdup(params->pid_file);
3494 [ + - ]: 4 : if (params->ctrl_interface)
3495 : 4 : global->params.ctrl_interface =
3496 : 4 : os_strdup(params->ctrl_interface);
3497 [ + - ]: 4 : if (params->ctrl_interface_group)
3498 : 4 : global->params.ctrl_interface_group =
3499 : 4 : os_strdup(params->ctrl_interface_group);
3500 [ - + ]: 4 : if (params->override_driver)
3501 : 0 : global->params.override_driver =
3502 : 0 : os_strdup(params->override_driver);
3503 [ - + ]: 4 : if (params->override_ctrl_interface)
3504 : 0 : global->params.override_ctrl_interface =
3505 : 0 : os_strdup(params->override_ctrl_interface);
3506 : 4 : wpa_debug_level = global->params.wpa_debug_level =
3507 : 4 : params->wpa_debug_level;
3508 : 4 : wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3509 : 4 : params->wpa_debug_show_keys;
3510 : 4 : wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3511 : 4 : params->wpa_debug_timestamp;
3512 : :
3513 : 4 : wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3514 : :
3515 [ - + ]: 4 : if (eloop_init()) {
3516 : 0 : wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3517 : 0 : wpa_supplicant_deinit(global);
3518 : 0 : return NULL;
3519 : : }
3520 : :
3521 : : random_init(params->entropy_file);
3522 : :
3523 : 4 : global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3524 [ - + ]: 4 : if (global->ctrl_iface == NULL) {
3525 : 0 : wpa_supplicant_deinit(global);
3526 : 0 : return NULL;
3527 : : }
3528 : :
3529 [ - + ]: 4 : if (wpas_notify_supplicant_initialized(global)) {
3530 : 0 : wpa_supplicant_deinit(global);
3531 : 0 : return NULL;
3532 : : }
3533 : :
3534 [ + + ]: 24 : for (i = 0; wpa_drivers[i]; i++)
3535 : 20 : global->drv_count++;
3536 [ - + ]: 4 : if (global->drv_count == 0) {
3537 : 0 : wpa_printf(MSG_ERROR, "No drivers enabled");
3538 : 0 : wpa_supplicant_deinit(global);
3539 : 0 : return NULL;
3540 : : }
3541 : 4 : global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3542 [ - + ]: 4 : if (global->drv_priv == NULL) {
3543 : 0 : wpa_supplicant_deinit(global);
3544 : 0 : return NULL;
3545 : : }
3546 : :
3547 : : #ifdef CONFIG_WIFI_DISPLAY
3548 [ - + ]: 4 : if (wifi_display_init(global) < 0) {
3549 : 0 : wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3550 : 0 : wpa_supplicant_deinit(global);
3551 : 0 : return NULL;
3552 : : }
3553 : : #endif /* CONFIG_WIFI_DISPLAY */
3554 : :
3555 : 4 : return global;
3556 : : }
3557 : :
3558 : :
3559 : : /**
3560 : : * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3561 : : * @global: Pointer to global data from wpa_supplicant_init()
3562 : : * Returns: 0 after successful event loop run, -1 on failure
3563 : : *
3564 : : * This function starts the main event loop and continues running as long as
3565 : : * there are any remaining events. In most cases, this function is running as
3566 : : * long as the %wpa_supplicant process in still in use.
3567 : : */
3568 : 4 : int wpa_supplicant_run(struct wpa_global *global)
3569 : : {
3570 : : struct wpa_supplicant *wpa_s;
3571 : :
3572 [ - + # # ]: 4 : if (global->params.daemonize &&
3573 : 0 : wpa_supplicant_daemon(global->params.pid_file))
3574 : 0 : return -1;
3575 : :
3576 [ - + ]: 4 : if (global->params.wait_for_monitor) {
3577 [ # # ]: 0 : for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3578 [ # # ]: 0 : if (wpa_s->ctrl_iface)
3579 : 0 : wpa_supplicant_ctrl_iface_wait(
3580 : : wpa_s->ctrl_iface);
3581 : : }
3582 : :
3583 : 4 : eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3584 : 4 : eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3585 : :
3586 : 4 : eloop_run();
3587 : :
3588 : 4 : return 0;
3589 : : }
3590 : :
3591 : :
3592 : : /**
3593 : : * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3594 : : * @global: Pointer to global data from wpa_supplicant_init()
3595 : : *
3596 : : * This function is called to deinitialize %wpa_supplicant and to free all
3597 : : * allocated resources. Remaining network interfaces will also be removed.
3598 : : */
3599 : 4 : void wpa_supplicant_deinit(struct wpa_global *global)
3600 : : {
3601 : : int i;
3602 : :
3603 [ - + ]: 4 : if (global == NULL)
3604 : 4 : return;
3605 : :
3606 : : #ifdef CONFIG_WIFI_DISPLAY
3607 : 4 : wifi_display_deinit(global);
3608 : : #endif /* CONFIG_WIFI_DISPLAY */
3609 : :
3610 [ + + ]: 7 : while (global->ifaces)
3611 : 3 : wpa_supplicant_remove_iface(global, global->ifaces, 1);
3612 : :
3613 [ + - ]: 4 : if (global->ctrl_iface)
3614 : 4 : wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3615 : :
3616 : 4 : wpas_notify_supplicant_deinitialized(global);
3617 : :
3618 : 4 : eap_peer_unregister_methods();
3619 : : #ifdef CONFIG_AP
3620 : 4 : eap_server_unregister_methods();
3621 : : #endif /* CONFIG_AP */
3622 : :
3623 [ + + ][ + - ]: 24 : for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3624 [ + + ]: 20 : if (!global->drv_priv[i])
3625 : 16 : continue;
3626 : 4 : wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3627 : : }
3628 : 4 : os_free(global->drv_priv);
3629 : :
3630 : : random_deinit();
3631 : :
3632 : 4 : eloop_destroy();
3633 : :
3634 [ - + ]: 4 : if (global->params.pid_file) {
3635 : 0 : os_daemonize_terminate(global->params.pid_file);
3636 : 0 : os_free(global->params.pid_file);
3637 : : }
3638 : 4 : os_free(global->params.ctrl_interface);
3639 : 4 : os_free(global->params.ctrl_interface_group);
3640 : 4 : os_free(global->params.override_driver);
3641 : 4 : os_free(global->params.override_ctrl_interface);
3642 : :
3643 : 4 : os_free(global->p2p_disallow_freq.range);
3644 : 4 : os_free(global->add_psk);
3645 : :
3646 : 4 : os_free(global);
3647 : 4 : wpa_debug_close_syslog();
3648 : 4 : wpa_debug_close_file();
3649 : 4 : wpa_debug_close_linux_tracing();
3650 : : }
3651 : :
3652 : :
3653 : 5983 : void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3654 : : {
3655 [ - + ][ # # ]: 5983 : if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3656 [ # # ]: 0 : wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3657 : : char country[3];
3658 : 0 : country[0] = wpa_s->conf->country[0];
3659 : 0 : country[1] = wpa_s->conf->country[1];
3660 : 0 : country[2] = '\0';
3661 [ # # ]: 0 : if (wpa_drv_set_country(wpa_s, country) < 0) {
3662 : 0 : wpa_printf(MSG_ERROR, "Failed to set country code "
3663 : : "'%s'", country);
3664 : : }
3665 : : }
3666 : :
3667 [ - + ]: 5983 : if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3668 : 0 : wpas_init_ext_pw(wpa_s);
3669 : :
3670 : : #ifdef CONFIG_WPS
3671 : 5983 : wpas_wps_update_config(wpa_s);
3672 : : #endif /* CONFIG_WPS */
3673 : :
3674 : : #ifdef CONFIG_P2P
3675 : 5983 : wpas_p2p_update_config(wpa_s);
3676 : : #endif /* CONFIG_P2P */
3677 : :
3678 : 5983 : wpa_s->conf->changed_parameters = 0;
3679 : 5983 : }
3680 : :
3681 : :
3682 : 17 : static void add_freq(int *freqs, int *num_freqs, int freq)
3683 : : {
3684 : : int i;
3685 : :
3686 [ - + ]: 17 : for (i = 0; i < *num_freqs; i++) {
3687 [ # # ]: 0 : if (freqs[i] == freq)
3688 : 17 : return;
3689 : : }
3690 : :
3691 : 17 : freqs[*num_freqs] = freq;
3692 : 17 : (*num_freqs)++;
3693 : : }
3694 : :
3695 : :
3696 : 411 : static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3697 : : {
3698 : : struct wpa_bss *bss, *cbss;
3699 : 411 : const int max_freqs = 10;
3700 : : int *freqs;
3701 : 411 : int num_freqs = 0;
3702 : :
3703 : 411 : freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3704 [ - + ]: 411 : if (freqs == NULL)
3705 : 0 : return NULL;
3706 : :
3707 : 411 : cbss = wpa_s->current_bss;
3708 : :
3709 [ + + ]: 1612 : dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3710 [ + + ]: 1201 : if (bss == cbss)
3711 : 411 : continue;
3712 [ + + ][ + + ]: 790 : if (bss->ssid_len == cbss->ssid_len &&
3713 [ + - ]: 17 : os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3714 : 17 : wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3715 : 17 : add_freq(freqs, &num_freqs, bss->freq);
3716 [ - + ]: 17 : if (num_freqs == max_freqs)
3717 : 0 : break;
3718 : : }
3719 : : }
3720 : :
3721 [ + + ]: 411 : if (num_freqs == 0) {
3722 : 394 : os_free(freqs);
3723 : 394 : freqs = NULL;
3724 : : }
3725 : :
3726 : 411 : return freqs;
3727 : : }
3728 : :
3729 : :
3730 : 489 : void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
3731 : : {
3732 : : int timeout;
3733 : : int count;
3734 : 489 : int *freqs = NULL;
3735 : :
3736 : : /*
3737 : : * Remove possible authentication timeout since the connection failed.
3738 : : */
3739 : 489 : eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3740 : :
3741 [ + + ]: 489 : if (wpa_s->disconnected) {
3742 : : /*
3743 : : * There is no point in blacklisting the AP if this event is
3744 : : * generated based on local request to disconnect.
3745 : : */
3746 : 74 : wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
3747 : : "indication since interface has been put into "
3748 : : "disconnected state");
3749 : 489 : return;
3750 : : }
3751 : :
3752 : : /*
3753 : : * Add the failed BSSID into the blacklist and speed up next scan
3754 : : * attempt if there could be other APs that could accept association.
3755 : : * The current blacklist count indicates how many times we have tried
3756 : : * connecting to this AP and multiple attempts mean that other APs are
3757 : : * either not available or has already been tried, so that we can start
3758 : : * increasing the delay here to avoid constant scanning.
3759 : : */
3760 : 415 : count = wpa_blacklist_add(wpa_s, bssid);
3761 [ + + ][ + - ]: 415 : if (count == 1 && wpa_s->current_bss) {
3762 : : /*
3763 : : * This BSS was not in the blacklist before. If there is
3764 : : * another BSS available for the same ESS, we should try that
3765 : : * next. Otherwise, we may as well try this one once more
3766 : : * before allowing other, likely worse, ESSes to be considered.
3767 : : */
3768 : 411 : freqs = get_bss_freqs_in_ess(wpa_s);
3769 [ + + ]: 411 : if (freqs) {
3770 : 17 : wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
3771 : : "has been seen; try it next");
3772 : 17 : wpa_blacklist_add(wpa_s, bssid);
3773 : : /*
3774 : : * On the next scan, go through only the known channels
3775 : : * used in this ESS based on previous scans to speed up
3776 : : * common load balancing use case.
3777 : : */
3778 : 17 : os_free(wpa_s->next_scan_freqs);
3779 : 17 : wpa_s->next_scan_freqs = freqs;
3780 : : }
3781 : : }
3782 : :
3783 : : /*
3784 : : * Add previous failure count in case the temporary blacklist was
3785 : : * cleared due to no other BSSes being available.
3786 : : */
3787 : 415 : count += wpa_s->extra_blacklist_count;
3788 : :
3789 [ + + ][ + - ]: 415 : if (count > 3 && wpa_s->current_ssid) {
3790 : 2 : wpa_printf(MSG_DEBUG, "Continuous association failures - "
3791 : : "consider temporary network disabling");
3792 : 2 : wpas_auth_failed(wpa_s);
3793 : : }
3794 : :
3795 [ + + + + : 415 : switch (count) {
+ ]
3796 : : case 1:
3797 : 331 : timeout = 100;
3798 : 331 : break;
3799 : : case 2:
3800 : 80 : timeout = 500;
3801 : 80 : break;
3802 : : case 3:
3803 : 2 : timeout = 1000;
3804 : 2 : break;
3805 : : case 4:
3806 : 1 : timeout = 5000;
3807 : 1 : break;
3808 : : default:
3809 : 1 : timeout = 10000;
3810 : 1 : break;
3811 : : }
3812 : :
3813 : 415 : wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
3814 : : "ms", count, timeout);
3815 : :
3816 : : /*
3817 : : * TODO: if more than one possible AP is available in scan results,
3818 : : * could try the other ones before requesting a new scan.
3819 : : */
3820 : 415 : wpa_supplicant_req_scan(wpa_s, timeout / 1000,
3821 : 415 : 1000 * (timeout % 1000));
3822 : :
3823 : 415 : wpas_p2p_continue_after_scan(wpa_s);
3824 : : }
3825 : :
3826 : :
3827 : 421 : int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
3828 : : {
3829 [ + - ][ - + ]: 421 : return wpa_s->conf->ap_scan == 2 ||
3830 : 421 : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
3831 : : }
3832 : :
3833 : :
3834 : : #if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
3835 : 2 : int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
3836 : : struct wpa_ssid *ssid,
3837 : : const char *field,
3838 : : const char *value)
3839 : : {
3840 : : #ifdef IEEE8021X_EAPOL
3841 : 2 : struct eap_peer_config *eap = &ssid->eap;
3842 : :
3843 : 2 : wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
3844 : 2 : wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
3845 : : (const u8 *) value, os_strlen(value));
3846 : :
3847 [ - - - - : 2 : switch (wpa_supplicant_ctrl_req_from_string(field)) {
- - + - ]
3848 : : case WPA_CTRL_REQ_EAP_IDENTITY:
3849 : 0 : os_free(eap->identity);
3850 : 0 : eap->identity = (u8 *) os_strdup(value);
3851 : 0 : eap->identity_len = os_strlen(value);
3852 : 0 : eap->pending_req_identity = 0;
3853 [ # # ]: 0 : if (ssid == wpa_s->current_ssid)
3854 : 0 : wpa_s->reassociate = 1;
3855 : 0 : break;
3856 : : case WPA_CTRL_REQ_EAP_PASSWORD:
3857 : 0 : os_free(eap->password);
3858 : 0 : eap->password = (u8 *) os_strdup(value);
3859 : 0 : eap->password_len = os_strlen(value);
3860 : 0 : eap->pending_req_password = 0;
3861 [ # # ]: 0 : if (ssid == wpa_s->current_ssid)
3862 : 0 : wpa_s->reassociate = 1;
3863 : 0 : break;
3864 : : case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
3865 : 0 : os_free(eap->new_password);
3866 : 0 : eap->new_password = (u8 *) os_strdup(value);
3867 : 0 : eap->new_password_len = os_strlen(value);
3868 : 0 : eap->pending_req_new_password = 0;
3869 [ # # ]: 0 : if (ssid == wpa_s->current_ssid)
3870 : 0 : wpa_s->reassociate = 1;
3871 : 0 : break;
3872 : : case WPA_CTRL_REQ_EAP_PIN:
3873 : 0 : os_free(eap->pin);
3874 : 0 : eap->pin = os_strdup(value);
3875 : 0 : eap->pending_req_pin = 0;
3876 [ # # ]: 0 : if (ssid == wpa_s->current_ssid)
3877 : 0 : wpa_s->reassociate = 1;
3878 : 0 : break;
3879 : : case WPA_CTRL_REQ_EAP_OTP:
3880 : 0 : os_free(eap->otp);
3881 : 0 : eap->otp = (u8 *) os_strdup(value);
3882 : 0 : eap->otp_len = os_strlen(value);
3883 : 0 : os_free(eap->pending_req_otp);
3884 : 0 : eap->pending_req_otp = NULL;
3885 : 0 : eap->pending_req_otp_len = 0;
3886 : 0 : break;
3887 : : case WPA_CTRL_REQ_EAP_PASSPHRASE:
3888 : 0 : os_free(eap->private_key_passwd);
3889 : 0 : eap->private_key_passwd = (u8 *) os_strdup(value);
3890 : 0 : eap->pending_req_passphrase = 0;
3891 [ # # ]: 0 : if (ssid == wpa_s->current_ssid)
3892 : 0 : wpa_s->reassociate = 1;
3893 : 0 : break;
3894 : : case WPA_CTRL_REQ_SIM:
3895 : 2 : os_free(eap->external_sim_resp);
3896 : 2 : eap->external_sim_resp = os_strdup(value);
3897 : 2 : break;
3898 : : default:
3899 : 0 : wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
3900 : 0 : return -1;
3901 : : }
3902 : :
3903 : 2 : return 0;
3904 : : #else /* IEEE8021X_EAPOL */
3905 : : wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
3906 : : return -1;
3907 : : #endif /* IEEE8021X_EAPOL */
3908 : : }
3909 : : #endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
3910 : :
3911 : :
3912 : 3452 : int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
3913 : : {
3914 : : int i;
3915 : : unsigned int drv_enc;
3916 : :
3917 [ - + ]: 3452 : if (ssid == NULL)
3918 : 0 : return 1;
3919 : :
3920 [ + + ]: 3452 : if (ssid->disabled)
3921 : 229 : return 1;
3922 : :
3923 [ + - ][ + - ]: 3223 : if (wpa_s && wpa_s->drv_capa_known)
3924 : 3223 : drv_enc = wpa_s->drv_enc;
3925 : : else
3926 : 0 : drv_enc = (unsigned int) -1;
3927 : :
3928 [ + + ]: 16115 : for (i = 0; i < NUM_WEP_KEYS; i++) {
3929 : 12892 : size_t len = ssid->wep_key_len[i];
3930 [ + + ]: 12892 : if (len == 0)
3931 : 12883 : continue;
3932 [ + - ][ + - ]: 9 : if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
3933 : 9 : continue;
3934 [ # # ][ # # ]: 0 : if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
3935 : 0 : continue;
3936 [ # # ][ # # ]: 0 : if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
3937 : 0 : continue;
3938 : 0 : return 1; /* invalid WEP key */
3939 : : }
3940 : :
3941 [ + + ][ - + ]: 3223 : if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
[ # # ]
3942 : 0 : !ssid->ext_psk)
3943 : 0 : return 1;
3944 : :
3945 : 3452 : return 0;
3946 : : }
3947 : :
3948 : :
3949 : 5 : int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
3950 : : {
3951 [ - + ]: 5 : if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
3952 : 0 : return 1;
3953 [ - + ]: 5 : if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
3954 : 0 : return 0;
3955 : 5 : return -1;
3956 : : }
3957 : :
3958 : :
3959 : 12 : void wpas_auth_failed(struct wpa_supplicant *wpa_s)
3960 : : {
3961 : 12 : struct wpa_ssid *ssid = wpa_s->current_ssid;
3962 : : int dur;
3963 : : struct os_reltime now;
3964 : :
3965 [ - + ]: 12 : if (ssid == NULL) {
3966 : 0 : wpa_printf(MSG_DEBUG, "Authentication failure but no known "
3967 : : "SSID block");
3968 : 0 : return;
3969 : : }
3970 : :
3971 [ + + ]: 12 : if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
3972 : 2 : return;
3973 : :
3974 : 10 : ssid->auth_failures++;
3975 : :
3976 : : #ifdef CONFIG_P2P
3977 [ + + ][ + - ]: 10 : if (ssid->p2p_group &&
3978 [ + - ]: 5 : (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
3979 : : /*
3980 : : * Skip the wait time since there is a short timeout on the
3981 : : * connection to a P2P group.
3982 : : */
3983 : 5 : return;
3984 : : }
3985 : : #endif /* CONFIG_P2P */
3986 : :
3987 [ - + ]: 5 : if (ssid->auth_failures > 50)
3988 : 0 : dur = 300;
3989 [ - + ]: 5 : else if (ssid->auth_failures > 20)
3990 : 0 : dur = 120;
3991 [ - + ]: 5 : else if (ssid->auth_failures > 10)
3992 : 0 : dur = 60;
3993 [ - + ]: 5 : else if (ssid->auth_failures > 5)
3994 : 0 : dur = 30;
3995 [ - + ]: 5 : else if (ssid->auth_failures > 1)
3996 : 0 : dur = 20;
3997 : : else
3998 : 5 : dur = 10;
3999 : :
4000 : 5 : os_get_reltime(&now);
4001 [ - + ]: 5 : if (now.sec + dur <= ssid->disabled_until.sec)
4002 : 0 : return;
4003 : :
4004 : 5 : ssid->disabled_until.sec = now.sec + dur;
4005 : :
4006 : 12 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4007 : : "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4008 : 5 : ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4009 : : ssid->auth_failures, dur);
4010 : : }
4011 : :
4012 : :
4013 : 951 : void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4014 : : struct wpa_ssid *ssid, int clear_failures)
4015 : : {
4016 [ - + ]: 951 : if (ssid == NULL)
4017 : 951 : return;
4018 : :
4019 [ + + ]: 951 : if (ssid->disabled_until.sec) {
4020 : 1 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4021 : : "id=%d ssid=\"%s\"",
4022 : 1 : ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4023 : : }
4024 : 951 : ssid->disabled_until.sec = 0;
4025 : 951 : ssid->disabled_until.usec = 0;
4026 [ + + ]: 951 : if (clear_failures)
4027 : 723 : ssid->auth_failures = 0;
4028 : : }
4029 : :
4030 : :
4031 : 1560 : int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4032 : : {
4033 : : size_t i;
4034 : :
4035 [ + + ]: 1560 : if (wpa_s->disallow_aps_bssid == NULL)
4036 : 1557 : return 0;
4037 : :
4038 [ + - ]: 3 : for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4039 [ + - ]: 3 : if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4040 : : bssid, ETH_ALEN) == 0)
4041 : 3 : return 1;
4042 : : }
4043 : :
4044 : 1560 : return 0;
4045 : : }
4046 : :
4047 : :
4048 : 1557 : int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4049 : : size_t ssid_len)
4050 : : {
4051 : : size_t i;
4052 : :
4053 [ + + ][ - + ]: 1557 : if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4054 : 1555 : return 0;
4055 : :
4056 [ + - ]: 2 : for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4057 : 2 : struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4058 [ + - ][ + - ]: 2 : if (ssid_len == s->ssid_len &&
4059 : 2 : os_memcmp(ssid, s->ssid, ssid_len) == 0)
4060 : 2 : return 1;
4061 : : }
4062 : :
4063 : 1557 : return 0;
4064 : : }
4065 : :
4066 : :
4067 : : /**
4068 : : * wpas_request_connection - Request a new connection
4069 : : * @wpa_s: Pointer to the network interface
4070 : : *
4071 : : * This function is used to request a new connection to be found. It will mark
4072 : : * the interface to allow reassociation and request a new scan to find a
4073 : : * suitable network to connect to.
4074 : : */
4075 : 2 : void wpas_request_connection(struct wpa_supplicant *wpa_s)
4076 : : {
4077 : 2 : wpa_s->normal_scans = 0;
4078 : 2 : wpa_supplicant_reinit_autoscan(wpa_s);
4079 : 2 : wpa_s->extra_blacklist_count = 0;
4080 : 2 : wpa_s->disconnected = 0;
4081 : 2 : wpa_s->reassociate = 1;
4082 : :
4083 [ + + ]: 2 : if (wpa_supplicant_fast_associate(wpa_s) != 1)
4084 : 1 : wpa_supplicant_req_scan(wpa_s, 0, 0);
4085 : 2 : }
4086 : :
4087 : :
4088 : 91 : static int wpas_conn_in_progress(struct wpa_supplicant *wpa_s)
4089 : : {
4090 [ + + ][ + + ]: 91 : return wpa_s->wpa_state >= WPA_AUTHENTICATING &&
4091 : 10 : wpa_s->wpa_state != WPA_COMPLETED;
4092 : : }
4093 : :
4094 : :
4095 : : /**
4096 : : * wpas_wpa_is_in_progress - Check whether a connection is in progress
4097 : : * @wpa_s: Pointer to wpa_supplicant data
4098 : : * @include_current: Whether to consider specified interface
4099 : : *
4100 : : * This function is to check if the wpa state is in beginning of the connection
4101 : : * during 4-way handshake or group key handshake with WPA on any shared
4102 : : * interface.
4103 : : */
4104 : 585 : int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s, int include_current)
4105 : : {
4106 : : struct wpa_supplicant *ifs;
4107 : :
4108 [ + + ]: 1192 : dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4109 : : radio_list) {
4110 [ + + ][ + + ]: 608 : if (!include_current && ifs == wpa_s)
4111 : 517 : continue;
4112 : :
4113 [ + + ]: 91 : if (wpas_conn_in_progress(ifs)) {
4114 : 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Connection is in progress "
4115 : : "on interface %s - defer", ifs->ifname);
4116 : 1 : return 1;
4117 : : }
4118 : : }
4119 : :
4120 : 585 : return 0;
4121 : : }
4122 : :
4123 : :
4124 : 199 : void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4125 : : int *freq_array, unsigned int len)
4126 : : {
4127 : : unsigned int i;
4128 : :
4129 : 199 : wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4130 : : len, title);
4131 [ + + ]: 211 : for (i = 0; i < len; i++)
4132 : 12 : wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4133 : 199 : }
4134 : :
4135 : :
4136 : : /*
4137 : : * Find the operating frequencies of any of the virtual interfaces that
4138 : : * are using the same radio as the current interface.
4139 : : */
4140 : 167 : int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4141 : : int *freq_array, unsigned int len)
4142 : : {
4143 : : struct wpa_supplicant *ifs;
4144 : : u8 bssid[ETH_ALEN];
4145 : : int freq;
4146 : 167 : unsigned int idx = 0, i;
4147 : :
4148 : 167 : wpa_dbg(wpa_s, MSG_DEBUG,
4149 : : "Determining shared radio frequencies (max len %u)", len);
4150 : 167 : os_memset(freq_array, 0, sizeof(int) * len);
4151 : :
4152 : : /* First add the frequency of the local interface */
4153 [ + + ][ + + ]: 167 : if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4154 [ + - ][ + + ]: 10 : if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4155 : 10 : wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4156 : 4 : freq_array[idx++] = wpa_s->current_ssid->frequency;
4157 [ + - ]: 6 : else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4158 : 6 : freq_array[idx++] = wpa_s->assoc_freq;
4159 : : }
4160 : :
4161 : : /* If get_radio_name is not supported, use only the local freq */
4162 [ - + ]: 167 : if (!wpa_s->driver->get_radio_name) {
4163 : 0 : freq = wpa_drv_shared_freq(wpa_s);
4164 [ # # ][ # # ]: 0 : if (freq > 0 && idx < len &&
[ # # ]
4165 [ # # ]: 0 : (idx == 0 || freq_array[0] != freq))
4166 : 0 : freq_array[idx++] = freq;
4167 : 0 : dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
4168 : 0 : return idx;
4169 : : }
4170 : :
4171 [ + + ]: 334 : dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4172 : : radio_list) {
4173 [ + - ]: 167 : if (wpa_s == ifs)
4174 : 167 : continue;
4175 : :
4176 [ # # ][ # # ]: 0 : if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4177 : 0 : continue;
4178 : :
4179 [ # # ][ # # ]: 0 : if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4180 : 0 : ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4181 : 0 : freq = ifs->current_ssid->frequency;
4182 [ # # ]: 0 : else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4183 : 0 : freq = ifs->assoc_freq;
4184 : : else
4185 : 0 : continue;
4186 : :
4187 : : /* Hold only distinct freqs */
4188 [ # # ]: 0 : for (i = 0; i < idx; i++)
4189 [ # # ]: 0 : if (freq_array[i] == freq)
4190 : 0 : break;
4191 : :
4192 [ # # ]: 0 : if (i == idx)
4193 : 0 : freq_array[idx++] = freq;
4194 : : }
4195 : :
4196 : 167 : dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
4197 : 167 : return idx;
4198 : : }
|