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