Line data Source code
1 : /*
2 : * WPA Supplicant - Scanning
3 : * Copyright (c) 2003-2014, 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 :
9 : #include "utils/includes.h"
10 :
11 : #include "utils/common.h"
12 : #include "utils/eloop.h"
13 : #include "common/ieee802_11_defs.h"
14 : #include "common/wpa_ctrl.h"
15 : #include "config.h"
16 : #include "wpa_supplicant_i.h"
17 : #include "driver_i.h"
18 : #include "wps_supplicant.h"
19 : #include "p2p_supplicant.h"
20 : #include "p2p/p2p.h"
21 : #include "hs20_supplicant.h"
22 : #include "notify.h"
23 : #include "bss.h"
24 : #include "scan.h"
25 : #include "mesh.h"
26 :
27 :
28 2 : static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
29 : {
30 : struct wpa_ssid *ssid;
31 : union wpa_event_data data;
32 :
33 2 : ssid = wpa_supplicant_get_ssid(wpa_s);
34 2 : if (ssid == NULL)
35 3 : return;
36 :
37 1 : if (wpa_s->current_ssid == NULL) {
38 0 : wpa_s->current_ssid = ssid;
39 0 : if (wpa_s->current_ssid != NULL)
40 0 : wpas_notify_network_changed(wpa_s);
41 : }
42 1 : wpa_supplicant_initiate_eapol(wpa_s);
43 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
44 : "network - generating associated event");
45 1 : os_memset(&data, 0, sizeof(data));
46 1 : wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
47 : }
48 :
49 :
50 : #ifdef CONFIG_WPS
51 1953 : static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
52 : enum wps_request_type *req_type)
53 : {
54 : struct wpa_ssid *ssid;
55 1953 : int wps = 0;
56 :
57 3436 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
58 1579 : if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
59 1199 : continue;
60 :
61 380 : wps = 1;
62 380 : *req_type = wpas_wps_get_req_type(ssid);
63 380 : if (!ssid->eap.phase1)
64 0 : continue;
65 :
66 380 : if (os_strstr(ssid->eap.phase1, "pbc=1"))
67 96 : return 2;
68 : }
69 :
70 : #ifdef CONFIG_P2P
71 3692 : if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p &&
72 1835 : !wpa_s->conf->p2p_disabled) {
73 1835 : wpa_s->wps->dev.p2p = 1;
74 1835 : if (!wps) {
75 1553 : wps = 1;
76 1553 : *req_type = WPS_REQ_ENROLLEE_INFO;
77 : }
78 : }
79 : #endif /* CONFIG_P2P */
80 :
81 1857 : return wps;
82 : }
83 : #endif /* CONFIG_WPS */
84 :
85 :
86 : /**
87 : * wpa_supplicant_enabled_networks - Check whether there are enabled networks
88 : * @wpa_s: Pointer to wpa_supplicant data
89 : * Returns: 0 if no networks are enabled, >0 if networks are enabled
90 : *
91 : * This function is used to figure out whether any networks (or Interworking
92 : * with enabled credentials and auto_interworking) are present in the current
93 : * configuration.
94 : */
95 4463 : int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
96 : {
97 4463 : struct wpa_ssid *ssid = wpa_s->conf->ssid;
98 4463 : int count = 0, disabled = 0;
99 12206 : while (ssid) {
100 3280 : if (!wpas_network_disabled(wpa_s, ssid))
101 3052 : count++;
102 : else
103 228 : disabled++;
104 3280 : ssid = ssid->next;
105 : }
106 4738 : if (wpa_s->conf->cred && wpa_s->conf->interworking &&
107 275 : wpa_s->conf->auto_interworking)
108 30 : count++;
109 4463 : if (count == 0 && disabled > 0) {
110 25 : wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled "
111 : "networks)", disabled);
112 : }
113 4463 : return count;
114 : }
115 :
116 :
117 14 : static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
118 : struct wpa_ssid *ssid)
119 : {
120 31 : while (ssid) {
121 15 : if (!wpas_network_disabled(wpa_s, ssid))
122 12 : break;
123 3 : ssid = ssid->next;
124 : }
125 :
126 : /* ap_scan=2 mode - try to associate with each SSID. */
127 14 : if (ssid == NULL) {
128 2 : wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached "
129 : "end of scan list - go back to beginning");
130 2 : wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
131 2 : wpa_supplicant_req_scan(wpa_s, 0, 0);
132 16 : return;
133 : }
134 12 : if (ssid->next) {
135 : /* Continue from the next SSID on the next attempt. */
136 3 : wpa_s->prev_scan_ssid = ssid;
137 : } else {
138 : /* Start from the beginning of the SSID list. */
139 9 : wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
140 : }
141 12 : wpa_supplicant_associate(wpa_s, NULL, ssid);
142 : }
143 :
144 :
145 1987 : static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
146 : {
147 1987 : struct wpa_supplicant *wpa_s = work->wpa_s;
148 1987 : struct wpa_driver_scan_params *params = work->ctx;
149 : int ret;
150 :
151 1987 : if (deinit) {
152 25 : if (!work->started) {
153 3 : wpa_scan_free_params(params);
154 3 : return;
155 : }
156 22 : wpa_supplicant_notify_scanning(wpa_s, 0);
157 22 : wpas_notify_scan_done(wpa_s, 0);
158 22 : wpa_s->scan_work = NULL;
159 22 : return;
160 : }
161 :
162 1962 : if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
163 0 : wpa_msg(wpa_s, MSG_INFO,
164 : "Failed to assign random MAC address for a scan");
165 0 : radio_work_done(work);
166 0 : return;
167 : }
168 :
169 1962 : wpa_supplicant_notify_scanning(wpa_s, 1);
170 :
171 1962 : if (wpa_s->clear_driver_scan_cache) {
172 1176 : wpa_printf(MSG_DEBUG,
173 : "Request driver to clear scan cache due to local BSS flush");
174 1176 : params->only_new_results = 1;
175 : }
176 1962 : ret = wpa_drv_scan(wpa_s, params);
177 1962 : wpa_scan_free_params(params);
178 1962 : work->ctx = NULL;
179 1962 : if (ret) {
180 3 : int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ;
181 :
182 3 : if (wpa_s->disconnected)
183 0 : retry = 0;
184 :
185 3 : wpa_supplicant_notify_scanning(wpa_s, 0);
186 3 : wpas_notify_scan_done(wpa_s, 0);
187 3 : if (wpa_s->wpa_state == WPA_SCANNING)
188 2 : wpa_supplicant_set_state(wpa_s,
189 : wpa_s->scan_prev_wpa_state);
190 3 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=%d%s",
191 : ret, retry ? " retry=1" : "");
192 3 : radio_work_done(work);
193 :
194 3 : if (retry) {
195 : /* Restore scan_req since we will try to scan again */
196 1 : wpa_s->scan_req = wpa_s->last_scan_req;
197 1 : wpa_supplicant_req_scan(wpa_s, 1, 0);
198 : }
199 3 : return;
200 : }
201 :
202 1959 : os_get_reltime(&wpa_s->scan_trigger_time);
203 1959 : wpa_s->scan_runs++;
204 1959 : wpa_s->normal_scans++;
205 1959 : wpa_s->own_scan_requested = 1;
206 1959 : wpa_s->clear_driver_scan_cache = 0;
207 1959 : wpa_s->scan_work = work;
208 : }
209 :
210 :
211 : /**
212 : * wpa_supplicant_trigger_scan - Request driver to start a scan
213 : * @wpa_s: Pointer to wpa_supplicant data
214 : * @params: Scan parameters
215 : * Returns: 0 on success, -1 on failure
216 : */
217 1968 : int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
218 : struct wpa_driver_scan_params *params)
219 : {
220 : struct wpa_driver_scan_params *ctx;
221 :
222 1968 : if (wpa_s->scan_work) {
223 1 : wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending");
224 1 : return -1;
225 : }
226 :
227 1967 : ctx = wpa_scan_clone_params(params);
228 1967 : if (ctx == NULL)
229 2 : return -1;
230 :
231 1965 : if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
232 : {
233 0 : wpa_scan_free_params(ctx);
234 0 : return -1;
235 : }
236 :
237 1965 : return 0;
238 : }
239 :
240 :
241 : static void
242 0 : wpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
243 : {
244 0 : struct wpa_supplicant *wpa_s = eloop_ctx;
245 :
246 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan");
247 :
248 0 : if (wpa_supplicant_req_sched_scan(wpa_s))
249 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
250 0 : }
251 :
252 :
253 : static void
254 0 : wpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
255 : {
256 0 : struct wpa_supplicant *wpa_s = eloop_ctx;
257 :
258 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it");
259 :
260 0 : wpa_s->sched_scan_timed_out = 1;
261 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
262 0 : }
263 :
264 :
265 0 : int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
266 : struct wpa_driver_scan_params *params,
267 : int interval)
268 : {
269 : int ret;
270 :
271 0 : wpa_supplicant_notify_scanning(wpa_s, 1);
272 0 : ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
273 0 : if (ret)
274 0 : wpa_supplicant_notify_scanning(wpa_s, 0);
275 : else
276 0 : wpa_s->sched_scanning = 1;
277 :
278 0 : return ret;
279 : }
280 :
281 :
282 0 : int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
283 : {
284 : int ret;
285 :
286 0 : ret = wpa_drv_stop_sched_scan(wpa_s);
287 0 : if (ret) {
288 0 : wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!");
289 : /* TODO: what to do if stopping fails? */
290 0 : return -1;
291 : }
292 :
293 0 : return ret;
294 : }
295 :
296 :
297 : static struct wpa_driver_scan_filter *
298 1953 : wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
299 : {
300 : struct wpa_driver_scan_filter *ssids;
301 : struct wpa_ssid *ssid;
302 : size_t count;
303 :
304 1953 : *num_ssids = 0;
305 1953 : if (!conf->filter_ssids)
306 1950 : return NULL;
307 :
308 7 : for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
309 4 : if (ssid->ssid && ssid->ssid_len)
310 2 : count++;
311 : }
312 3 : if (count == 0)
313 1 : return NULL;
314 2 : ssids = os_calloc(count, sizeof(struct wpa_driver_scan_filter));
315 2 : if (ssids == NULL)
316 0 : return NULL;
317 :
318 5 : for (ssid = conf->ssid; ssid; ssid = ssid->next) {
319 3 : if (!ssid->ssid || !ssid->ssid_len)
320 1 : continue;
321 2 : os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
322 2 : ssids[*num_ssids].ssid_len = ssid->ssid_len;
323 2 : (*num_ssids)++;
324 : }
325 :
326 2 : return ssids;
327 : }
328 :
329 :
330 1953 : static void wpa_supplicant_optimize_freqs(
331 : struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params)
332 : {
333 : #ifdef CONFIG_P2P
334 2174 : if (params->freqs == NULL && wpa_s->p2p_in_provisioning &&
335 221 : wpa_s->go_params) {
336 : /* Optimize provisioning state scan based on GO information */
337 439 : if (wpa_s->p2p_in_provisioning < 5 &&
338 218 : wpa_s->go_params->freq > 0) {
339 218 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO "
340 : "preferred frequency %d MHz",
341 : wpa_s->go_params->freq);
342 218 : params->freqs = os_calloc(2, sizeof(int));
343 436 : if (params->freqs)
344 218 : params->freqs[0] = wpa_s->go_params->freq;
345 6 : } else if (wpa_s->p2p_in_provisioning < 8 &&
346 3 : wpa_s->go_params->freq_list[0]) {
347 0 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common "
348 : "channels");
349 0 : int_array_concat(¶ms->freqs,
350 0 : wpa_s->go_params->freq_list);
351 0 : if (params->freqs)
352 0 : int_array_sort_unique(params->freqs);
353 : }
354 221 : wpa_s->p2p_in_provisioning++;
355 : }
356 :
357 1953 : if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
358 : /*
359 : * Optimize scan based on GO information during persistent
360 : * group reinvocation
361 : */
362 34 : if (wpa_s->p2p_in_invitation < 5 &&
363 17 : wpa_s->p2p_invite_go_freq > 0) {
364 14 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
365 : wpa_s->p2p_invite_go_freq);
366 14 : params->freqs = os_calloc(2, sizeof(int));
367 14 : if (params->freqs)
368 14 : params->freqs[0] = wpa_s->p2p_invite_go_freq;
369 : }
370 17 : wpa_s->p2p_in_invitation++;
371 17 : if (wpa_s->p2p_in_invitation > 20) {
372 : /*
373 : * This should not really happen since the variable is
374 : * cleared on group removal, but if it does happen, make
375 : * sure we do not get stuck in special invitation scan
376 : * mode.
377 : */
378 0 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
379 0 : wpa_s->p2p_in_invitation = 0;
380 : }
381 : }
382 : #endif /* CONFIG_P2P */
383 :
384 : #ifdef CONFIG_WPS
385 1953 : if (params->freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
386 : /*
387 : * Optimize post-provisioning scan based on channel used
388 : * during provisioning.
389 : */
390 34 : wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz "
391 : "that was used during provisioning", wpa_s->wps_freq);
392 34 : params->freqs = os_calloc(2, sizeof(int));
393 34 : if (params->freqs)
394 34 : params->freqs[0] = wpa_s->wps_freq;
395 34 : wpa_s->after_wps--;
396 1919 : } else if (wpa_s->after_wps)
397 1 : wpa_s->after_wps--;
398 :
399 1953 : if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
400 : {
401 : /* Optimize provisioning scan based on already known channel */
402 81 : wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz",
403 : wpa_s->wps_freq);
404 81 : params->freqs = os_calloc(2, sizeof(int));
405 81 : if (params->freqs)
406 81 : params->freqs[0] = wpa_s->wps_freq;
407 81 : wpa_s->known_wps_freq = 0; /* only do this once */
408 : }
409 : #endif /* CONFIG_WPS */
410 1953 : }
411 :
412 :
413 : #ifdef CONFIG_INTERWORKING
414 633 : static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
415 : struct wpabuf *buf)
416 : {
417 633 : if (wpa_s->conf->interworking == 0)
418 633 : return;
419 :
420 633 : wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB);
421 633 : wpabuf_put_u8(buf, 6);
422 633 : wpabuf_put_u8(buf, 0x00);
423 633 : wpabuf_put_u8(buf, 0x00);
424 633 : wpabuf_put_u8(buf, 0x00);
425 633 : wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */
426 633 : wpabuf_put_u8(buf, 0x00);
427 : #ifdef CONFIG_HS20
428 633 : wpabuf_put_u8(buf, 0x40); /* Bit 46 - WNM-Notification */
429 : #else /* CONFIG_HS20 */
430 : wpabuf_put_u8(buf, 0x00);
431 : #endif /* CONFIG_HS20 */
432 :
433 633 : wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
434 633 : wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
435 : 1 + ETH_ALEN);
436 633 : wpabuf_put_u8(buf, wpa_s->conf->access_network_type);
437 : /* No Venue Info */
438 633 : if (!is_zero_ether_addr(wpa_s->conf->hessid))
439 4 : wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN);
440 : }
441 : #endif /* CONFIG_INTERWORKING */
442 :
443 :
444 1953 : static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
445 : {
446 1953 : struct wpabuf *extra_ie = NULL;
447 : #ifdef CONFIG_WPS
448 1953 : int wps = 0;
449 1953 : enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
450 : #endif /* CONFIG_WPS */
451 :
452 : #ifdef CONFIG_INTERWORKING
453 2586 : if (wpa_s->conf->interworking &&
454 633 : wpabuf_resize(&extra_ie, 100) == 0)
455 633 : wpas_add_interworking_elements(wpa_s, extra_ie);
456 : #endif /* CONFIG_INTERWORKING */
457 :
458 : #ifdef CONFIG_WPS
459 1953 : wps = wpas_wps_in_use(wpa_s, &req_type);
460 :
461 1953 : if (wps) {
462 : struct wpabuf *wps_ie;
463 3866 : wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
464 : DEV_PW_DEFAULT,
465 1933 : &wpa_s->wps->dev,
466 1933 : wpa_s->wps->uuid, req_type,
467 : 0, NULL);
468 1933 : if (wps_ie) {
469 1933 : if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
470 1933 : wpabuf_put_buf(extra_ie, wps_ie);
471 1933 : wpabuf_free(wps_ie);
472 : }
473 : }
474 :
475 : #ifdef CONFIG_P2P
476 1953 : if (wps) {
477 1933 : size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
478 1933 : if (wpabuf_resize(&extra_ie, ielen) == 0)
479 1932 : wpas_p2p_scan_ie(wpa_s, extra_ie);
480 : }
481 : #endif /* CONFIG_P2P */
482 :
483 1953 : wpa_supplicant_mesh_add_scan_ie(wpa_s, &extra_ie);
484 :
485 : #endif /* CONFIG_WPS */
486 :
487 : #ifdef CONFIG_HS20
488 1953 : if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
489 633 : wpas_hs20_add_indication(extra_ie, -1);
490 : #endif /* CONFIG_HS20 */
491 :
492 1953 : return extra_ie;
493 : }
494 :
495 :
496 : #ifdef CONFIG_P2P
497 :
498 : /*
499 : * Check whether there are any enabled networks or credentials that could be
500 : * used for a non-P2P connection.
501 : */
502 42 : static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
503 : {
504 : struct wpa_ssid *ssid;
505 :
506 44 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
507 44 : if (wpas_network_disabled(wpa_s, ssid))
508 2 : continue;
509 42 : if (!ssid->p2p_group)
510 42 : return 1;
511 : }
512 :
513 0 : if (wpa_s->conf->cred && wpa_s->conf->interworking &&
514 0 : wpa_s->conf->auto_interworking)
515 0 : return 1;
516 :
517 0 : return 0;
518 : }
519 :
520 : #endif /* CONFIG_P2P */
521 :
522 :
523 2 : static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
524 : u16 num_modes,
525 : enum hostapd_hw_mode mode)
526 : {
527 : u16 i;
528 :
529 3 : for (i = 0; i < num_modes; i++) {
530 3 : if (modes[i].mode == mode)
531 2 : return &modes[i];
532 : }
533 :
534 0 : return NULL;
535 : }
536 :
537 :
538 2 : static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
539 : enum hostapd_hw_mode band,
540 : struct wpa_driver_scan_params *params)
541 : {
542 : /* Include only supported channels for the specified band */
543 : struct hostapd_hw_modes *mode;
544 : int count, i;
545 :
546 2 : mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
547 2 : if (mode == NULL) {
548 : /* No channels supported in this band - use empty list */
549 0 : params->freqs = os_zalloc(sizeof(int));
550 0 : return;
551 : }
552 :
553 2 : params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
554 2 : if (params->freqs == NULL)
555 0 : return;
556 40 : for (count = 0, i = 0; i < mode->num_channels; i++) {
557 38 : if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
558 14 : continue;
559 24 : params->freqs[count++] = mode->channels[i].freq;
560 : }
561 : }
562 :
563 :
564 1953 : static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
565 : struct wpa_driver_scan_params *params)
566 : {
567 1953 : if (wpa_s->hw.modes == NULL)
568 18 : return; /* unknown what channels the driver supports */
569 1935 : if (params->freqs)
570 1777 : return; /* already using a limited channel set */
571 158 : if (wpa_s->setband == WPA_SETBAND_5G)
572 1 : wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
573 : params);
574 157 : else if (wpa_s->setband == WPA_SETBAND_2G)
575 1 : wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
576 : params);
577 : }
578 :
579 :
580 2 : static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
581 : struct wpa_driver_scan_params *params,
582 : size_t max_ssids)
583 : {
584 : unsigned int i;
585 : struct wpa_ssid *ssid;
586 :
587 6 : for (i = 0; i < wpa_s->scan_id_count; i++) {
588 : unsigned int j;
589 :
590 4 : ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
591 4 : if (!ssid || !ssid->scan_ssid)
592 1 : continue;
593 :
594 4 : for (j = 0; j < params->num_ssids; j++) {
595 1 : if (params->ssids[j].ssid_len == ssid->ssid_len &&
596 0 : params->ssids[j].ssid &&
597 0 : os_memcmp(params->ssids[j].ssid, ssid->ssid,
598 : ssid->ssid_len) == 0)
599 0 : break;
600 : }
601 3 : if (j < params->num_ssids)
602 0 : continue; /* already in the list */
603 :
604 3 : if (params->num_ssids + 1 > max_ssids) {
605 0 : wpa_printf(MSG_DEBUG,
606 : "Over max scan SSIDs for manual request");
607 0 : break;
608 : }
609 :
610 6 : wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
611 3 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
612 3 : params->ssids[params->num_ssids].ssid = ssid->ssid;
613 3 : params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
614 3 : params->num_ssids++;
615 : }
616 :
617 2 : wpa_s->scan_id_count = 0;
618 2 : }
619 :
620 :
621 2897 : static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
622 : {
623 2897 : struct wpa_supplicant *wpa_s = eloop_ctx;
624 : struct wpa_ssid *ssid;
625 : int ret, p2p_in_prog;
626 2897 : struct wpabuf *extra_ie = NULL;
627 : struct wpa_driver_scan_params params;
628 : struct wpa_driver_scan_params *scan_params;
629 : size_t max_ssids;
630 :
631 2897 : if (wpa_s->pno || wpa_s->pno_sched_pending) {
632 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
633 0 : return;
634 : }
635 :
636 2897 : if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
637 5 : wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
638 5 : return;
639 : }
640 :
641 2892 : if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
642 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
643 0 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
644 0 : return;
645 : }
646 :
647 2892 : if (wpa_s->scanning) {
648 : /*
649 : * If we are already in scanning state, we shall reschedule the
650 : * the incoming scan request.
651 : */
652 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req");
653 0 : wpa_supplicant_req_scan(wpa_s, 1, 0);
654 0 : return;
655 : }
656 :
657 4027 : if (!wpa_supplicant_enabled_networks(wpa_s) &&
658 1135 : wpa_s->scan_req == NORMAL_SCAN_REQ) {
659 668 : wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
660 668 : wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
661 668 : return;
662 : }
663 :
664 4446 : if (wpa_s->conf->ap_scan != 0 &&
665 2222 : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
666 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - "
667 : "overriding ap_scan configuration");
668 0 : wpa_s->conf->ap_scan = 0;
669 0 : wpas_notify_ap_scan_changed(wpa_s);
670 : }
671 :
672 2224 : if (wpa_s->conf->ap_scan == 0) {
673 2 : wpa_supplicant_gen_assoc_event(wpa_s);
674 2 : return;
675 : }
676 :
677 2222 : p2p_in_prog = wpas_p2p_in_progress(wpa_s);
678 2222 : if (p2p_in_prog && p2p_in_prog != 2) {
679 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
680 1 : wpa_supplicant_req_scan(wpa_s, 5, 0);
681 1 : return;
682 : }
683 :
684 2221 : if (wpa_s->conf->ap_scan == 2)
685 16 : max_ssids = 1;
686 : else {
687 2205 : max_ssids = wpa_s->max_scan_ssids;
688 2205 : if (max_ssids > WPAS_MAX_SCAN_SSIDS)
689 15 : max_ssids = WPAS_MAX_SCAN_SSIDS;
690 : }
691 :
692 2221 : wpa_s->last_scan_req = wpa_s->scan_req;
693 2221 : wpa_s->scan_req = NORMAL_SCAN_REQ;
694 :
695 2221 : os_memset(¶ms, 0, sizeof(params));
696 :
697 2221 : wpa_s->scan_prev_wpa_state = wpa_s->wpa_state;
698 3432 : if (wpa_s->wpa_state == WPA_DISCONNECTED ||
699 1211 : wpa_s->wpa_state == WPA_INACTIVE)
700 1757 : wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
701 :
702 : /*
703 : * If autoscan has set its own scanning parameters
704 : */
705 2221 : if (wpa_s->autoscan_params != NULL) {
706 0 : scan_params = wpa_s->autoscan_params;
707 0 : goto scan;
708 : }
709 :
710 3813 : if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
711 1592 : wpa_s->connect_without_scan) {
712 286 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
713 286 : if (ssid == wpa_s->connect_without_scan)
714 254 : break;
715 : }
716 254 : wpa_s->connect_without_scan = NULL;
717 254 : if (ssid) {
718 254 : wpa_printf(MSG_DEBUG, "Start a pre-selected network "
719 : "without scan step");
720 254 : wpa_supplicant_associate(wpa_s, NULL, ssid);
721 254 : return;
722 : }
723 : }
724 :
725 : #ifdef CONFIG_P2P
726 2205 : if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
727 459 : wpa_s->go_params && !wpa_s->conf->passive_scan) {
728 214 : wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)",
729 : wpa_s->p2p_in_provisioning,
730 : wpa_s->show_group_started);
731 214 : params.ssids[0].ssid = wpa_s->go_params->ssid;
732 214 : params.ssids[0].ssid_len = wpa_s->go_params->ssid_len;
733 214 : params.num_ssids = 1;
734 214 : goto ssid_list_set;
735 : }
736 :
737 1753 : if (wpa_s->p2p_in_invitation) {
738 17 : if (wpa_s->current_ssid) {
739 5 : wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation");
740 5 : params.ssids[0].ssid = wpa_s->current_ssid->ssid;
741 5 : params.ssids[0].ssid_len =
742 5 : wpa_s->current_ssid->ssid_len;
743 5 : params.num_ssids = 1;
744 : } else {
745 12 : wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation");
746 : }
747 17 : goto ssid_list_set;
748 : }
749 : #endif /* CONFIG_P2P */
750 :
751 : /* Find the starting point from which to continue scanning */
752 1736 : ssid = wpa_s->conf->ssid;
753 1736 : if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
754 10 : while (ssid) {
755 5 : if (ssid == wpa_s->prev_scan_ssid) {
756 3 : ssid = ssid->next;
757 3 : break;
758 : }
759 2 : ssid = ssid->next;
760 : }
761 : }
762 :
763 2843 : if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
764 1107 : wpa_s->conf->ap_scan == 2) {
765 14 : wpa_s->connect_without_scan = NULL;
766 14 : wpa_s->prev_scan_wildcard = 0;
767 14 : wpa_supplicant_assoc_try(wpa_s, ssid);
768 14 : return;
769 1722 : } else if (wpa_s->conf->ap_scan == 2) {
770 : /*
771 : * User-initiated scan request in ap_scan == 2; scan with
772 : * wildcard SSID.
773 : */
774 2 : ssid = NULL;
775 1720 : } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
776 : /*
777 : * Perform single-channel single-SSID scan for
778 : * reassociate-to-same-BSS operation.
779 : */
780 : /* Setup SSID */
781 0 : ssid = wpa_s->current_ssid;
782 0 : wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
783 0 : ssid->ssid, ssid->ssid_len);
784 0 : params.ssids[0].ssid = ssid->ssid;
785 0 : params.ssids[0].ssid_len = ssid->ssid_len;
786 0 : params.num_ssids = 1;
787 :
788 : /*
789 : * Allocate memory for frequency array, allocate one extra
790 : * slot for the zero-terminator.
791 : */
792 0 : params.freqs = os_malloc(sizeof(int) * 2);
793 0 : if (params.freqs == NULL) {
794 0 : wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
795 0 : return;
796 : }
797 0 : params.freqs[0] = wpa_s->assoc_freq;
798 0 : params.freqs[1] = 0;
799 :
800 : /*
801 : * Reset the reattach flag so that we fall back to full scan if
802 : * this scan fails.
803 : */
804 0 : wpa_s->reattach = 0;
805 : } else {
806 1720 : struct wpa_ssid *start = ssid, *tssid;
807 1720 : int freqs_set = 0;
808 1720 : if (ssid == NULL && max_ssids > 1)
809 452 : ssid = wpa_s->conf->ssid;
810 4751 : while (ssid) {
811 2575 : if (!wpas_network_disabled(wpa_s, ssid) &&
812 1260 : ssid->scan_ssid) {
813 28 : wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
814 14 : ssid->ssid, ssid->ssid_len);
815 28 : params.ssids[params.num_ssids].ssid =
816 14 : ssid->ssid;
817 28 : params.ssids[params.num_ssids].ssid_len =
818 14 : ssid->ssid_len;
819 14 : params.num_ssids++;
820 14 : if (params.num_ssids + 1 >= max_ssids)
821 4 : break;
822 : }
823 1311 : ssid = ssid->next;
824 1311 : if (ssid == start)
825 0 : break;
826 2559 : if (ssid == NULL && max_ssids > 1 &&
827 1248 : start != wpa_s->conf->ssid)
828 0 : ssid = wpa_s->conf->ssid;
829 : }
830 :
831 1722 : if (wpa_s->scan_id_count &&
832 2 : wpa_s->last_scan_req == MANUAL_SCAN_REQ)
833 2 : wpa_set_scan_ssids(wpa_s, ¶ms, max_ssids);
834 :
835 4581 : for (tssid = wpa_s->conf->ssid;
836 5095 : wpa_s->last_scan_req != MANUAL_SCAN_REQ && tssid;
837 1141 : tssid = tssid->next) {
838 1141 : if (wpas_network_disabled(wpa_s, tssid))
839 32 : continue;
840 1109 : if ((params.freqs || !freqs_set) && tssid->scan_freq) {
841 863 : int_array_concat(¶ms.freqs,
842 863 : tssid->scan_freq);
843 : } else {
844 246 : os_free(params.freqs);
845 246 : params.freqs = NULL;
846 : }
847 1109 : freqs_set = 1;
848 : }
849 1720 : int_array_sort_unique(params.freqs);
850 : }
851 :
852 1722 : if (ssid && max_ssids == 1) {
853 : /*
854 : * If the driver is limited to 1 SSID at a time interleave
855 : * wildcard SSID scans with specific SSID scans to avoid
856 : * waiting a long time for a wildcard scan.
857 : */
858 4 : if (!wpa_s->prev_scan_wildcard) {
859 1 : params.ssids[0].ssid = NULL;
860 1 : params.ssids[0].ssid_len = 0;
861 1 : wpa_s->prev_scan_wildcard = 1;
862 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for "
863 : "wildcard SSID (Interleave with specific)");
864 : } else {
865 1 : wpa_s->prev_scan_ssid = ssid;
866 1 : wpa_s->prev_scan_wildcard = 0;
867 1 : wpa_dbg(wpa_s, MSG_DEBUG,
868 : "Starting AP scan for specific SSID: %s",
869 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
870 : }
871 1720 : } else if (ssid) {
872 : /* max_ssids > 1 */
873 :
874 2 : wpa_s->prev_scan_ssid = ssid;
875 2 : wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
876 : "the scan request");
877 2 : params.num_ssids++;
878 1718 : } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
879 2 : wpa_s->manual_scan_passive && params.num_ssids == 0) {
880 2 : wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request");
881 1716 : } else if (wpa_s->conf->passive_scan) {
882 7 : wpa_dbg(wpa_s, MSG_DEBUG,
883 : "Use passive scan based on configuration");
884 : } else {
885 1709 : wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
886 1709 : params.num_ssids++;
887 1709 : wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard "
888 : "SSID");
889 : }
890 : #ifdef CONFIG_P2P
891 : ssid_list_set:
892 : #endif /* CONFIG_P2P */
893 :
894 1953 : wpa_supplicant_optimize_freqs(wpa_s, ¶ms);
895 1953 : extra_ie = wpa_supplicant_extra_ies(wpa_s);
896 :
897 1953 : if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
898 : wpa_s->manual_scan_only_new) {
899 156 : wpa_printf(MSG_DEBUG,
900 : "Request driver to clear scan cache due to manual only_new=1 scan");
901 156 : params.only_new_results = 1;
902 : }
903 :
904 2581 : if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
905 628 : wpa_s->manual_scan_freqs) {
906 593 : wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
907 593 : params.freqs = wpa_s->manual_scan_freqs;
908 593 : wpa_s->manual_scan_freqs = NULL;
909 : }
910 :
911 1953 : if (params.freqs == NULL && wpa_s->next_scan_freqs) {
912 2 : wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
913 : "generated frequency list");
914 2 : params.freqs = wpa_s->next_scan_freqs;
915 : } else
916 1951 : os_free(wpa_s->next_scan_freqs);
917 1953 : wpa_s->next_scan_freqs = NULL;
918 1953 : wpa_setband_scan_freqs(wpa_s, ¶ms);
919 :
920 : /* See if user specified frequencies. If so, scan only those. */
921 1953 : if (wpa_s->conf->freq_list && !params.freqs) {
922 0 : wpa_dbg(wpa_s, MSG_DEBUG,
923 : "Optimize scan based on conf->freq_list");
924 0 : int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);
925 : }
926 :
927 : /* Use current associated channel? */
928 1953 : if (wpa_s->conf->scan_cur_freq && !params.freqs) {
929 0 : unsigned int num = wpa_s->num_multichan_concurrent;
930 :
931 0 : params.freqs = os_calloc(num + 1, sizeof(int));
932 0 : if (params.freqs) {
933 0 : num = get_shared_radio_freqs(wpa_s, params.freqs, num);
934 0 : if (num > 0) {
935 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
936 : "current operating channels since "
937 : "scan_cur_freq is enabled");
938 : } else {
939 0 : os_free(params.freqs);
940 0 : params.freqs = NULL;
941 : }
942 : }
943 : }
944 :
945 1953 : params.filter_ssids = wpa_supplicant_build_filter_ssids(
946 : wpa_s->conf, ¶ms.num_filter_ssids);
947 1953 : if (extra_ie) {
948 1953 : params.extra_ies = wpabuf_head(extra_ie);
949 1953 : params.extra_ies_len = wpabuf_len(extra_ie);
950 : }
951 :
952 : #ifdef CONFIG_P2P
953 3668 : if (wpa_s->p2p_in_provisioning || wpa_s->p2p_in_invitation ||
954 1715 : (wpa_s->show_group_started && wpa_s->go_params)) {
955 : /*
956 : * The interface may not yet be in P2P mode, so we have to
957 : * explicitly request P2P probe to disable CCK rates.
958 : */
959 238 : params.p2p_probe = 1;
960 : }
961 : #endif /* CONFIG_P2P */
962 :
963 1953 : if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) {
964 3 : params.mac_addr_rand = 1;
965 3 : if (wpa_s->mac_addr_scan) {
966 2 : params.mac_addr = wpa_s->mac_addr_scan;
967 2 : params.mac_addr_mask = wpa_s->mac_addr_scan + ETH_ALEN;
968 : }
969 : }
970 :
971 1953 : scan_params = ¶ms;
972 :
973 : scan:
974 : #ifdef CONFIG_P2P
975 : /*
976 : * If the driver does not support multi-channel concurrency and a
977 : * virtual interface that shares the same radio with the wpa_s interface
978 : * is operating there may not be need to scan other channels apart from
979 : * the current operating channel on the other virtual interface. Filter
980 : * out other channels in case we are trying to find a connection for a
981 : * station interface when we are not configured to prefer station
982 : * connection and a concurrent operation is already in process.
983 : */
984 2148 : if (wpa_s->scan_for_connection &&
985 361 : wpa_s->last_scan_req == NORMAL_SCAN_REQ &&
986 250 : !scan_params->freqs && !params.freqs &&
987 84 : wpas_is_p2p_prioritized(wpa_s) &&
988 84 : wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
989 42 : non_p2p_network_enabled(wpa_s)) {
990 42 : unsigned int num = wpa_s->num_multichan_concurrent;
991 :
992 42 : params.freqs = os_calloc(num + 1, sizeof(int));
993 42 : if (params.freqs) {
994 42 : num = get_shared_radio_freqs(wpa_s, params.freqs, num);
995 42 : if (num > 0 && num == wpa_s->num_multichan_concurrent) {
996 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used");
997 : } else {
998 42 : os_free(params.freqs);
999 42 : params.freqs = NULL;
1000 : }
1001 : }
1002 : }
1003 : #endif /* CONFIG_P2P */
1004 :
1005 1953 : ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
1006 :
1007 1953 : if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
1008 0 : !wpa_s->manual_scan_freqs) {
1009 : /* Restore manual_scan_freqs for the next attempt */
1010 0 : wpa_s->manual_scan_freqs = params.freqs;
1011 0 : params.freqs = NULL;
1012 : }
1013 :
1014 1953 : wpabuf_free(extra_ie);
1015 1953 : os_free(params.freqs);
1016 1953 : os_free(params.filter_ssids);
1017 :
1018 1953 : if (ret) {
1019 1 : wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
1020 1 : if (wpa_s->scan_prev_wpa_state != wpa_s->wpa_state)
1021 1 : wpa_supplicant_set_state(wpa_s,
1022 : wpa_s->scan_prev_wpa_state);
1023 : /* Restore scan_req since we will try to scan again */
1024 1 : wpa_s->scan_req = wpa_s->last_scan_req;
1025 1 : wpa_supplicant_req_scan(wpa_s, 1, 0);
1026 : } else {
1027 1952 : wpa_s->scan_for_connection = 0;
1028 : #ifdef CONFIG_INTERWORKING
1029 1952 : wpa_s->interworking_fast_assoc_tried = 0;
1030 : #endif /* CONFIG_INTERWORKING */
1031 : }
1032 : }
1033 :
1034 :
1035 19 : void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec)
1036 : {
1037 : struct os_reltime remaining, new_int;
1038 : int cancelled;
1039 :
1040 19 : cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL,
1041 : &remaining);
1042 :
1043 19 : new_int.sec = sec;
1044 19 : new_int.usec = 0;
1045 19 : if (cancelled && os_reltime_before(&remaining, &new_int)) {
1046 6 : new_int.sec = remaining.sec;
1047 6 : new_int.usec = remaining.usec;
1048 : }
1049 :
1050 19 : if (cancelled) {
1051 6 : eloop_register_timeout(new_int.sec, new_int.usec,
1052 : wpa_supplicant_scan, wpa_s, NULL);
1053 : }
1054 19 : wpa_s->scan_interval = sec;
1055 19 : }
1056 :
1057 :
1058 : /**
1059 : * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
1060 : * @wpa_s: Pointer to wpa_supplicant data
1061 : * @sec: Number of seconds after which to scan
1062 : * @usec: Number of microseconds after which to scan
1063 : *
1064 : * This function is used to schedule a scan for neighboring access points after
1065 : * the specified time.
1066 : */
1067 5584 : void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
1068 : {
1069 5584 : int res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
1070 : NULL);
1071 5584 : if (res == 1) {
1072 111 : wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d.%06d sec",
1073 : sec, usec);
1074 5473 : } else if (res == 0) {
1075 1703 : wpa_dbg(wpa_s, MSG_DEBUG, "Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner",
1076 : sec, usec);
1077 : } else {
1078 3770 : wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d.%06d sec",
1079 : sec, usec);
1080 3770 : eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
1081 : }
1082 5584 : }
1083 :
1084 :
1085 : /**
1086 : * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan
1087 : * @wpa_s: Pointer to wpa_supplicant data
1088 : * @sec: Number of seconds after which to scan
1089 : * @usec: Number of microseconds after which to scan
1090 : * Returns: 0 on success or -1 otherwise
1091 : *
1092 : * This function is used to schedule periodic scans for neighboring
1093 : * access points after the specified time.
1094 : */
1095 0 : int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
1096 : int sec, int usec)
1097 : {
1098 0 : if (!wpa_s->sched_scan_supported)
1099 0 : return -1;
1100 :
1101 0 : eloop_register_timeout(sec, usec,
1102 : wpa_supplicant_delayed_sched_scan_timeout,
1103 : wpa_s, NULL);
1104 :
1105 0 : return 0;
1106 : }
1107 :
1108 :
1109 : /**
1110 : * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
1111 : * @wpa_s: Pointer to wpa_supplicant data
1112 : * Returns: 0 is sched_scan was started or -1 otherwise
1113 : *
1114 : * This function is used to schedule periodic scans for neighboring
1115 : * access points repeating the scan continuously.
1116 : */
1117 222 : int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
1118 : {
1119 : struct wpa_driver_scan_params params;
1120 : struct wpa_driver_scan_params *scan_params;
1121 : enum wpa_states prev_state;
1122 222 : struct wpa_ssid *ssid = NULL;
1123 222 : struct wpabuf *extra_ie = NULL;
1124 : int ret;
1125 : unsigned int max_sched_scan_ssids;
1126 222 : int wildcard = 0;
1127 : int need_ssids;
1128 :
1129 222 : if (!wpa_s->sched_scan_supported)
1130 222 : return -1;
1131 :
1132 0 : if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
1133 0 : max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
1134 : else
1135 0 : max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
1136 0 : if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
1137 0 : return -1;
1138 :
1139 0 : if (wpa_s->sched_scanning) {
1140 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
1141 0 : return 0;
1142 : }
1143 :
1144 0 : need_ssids = 0;
1145 0 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1146 0 : if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) {
1147 : /* Use wildcard SSID to find this network */
1148 0 : wildcard = 1;
1149 0 : } else if (!wpas_network_disabled(wpa_s, ssid) &&
1150 0 : ssid->ssid_len)
1151 0 : need_ssids++;
1152 :
1153 : #ifdef CONFIG_WPS
1154 0 : if (!wpas_network_disabled(wpa_s, ssid) &&
1155 0 : ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
1156 : /*
1157 : * Normal scan is more reliable and faster for WPS
1158 : * operations and since these are for short periods of
1159 : * time, the benefit of trying to use sched_scan would
1160 : * be limited.
1161 : */
1162 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
1163 : "sched_scan for WPS");
1164 0 : return -1;
1165 : }
1166 : #endif /* CONFIG_WPS */
1167 : }
1168 0 : if (wildcard)
1169 0 : need_ssids++;
1170 :
1171 0 : if (wpa_s->normal_scans < 3 &&
1172 0 : (need_ssids <= wpa_s->max_scan_ssids ||
1173 0 : wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) {
1174 : /*
1175 : * When normal scan can speed up operations, use that for the
1176 : * first operations before starting the sched_scan to allow
1177 : * user space sleep more. We do this only if the normal scan
1178 : * has functionality that is suitable for this or if the
1179 : * sched_scan does not have better support for multiple SSIDs.
1180 : */
1181 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
1182 : "sched_scan for initial scans (normal_scans=%d)",
1183 : wpa_s->normal_scans);
1184 0 : return -1;
1185 : }
1186 :
1187 0 : os_memset(¶ms, 0, sizeof(params));
1188 :
1189 : /* If we can't allocate space for the filters, we just don't filter */
1190 0 : params.filter_ssids = os_calloc(wpa_s->max_match_sets,
1191 : sizeof(struct wpa_driver_scan_filter));
1192 :
1193 0 : prev_state = wpa_s->wpa_state;
1194 0 : if (wpa_s->wpa_state == WPA_DISCONNECTED ||
1195 0 : wpa_s->wpa_state == WPA_INACTIVE)
1196 0 : wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
1197 :
1198 0 : if (wpa_s->autoscan_params != NULL) {
1199 0 : scan_params = wpa_s->autoscan_params;
1200 0 : goto scan;
1201 : }
1202 :
1203 : /* Find the starting point from which to continue scanning */
1204 0 : ssid = wpa_s->conf->ssid;
1205 0 : if (wpa_s->prev_sched_ssid) {
1206 0 : while (ssid) {
1207 0 : if (ssid == wpa_s->prev_sched_ssid) {
1208 0 : ssid = ssid->next;
1209 0 : break;
1210 : }
1211 0 : ssid = ssid->next;
1212 : }
1213 : }
1214 :
1215 0 : if (!ssid || !wpa_s->prev_sched_ssid) {
1216 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
1217 0 : if (wpa_s->conf->sched_scan_interval)
1218 0 : wpa_s->sched_scan_interval =
1219 0 : wpa_s->conf->sched_scan_interval;
1220 0 : if (wpa_s->sched_scan_interval == 0)
1221 0 : wpa_s->sched_scan_interval = 10;
1222 0 : wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
1223 0 : wpa_s->first_sched_scan = 1;
1224 0 : ssid = wpa_s->conf->ssid;
1225 0 : wpa_s->prev_sched_ssid = ssid;
1226 : }
1227 :
1228 0 : if (wildcard) {
1229 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan");
1230 0 : params.num_ssids++;
1231 : }
1232 :
1233 0 : while (ssid) {
1234 0 : if (wpas_network_disabled(wpa_s, ssid))
1235 0 : goto next;
1236 :
1237 0 : if (params.num_filter_ssids < wpa_s->max_match_sets &&
1238 0 : params.filter_ssids && ssid->ssid && ssid->ssid_len) {
1239 0 : wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s",
1240 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1241 0 : os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid,
1242 : ssid->ssid, ssid->ssid_len);
1243 0 : params.filter_ssids[params.num_filter_ssids].ssid_len =
1244 0 : ssid->ssid_len;
1245 0 : params.num_filter_ssids++;
1246 0 : } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len)
1247 : {
1248 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID "
1249 : "filter for sched_scan - drop filter");
1250 0 : os_free(params.filter_ssids);
1251 0 : params.filter_ssids = NULL;
1252 0 : params.num_filter_ssids = 0;
1253 : }
1254 :
1255 0 : if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) {
1256 0 : if (params.num_ssids == max_sched_scan_ssids)
1257 0 : break; /* only room for broadcast SSID */
1258 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1259 : "add to active scan ssid: %s",
1260 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1261 0 : params.ssids[params.num_ssids].ssid =
1262 0 : ssid->ssid;
1263 0 : params.ssids[params.num_ssids].ssid_len =
1264 0 : ssid->ssid_len;
1265 0 : params.num_ssids++;
1266 0 : if (params.num_ssids >= max_sched_scan_ssids) {
1267 0 : wpa_s->prev_sched_ssid = ssid;
1268 : do {
1269 0 : ssid = ssid->next;
1270 0 : } while (ssid &&
1271 0 : (wpas_network_disabled(wpa_s, ssid) ||
1272 0 : !ssid->scan_ssid));
1273 0 : break;
1274 : }
1275 : }
1276 :
1277 : next:
1278 0 : wpa_s->prev_sched_ssid = ssid;
1279 0 : ssid = ssid->next;
1280 : }
1281 :
1282 0 : if (params.num_filter_ssids == 0) {
1283 0 : os_free(params.filter_ssids);
1284 0 : params.filter_ssids = NULL;
1285 : }
1286 :
1287 0 : extra_ie = wpa_supplicant_extra_ies(wpa_s);
1288 0 : if (extra_ie) {
1289 0 : params.extra_ies = wpabuf_head(extra_ie);
1290 0 : params.extra_ies_len = wpabuf_len(extra_ie);
1291 : }
1292 :
1293 0 : if (wpa_s->conf->filter_rssi)
1294 0 : params.filter_rssi = wpa_s->conf->filter_rssi;
1295 :
1296 : /* See if user specified frequencies. If so, scan only those. */
1297 0 : if (wpa_s->conf->freq_list && !params.freqs) {
1298 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1299 : "Optimize scan based on conf->freq_list");
1300 0 : int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);
1301 : }
1302 :
1303 0 : scan_params = ¶ms;
1304 :
1305 : scan:
1306 0 : if (ssid || !wpa_s->first_sched_scan) {
1307 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1308 : "Starting sched scan: interval %d timeout %d",
1309 : wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout);
1310 : } else {
1311 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1312 : "Starting sched scan: interval %d (no timeout)",
1313 : wpa_s->sched_scan_interval);
1314 : }
1315 :
1316 0 : wpa_setband_scan_freqs(wpa_s, scan_params);
1317 :
1318 0 : if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) {
1319 0 : params.mac_addr_rand = 1;
1320 0 : if (wpa_s->mac_addr_sched_scan) {
1321 0 : params.mac_addr = wpa_s->mac_addr_sched_scan;
1322 0 : params.mac_addr_mask = wpa_s->mac_addr_sched_scan +
1323 : ETH_ALEN;
1324 : }
1325 : }
1326 :
1327 0 : ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
1328 : wpa_s->sched_scan_interval);
1329 0 : wpabuf_free(extra_ie);
1330 0 : os_free(params.filter_ssids);
1331 0 : if (ret) {
1332 0 : wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan");
1333 0 : if (prev_state != wpa_s->wpa_state)
1334 0 : wpa_supplicant_set_state(wpa_s, prev_state);
1335 0 : return ret;
1336 : }
1337 :
1338 : /* If we have more SSIDs to scan, add a timeout so we scan them too */
1339 0 : if (ssid || !wpa_s->first_sched_scan) {
1340 0 : wpa_s->sched_scan_timed_out = 0;
1341 0 : eloop_register_timeout(wpa_s->sched_scan_timeout, 0,
1342 : wpa_supplicant_sched_scan_timeout,
1343 : wpa_s, NULL);
1344 0 : wpa_s->first_sched_scan = 0;
1345 0 : wpa_s->sched_scan_timeout /= 2;
1346 0 : wpa_s->sched_scan_interval *= 2;
1347 0 : if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) {
1348 0 : wpa_s->sched_scan_interval = 10;
1349 0 : wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
1350 : }
1351 : }
1352 :
1353 : /* If there is no more ssids, start next time from the beginning */
1354 0 : if (!ssid)
1355 0 : wpa_s->prev_sched_ssid = NULL;
1356 :
1357 0 : return 0;
1358 : }
1359 :
1360 :
1361 : /**
1362 : * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
1363 : * @wpa_s: Pointer to wpa_supplicant data
1364 : *
1365 : * This function is used to cancel a scan request scheduled with
1366 : * wpa_supplicant_req_scan().
1367 : */
1368 7058 : void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
1369 : {
1370 7058 : wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
1371 7058 : eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
1372 7058 : }
1373 :
1374 :
1375 : /**
1376 : * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan
1377 : * @wpa_s: Pointer to wpa_supplicant data
1378 : *
1379 : * This function is used to stop a delayed scheduled scan.
1380 : */
1381 212 : void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s)
1382 : {
1383 212 : if (!wpa_s->sched_scan_supported)
1384 424 : return;
1385 :
1386 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan");
1387 0 : eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout,
1388 : wpa_s, NULL);
1389 : }
1390 :
1391 :
1392 : /**
1393 : * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans
1394 : * @wpa_s: Pointer to wpa_supplicant data
1395 : *
1396 : * This function is used to stop a periodic scheduled scan.
1397 : */
1398 4892 : void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
1399 : {
1400 4892 : if (!wpa_s->sched_scanning)
1401 9784 : return;
1402 :
1403 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
1404 0 : eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
1405 0 : wpa_supplicant_stop_sched_scan(wpa_s);
1406 : }
1407 :
1408 :
1409 : /**
1410 : * wpa_supplicant_notify_scanning - Indicate possible scan state change
1411 : * @wpa_s: Pointer to wpa_supplicant data
1412 : * @scanning: Whether scanning is currently in progress
1413 : *
1414 : * This function is to generate scanning notifycations. It is called whenever
1415 : * there may have been a change in scanning (scan started, completed, stopped).
1416 : * wpas_notify_scanning() is called whenever the scanning state changed from the
1417 : * previously notified state.
1418 : */
1419 24699 : void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
1420 : int scanning)
1421 : {
1422 24699 : if (wpa_s->scanning != scanning) {
1423 3924 : wpa_s->scanning = scanning;
1424 3924 : wpas_notify_scanning(wpa_s);
1425 : }
1426 24699 : }
1427 :
1428 :
1429 1442 : static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
1430 : {
1431 1442 : int rate = 0;
1432 : const u8 *ie;
1433 : int i;
1434 :
1435 1442 : ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
1436 12978 : for (i = 0; ie && i < ie[1]; i++) {
1437 11536 : if ((ie[i + 2] & 0x7f) > rate)
1438 10066 : rate = ie[i + 2] & 0x7f;
1439 : }
1440 :
1441 1442 : ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
1442 4382 : for (i = 0; ie && i < ie[1]; i++) {
1443 2940 : if ((ie[i + 2] & 0x7f) > rate)
1444 2940 : rate = ie[i + 2] & 0x7f;
1445 : }
1446 :
1447 1442 : return rate;
1448 : }
1449 :
1450 :
1451 : /**
1452 : * wpa_scan_get_ie - Fetch a specified information element from a scan result
1453 : * @res: Scan result entry
1454 : * @ie: Information element identitifier (WLAN_EID_*)
1455 : * Returns: Pointer to the information element (id field) or %NULL if not found
1456 : *
1457 : * This function returns the first matching information element in the scan
1458 : * result.
1459 : */
1460 12150 : const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
1461 : {
1462 : const u8 *end, *pos;
1463 :
1464 12150 : pos = (const u8 *) (res + 1);
1465 12150 : end = pos + res->ie_len;
1466 :
1467 78554 : while (pos + 1 < end) {
1468 61258 : if (pos + 2 + pos[1] > end)
1469 0 : break;
1470 61258 : if (pos[0] == ie)
1471 7004 : return pos;
1472 54254 : pos += 2 + pos[1];
1473 : }
1474 :
1475 5146 : return NULL;
1476 : }
1477 :
1478 :
1479 : /**
1480 : * wpa_scan_get_vendor_ie - Fetch vendor information element from a scan result
1481 : * @res: Scan result entry
1482 : * @vendor_type: Vendor type (four octets starting the IE payload)
1483 : * Returns: Pointer to the information element (id field) or %NULL if not found
1484 : *
1485 : * This function returns the first matching information element in the scan
1486 : * result.
1487 : */
1488 8792 : const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
1489 : u32 vendor_type)
1490 : {
1491 : const u8 *end, *pos;
1492 :
1493 8792 : pos = (const u8 *) (res + 1);
1494 8792 : end = pos + res->ie_len;
1495 :
1496 95700 : while (pos + 1 < end) {
1497 80669 : if (pos + 2 + pos[1] > end)
1498 0 : break;
1499 95865 : if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1500 15196 : vendor_type == WPA_GET_BE32(&pos[2]))
1501 2553 : return pos;
1502 78116 : pos += 2 + pos[1];
1503 : }
1504 :
1505 6239 : return NULL;
1506 : }
1507 :
1508 :
1509 : /**
1510 : * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result
1511 : * @res: Scan result entry
1512 : * @vendor_type: Vendor type (four octets starting the IE payload)
1513 : * Returns: Pointer to the information element (id field) or %NULL if not found
1514 : *
1515 : * This function returns the first matching information element in the scan
1516 : * result.
1517 : *
1518 : * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only
1519 : * from Beacon frames instead of either Beacon or Probe Response frames.
1520 : */
1521 305 : const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
1522 : u32 vendor_type)
1523 : {
1524 : const u8 *end, *pos;
1525 :
1526 305 : if (res->beacon_ie_len == 0)
1527 0 : return NULL;
1528 :
1529 305 : pos = (const u8 *) (res + 1);
1530 305 : pos += res->ie_len;
1531 305 : end = pos + res->beacon_ie_len;
1532 :
1533 3829 : while (pos + 1 < end) {
1534 3250 : if (pos + 2 + pos[1] > end)
1535 0 : break;
1536 3635 : if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1537 385 : vendor_type == WPA_GET_BE32(&pos[2]))
1538 31 : return pos;
1539 3219 : pos += 2 + pos[1];
1540 : }
1541 :
1542 274 : return NULL;
1543 : }
1544 :
1545 :
1546 : /**
1547 : * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result
1548 : * @res: Scan result entry
1549 : * @vendor_type: Vendor type (four octets starting the IE payload)
1550 : * Returns: Pointer to the information element payload or %NULL if not found
1551 : *
1552 : * This function returns concatenated payload of possibly fragmented vendor
1553 : * specific information elements in the scan result. The caller is responsible
1554 : * for freeing the returned buffer.
1555 : */
1556 697 : struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
1557 : u32 vendor_type)
1558 : {
1559 : struct wpabuf *buf;
1560 : const u8 *end, *pos;
1561 :
1562 697 : buf = wpabuf_alloc(res->ie_len);
1563 697 : if (buf == NULL)
1564 0 : return NULL;
1565 :
1566 697 : pos = (const u8 *) (res + 1);
1567 697 : end = pos + res->ie_len;
1568 :
1569 8706 : while (pos + 1 < end) {
1570 7312 : if (pos + 2 + pos[1] > end)
1571 0 : break;
1572 9049 : if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1573 1737 : vendor_type == WPA_GET_BE32(&pos[2]))
1574 680 : wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
1575 7312 : pos += 2 + pos[1];
1576 : }
1577 :
1578 697 : if (wpabuf_len(buf) == 0) {
1579 18 : wpabuf_free(buf);
1580 18 : buf = NULL;
1581 : }
1582 :
1583 697 : return buf;
1584 : }
1585 :
1586 :
1587 : /*
1588 : * Channels with a great SNR can operate at full rate. What is a great SNR?
1589 : * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
1590 : * rule of thumb is that any SNR above 20 is good." This one
1591 : * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
1592 : * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
1593 : * conservative value.
1594 : */
1595 : #define GREAT_SNR 30
1596 :
1597 : #define IS_5GHZ(n) (n > 4000)
1598 :
1599 : /* Compare function for sorting scan results. Return >0 if @b is considered
1600 : * better. */
1601 1220 : static int wpa_scan_result_compar(const void *a, const void *b)
1602 : {
1603 : #define MIN(a,b) a < b ? a : b
1604 1220 : struct wpa_scan_res **_wa = (void *) a;
1605 1220 : struct wpa_scan_res **_wb = (void *) b;
1606 1220 : struct wpa_scan_res *wa = *_wa;
1607 1220 : struct wpa_scan_res *wb = *_wb;
1608 : int wpa_a, wpa_b, maxrate_a, maxrate_b;
1609 : int snr_a, snr_b;
1610 :
1611 : /* WPA/WPA2 support preferred */
1612 2427 : wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
1613 1207 : wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
1614 2427 : wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
1615 1207 : wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
1616 :
1617 1220 : if (wpa_b && !wpa_a)
1618 152 : return 1;
1619 1068 : if (!wpa_b && wpa_a)
1620 229 : return -1;
1621 :
1622 : /* privacy support preferred */
1623 1146 : if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
1624 307 : (wb->caps & IEEE80211_CAP_PRIVACY))
1625 102 : return 1;
1626 1269 : if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
1627 532 : (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
1628 16 : return -1;
1629 :
1630 721 : if (wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) {
1631 721 : snr_a = MIN(wa->level - wa->noise, GREAT_SNR);
1632 721 : snr_b = MIN(wb->level - wb->noise, GREAT_SNR);
1633 : } else {
1634 : /* Level is not in dBm, so we can't calculate
1635 : * SNR. Just use raw level (units unknown). */
1636 0 : snr_a = wa->level;
1637 0 : snr_b = wb->level;
1638 : }
1639 :
1640 : /* if SNR is close, decide by max rate or frequency band */
1641 721 : if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
1642 0 : (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
1643 721 : maxrate_a = wpa_scan_get_max_rate(wa);
1644 721 : maxrate_b = wpa_scan_get_max_rate(wb);
1645 721 : if (maxrate_a != maxrate_b)
1646 0 : return maxrate_b - maxrate_a;
1647 721 : if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
1648 3 : return IS_5GHZ(wa->freq) ? -1 : 1;
1649 : }
1650 :
1651 : /* all things being equal, use SNR; if SNRs are
1652 : * identical, use quality values since some drivers may only report
1653 : * that value and leave the signal level zero */
1654 718 : if (snr_b == snr_a)
1655 718 : return wb->qual - wa->qual;
1656 0 : return snr_b - snr_a;
1657 : #undef MIN
1658 : }
1659 :
1660 :
1661 : #ifdef CONFIG_WPS
1662 : /* Compare function for sorting scan results when searching a WPS AP for
1663 : * provisioning. Return >0 if @b is considered better. */
1664 83 : static int wpa_scan_result_wps_compar(const void *a, const void *b)
1665 : {
1666 83 : struct wpa_scan_res **_wa = (void *) a;
1667 83 : struct wpa_scan_res **_wb = (void *) b;
1668 83 : struct wpa_scan_res *wa = *_wa;
1669 83 : struct wpa_scan_res *wb = *_wb;
1670 : int uses_wps_a, uses_wps_b;
1671 : struct wpabuf *wps_a, *wps_b;
1672 : int res;
1673 :
1674 : /* Optimization - check WPS IE existence before allocated memory and
1675 : * doing full reassembly. */
1676 83 : uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
1677 83 : uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
1678 83 : if (uses_wps_a && !uses_wps_b)
1679 5 : return -1;
1680 78 : if (!uses_wps_a && uses_wps_b)
1681 22 : return 1;
1682 :
1683 56 : if (uses_wps_a && uses_wps_b) {
1684 55 : wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
1685 55 : wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
1686 55 : res = wps_ap_priority_compar(wps_a, wps_b);
1687 55 : wpabuf_free(wps_a);
1688 55 : wpabuf_free(wps_b);
1689 55 : if (res)
1690 25 : return res;
1691 : }
1692 :
1693 : /*
1694 : * Do not use current AP security policy as a sorting criteria during
1695 : * WPS provisioning step since the AP may get reconfigured at the
1696 : * completion of provisioning.
1697 : */
1698 :
1699 : /* all things being equal, use signal level; if signal levels are
1700 : * identical, use quality values since some drivers may only report
1701 : * that value and leave the signal level zero */
1702 31 : if (wb->level == wa->level)
1703 30 : return wb->qual - wa->qual;
1704 1 : return wb->level - wa->level;
1705 : }
1706 : #endif /* CONFIG_WPS */
1707 :
1708 :
1709 2788 : static void dump_scan_res(struct wpa_scan_results *scan_res)
1710 : {
1711 : #ifndef CONFIG_NO_STDOUT_DEBUG
1712 : size_t i;
1713 :
1714 2788 : if (scan_res->res == NULL || scan_res->num == 0)
1715 3030 : return;
1716 :
1717 2546 : wpa_printf(MSG_EXCESSIVE, "Sorted scan results");
1718 :
1719 6280 : for (i = 0; i < scan_res->num; i++) {
1720 3734 : struct wpa_scan_res *r = scan_res->res[i];
1721 : u8 *pos;
1722 3734 : if (r->flags & WPA_SCAN_LEVEL_DBM) {
1723 3734 : int snr = r->level - r->noise;
1724 3734 : int noise_valid = !(r->flags & WPA_SCAN_NOISE_INVALID);
1725 :
1726 26138 : wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1727 : "noise=%d%s level=%d snr=%d%s flags=0x%x age=%u",
1728 22404 : MAC2STR(r->bssid), r->freq, r->qual,
1729 : r->noise, noise_valid ? "" : "~", r->level,
1730 : snr, snr >= GREAT_SNR ? "*" : "", r->flags,
1731 : r->age);
1732 : } else {
1733 0 : wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1734 : "noise=%d level=%d flags=0x%x age=%u",
1735 0 : MAC2STR(r->bssid), r->freq, r->qual,
1736 : r->noise, r->level, r->flags, r->age);
1737 : }
1738 3734 : pos = (u8 *) (r + 1);
1739 3734 : if (r->ie_len)
1740 3734 : wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len);
1741 3734 : pos += r->ie_len;
1742 3734 : if (r->beacon_ie_len)
1743 2025 : wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs",
1744 : pos, r->beacon_ie_len);
1745 : }
1746 : #endif /* CONFIG_NO_STDOUT_DEBUG */
1747 : }
1748 :
1749 :
1750 : /**
1751 : * wpa_supplicant_filter_bssid_match - Is the specified BSSID allowed
1752 : * @wpa_s: Pointer to wpa_supplicant data
1753 : * @bssid: BSSID to check
1754 : * Returns: 0 if the BSSID is filtered or 1 if not
1755 : *
1756 : * This function is used to filter out specific BSSIDs from scan reslts mainly
1757 : * for testing purposes (SET bssid_filter ctrl_iface command).
1758 : */
1759 7800 : int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
1760 : const u8 *bssid)
1761 : {
1762 : size_t i;
1763 :
1764 7800 : if (wpa_s->bssid_filter == NULL)
1765 7790 : return 1;
1766 :
1767 13 : for (i = 0; i < wpa_s->bssid_filter_count; i++) {
1768 10 : if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
1769 : ETH_ALEN) == 0)
1770 7 : return 1;
1771 : }
1772 :
1773 3 : return 0;
1774 : }
1775 :
1776 :
1777 2788 : static void filter_scan_res(struct wpa_supplicant *wpa_s,
1778 : struct wpa_scan_results *res)
1779 : {
1780 : size_t i, j;
1781 :
1782 2788 : if (wpa_s->bssid_filter == NULL)
1783 5574 : return;
1784 :
1785 6 : for (i = 0, j = 0; i < res->num; i++) {
1786 4 : if (wpa_supplicant_filter_bssid_match(wpa_s,
1787 4 : res->res[i]->bssid)) {
1788 2 : res->res[j++] = res->res[i];
1789 : } else {
1790 2 : os_free(res->res[i]);
1791 2 : res->res[i] = NULL;
1792 : }
1793 : }
1794 :
1795 2 : if (res->num != j) {
1796 2 : wpa_printf(MSG_DEBUG, "Filtered out %d scan results",
1797 2 : (int) (res->num - j));
1798 2 : res->num = j;
1799 : }
1800 : }
1801 :
1802 :
1803 : /*
1804 : * Noise floor values to use when we have signal strength
1805 : * measurements, but no noise floor measurments. These values were
1806 : * measured in an office environment with many APs.
1807 : */
1808 : #define DEFAULT_NOISE_FLOOR_2GHZ (-89)
1809 : #define DEFAULT_NOISE_FLOOR_5GHZ (-92)
1810 :
1811 : /**
1812 : * wpa_supplicant_get_scan_results - Get scan results
1813 : * @wpa_s: Pointer to wpa_supplicant data
1814 : * @info: Information about what was scanned or %NULL if not available
1815 : * @new_scan: Whether a new scan was performed
1816 : * Returns: Scan results, %NULL on failure
1817 : *
1818 : * This function request the current scan results from the driver and updates
1819 : * the local BSS list wpa_s->bss. The caller is responsible for freeing the
1820 : * results with wpa_scan_results_free().
1821 : */
1822 : struct wpa_scan_results *
1823 2788 : wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
1824 : struct scan_info *info, int new_scan)
1825 : {
1826 : struct wpa_scan_results *scan_res;
1827 : size_t i;
1828 2788 : int (*compar)(const void *, const void *) = wpa_scan_result_compar;
1829 :
1830 2788 : scan_res = wpa_drv_get_scan_results2(wpa_s);
1831 2788 : if (scan_res == NULL) {
1832 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
1833 0 : return NULL;
1834 : }
1835 2788 : if (scan_res->fetch_time.sec == 0) {
1836 : /*
1837 : * Make sure we have a valid timestamp if the driver wrapper
1838 : * does not set this.
1839 : */
1840 2788 : os_get_reltime(&scan_res->fetch_time);
1841 : }
1842 2788 : filter_scan_res(wpa_s, scan_res);
1843 :
1844 6522 : for (i = 0; i < scan_res->num; i++) {
1845 3734 : struct wpa_scan_res *scan_res_item = scan_res->res[i];
1846 :
1847 3734 : if (scan_res_item->flags & WPA_SCAN_NOISE_INVALID) {
1848 1367 : scan_res_item->noise =
1849 1367 : IS_5GHZ(scan_res_item->freq) ?
1850 1367 : DEFAULT_NOISE_FLOOR_5GHZ :
1851 : DEFAULT_NOISE_FLOOR_2GHZ;
1852 : }
1853 : }
1854 :
1855 : #ifdef CONFIG_WPS
1856 2788 : if (wpas_wps_searching(wpa_s)) {
1857 375 : wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
1858 : "provisioning rules");
1859 375 : compar = wpa_scan_result_wps_compar;
1860 : }
1861 : #endif /* CONFIG_WPS */
1862 :
1863 2788 : qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
1864 : compar);
1865 2788 : dump_scan_res(scan_res);
1866 :
1867 2788 : wpa_bss_update_start(wpa_s);
1868 6522 : for (i = 0; i < scan_res->num; i++)
1869 3734 : wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
1870 : &scan_res->fetch_time);
1871 2788 : wpa_bss_update_end(wpa_s, info, new_scan);
1872 :
1873 2788 : return scan_res;
1874 : }
1875 :
1876 :
1877 : /**
1878 : * wpa_supplicant_update_scan_results - Update scan results from the driver
1879 : * @wpa_s: Pointer to wpa_supplicant data
1880 : * Returns: 0 on success, -1 on failure
1881 : *
1882 : * This function updates the BSS table within wpa_supplicant based on the
1883 : * currently available scan results from the driver without requesting a new
1884 : * scan. This is used in cases where the driver indicates an association
1885 : * (including roaming within ESS) and wpa_supplicant does not yet have the
1886 : * needed information to complete the connection (e.g., to perform validation
1887 : * steps in 4-way handshake).
1888 : */
1889 14 : int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
1890 : {
1891 : struct wpa_scan_results *scan_res;
1892 14 : scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1893 14 : if (scan_res == NULL)
1894 0 : return -1;
1895 14 : wpa_scan_results_free(scan_res);
1896 :
1897 14 : return 0;
1898 : }
1899 :
1900 :
1901 : /**
1902 : * scan_only_handler - Reports scan results
1903 : */
1904 284 : void scan_only_handler(struct wpa_supplicant *wpa_s,
1905 : struct wpa_scan_results *scan_res)
1906 : {
1907 284 : wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received");
1908 284 : if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
1909 3 : wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
1910 3 : wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
1911 : wpa_s->manual_scan_id);
1912 3 : wpa_s->manual_scan_use_id = 0;
1913 : } else {
1914 281 : wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
1915 : }
1916 284 : wpas_notify_scan_results(wpa_s);
1917 284 : wpas_notify_scan_done(wpa_s, 1);
1918 284 : if (wpa_s->scan_work) {
1919 284 : struct wpa_radio_work *work = wpa_s->scan_work;
1920 284 : wpa_s->scan_work = NULL;
1921 284 : radio_work_done(work);
1922 : }
1923 284 : }
1924 :
1925 :
1926 0 : int wpas_scan_scheduled(struct wpa_supplicant *wpa_s)
1927 : {
1928 0 : return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL);
1929 : }
1930 :
1931 :
1932 : struct wpa_driver_scan_params *
1933 1967 : wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
1934 : {
1935 : struct wpa_driver_scan_params *params;
1936 : size_t i;
1937 : u8 *n;
1938 :
1939 1967 : params = os_zalloc(sizeof(*params));
1940 1967 : if (params == NULL)
1941 2 : return NULL;
1942 :
1943 3920 : for (i = 0; i < src->num_ssids; i++) {
1944 1955 : if (src->ssids[i].ssid) {
1945 243 : n = os_malloc(src->ssids[i].ssid_len);
1946 243 : if (n == NULL)
1947 0 : goto failed;
1948 243 : os_memcpy(n, src->ssids[i].ssid,
1949 : src->ssids[i].ssid_len);
1950 243 : params->ssids[i].ssid = n;
1951 243 : params->ssids[i].ssid_len = src->ssids[i].ssid_len;
1952 : }
1953 : }
1954 1965 : params->num_ssids = src->num_ssids;
1955 :
1956 1965 : if (src->extra_ies) {
1957 1953 : n = os_malloc(src->extra_ies_len);
1958 1953 : if (n == NULL)
1959 0 : goto failed;
1960 1953 : os_memcpy(n, src->extra_ies, src->extra_ies_len);
1961 1953 : params->extra_ies = n;
1962 1953 : params->extra_ies_len = src->extra_ies_len;
1963 : }
1964 :
1965 1965 : if (src->freqs) {
1966 1801 : int len = int_array_len(src->freqs);
1967 1801 : params->freqs = os_malloc((len + 1) * sizeof(int));
1968 1801 : if (params->freqs == NULL)
1969 0 : goto failed;
1970 1801 : os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int));
1971 : }
1972 :
1973 1965 : if (src->filter_ssids) {
1974 2 : params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) *
1975 2 : src->num_filter_ssids);
1976 2 : if (params->filter_ssids == NULL)
1977 0 : goto failed;
1978 2 : os_memcpy(params->filter_ssids, src->filter_ssids,
1979 : sizeof(*params->filter_ssids) *
1980 : src->num_filter_ssids);
1981 2 : params->num_filter_ssids = src->num_filter_ssids;
1982 : }
1983 :
1984 1965 : params->filter_rssi = src->filter_rssi;
1985 1965 : params->p2p_probe = src->p2p_probe;
1986 1965 : params->only_new_results = src->only_new_results;
1987 1965 : params->low_priority = src->low_priority;
1988 :
1989 1965 : if (src->mac_addr_rand) {
1990 3 : params->mac_addr_rand = src->mac_addr_rand;
1991 :
1992 3 : if (src->mac_addr && src->mac_addr_mask) {
1993 : u8 *mac_addr;
1994 :
1995 2 : mac_addr = os_malloc(2 * ETH_ALEN);
1996 2 : if (!mac_addr)
1997 0 : goto failed;
1998 :
1999 2 : os_memcpy(mac_addr, src->mac_addr, ETH_ALEN);
2000 2 : os_memcpy(mac_addr + ETH_ALEN, src->mac_addr_mask,
2001 : ETH_ALEN);
2002 2 : params->mac_addr = mac_addr;
2003 2 : params->mac_addr_mask = mac_addr + ETH_ALEN;
2004 : }
2005 : }
2006 1965 : return params;
2007 :
2008 : failed:
2009 0 : wpa_scan_free_params(params);
2010 0 : return NULL;
2011 : }
2012 :
2013 :
2014 2694 : void wpa_scan_free_params(struct wpa_driver_scan_params *params)
2015 : {
2016 : size_t i;
2017 :
2018 2694 : if (params == NULL)
2019 2694 : return;
2020 :
2021 5378 : for (i = 0; i < params->num_ssids; i++)
2022 2684 : os_free((u8 *) params->ssids[i].ssid);
2023 2694 : os_free((u8 *) params->extra_ies);
2024 2694 : os_free(params->freqs);
2025 2694 : os_free(params->filter_ssids);
2026 :
2027 : /*
2028 : * Note: params->mac_addr_mask points to same memory allocation and
2029 : * must not be freed separately.
2030 : */
2031 2694 : os_free((u8 *) params->mac_addr);
2032 :
2033 2694 : os_free(params);
2034 : }
2035 :
2036 :
2037 4 : int wpas_start_pno(struct wpa_supplicant *wpa_s)
2038 : {
2039 : int ret, interval;
2040 : size_t i, num_ssid, num_match_ssid;
2041 : struct wpa_ssid *ssid;
2042 : struct wpa_driver_scan_params params;
2043 :
2044 4 : if (!wpa_s->sched_scan_supported)
2045 4 : return -1;
2046 :
2047 0 : if (wpa_s->pno || wpa_s->pno_sched_pending)
2048 0 : return 0;
2049 :
2050 0 : if ((wpa_s->wpa_state > WPA_SCANNING) &&
2051 0 : (wpa_s->wpa_state <= WPA_COMPLETED)) {
2052 0 : wpa_printf(MSG_ERROR, "PNO: In assoc process");
2053 0 : return -EAGAIN;
2054 : }
2055 :
2056 0 : if (wpa_s->wpa_state == WPA_SCANNING) {
2057 0 : wpa_supplicant_cancel_scan(wpa_s);
2058 0 : if (wpa_s->sched_scanning) {
2059 0 : wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
2060 : "ongoing sched scan");
2061 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
2062 0 : wpa_s->pno_sched_pending = 1;
2063 0 : return 0;
2064 : }
2065 : }
2066 :
2067 0 : os_memset(¶ms, 0, sizeof(params));
2068 :
2069 0 : num_ssid = num_match_ssid = 0;
2070 0 : ssid = wpa_s->conf->ssid;
2071 0 : while (ssid) {
2072 0 : if (!wpas_network_disabled(wpa_s, ssid)) {
2073 0 : num_match_ssid++;
2074 0 : if (ssid->scan_ssid)
2075 0 : num_ssid++;
2076 : }
2077 0 : ssid = ssid->next;
2078 : }
2079 :
2080 0 : if (num_match_ssid == 0) {
2081 0 : wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
2082 0 : return -1;
2083 : }
2084 :
2085 0 : if (num_match_ssid > num_ssid) {
2086 0 : params.num_ssids++; /* wildcard */
2087 0 : num_ssid++;
2088 : }
2089 :
2090 0 : if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
2091 0 : wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
2092 : "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
2093 0 : num_ssid = WPAS_MAX_SCAN_SSIDS;
2094 : }
2095 :
2096 0 : if (num_match_ssid > wpa_s->max_match_sets) {
2097 0 : num_match_ssid = wpa_s->max_match_sets;
2098 0 : wpa_dbg(wpa_s, MSG_DEBUG, "PNO: Too many SSIDs to match");
2099 : }
2100 0 : params.filter_ssids = os_calloc(num_match_ssid,
2101 : sizeof(struct wpa_driver_scan_filter));
2102 0 : if (params.filter_ssids == NULL)
2103 0 : return -1;
2104 0 : i = 0;
2105 0 : ssid = wpa_s->conf->ssid;
2106 0 : while (ssid) {
2107 0 : if (!wpas_network_disabled(wpa_s, ssid)) {
2108 0 : if (ssid->scan_ssid && params.num_ssids < num_ssid) {
2109 0 : params.ssids[params.num_ssids].ssid =
2110 0 : ssid->ssid;
2111 0 : params.ssids[params.num_ssids].ssid_len =
2112 0 : ssid->ssid_len;
2113 0 : params.num_ssids++;
2114 : }
2115 0 : os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
2116 : ssid->ssid_len);
2117 0 : params.filter_ssids[i].ssid_len = ssid->ssid_len;
2118 0 : params.num_filter_ssids++;
2119 0 : i++;
2120 0 : if (i == num_match_ssid)
2121 0 : break;
2122 : }
2123 0 : ssid = ssid->next;
2124 : }
2125 :
2126 0 : if (wpa_s->conf->filter_rssi)
2127 0 : params.filter_rssi = wpa_s->conf->filter_rssi;
2128 :
2129 0 : interval = wpa_s->conf->sched_scan_interval ?
2130 0 : wpa_s->conf->sched_scan_interval : 10;
2131 :
2132 0 : if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
2133 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
2134 0 : params.freqs = wpa_s->manual_sched_scan_freqs;
2135 : }
2136 :
2137 0 : if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) {
2138 0 : params.mac_addr_rand = 1;
2139 0 : if (wpa_s->mac_addr_pno) {
2140 0 : params.mac_addr = wpa_s->mac_addr_pno;
2141 0 : params.mac_addr_mask = wpa_s->mac_addr_pno + ETH_ALEN;
2142 : }
2143 : }
2144 :
2145 0 : ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval);
2146 0 : os_free(params.filter_ssids);
2147 0 : if (ret == 0)
2148 0 : wpa_s->pno = 1;
2149 : else
2150 0 : wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
2151 0 : return ret;
2152 : }
2153 :
2154 :
2155 1 : int wpas_stop_pno(struct wpa_supplicant *wpa_s)
2156 : {
2157 1 : int ret = 0;
2158 :
2159 1 : if (!wpa_s->pno)
2160 1 : return 0;
2161 :
2162 0 : ret = wpa_supplicant_stop_sched_scan(wpa_s);
2163 :
2164 0 : wpa_s->pno = 0;
2165 0 : wpa_s->pno_sched_pending = 0;
2166 :
2167 0 : if (wpa_s->wpa_state == WPA_SCANNING)
2168 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
2169 :
2170 0 : return ret;
2171 : }
2172 :
2173 :
2174 216 : void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s,
2175 : unsigned int type)
2176 : {
2177 216 : type &= MAC_ADDR_RAND_ALL;
2178 216 : wpa_s->mac_addr_rand_enable &= ~type;
2179 :
2180 216 : if (type & MAC_ADDR_RAND_SCAN) {
2181 216 : os_free(wpa_s->mac_addr_scan);
2182 216 : wpa_s->mac_addr_scan = NULL;
2183 : }
2184 :
2185 216 : if (type & MAC_ADDR_RAND_SCHED_SCAN) {
2186 212 : os_free(wpa_s->mac_addr_sched_scan);
2187 212 : wpa_s->mac_addr_sched_scan = NULL;
2188 : }
2189 :
2190 216 : if (type & MAC_ADDR_RAND_PNO) {
2191 212 : os_free(wpa_s->mac_addr_pno);
2192 212 : wpa_s->mac_addr_pno = NULL;
2193 : }
2194 216 : }
2195 :
2196 :
2197 3 : int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
2198 : unsigned int type, const u8 *addr,
2199 : const u8 *mask)
2200 : {
2201 3 : u8 *tmp = NULL;
2202 :
2203 3 : wpas_mac_addr_rand_scan_clear(wpa_s, type);
2204 :
2205 3 : if (addr) {
2206 2 : tmp = os_malloc(2 * ETH_ALEN);
2207 2 : if (!tmp)
2208 0 : return -1;
2209 2 : os_memcpy(tmp, addr, ETH_ALEN);
2210 2 : os_memcpy(tmp + ETH_ALEN, mask, ETH_ALEN);
2211 : }
2212 :
2213 3 : if (type == MAC_ADDR_RAND_SCAN) {
2214 3 : wpa_s->mac_addr_scan = tmp;
2215 0 : } else if (type == MAC_ADDR_RAND_SCHED_SCAN) {
2216 0 : wpa_s->mac_addr_sched_scan = tmp;
2217 0 : } else if (type == MAC_ADDR_RAND_PNO) {
2218 0 : wpa_s->mac_addr_pno = tmp;
2219 : } else {
2220 0 : wpa_printf(MSG_INFO,
2221 : "scan: Invalid MAC randomization type=0x%x",
2222 : type);
2223 0 : os_free(tmp);
2224 0 : return -1;
2225 : }
2226 :
2227 3 : wpa_s->mac_addr_rand_enable |= type;
2228 3 : return 0;
2229 : }
|