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 : wpas_notify_network_changed(wpa_s);
40 : }
41 1 : wpa_supplicant_initiate_eapol(wpa_s);
42 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
43 : "network - generating associated event");
44 1 : os_memset(&data, 0, sizeof(data));
45 1 : wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
46 : }
47 :
48 :
49 : #ifdef CONFIG_WPS
50 4564 : static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
51 : enum wps_request_type *req_type)
52 : {
53 : struct wpa_ssid *ssid;
54 4564 : int wps = 0;
55 :
56 7177 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
57 2764 : if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
58 2035 : continue;
59 :
60 729 : wps = 1;
61 729 : *req_type = wpas_wps_get_req_type(ssid);
62 729 : if (ssid->eap.phase1 && os_strstr(ssid->eap.phase1, "pbc=1"))
63 151 : return 2;
64 : }
65 :
66 : #ifdef CONFIG_P2P
67 8806 : if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p &&
68 4393 : !wpa_s->conf->p2p_disabled) {
69 4391 : wpa_s->wps->dev.p2p = 1;
70 4391 : if (!wps) {
71 3815 : wps = 1;
72 3815 : *req_type = WPS_REQ_ENROLLEE_INFO;
73 : }
74 : }
75 : #endif /* CONFIG_P2P */
76 :
77 4413 : return wps;
78 : }
79 : #endif /* CONFIG_WPS */
80 :
81 :
82 : /**
83 : * wpa_supplicant_enabled_networks - Check whether there are enabled networks
84 : * @wpa_s: Pointer to wpa_supplicant data
85 : * Returns: 0 if no networks are enabled, >0 if networks are enabled
86 : *
87 : * This function is used to figure out whether any networks (or Interworking
88 : * with enabled credentials and auto_interworking) are present in the current
89 : * configuration.
90 : */
91 7543 : int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
92 : {
93 7543 : struct wpa_ssid *ssid = wpa_s->conf->ssid;
94 7543 : int count = 0, disabled = 0;
95 :
96 7543 : if (wpa_s->p2p_mgmt)
97 27 : return 0; /* no normal network profiles on p2p_mgmt interface */
98 :
99 21817 : while (ssid) {
100 6785 : if (!wpas_network_disabled(wpa_s, ssid))
101 3967 : count++;
102 : else
103 2818 : disabled++;
104 6785 : ssid = ssid->next;
105 : }
106 7890 : if (wpa_s->conf->cred && wpa_s->conf->interworking &&
107 374 : wpa_s->conf->auto_interworking)
108 23 : count++;
109 7516 : if (count == 0 && disabled > 0) {
110 174 : wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled "
111 : "networks)", disabled);
112 : }
113 7516 : return count;
114 : }
115 :
116 :
117 16 : static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
118 : struct wpa_ssid *ssid)
119 : {
120 35 : while (ssid) {
121 17 : if (!wpas_network_disabled(wpa_s, ssid))
122 14 : break;
123 3 : ssid = ssid->next;
124 : }
125 :
126 : /* ap_scan=2 mode - try to associate with each SSID. */
127 16 : 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 18 : return;
133 : }
134 14 : 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 11 : wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
140 : }
141 14 : wpa_supplicant_associate(wpa_s, NULL, ssid);
142 : }
143 :
144 :
145 4590 : static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
146 : {
147 4590 : struct wpa_supplicant *wpa_s = work->wpa_s;
148 4590 : struct wpa_driver_scan_params *params = work->ctx;
149 : int ret;
150 :
151 4590 : if (deinit) {
152 18 : if (!work->started) {
153 2 : wpa_scan_free_params(params);
154 2 : return;
155 : }
156 16 : wpa_supplicant_notify_scanning(wpa_s, 0);
157 16 : wpas_notify_scan_done(wpa_s, 0);
158 16 : wpa_s->scan_work = NULL;
159 16 : return;
160 : }
161 :
162 4572 : if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
163 1 : wpa_msg(wpa_s, MSG_INFO,
164 : "Failed to assign random MAC address for a scan");
165 1 : wpa_scan_free_params(params);
166 1 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
167 1 : radio_work_done(work);
168 1 : return;
169 : }
170 :
171 4571 : wpa_supplicant_notify_scanning(wpa_s, 1);
172 :
173 4571 : if (wpa_s->clear_driver_scan_cache) {
174 2723 : wpa_printf(MSG_DEBUG,
175 : "Request driver to clear scan cache due to local BSS flush");
176 2723 : params->only_new_results = 1;
177 : }
178 4571 : ret = wpa_drv_scan(wpa_s, params);
179 4571 : wpa_scan_free_params(params);
180 4571 : work->ctx = NULL;
181 4571 : if (ret) {
182 11 : int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ;
183 :
184 11 : if (wpa_s->disconnected)
185 1 : retry = 0;
186 :
187 11 : wpa_supplicant_notify_scanning(wpa_s, 0);
188 11 : wpas_notify_scan_done(wpa_s, 0);
189 11 : if (wpa_s->wpa_state == WPA_SCANNING)
190 3 : wpa_supplicant_set_state(wpa_s,
191 : wpa_s->scan_prev_wpa_state);
192 11 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=%d%s",
193 : ret, retry ? " retry=1" : "");
194 11 : radio_work_done(work);
195 :
196 11 : if (retry) {
197 : /* Restore scan_req since we will try to scan again */
198 6 : wpa_s->scan_req = wpa_s->last_scan_req;
199 6 : wpa_supplicant_req_scan(wpa_s, 1, 0);
200 : }
201 11 : return;
202 : }
203 :
204 4560 : os_get_reltime(&wpa_s->scan_trigger_time);
205 4560 : wpa_s->scan_runs++;
206 4560 : wpa_s->normal_scans++;
207 4560 : wpa_s->own_scan_requested = 1;
208 4560 : wpa_s->clear_driver_scan_cache = 0;
209 4560 : wpa_s->scan_work = work;
210 : }
211 :
212 :
213 : /**
214 : * wpa_supplicant_trigger_scan - Request driver to start a scan
215 : * @wpa_s: Pointer to wpa_supplicant data
216 : * @params: Scan parameters
217 : * Returns: 0 on success, -1 on failure
218 : */
219 4581 : int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
220 : struct wpa_driver_scan_params *params)
221 : {
222 : struct wpa_driver_scan_params *ctx;
223 :
224 4581 : if (wpa_s->scan_work) {
225 1 : wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending");
226 1 : return -1;
227 : }
228 :
229 4580 : ctx = wpa_scan_clone_params(params);
230 9155 : if (!ctx ||
231 4575 : radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
232 : {
233 6 : wpa_scan_free_params(ctx);
234 6 : wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
235 6 : return -1;
236 : }
237 :
238 4574 : return 0;
239 : }
240 :
241 :
242 : static void
243 0 : wpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
244 : {
245 0 : struct wpa_supplicant *wpa_s = eloop_ctx;
246 :
247 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan");
248 :
249 0 : if (wpa_supplicant_req_sched_scan(wpa_s))
250 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
251 0 : }
252 :
253 :
254 : static void
255 0 : wpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
256 : {
257 0 : struct wpa_supplicant *wpa_s = eloop_ctx;
258 :
259 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it");
260 :
261 0 : wpa_s->sched_scan_timed_out = 1;
262 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
263 0 : }
264 :
265 :
266 : static int
267 0 : wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
268 : struct wpa_driver_scan_params *params)
269 : {
270 : int ret;
271 :
272 0 : wpa_supplicant_notify_scanning(wpa_s, 1);
273 0 : ret = wpa_drv_sched_scan(wpa_s, params);
274 0 : if (ret)
275 0 : wpa_supplicant_notify_scanning(wpa_s, 0);
276 : else
277 0 : wpa_s->sched_scanning = 1;
278 :
279 0 : return ret;
280 : }
281 :
282 :
283 0 : static int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
284 : {
285 : int ret;
286 :
287 0 : ret = wpa_drv_stop_sched_scan(wpa_s);
288 0 : if (ret) {
289 0 : wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!");
290 : /* TODO: what to do if stopping fails? */
291 0 : return -1;
292 : }
293 :
294 0 : return ret;
295 : }
296 :
297 :
298 : static struct wpa_driver_scan_filter *
299 4564 : wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
300 : {
301 : struct wpa_driver_scan_filter *ssids;
302 : struct wpa_ssid *ssid;
303 : size_t count;
304 :
305 4564 : *num_ssids = 0;
306 4564 : if (!conf->filter_ssids)
307 4560 : return NULL;
308 :
309 9 : for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
310 5 : if (ssid->ssid && ssid->ssid_len)
311 3 : count++;
312 : }
313 4 : if (count == 0)
314 1 : return NULL;
315 3 : ssids = os_calloc(count, sizeof(struct wpa_driver_scan_filter));
316 3 : if (ssids == NULL)
317 1 : return NULL;
318 :
319 5 : for (ssid = conf->ssid; ssid; ssid = ssid->next) {
320 3 : if (!ssid->ssid || !ssid->ssid_len)
321 1 : continue;
322 2 : os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
323 2 : ssids[*num_ssids].ssid_len = ssid->ssid_len;
324 2 : (*num_ssids)++;
325 : }
326 :
327 2 : return ssids;
328 : }
329 :
330 :
331 4564 : static void wpa_supplicant_optimize_freqs(
332 : struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params)
333 : {
334 : #ifdef CONFIG_P2P
335 4893 : if (params->freqs == NULL && wpa_s->p2p_in_provisioning &&
336 329 : wpa_s->go_params) {
337 : /* Optimize provisioning state scan based on GO information */
338 637 : if (wpa_s->p2p_in_provisioning < 5 &&
339 308 : wpa_s->go_params->freq > 0) {
340 308 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO "
341 : "preferred frequency %d MHz",
342 : wpa_s->go_params->freq);
343 308 : params->freqs = os_calloc(2, sizeof(int));
344 616 : if (params->freqs)
345 308 : params->freqs[0] = wpa_s->go_params->freq;
346 30 : } else if (wpa_s->p2p_in_provisioning < 8 &&
347 9 : wpa_s->go_params->freq_list[0]) {
348 3 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common "
349 : "channels");
350 3 : int_array_concat(¶ms->freqs,
351 3 : wpa_s->go_params->freq_list);
352 3 : if (params->freqs)
353 3 : int_array_sort_unique(params->freqs);
354 : }
355 329 : wpa_s->p2p_in_provisioning++;
356 : }
357 :
358 4564 : if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
359 : /*
360 : * Optimize scan based on GO information during persistent
361 : * group reinvocation
362 : */
363 148 : if (wpa_s->p2p_in_invitation < 5 &&
364 72 : wpa_s->p2p_invite_go_freq > 0) {
365 72 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
366 : wpa_s->p2p_invite_go_freq);
367 72 : params->freqs = os_calloc(2, sizeof(int));
368 72 : if (params->freqs)
369 72 : params->freqs[0] = wpa_s->p2p_invite_go_freq;
370 : }
371 76 : wpa_s->p2p_in_invitation++;
372 76 : if (wpa_s->p2p_in_invitation > 20) {
373 : /*
374 : * This should not really happen since the variable is
375 : * cleared on group removal, but if it does happen, make
376 : * sure we do not get stuck in special invitation scan
377 : * mode.
378 : */
379 0 : wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
380 0 : wpa_s->p2p_in_invitation = 0;
381 : }
382 : }
383 : #endif /* CONFIG_P2P */
384 :
385 : #ifdef CONFIG_WPS
386 4564 : if (params->freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
387 : /*
388 : * Optimize post-provisioning scan based on channel used
389 : * during provisioning.
390 : */
391 25 : wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz "
392 : "that was used during provisioning", wpa_s->wps_freq);
393 25 : params->freqs = os_calloc(2, sizeof(int));
394 25 : if (params->freqs)
395 25 : params->freqs[0] = wpa_s->wps_freq;
396 25 : wpa_s->after_wps--;
397 4539 : } else if (wpa_s->after_wps)
398 6 : wpa_s->after_wps--;
399 :
400 4564 : if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
401 : {
402 : /* Optimize provisioning scan based on already known channel */
403 318 : wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz",
404 : wpa_s->wps_freq);
405 318 : params->freqs = os_calloc(2, sizeof(int));
406 318 : if (params->freqs)
407 318 : params->freqs[0] = wpa_s->wps_freq;
408 318 : wpa_s->known_wps_freq = 0; /* only do this once */
409 : }
410 : #endif /* CONFIG_WPS */
411 4564 : }
412 :
413 :
414 : #ifdef CONFIG_INTERWORKING
415 1815 : static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
416 : struct wpabuf *buf)
417 : {
418 1815 : wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
419 1815 : wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
420 : 1 + ETH_ALEN);
421 1815 : wpabuf_put_u8(buf, wpa_s->conf->access_network_type);
422 : /* No Venue Info */
423 1815 : if (!is_zero_ether_addr(wpa_s->conf->hessid))
424 4 : wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN);
425 1815 : }
426 : #endif /* CONFIG_INTERWORKING */
427 :
428 :
429 959 : void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
430 : {
431 959 : struct wpabuf *default_ies = NULL;
432 : u8 ext_capab[18];
433 : int ext_capab_len;
434 959 : enum wpa_driver_if_type type = WPA_IF_STATION;
435 :
436 : #ifdef CONFIG_P2P
437 959 : if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
438 0 : type = WPA_IF_P2P_CLIENT;
439 : #endif /* CONFIG_P2P */
440 :
441 959 : wpa_drv_get_ext_capa(wpa_s, type);
442 :
443 959 : ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
444 : sizeof(ext_capab));
445 1918 : if (ext_capab_len > 0 &&
446 959 : wpabuf_resize(&default_ies, ext_capab_len) == 0)
447 958 : wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
448 :
449 : #ifdef CONFIG_MBO
450 : /* Send cellular capabilities for potential MBO STAs */
451 959 : if (wpabuf_resize(&default_ies, 9) == 0)
452 958 : wpas_mbo_scan_ie(wpa_s, default_ies);
453 : #endif /* CONFIG_MBO */
454 :
455 959 : if (default_ies)
456 959 : wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
457 : wpabuf_len(default_ies));
458 959 : wpabuf_free(default_ies);
459 959 : }
460 :
461 :
462 4564 : static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
463 : {
464 4564 : struct wpabuf *extra_ie = NULL;
465 : u8 ext_capab[18];
466 : int ext_capab_len;
467 : #ifdef CONFIG_WPS
468 4564 : int wps = 0;
469 4564 : enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
470 : #endif /* CONFIG_WPS */
471 :
472 : #ifdef CONFIG_P2P
473 4564 : if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
474 79 : wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
475 : else
476 : #endif /* CONFIG_P2P */
477 4485 : wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
478 :
479 4564 : ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
480 : sizeof(ext_capab));
481 9128 : if (ext_capab_len > 0 &&
482 4564 : wpabuf_resize(&extra_ie, ext_capab_len) == 0)
483 4564 : wpabuf_put_data(extra_ie, ext_capab, ext_capab_len);
484 :
485 : #ifdef CONFIG_INTERWORKING
486 6379 : if (wpa_s->conf->interworking &&
487 1815 : wpabuf_resize(&extra_ie, 100) == 0)
488 1815 : wpas_add_interworking_elements(wpa_s, extra_ie);
489 : #endif /* CONFIG_INTERWORKING */
490 :
491 : #ifdef CONFIG_WPS
492 4564 : wps = wpas_wps_in_use(wpa_s, &req_type);
493 :
494 4564 : if (wps) {
495 : struct wpabuf *wps_ie;
496 9088 : wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
497 : DEV_PW_DEFAULT,
498 4544 : &wpa_s->wps->dev,
499 4544 : wpa_s->wps->uuid, req_type,
500 : 0, NULL);
501 4544 : if (wps_ie) {
502 4542 : if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
503 4542 : wpabuf_put_buf(extra_ie, wps_ie);
504 4542 : wpabuf_free(wps_ie);
505 : }
506 : }
507 :
508 : #ifdef CONFIG_P2P
509 4564 : if (wps) {
510 4544 : size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
511 4544 : if (wpabuf_resize(&extra_ie, ielen) == 0)
512 4544 : wpas_p2p_scan_ie(wpa_s, extra_ie);
513 : }
514 : #endif /* CONFIG_P2P */
515 :
516 4564 : wpa_supplicant_mesh_add_scan_ie(wpa_s, &extra_ie);
517 :
518 : #endif /* CONFIG_WPS */
519 :
520 : #ifdef CONFIG_HS20
521 4564 : if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
522 1815 : wpas_hs20_add_indication(extra_ie, -1);
523 : #endif /* CONFIG_HS20 */
524 :
525 : #ifdef CONFIG_FST
526 4818 : if (wpa_s->fst_ies &&
527 254 : wpabuf_resize(&extra_ie, wpabuf_len(wpa_s->fst_ies)) == 0)
528 254 : wpabuf_put_buf(extra_ie, wpa_s->fst_ies);
529 : #endif /* CONFIG_FST */
530 :
531 : #ifdef CONFIG_MBO
532 : /* Send cellular capabilities for potential MBO STAs */
533 4564 : if (wpabuf_resize(&extra_ie, 9) == 0)
534 4564 : wpas_mbo_scan_ie(wpa_s, extra_ie);
535 : #endif /* CONFIG_MBO */
536 :
537 4564 : if (wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ]) {
538 1 : struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ];
539 :
540 1 : if (wpabuf_resize(&extra_ie, wpabuf_len(buf)) == 0)
541 1 : wpabuf_put_buf(extra_ie, buf);
542 : }
543 :
544 4564 : return extra_ie;
545 : }
546 :
547 :
548 : #ifdef CONFIG_P2P
549 :
550 : /*
551 : * Check whether there are any enabled networks or credentials that could be
552 : * used for a non-P2P connection.
553 : */
554 55 : static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
555 : {
556 : struct wpa_ssid *ssid;
557 :
558 74 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
559 61 : if (wpas_network_disabled(wpa_s, ssid))
560 6 : continue;
561 55 : if (!ssid->p2p_group)
562 42 : return 1;
563 : }
564 :
565 13 : if (wpa_s->conf->cred && wpa_s->conf->interworking &&
566 0 : wpa_s->conf->auto_interworking)
567 0 : return 1;
568 :
569 13 : return 0;
570 : }
571 :
572 : #endif /* CONFIG_P2P */
573 :
574 :
575 3 : static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
576 : enum hostapd_hw_mode band,
577 : struct wpa_driver_scan_params *params)
578 : {
579 : /* Include only supported channels for the specified band */
580 : struct hostapd_hw_modes *mode;
581 : int count, i;
582 :
583 3 : mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
584 3 : if (mode == NULL) {
585 : /* No channels supported in this band - use empty list */
586 0 : params->freqs = os_zalloc(sizeof(int));
587 0 : return;
588 : }
589 :
590 3 : params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
591 3 : if (params->freqs == NULL)
592 1 : return;
593 40 : for (count = 0, i = 0; i < mode->num_channels; i++) {
594 38 : if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
595 3 : continue;
596 35 : params->freqs[count++] = mode->channels[i].freq;
597 : }
598 : }
599 :
600 :
601 4564 : static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
602 : struct wpa_driver_scan_params *params)
603 : {
604 4564 : if (wpa_s->hw.modes == NULL)
605 15 : return; /* unknown what channels the driver supports */
606 4549 : if (params->freqs)
607 4343 : return; /* already using a limited channel set */
608 206 : if (wpa_s->setband == WPA_SETBAND_5G)
609 1 : wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
610 : params);
611 205 : else if (wpa_s->setband == WPA_SETBAND_2G)
612 2 : wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
613 : params);
614 : }
615 :
616 :
617 3 : static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
618 : struct wpa_driver_scan_params *params,
619 : size_t max_ssids)
620 : {
621 : unsigned int i;
622 : struct wpa_ssid *ssid;
623 :
624 : /*
625 : * For devices with max_ssids greater than 1, leave the last slot empty
626 : * for adding the wildcard scan entry.
627 : */
628 3 : max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
629 :
630 10 : for (i = 0; i < wpa_s->scan_id_count; i++) {
631 : unsigned int j;
632 :
633 7 : ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
634 7 : if (!ssid || !ssid->scan_ssid)
635 1 : continue;
636 :
637 8 : for (j = 0; j < params->num_ssids; j++) {
638 4 : if (params->ssids[j].ssid_len == ssid->ssid_len &&
639 2 : params->ssids[j].ssid &&
640 1 : os_memcmp(params->ssids[j].ssid, ssid->ssid,
641 : ssid->ssid_len) == 0)
642 1 : break;
643 : }
644 6 : if (j < params->num_ssids)
645 1 : continue; /* already in the list */
646 :
647 5 : if (params->num_ssids + 1 > max_ssids) {
648 0 : wpa_printf(MSG_DEBUG,
649 : "Over max scan SSIDs for manual request");
650 0 : break;
651 : }
652 :
653 10 : wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
654 5 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
655 5 : params->ssids[params->num_ssids].ssid = ssid->ssid;
656 5 : params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
657 5 : params->num_ssids++;
658 : }
659 :
660 3 : wpa_s->scan_id_count = 0;
661 3 : }
662 :
663 :
664 2214 : static int wpa_set_ssids_from_scan_req(struct wpa_supplicant *wpa_s,
665 : struct wpa_driver_scan_params *params,
666 : size_t max_ssids)
667 : {
668 : unsigned int i;
669 :
670 2220 : if (wpa_s->ssids_from_scan_req == NULL ||
671 6 : wpa_s->num_ssids_from_scan_req == 0)
672 2208 : return 0;
673 :
674 6 : if (wpa_s->num_ssids_from_scan_req > max_ssids) {
675 0 : wpa_s->num_ssids_from_scan_req = max_ssids;
676 0 : wpa_printf(MSG_DEBUG, "Over max scan SSIDs from scan req: %u",
677 : (unsigned int) max_ssids);
678 : }
679 :
680 14 : for (i = 0; i < wpa_s->num_ssids_from_scan_req; i++) {
681 8 : params->ssids[i].ssid = wpa_s->ssids_from_scan_req[i].ssid;
682 8 : params->ssids[i].ssid_len =
683 8 : wpa_s->ssids_from_scan_req[i].ssid_len;
684 16 : wpa_hexdump_ascii(MSG_DEBUG, "specific SSID",
685 8 : params->ssids[i].ssid,
686 : params->ssids[i].ssid_len);
687 : }
688 :
689 6 : params->num_ssids = wpa_s->num_ssids_from_scan_req;
690 6 : wpa_s->num_ssids_from_scan_req = 0;
691 6 : return 1;
692 : }
693 :
694 :
695 5565 : static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
696 : {
697 5565 : struct wpa_supplicant *wpa_s = eloop_ctx;
698 : struct wpa_ssid *ssid;
699 : int ret, p2p_in_prog;
700 5565 : struct wpabuf *extra_ie = NULL;
701 : struct wpa_driver_scan_params params;
702 : struct wpa_driver_scan_params *scan_params;
703 : size_t max_ssids;
704 5565 : int connect_without_scan = 0;
705 :
706 5565 : if (wpa_s->pno || wpa_s->pno_sched_pending) {
707 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
708 0 : return;
709 : }
710 :
711 5565 : if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
712 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
713 0 : return;
714 : }
715 :
716 5565 : if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
717 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
718 0 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
719 0 : return;
720 : }
721 :
722 5565 : if (wpa_s->scanning) {
723 : /*
724 : * If we are already in scanning state, we shall reschedule the
725 : * the incoming scan request.
726 : */
727 11 : wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req");
728 11 : wpa_supplicant_req_scan(wpa_s, 1, 0);
729 11 : return;
730 : }
731 :
732 7894 : if (!wpa_supplicant_enabled_networks(wpa_s) &&
733 2340 : wpa_s->scan_req == NORMAL_SCAN_REQ) {
734 377 : wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
735 377 : wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
736 377 : return;
737 : }
738 :
739 10352 : if (wpa_s->conf->ap_scan != 0 &&
740 5175 : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
741 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - "
742 : "overriding ap_scan configuration");
743 0 : wpa_s->conf->ap_scan = 0;
744 0 : wpas_notify_ap_scan_changed(wpa_s);
745 : }
746 :
747 5177 : if (wpa_s->conf->ap_scan == 0) {
748 2 : wpa_supplicant_gen_assoc_event(wpa_s);
749 2 : return;
750 : }
751 :
752 5175 : ssid = NULL;
753 8135 : if (wpa_s->scan_req != MANUAL_SCAN_REQ &&
754 2960 : wpa_s->connect_without_scan) {
755 594 : connect_without_scan = 1;
756 2984 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
757 2984 : if (ssid == wpa_s->connect_without_scan)
758 594 : break;
759 : }
760 : }
761 :
762 5175 : p2p_in_prog = wpas_p2p_in_progress(wpa_s);
763 5175 : if (p2p_in_prog && p2p_in_prog != 2 &&
764 62 : (!ssid ||
765 124 : (ssid->mode != WPAS_MODE_AP && ssid->mode != WPAS_MODE_P2P_GO))) {
766 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
767 1 : wpa_supplicant_req_scan(wpa_s, 5, 0);
768 1 : return;
769 : }
770 :
771 5174 : if (wpa_s->conf->ap_scan == 2)
772 20 : max_ssids = 1;
773 : else {
774 5154 : max_ssids = wpa_s->max_scan_ssids;
775 5154 : if (max_ssids > WPAS_MAX_SCAN_SSIDS)
776 40 : max_ssids = WPAS_MAX_SCAN_SSIDS;
777 : }
778 :
779 5174 : wpa_s->last_scan_req = wpa_s->scan_req;
780 5174 : wpa_s->scan_req = NORMAL_SCAN_REQ;
781 :
782 5174 : if (connect_without_scan) {
783 594 : wpa_s->connect_without_scan = NULL;
784 594 : if (ssid) {
785 594 : wpa_printf(MSG_DEBUG, "Start a pre-selected network "
786 : "without scan step");
787 594 : wpa_supplicant_associate(wpa_s, NULL, ssid);
788 594 : return;
789 : }
790 : }
791 :
792 4580 : os_memset(¶ms, 0, sizeof(params));
793 :
794 4580 : wpa_s->scan_prev_wpa_state = wpa_s->wpa_state;
795 5620 : if (wpa_s->wpa_state == WPA_DISCONNECTED ||
796 1040 : wpa_s->wpa_state == WPA_INACTIVE)
797 4019 : wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
798 :
799 : /*
800 : * If autoscan has set its own scanning parameters
801 : */
802 4580 : if (wpa_s->autoscan_params != NULL) {
803 0 : scan_params = wpa_s->autoscan_params;
804 0 : goto scan;
805 : }
806 :
807 6794 : if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
808 2214 : wpa_set_ssids_from_scan_req(wpa_s, ¶ms, max_ssids)) {
809 6 : wpa_printf(MSG_DEBUG, "Use specific SSIDs from SCAN command");
810 6 : goto ssid_list_set;
811 : }
812 :
813 : #ifdef CONFIG_P2P
814 4979 : if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
815 734 : wpa_s->go_params && !wpa_s->conf->passive_scan) {
816 324 : wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)",
817 : wpa_s->p2p_in_provisioning,
818 : wpa_s->show_group_started);
819 324 : params.ssids[0].ssid = wpa_s->go_params->ssid;
820 324 : params.ssids[0].ssid_len = wpa_s->go_params->ssid_len;
821 324 : params.num_ssids = 1;
822 324 : goto ssid_list_set;
823 : }
824 :
825 4250 : if (wpa_s->p2p_in_invitation) {
826 76 : if (wpa_s->current_ssid) {
827 65 : wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation");
828 65 : params.ssids[0].ssid = wpa_s->current_ssid->ssid;
829 65 : params.ssids[0].ssid_len =
830 65 : wpa_s->current_ssid->ssid_len;
831 65 : params.num_ssids = 1;
832 : } else {
833 11 : wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation");
834 : }
835 76 : goto ssid_list_set;
836 : }
837 : #endif /* CONFIG_P2P */
838 :
839 : /* Find the starting point from which to continue scanning */
840 4174 : ssid = wpa_s->conf->ssid;
841 4174 : if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
842 12 : while (ssid) {
843 5 : if (ssid == wpa_s->prev_scan_ssid) {
844 3 : ssid = ssid->next;
845 3 : break;
846 : }
847 2 : ssid = ssid->next;
848 : }
849 : }
850 :
851 6140 : if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
852 : #ifdef CONFIG_AP
853 3927 : !wpa_s->ap_iface &&
854 : #endif /* CONFIG_AP */
855 1961 : wpa_s->conf->ap_scan == 2) {
856 16 : wpa_s->connect_without_scan = NULL;
857 16 : wpa_s->prev_scan_wildcard = 0;
858 16 : wpa_supplicant_assoc_try(wpa_s, ssid);
859 16 : return;
860 4158 : } else if (wpa_s->conf->ap_scan == 2) {
861 : /*
862 : * User-initiated scan request in ap_scan == 2; scan with
863 : * wildcard SSID.
864 : */
865 4 : ssid = NULL;
866 4154 : } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
867 : /*
868 : * Perform single-channel single-SSID scan for
869 : * reassociate-to-same-BSS operation.
870 : */
871 : /* Setup SSID */
872 1 : ssid = wpa_s->current_ssid;
873 2 : wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
874 1 : ssid->ssid, ssid->ssid_len);
875 1 : params.ssids[0].ssid = ssid->ssid;
876 1 : params.ssids[0].ssid_len = ssid->ssid_len;
877 1 : params.num_ssids = 1;
878 :
879 : /*
880 : * Allocate memory for frequency array, allocate one extra
881 : * slot for the zero-terminator.
882 : */
883 1 : params.freqs = os_malloc(sizeof(int) * 2);
884 1 : if (params.freqs) {
885 1 : params.freqs[0] = wpa_s->assoc_freq;
886 1 : params.freqs[1] = 0;
887 : }
888 :
889 : /*
890 : * Reset the reattach flag so that we fall back to full scan if
891 : * this scan fails.
892 : */
893 1 : wpa_s->reattach = 0;
894 : } else {
895 4153 : struct wpa_ssid *start = ssid, *tssid;
896 4153 : int freqs_set = 0;
897 4153 : if (ssid == NULL && max_ssids > 1)
898 1937 : ssid = wpa_s->conf->ssid;
899 10579 : while (ssid) {
900 4481 : if (!wpas_network_disabled(wpa_s, ssid) &&
901 2204 : ssid->scan_ssid) {
902 22 : wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
903 11 : ssid->ssid, ssid->ssid_len);
904 22 : params.ssids[params.num_ssids].ssid =
905 11 : ssid->ssid;
906 22 : params.ssids[params.num_ssids].ssid_len =
907 11 : ssid->ssid_len;
908 11 : params.num_ssids++;
909 11 : if (params.num_ssids + 1 >= max_ssids)
910 4 : break;
911 : }
912 2273 : ssid = ssid->next;
913 2273 : if (ssid == start)
914 0 : break;
915 4472 : if (ssid == NULL && max_ssids > 1 &&
916 2199 : start != wpa_s->conf->ssid)
917 0 : ssid = wpa_s->conf->ssid;
918 : }
919 :
920 4156 : if (wpa_s->scan_id_count &&
921 3 : wpa_s->last_scan_req == MANUAL_SCAN_REQ)
922 3 : wpa_set_scan_ssids(wpa_s, ¶ms, max_ssids);
923 :
924 10315 : for (tssid = wpa_s->conf->ssid;
925 10120 : wpa_s->last_scan_req != MANUAL_SCAN_REQ && tssid;
926 2009 : tssid = tssid->next) {
927 2009 : if (wpas_network_disabled(wpa_s, tssid))
928 44 : continue;
929 1965 : if ((params.freqs || !freqs_set) && tssid->scan_freq) {
930 1468 : int_array_concat(¶ms.freqs,
931 1468 : tssid->scan_freq);
932 : } else {
933 497 : os_free(params.freqs);
934 497 : params.freqs = NULL;
935 : }
936 1965 : freqs_set = 1;
937 : }
938 4153 : int_array_sort_unique(params.freqs);
939 : }
940 :
941 4158 : if (ssid && max_ssids == 1) {
942 : /*
943 : * If the driver is limited to 1 SSID at a time interleave
944 : * wildcard SSID scans with specific SSID scans to avoid
945 : * waiting a long time for a wildcard scan.
946 : */
947 4 : if (!wpa_s->prev_scan_wildcard) {
948 1 : params.ssids[0].ssid = NULL;
949 1 : params.ssids[0].ssid_len = 0;
950 1 : wpa_s->prev_scan_wildcard = 1;
951 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for "
952 : "wildcard SSID (Interleave with specific)");
953 : } else {
954 1 : wpa_s->prev_scan_ssid = ssid;
955 1 : wpa_s->prev_scan_wildcard = 0;
956 1 : wpa_dbg(wpa_s, MSG_DEBUG,
957 : "Starting AP scan for specific SSID: %s",
958 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
959 : }
960 4156 : } else if (ssid) {
961 : /* max_ssids > 1 */
962 :
963 3 : wpa_s->prev_scan_ssid = ssid;
964 3 : wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
965 : "the scan request");
966 3 : params.num_ssids++;
967 4153 : } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
968 14 : wpa_s->manual_scan_passive && params.num_ssids == 0) {
969 14 : wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request");
970 4139 : } else if (wpa_s->conf->passive_scan) {
971 5 : wpa_dbg(wpa_s, MSG_DEBUG,
972 : "Use passive scan based on configuration");
973 : } else {
974 4134 : wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
975 4134 : params.num_ssids++;
976 4134 : wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard "
977 : "SSID");
978 : }
979 :
980 : ssid_list_set:
981 4564 : wpa_supplicant_optimize_freqs(wpa_s, ¶ms);
982 4564 : extra_ie = wpa_supplicant_extra_ies(wpa_s);
983 :
984 4564 : if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
985 : wpa_s->manual_scan_only_new) {
986 954 : wpa_printf(MSG_DEBUG,
987 : "Request driver to clear scan cache due to manual only_new=1 scan");
988 954 : params.only_new_results = 1;
989 : }
990 :
991 6777 : if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
992 2213 : wpa_s->manual_scan_freqs) {
993 2164 : wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
994 2164 : params.freqs = wpa_s->manual_scan_freqs;
995 2164 : wpa_s->manual_scan_freqs = NULL;
996 : }
997 :
998 4564 : if (params.freqs == NULL && wpa_s->next_scan_freqs) {
999 10 : wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
1000 : "generated frequency list");
1001 10 : params.freqs = wpa_s->next_scan_freqs;
1002 : } else
1003 4554 : os_free(wpa_s->next_scan_freqs);
1004 4564 : wpa_s->next_scan_freqs = NULL;
1005 4564 : wpa_setband_scan_freqs(wpa_s, ¶ms);
1006 :
1007 : /* See if user specified frequencies. If so, scan only those. */
1008 4564 : if (wpa_s->conf->freq_list && !params.freqs) {
1009 1 : wpa_dbg(wpa_s, MSG_DEBUG,
1010 : "Optimize scan based on conf->freq_list");
1011 1 : int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);
1012 : }
1013 :
1014 : /* Use current associated channel? */
1015 4564 : if (wpa_s->conf->scan_cur_freq && !params.freqs) {
1016 1 : unsigned int num = wpa_s->num_multichan_concurrent;
1017 :
1018 1 : params.freqs = os_calloc(num + 1, sizeof(int));
1019 1 : if (params.freqs) {
1020 1 : num = get_shared_radio_freqs(wpa_s, params.freqs, num);
1021 1 : if (num > 0) {
1022 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
1023 : "current operating channels since "
1024 : "scan_cur_freq is enabled");
1025 : } else {
1026 0 : os_free(params.freqs);
1027 0 : params.freqs = NULL;
1028 : }
1029 : }
1030 : }
1031 :
1032 4564 : params.filter_ssids = wpa_supplicant_build_filter_ssids(
1033 : wpa_s->conf, ¶ms.num_filter_ssids);
1034 4564 : if (extra_ie) {
1035 4564 : params.extra_ies = wpabuf_head(extra_ie);
1036 4564 : params.extra_ies_len = wpabuf_len(extra_ie);
1037 : }
1038 :
1039 : #ifdef CONFIG_P2P
1040 8723 : if (wpa_s->p2p_in_provisioning || wpa_s->p2p_in_invitation ||
1041 4159 : (wpa_s->show_group_started && wpa_s->go_params)) {
1042 : /*
1043 : * The interface may not yet be in P2P mode, so we have to
1044 : * explicitly request P2P probe to disable CCK rates.
1045 : */
1046 405 : params.p2p_probe = 1;
1047 : }
1048 : #endif /* CONFIG_P2P */
1049 :
1050 4564 : if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) {
1051 3 : params.mac_addr_rand = 1;
1052 3 : if (wpa_s->mac_addr_scan) {
1053 2 : params.mac_addr = wpa_s->mac_addr_scan;
1054 2 : params.mac_addr_mask = wpa_s->mac_addr_scan + ETH_ALEN;
1055 : }
1056 : }
1057 :
1058 4564 : if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
1059 : struct wpa_bss *bss;
1060 :
1061 8 : params.bssid = wpa_s->next_scan_bssid;
1062 8 : bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid);
1063 10 : if (bss && bss->ssid_len && params.num_ssids == 1 &&
1064 2 : params.ssids[0].ssid_len == 0) {
1065 2 : params.ssids[0].ssid = bss->ssid;
1066 2 : params.ssids[0].ssid_len = bss->ssid_len;
1067 2 : wpa_dbg(wpa_s, MSG_DEBUG,
1068 : "Scan a previously specified BSSID " MACSTR
1069 : " and SSID %s",
1070 : MAC2STR(params.bssid),
1071 : wpa_ssid_txt(bss->ssid, bss->ssid_len));
1072 : } else {
1073 6 : wpa_dbg(wpa_s, MSG_DEBUG,
1074 : "Scan a previously specified BSSID " MACSTR,
1075 : MAC2STR(params.bssid));
1076 : }
1077 : }
1078 :
1079 4564 : scan_params = ¶ms;
1080 :
1081 : scan:
1082 : #ifdef CONFIG_P2P
1083 : /*
1084 : * If the driver does not support multi-channel concurrency and a
1085 : * virtual interface that shares the same radio with the wpa_s interface
1086 : * is operating there may not be need to scan other channels apart from
1087 : * the current operating channel on the other virtual interface. Filter
1088 : * out other channels in case we are trying to find a connection for a
1089 : * station interface when we are not configured to prefer station
1090 : * connection and a concurrent operation is already in process.
1091 : */
1092 4921 : if (wpa_s->scan_for_connection &&
1093 680 : wpa_s->last_scan_req == NORMAL_SCAN_REQ &&
1094 441 : !scan_params->freqs && !params.freqs &&
1095 118 : wpas_is_p2p_prioritized(wpa_s) &&
1096 114 : wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
1097 55 : non_p2p_network_enabled(wpa_s)) {
1098 42 : unsigned int num = wpa_s->num_multichan_concurrent;
1099 :
1100 42 : params.freqs = os_calloc(num + 1, sizeof(int));
1101 42 : if (params.freqs) {
1102 42 : num = get_shared_radio_freqs(wpa_s, params.freqs, num);
1103 42 : if (num > 0 && num == wpa_s->num_multichan_concurrent) {
1104 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used");
1105 : } else {
1106 42 : os_free(params.freqs);
1107 42 : params.freqs = NULL;
1108 : }
1109 : }
1110 : }
1111 : #endif /* CONFIG_P2P */
1112 :
1113 4564 : ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
1114 :
1115 4569 : if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
1116 5 : !wpa_s->manual_scan_freqs) {
1117 : /* Restore manual_scan_freqs for the next attempt */
1118 5 : wpa_s->manual_scan_freqs = params.freqs;
1119 5 : params.freqs = NULL;
1120 : }
1121 :
1122 4564 : wpabuf_free(extra_ie);
1123 4564 : os_free(params.freqs);
1124 4564 : os_free(params.filter_ssids);
1125 :
1126 4564 : if (ret) {
1127 5 : wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
1128 5 : if (wpa_s->scan_prev_wpa_state != wpa_s->wpa_state)
1129 5 : wpa_supplicant_set_state(wpa_s,
1130 : wpa_s->scan_prev_wpa_state);
1131 : /* Restore scan_req since we will try to scan again */
1132 5 : wpa_s->scan_req = wpa_s->last_scan_req;
1133 5 : wpa_supplicant_req_scan(wpa_s, 1, 0);
1134 : } else {
1135 4559 : wpa_s->scan_for_connection = 0;
1136 : #ifdef CONFIG_INTERWORKING
1137 4559 : wpa_s->interworking_fast_assoc_tried = 0;
1138 : #endif /* CONFIG_INTERWORKING */
1139 4559 : if (params.bssid)
1140 8 : os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
1141 : }
1142 : }
1143 :
1144 :
1145 26 : void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec)
1146 : {
1147 : struct os_reltime remaining, new_int;
1148 : int cancelled;
1149 :
1150 26 : cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL,
1151 : &remaining);
1152 :
1153 26 : new_int.sec = sec;
1154 26 : new_int.usec = 0;
1155 26 : if (cancelled && os_reltime_before(&remaining, &new_int)) {
1156 7 : new_int.sec = remaining.sec;
1157 7 : new_int.usec = remaining.usec;
1158 : }
1159 :
1160 26 : if (cancelled) {
1161 7 : eloop_register_timeout(new_int.sec, new_int.usec,
1162 : wpa_supplicant_scan, wpa_s, NULL);
1163 : }
1164 26 : wpa_s->scan_interval = sec;
1165 26 : }
1166 :
1167 :
1168 : /**
1169 : * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
1170 : * @wpa_s: Pointer to wpa_supplicant data
1171 : * @sec: Number of seconds after which to scan
1172 : * @usec: Number of microseconds after which to scan
1173 : *
1174 : * This function is used to schedule a scan for neighboring access points after
1175 : * the specified time.
1176 : */
1177 8457 : void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
1178 : {
1179 : int res;
1180 :
1181 8457 : if (wpa_s->p2p_mgmt) {
1182 2 : wpa_dbg(wpa_s, MSG_DEBUG,
1183 : "Ignore scan request (%d.%06d sec) on p2p_mgmt interface",
1184 : sec, usec);
1185 8459 : return;
1186 : }
1187 :
1188 8455 : res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
1189 : NULL);
1190 8455 : if (res == 1) {
1191 218 : wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d.%06d sec",
1192 : sec, usec);
1193 8237 : } else if (res == 0) {
1194 481 : wpa_dbg(wpa_s, MSG_DEBUG, "Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner",
1195 : sec, usec);
1196 : } else {
1197 7756 : wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d.%06d sec",
1198 : sec, usec);
1199 7756 : eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
1200 : }
1201 : }
1202 :
1203 :
1204 : /**
1205 : * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan
1206 : * @wpa_s: Pointer to wpa_supplicant data
1207 : * @sec: Number of seconds after which to scan
1208 : * @usec: Number of microseconds after which to scan
1209 : * Returns: 0 on success or -1 otherwise
1210 : *
1211 : * This function is used to schedule periodic scans for neighboring
1212 : * access points after the specified time.
1213 : */
1214 0 : int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
1215 : int sec, int usec)
1216 : {
1217 0 : if (!wpa_s->sched_scan_supported)
1218 0 : return -1;
1219 :
1220 0 : eloop_register_timeout(sec, usec,
1221 : wpa_supplicant_delayed_sched_scan_timeout,
1222 : wpa_s, NULL);
1223 :
1224 0 : return 0;
1225 : }
1226 :
1227 :
1228 : /**
1229 : * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
1230 : * @wpa_s: Pointer to wpa_supplicant data
1231 : * Returns: 0 is sched_scan was started or -1 otherwise
1232 : *
1233 : * This function is used to schedule periodic scans for neighboring
1234 : * access points repeating the scan continuously.
1235 : */
1236 678 : int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
1237 : {
1238 : struct wpa_driver_scan_params params;
1239 : struct wpa_driver_scan_params *scan_params;
1240 : enum wpa_states prev_state;
1241 678 : struct wpa_ssid *ssid = NULL;
1242 678 : struct wpabuf *extra_ie = NULL;
1243 : int ret;
1244 : unsigned int max_sched_scan_ssids;
1245 678 : int wildcard = 0;
1246 : int need_ssids;
1247 : struct sched_scan_plan scan_plan;
1248 :
1249 678 : if (!wpa_s->sched_scan_supported)
1250 678 : return -1;
1251 :
1252 0 : if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
1253 0 : max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
1254 : else
1255 0 : max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
1256 0 : if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
1257 0 : return -1;
1258 :
1259 0 : wpa_s->sched_scan_stop_req = 0;
1260 :
1261 0 : if (wpa_s->sched_scanning) {
1262 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
1263 0 : return 0;
1264 : }
1265 :
1266 0 : need_ssids = 0;
1267 0 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1268 0 : if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) {
1269 : /* Use wildcard SSID to find this network */
1270 0 : wildcard = 1;
1271 0 : } else if (!wpas_network_disabled(wpa_s, ssid) &&
1272 0 : ssid->ssid_len)
1273 0 : need_ssids++;
1274 :
1275 : #ifdef CONFIG_WPS
1276 0 : if (!wpas_network_disabled(wpa_s, ssid) &&
1277 0 : ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
1278 : /*
1279 : * Normal scan is more reliable and faster for WPS
1280 : * operations and since these are for short periods of
1281 : * time, the benefit of trying to use sched_scan would
1282 : * be limited.
1283 : */
1284 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
1285 : "sched_scan for WPS");
1286 0 : return -1;
1287 : }
1288 : #endif /* CONFIG_WPS */
1289 : }
1290 0 : if (wildcard)
1291 0 : need_ssids++;
1292 :
1293 0 : if (wpa_s->normal_scans < 3 &&
1294 0 : (need_ssids <= wpa_s->max_scan_ssids ||
1295 0 : wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) {
1296 : /*
1297 : * When normal scan can speed up operations, use that for the
1298 : * first operations before starting the sched_scan to allow
1299 : * user space sleep more. We do this only if the normal scan
1300 : * has functionality that is suitable for this or if the
1301 : * sched_scan does not have better support for multiple SSIDs.
1302 : */
1303 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
1304 : "sched_scan for initial scans (normal_scans=%d)",
1305 : wpa_s->normal_scans);
1306 0 : return -1;
1307 : }
1308 :
1309 0 : os_memset(¶ms, 0, sizeof(params));
1310 :
1311 : /* If we can't allocate space for the filters, we just don't filter */
1312 0 : params.filter_ssids = os_calloc(wpa_s->max_match_sets,
1313 : sizeof(struct wpa_driver_scan_filter));
1314 :
1315 0 : prev_state = wpa_s->wpa_state;
1316 0 : if (wpa_s->wpa_state == WPA_DISCONNECTED ||
1317 0 : wpa_s->wpa_state == WPA_INACTIVE)
1318 0 : wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
1319 :
1320 0 : if (wpa_s->autoscan_params != NULL) {
1321 0 : scan_params = wpa_s->autoscan_params;
1322 0 : goto scan;
1323 : }
1324 :
1325 : /* Find the starting point from which to continue scanning */
1326 0 : ssid = wpa_s->conf->ssid;
1327 0 : if (wpa_s->prev_sched_ssid) {
1328 0 : while (ssid) {
1329 0 : if (ssid == wpa_s->prev_sched_ssid) {
1330 0 : ssid = ssid->next;
1331 0 : break;
1332 : }
1333 0 : ssid = ssid->next;
1334 : }
1335 : }
1336 :
1337 0 : if (!ssid || !wpa_s->prev_sched_ssid) {
1338 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
1339 0 : wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
1340 0 : wpa_s->first_sched_scan = 1;
1341 0 : ssid = wpa_s->conf->ssid;
1342 0 : wpa_s->prev_sched_ssid = ssid;
1343 : }
1344 :
1345 0 : if (wildcard) {
1346 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan");
1347 0 : params.num_ssids++;
1348 : }
1349 :
1350 0 : while (ssid) {
1351 0 : if (wpas_network_disabled(wpa_s, ssid))
1352 0 : goto next;
1353 :
1354 0 : if (params.num_filter_ssids < wpa_s->max_match_sets &&
1355 0 : params.filter_ssids && ssid->ssid && ssid->ssid_len) {
1356 0 : wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s",
1357 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1358 0 : os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid,
1359 : ssid->ssid, ssid->ssid_len);
1360 0 : params.filter_ssids[params.num_filter_ssids].ssid_len =
1361 0 : ssid->ssid_len;
1362 0 : params.num_filter_ssids++;
1363 0 : } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len)
1364 : {
1365 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID "
1366 : "filter for sched_scan - drop filter");
1367 0 : os_free(params.filter_ssids);
1368 0 : params.filter_ssids = NULL;
1369 0 : params.num_filter_ssids = 0;
1370 : }
1371 :
1372 0 : if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) {
1373 0 : if (params.num_ssids == max_sched_scan_ssids)
1374 0 : break; /* only room for broadcast SSID */
1375 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1376 : "add to active scan ssid: %s",
1377 : wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1378 0 : params.ssids[params.num_ssids].ssid =
1379 0 : ssid->ssid;
1380 0 : params.ssids[params.num_ssids].ssid_len =
1381 0 : ssid->ssid_len;
1382 0 : params.num_ssids++;
1383 0 : if (params.num_ssids >= max_sched_scan_ssids) {
1384 0 : wpa_s->prev_sched_ssid = ssid;
1385 : do {
1386 0 : ssid = ssid->next;
1387 0 : } while (ssid &&
1388 0 : (wpas_network_disabled(wpa_s, ssid) ||
1389 0 : !ssid->scan_ssid));
1390 0 : break;
1391 : }
1392 : }
1393 :
1394 : next:
1395 0 : wpa_s->prev_sched_ssid = ssid;
1396 0 : ssid = ssid->next;
1397 : }
1398 :
1399 0 : if (params.num_filter_ssids == 0) {
1400 0 : os_free(params.filter_ssids);
1401 0 : params.filter_ssids = NULL;
1402 : }
1403 :
1404 0 : extra_ie = wpa_supplicant_extra_ies(wpa_s);
1405 0 : if (extra_ie) {
1406 0 : params.extra_ies = wpabuf_head(extra_ie);
1407 0 : params.extra_ies_len = wpabuf_len(extra_ie);
1408 : }
1409 :
1410 0 : if (wpa_s->conf->filter_rssi)
1411 0 : params.filter_rssi = wpa_s->conf->filter_rssi;
1412 :
1413 : /* See if user specified frequencies. If so, scan only those. */
1414 0 : if (wpa_s->conf->freq_list && !params.freqs) {
1415 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1416 : "Optimize scan based on conf->freq_list");
1417 0 : int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);
1418 : }
1419 :
1420 0 : scan_params = ¶ms;
1421 :
1422 : scan:
1423 0 : wpa_s->sched_scan_timed_out = 0;
1424 :
1425 : /*
1426 : * We cannot support multiple scan plans if the scan request includes
1427 : * too many SSID's, so in this case use only the last scan plan and make
1428 : * it run infinitely. It will be stopped by the timeout.
1429 : */
1430 0 : if (wpa_s->sched_scan_plans_num == 1 ||
1431 0 : (wpa_s->sched_scan_plans_num && !ssid && wpa_s->first_sched_scan)) {
1432 0 : params.sched_scan_plans = wpa_s->sched_scan_plans;
1433 0 : params.sched_scan_plans_num = wpa_s->sched_scan_plans_num;
1434 0 : } else if (wpa_s->sched_scan_plans_num > 1) {
1435 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1436 : "Too many SSIDs. Default to using single scheduled_scan plan");
1437 0 : params.sched_scan_plans =
1438 0 : &wpa_s->sched_scan_plans[wpa_s->sched_scan_plans_num -
1439 : 1];
1440 0 : params.sched_scan_plans_num = 1;
1441 : } else {
1442 0 : if (wpa_s->conf->sched_scan_interval)
1443 0 : scan_plan.interval = wpa_s->conf->sched_scan_interval;
1444 : else
1445 0 : scan_plan.interval = 10;
1446 :
1447 0 : if (scan_plan.interval > wpa_s->max_sched_scan_plan_interval) {
1448 0 : wpa_printf(MSG_WARNING,
1449 : "Scan interval too long(%u), use the maximum allowed(%u)",
1450 : scan_plan.interval,
1451 : wpa_s->max_sched_scan_plan_interval);
1452 0 : scan_plan.interval =
1453 0 : wpa_s->max_sched_scan_plan_interval;
1454 : }
1455 :
1456 0 : scan_plan.iterations = 0;
1457 0 : params.sched_scan_plans = &scan_plan;
1458 0 : params.sched_scan_plans_num = 1;
1459 : }
1460 :
1461 0 : if (ssid || !wpa_s->first_sched_scan) {
1462 0 : wpa_dbg(wpa_s, MSG_DEBUG,
1463 : "Starting sched scan: interval %u timeout %d",
1464 : params.sched_scan_plans[0].interval,
1465 : wpa_s->sched_scan_timeout);
1466 : } else {
1467 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan (no timeout)");
1468 : }
1469 :
1470 0 : wpa_setband_scan_freqs(wpa_s, scan_params);
1471 :
1472 0 : if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) {
1473 0 : params.mac_addr_rand = 1;
1474 0 : if (wpa_s->mac_addr_sched_scan) {
1475 0 : params.mac_addr = wpa_s->mac_addr_sched_scan;
1476 0 : params.mac_addr_mask = wpa_s->mac_addr_sched_scan +
1477 : ETH_ALEN;
1478 : }
1479 : }
1480 :
1481 0 : ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params);
1482 0 : wpabuf_free(extra_ie);
1483 0 : os_free(params.filter_ssids);
1484 0 : if (ret) {
1485 0 : wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan");
1486 0 : if (prev_state != wpa_s->wpa_state)
1487 0 : wpa_supplicant_set_state(wpa_s, prev_state);
1488 0 : return ret;
1489 : }
1490 :
1491 : /* If we have more SSIDs to scan, add a timeout so we scan them too */
1492 0 : if (ssid || !wpa_s->first_sched_scan) {
1493 0 : wpa_s->sched_scan_timed_out = 0;
1494 0 : eloop_register_timeout(wpa_s->sched_scan_timeout, 0,
1495 : wpa_supplicant_sched_scan_timeout,
1496 : wpa_s, NULL);
1497 0 : wpa_s->first_sched_scan = 0;
1498 0 : wpa_s->sched_scan_timeout /= 2;
1499 0 : params.sched_scan_plans[0].interval *= 2;
1500 0 : if ((unsigned int) wpa_s->sched_scan_timeout <
1501 0 : params.sched_scan_plans[0].interval ||
1502 0 : params.sched_scan_plans[0].interval >
1503 0 : wpa_s->max_sched_scan_plan_interval) {
1504 0 : params.sched_scan_plans[0].interval = 10;
1505 0 : wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
1506 : }
1507 : }
1508 :
1509 : /* If there is no more ssids, start next time from the beginning */
1510 0 : if (!ssid)
1511 0 : wpa_s->prev_sched_ssid = NULL;
1512 :
1513 0 : return 0;
1514 : }
1515 :
1516 :
1517 : /**
1518 : * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
1519 : * @wpa_s: Pointer to wpa_supplicant data
1520 : *
1521 : * This function is used to cancel a scan request scheduled with
1522 : * wpa_supplicant_req_scan().
1523 : */
1524 16978 : void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
1525 : {
1526 16978 : wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
1527 16978 : eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
1528 16978 : }
1529 :
1530 :
1531 : /**
1532 : * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan
1533 : * @wpa_s: Pointer to wpa_supplicant data
1534 : *
1535 : * This function is used to stop a delayed scheduled scan.
1536 : */
1537 733 : void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s)
1538 : {
1539 733 : if (!wpa_s->sched_scan_supported)
1540 1466 : return;
1541 :
1542 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan");
1543 0 : eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout,
1544 : wpa_s, NULL);
1545 : }
1546 :
1547 :
1548 : /**
1549 : * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans
1550 : * @wpa_s: Pointer to wpa_supplicant data
1551 : *
1552 : * This function is used to stop a periodic scheduled scan.
1553 : */
1554 9997 : void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
1555 : {
1556 9997 : if (!wpa_s->sched_scanning)
1557 19994 : return;
1558 :
1559 0 : if (wpa_s->sched_scanning)
1560 0 : wpa_s->sched_scan_stop_req = 1;
1561 :
1562 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
1563 0 : eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
1564 0 : wpa_supplicant_stop_sched_scan(wpa_s);
1565 : }
1566 :
1567 :
1568 : /**
1569 : * wpa_supplicant_notify_scanning - Indicate possible scan state change
1570 : * @wpa_s: Pointer to wpa_supplicant data
1571 : * @scanning: Whether scanning is currently in progress
1572 : *
1573 : * This function is to generate scanning notifycations. It is called whenever
1574 : * there may have been a change in scanning (scan started, completed, stopped).
1575 : * wpas_notify_scanning() is called whenever the scanning state changed from the
1576 : * previously notified state.
1577 : */
1578 50745 : void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
1579 : int scanning)
1580 : {
1581 50745 : if (wpa_s->scanning != scanning) {
1582 9142 : wpa_s->scanning = scanning;
1583 9142 : wpas_notify_scanning(wpa_s);
1584 : }
1585 50745 : }
1586 :
1587 :
1588 6952 : static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
1589 : {
1590 6952 : int rate = 0;
1591 : const u8 *ie;
1592 : int i;
1593 :
1594 6952 : ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
1595 62529 : for (i = 0; ie && i < ie[1]; i++) {
1596 55577 : if ((ie[i + 2] & 0x7f) > rate)
1597 46461 : rate = ie[i + 2] & 0x7f;
1598 : }
1599 :
1600 6952 : ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
1601 25194 : for (i = 0; ie && i < ie[1]; i++) {
1602 18242 : if ((ie[i + 2] & 0x7f) > rate)
1603 18242 : rate = ie[i + 2] & 0x7f;
1604 : }
1605 :
1606 6952 : return rate;
1607 : }
1608 :
1609 :
1610 : /**
1611 : * wpa_scan_get_ie - Fetch a specified information element from a scan result
1612 : * @res: Scan result entry
1613 : * @ie: Information element identitifier (WLAN_EID_*)
1614 : * Returns: Pointer to the information element (id field) or %NULL if not found
1615 : *
1616 : * This function returns the first matching information element in the scan
1617 : * result.
1618 : */
1619 51394 : const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
1620 : {
1621 51394 : return get_ie((const u8 *) (res + 1), res->ie_len, ie);
1622 : }
1623 :
1624 :
1625 : /**
1626 : * wpa_scan_get_vendor_ie - Fetch vendor information element from a scan result
1627 : * @res: Scan result entry
1628 : * @vendor_type: Vendor type (four octets starting the IE payload)
1629 : * Returns: Pointer to the information element (id field) or %NULL if not found
1630 : *
1631 : * This function returns the first matching information element in the scan
1632 : * result.
1633 : */
1634 15309 : const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
1635 : u32 vendor_type)
1636 : {
1637 : const u8 *end, *pos;
1638 :
1639 15309 : pos = (const u8 *) (res + 1);
1640 15309 : end = pos + res->ie_len;
1641 :
1642 182971 : while (end - pos > 1) {
1643 156541 : if (2 + pos[1] > end - pos)
1644 3 : break;
1645 182560 : if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1646 26022 : vendor_type == WPA_GET_BE32(&pos[2]))
1647 4185 : return pos;
1648 152353 : pos += 2 + pos[1];
1649 : }
1650 :
1651 11124 : return NULL;
1652 : }
1653 :
1654 :
1655 : /**
1656 : * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result
1657 : * @res: Scan result entry
1658 : * @vendor_type: Vendor type (four octets starting the IE payload)
1659 : * Returns: Pointer to the information element (id field) or %NULL if not found
1660 : *
1661 : * This function returns the first matching information element in the scan
1662 : * result.
1663 : *
1664 : * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only
1665 : * from Beacon frames instead of either Beacon or Probe Response frames.
1666 : */
1667 418 : const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
1668 : u32 vendor_type)
1669 : {
1670 : const u8 *end, *pos;
1671 :
1672 418 : if (res->beacon_ie_len == 0)
1673 0 : return NULL;
1674 :
1675 418 : pos = (const u8 *) (res + 1);
1676 418 : pos += res->ie_len;
1677 418 : end = pos + res->beacon_ie_len;
1678 :
1679 5642 : while (end - pos > 1) {
1680 4817 : if (2 + pos[1] > end - pos)
1681 0 : break;
1682 5304 : if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1683 487 : vendor_type == WPA_GET_BE32(&pos[2]))
1684 11 : return pos;
1685 4806 : pos += 2 + pos[1];
1686 : }
1687 :
1688 407 : return NULL;
1689 : }
1690 :
1691 :
1692 : /**
1693 : * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result
1694 : * @res: Scan result entry
1695 : * @vendor_type: Vendor type (four octets starting the IE payload)
1696 : * Returns: Pointer to the information element payload or %NULL if not found
1697 : *
1698 : * This function returns concatenated payload of possibly fragmented vendor
1699 : * specific information elements in the scan result. The caller is responsible
1700 : * for freeing the returned buffer.
1701 : */
1702 1396 : struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
1703 : u32 vendor_type)
1704 : {
1705 : struct wpabuf *buf;
1706 : const u8 *end, *pos;
1707 :
1708 1396 : buf = wpabuf_alloc(res->ie_len);
1709 1396 : if (buf == NULL)
1710 0 : return NULL;
1711 :
1712 1396 : pos = (const u8 *) (res + 1);
1713 1396 : end = pos + res->ie_len;
1714 :
1715 18401 : while (end - pos > 1) {
1716 15609 : if (2 + pos[1] > end - pos)
1717 0 : break;
1718 19059 : if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1719 3450 : vendor_type == WPA_GET_BE32(&pos[2]))
1720 1359 : wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
1721 15609 : pos += 2 + pos[1];
1722 : }
1723 :
1724 1396 : if (wpabuf_len(buf) == 0) {
1725 40 : wpabuf_free(buf);
1726 40 : buf = NULL;
1727 : }
1728 :
1729 1396 : return buf;
1730 : }
1731 :
1732 :
1733 : /*
1734 : * Channels with a great SNR can operate at full rate. What is a great SNR?
1735 : * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
1736 : * rule of thumb is that any SNR above 20 is good." This one
1737 : * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
1738 : * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
1739 : * conservative value.
1740 : */
1741 : #define GREAT_SNR 30
1742 :
1743 : #define IS_5GHZ(n) (n > 4000)
1744 :
1745 : /* Compare function for sorting scan results. Return >0 if @b is considered
1746 : * better. */
1747 1778 : static int wpa_scan_result_compar(const void *a, const void *b)
1748 : {
1749 : #define MIN(a,b) a < b ? a : b
1750 1778 : struct wpa_scan_res **_wa = (void *) a;
1751 1778 : struct wpa_scan_res **_wb = (void *) b;
1752 1778 : struct wpa_scan_res *wa = *_wa;
1753 1778 : struct wpa_scan_res *wb = *_wb;
1754 : int wpa_a, wpa_b;
1755 : int snr_a, snr_b, snr_a_full, snr_b_full;
1756 :
1757 : /* WPA/WPA2 support preferred */
1758 3524 : wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
1759 1746 : wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
1760 3538 : wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
1761 1760 : wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
1762 :
1763 1778 : if (wpa_b && !wpa_a)
1764 188 : return 1;
1765 1590 : if (!wpa_b && wpa_a)
1766 373 : return -1;
1767 :
1768 : /* privacy support preferred */
1769 1744 : if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
1770 527 : (wb->caps & IEEE80211_CAP_PRIVACY))
1771 128 : return 1;
1772 1779 : if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
1773 690 : (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
1774 17 : return -1;
1775 :
1776 1072 : if (wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) {
1777 1072 : snr_a_full = wa->snr;
1778 1072 : snr_a = MIN(wa->snr, GREAT_SNR);
1779 1072 : snr_b_full = wb->snr;
1780 1072 : snr_b = MIN(wb->snr, GREAT_SNR);
1781 : } else {
1782 : /* Level is not in dBm, so we can't calculate
1783 : * SNR. Just use raw level (units unknown). */
1784 0 : snr_a = snr_a_full = wa->level;
1785 0 : snr_b = snr_b_full = wb->level;
1786 : }
1787 :
1788 : /* if SNR is close, decide by max rate or frequency band */
1789 1072 : if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
1790 0 : (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
1791 1072 : if (wa->est_throughput != wb->est_throughput)
1792 25 : return wb->est_throughput - wa->est_throughput;
1793 1047 : if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
1794 111 : return IS_5GHZ(wa->freq) ? -1 : 1;
1795 : }
1796 :
1797 : /* all things being equal, use SNR; if SNRs are
1798 : * identical, use quality values since some drivers may only report
1799 : * that value and leave the signal level zero */
1800 936 : if (snr_b_full == snr_a_full)
1801 584 : return wb->qual - wa->qual;
1802 352 : return snr_b_full - snr_a_full;
1803 : #undef MIN
1804 : }
1805 :
1806 :
1807 : #ifdef CONFIG_WPS
1808 : /* Compare function for sorting scan results when searching a WPS AP for
1809 : * provisioning. Return >0 if @b is considered better. */
1810 172 : static int wpa_scan_result_wps_compar(const void *a, const void *b)
1811 : {
1812 172 : struct wpa_scan_res **_wa = (void *) a;
1813 172 : struct wpa_scan_res **_wb = (void *) b;
1814 172 : struct wpa_scan_res *wa = *_wa;
1815 172 : struct wpa_scan_res *wb = *_wb;
1816 : int uses_wps_a, uses_wps_b;
1817 : struct wpabuf *wps_a, *wps_b;
1818 : int res;
1819 :
1820 : /* Optimization - check WPS IE existence before allocated memory and
1821 : * doing full reassembly. */
1822 172 : uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
1823 172 : uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
1824 172 : if (uses_wps_a && !uses_wps_b)
1825 9 : return -1;
1826 163 : if (!uses_wps_a && uses_wps_b)
1827 38 : return 1;
1828 :
1829 125 : if (uses_wps_a && uses_wps_b) {
1830 123 : wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
1831 123 : wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
1832 123 : res = wps_ap_priority_compar(wps_a, wps_b);
1833 123 : wpabuf_free(wps_a);
1834 123 : wpabuf_free(wps_b);
1835 123 : if (res)
1836 73 : return res;
1837 : }
1838 :
1839 : /*
1840 : * Do not use current AP security policy as a sorting criteria during
1841 : * WPS provisioning step since the AP may get reconfigured at the
1842 : * completion of provisioning.
1843 : */
1844 :
1845 : /* all things being equal, use signal level; if signal levels are
1846 : * identical, use quality values since some drivers may only report
1847 : * that value and leave the signal level zero */
1848 52 : if (wb->level == wa->level)
1849 52 : return wb->qual - wa->qual;
1850 0 : return wb->level - wa->level;
1851 : }
1852 : #endif /* CONFIG_WPS */
1853 :
1854 :
1855 5686 : static void dump_scan_res(struct wpa_scan_results *scan_res)
1856 : {
1857 : #ifndef CONFIG_NO_STDOUT_DEBUG
1858 : size_t i;
1859 :
1860 5686 : if (scan_res->res == NULL || scan_res->num == 0)
1861 6155 : return;
1862 :
1863 5217 : wpa_printf(MSG_EXCESSIVE, "Sorted scan results");
1864 :
1865 12159 : for (i = 0; i < scan_res->num; i++) {
1866 6942 : struct wpa_scan_res *r = scan_res->res[i];
1867 : u8 *pos;
1868 6942 : if (r->flags & WPA_SCAN_LEVEL_DBM) {
1869 6942 : int noise_valid = !(r->flags & WPA_SCAN_NOISE_INVALID);
1870 :
1871 55536 : wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1872 : "noise=%d%s level=%d snr=%d%s flags=0x%x age=%u est=%u",
1873 41652 : MAC2STR(r->bssid), r->freq, r->qual,
1874 : r->noise, noise_valid ? "" : "~", r->level,
1875 6942 : r->snr, r->snr >= GREAT_SNR ? "*" : "",
1876 : r->flags,
1877 : r->age, r->est_throughput);
1878 : } else {
1879 0 : wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1880 : "noise=%d level=%d flags=0x%x age=%u est=%u",
1881 0 : MAC2STR(r->bssid), r->freq, r->qual,
1882 : r->noise, r->level, r->flags, r->age,
1883 : r->est_throughput);
1884 : }
1885 6942 : pos = (u8 *) (r + 1);
1886 6942 : if (r->ie_len)
1887 6942 : wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len);
1888 6942 : pos += r->ie_len;
1889 6942 : if (r->beacon_ie_len)
1890 4721 : wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs",
1891 : pos, r->beacon_ie_len);
1892 : }
1893 : #endif /* CONFIG_NO_STDOUT_DEBUG */
1894 : }
1895 :
1896 :
1897 : /**
1898 : * wpa_supplicant_filter_bssid_match - Is the specified BSSID allowed
1899 : * @wpa_s: Pointer to wpa_supplicant data
1900 : * @bssid: BSSID to check
1901 : * Returns: 0 if the BSSID is filtered or 1 if not
1902 : *
1903 : * This function is used to filter out specific BSSIDs from scan reslts mainly
1904 : * for testing purposes (SET bssid_filter ctrl_iface command).
1905 : */
1906 16257 : int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
1907 : const u8 *bssid)
1908 : {
1909 : size_t i;
1910 :
1911 16257 : if (wpa_s->bssid_filter == NULL)
1912 16247 : return 1;
1913 :
1914 13 : for (i = 0; i < wpa_s->bssid_filter_count; i++) {
1915 10 : if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
1916 : ETH_ALEN) == 0)
1917 7 : return 1;
1918 : }
1919 :
1920 3 : return 0;
1921 : }
1922 :
1923 :
1924 5717 : void filter_scan_res(struct wpa_supplicant *wpa_s,
1925 : struct wpa_scan_results *res)
1926 : {
1927 : size_t i, j;
1928 :
1929 5717 : if (wpa_s->bssid_filter == NULL)
1930 11432 : return;
1931 :
1932 6 : for (i = 0, j = 0; i < res->num; i++) {
1933 4 : if (wpa_supplicant_filter_bssid_match(wpa_s,
1934 4 : res->res[i]->bssid)) {
1935 2 : res->res[j++] = res->res[i];
1936 : } else {
1937 2 : os_free(res->res[i]);
1938 2 : res->res[i] = NULL;
1939 : }
1940 : }
1941 :
1942 2 : if (res->num != j) {
1943 2 : wpa_printf(MSG_DEBUG, "Filtered out %d scan results",
1944 2 : (int) (res->num - j));
1945 2 : res->num = j;
1946 : }
1947 : }
1948 :
1949 :
1950 : /*
1951 : * Noise floor values to use when we have signal strength
1952 : * measurements, but no noise floor measurements. These values were
1953 : * measured in an office environment with many APs.
1954 : */
1955 : #define DEFAULT_NOISE_FLOOR_2GHZ (-89)
1956 : #define DEFAULT_NOISE_FLOOR_5GHZ (-92)
1957 :
1958 6952 : void scan_snr(struct wpa_scan_res *res)
1959 : {
1960 6952 : if (res->flags & WPA_SCAN_NOISE_INVALID) {
1961 3396 : res->noise = IS_5GHZ(res->freq) ?
1962 1698 : DEFAULT_NOISE_FLOOR_5GHZ :
1963 : DEFAULT_NOISE_FLOOR_2GHZ;
1964 : }
1965 :
1966 6952 : if (res->flags & WPA_SCAN_LEVEL_DBM) {
1967 6952 : res->snr = res->level - res->noise;
1968 : } else {
1969 : /* Level is not in dBm, so we can't calculate
1970 : * SNR. Just use raw level (units unknown). */
1971 0 : res->snr = res->level;
1972 : }
1973 6952 : }
1974 :
1975 :
1976 5654 : static unsigned int max_ht20_rate(int snr)
1977 : {
1978 5654 : if (snr < 6)
1979 0 : return 6500; /* HT20 MCS0 */
1980 5654 : if (snr < 8)
1981 0 : return 13000; /* HT20 MCS1 */
1982 5654 : if (snr < 13)
1983 0 : return 19500; /* HT20 MCS2 */
1984 5654 : if (snr < 17)
1985 0 : return 26000; /* HT20 MCS3 */
1986 5654 : if (snr < 20)
1987 0 : return 39000; /* HT20 MCS4 */
1988 5654 : if (snr < 23)
1989 0 : return 52000; /* HT20 MCS5 */
1990 5654 : if (snr < 24)
1991 0 : return 58500; /* HT20 MCS6 */
1992 5654 : return 65000; /* HT20 MCS7 */
1993 : }
1994 :
1995 :
1996 113 : static unsigned int max_ht40_rate(int snr)
1997 : {
1998 113 : if (snr < 3)
1999 0 : return 13500; /* HT40 MCS0 */
2000 113 : if (snr < 6)
2001 0 : return 27000; /* HT40 MCS1 */
2002 113 : if (snr < 10)
2003 0 : return 40500; /* HT40 MCS2 */
2004 113 : if (snr < 15)
2005 0 : return 54000; /* HT40 MCS3 */
2006 113 : if (snr < 17)
2007 0 : return 81000; /* HT40 MCS4 */
2008 113 : if (snr < 22)
2009 0 : return 108000; /* HT40 MCS5 */
2010 113 : if (snr < 24)
2011 0 : return 121500; /* HT40 MCS6 */
2012 113 : return 135000; /* HT40 MCS7 */
2013 : }
2014 :
2015 :
2016 31 : static unsigned int max_vht80_rate(int snr)
2017 : {
2018 31 : if (snr < 1)
2019 0 : return 0;
2020 31 : if (snr < 2)
2021 0 : return 29300; /* VHT80 MCS0 */
2022 31 : if (snr < 5)
2023 0 : return 58500; /* VHT80 MCS1 */
2024 31 : if (snr < 9)
2025 0 : return 87800; /* VHT80 MCS2 */
2026 31 : if (snr < 11)
2027 0 : return 117000; /* VHT80 MCS3 */
2028 31 : if (snr < 15)
2029 0 : return 175500; /* VHT80 MCS4 */
2030 31 : if (snr < 16)
2031 0 : return 234000; /* VHT80 MCS5 */
2032 31 : if (snr < 18)
2033 0 : return 263300; /* VHT80 MCS6 */
2034 31 : if (snr < 20)
2035 0 : return 292500; /* VHT80 MCS7 */
2036 31 : if (snr < 22)
2037 0 : return 351000; /* VHT80 MCS8 */
2038 31 : return 390000; /* VHT80 MCS9 */
2039 : }
2040 :
2041 :
2042 6952 : void scan_est_throughput(struct wpa_supplicant *wpa_s,
2043 : struct wpa_scan_res *res)
2044 : {
2045 6952 : enum local_hw_capab capab = wpa_s->hw_capab;
2046 : int rate; /* max legacy rate in 500 kb/s units */
2047 : const u8 *ie;
2048 : unsigned int est, tmp;
2049 6952 : int snr = res->snr;
2050 :
2051 6952 : if (res->est_throughput)
2052 6952 : return;
2053 :
2054 : /* Get maximum legacy rate */
2055 6952 : rate = wpa_scan_get_max_rate(res);
2056 :
2057 : /* Limit based on estimated SNR */
2058 6952 : if (rate > 1 * 2 && snr < 1)
2059 0 : rate = 1 * 2;
2060 6952 : else if (rate > 2 * 2 && snr < 4)
2061 0 : rate = 2 * 2;
2062 6952 : else if (rate > 6 * 2 && snr < 5)
2063 0 : rate = 6 * 2;
2064 6952 : else if (rate > 9 * 2 && snr < 6)
2065 0 : rate = 9 * 2;
2066 6952 : else if (rate > 12 * 2 && snr < 7)
2067 0 : rate = 12 * 2;
2068 6952 : else if (rate > 18 * 2 && snr < 10)
2069 0 : rate = 18 * 2;
2070 6952 : else if (rate > 24 * 2 && snr < 11)
2071 0 : rate = 24 * 2;
2072 6952 : else if (rate > 36 * 2 && snr < 15)
2073 0 : rate = 36 * 2;
2074 6952 : else if (rate > 48 * 2 && snr < 19)
2075 0 : rate = 48 * 2;
2076 6952 : else if (rate > 54 * 2 && snr < 21)
2077 0 : rate = 54 * 2;
2078 6952 : est = rate * 500;
2079 :
2080 6952 : if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) {
2081 6924 : ie = wpa_scan_get_ie(res, WLAN_EID_HT_CAP);
2082 6924 : if (ie) {
2083 5613 : tmp = max_ht20_rate(snr);
2084 5613 : if (tmp > est)
2085 5613 : est = tmp;
2086 : }
2087 : }
2088 :
2089 6952 : if (capab == CAPAB_HT40 || capab == CAPAB_VHT) {
2090 6924 : ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION);
2091 12536 : if (ie && ie[1] >= 2 &&
2092 5612 : (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
2093 80 : tmp = max_ht40_rate(snr);
2094 80 : if (tmp > est)
2095 80 : est = tmp;
2096 : }
2097 : }
2098 :
2099 6952 : if (capab == CAPAB_VHT) {
2100 : /* Use +1 to assume VHT is always faster than HT */
2101 6924 : ie = wpa_scan_get_ie(res, WLAN_EID_VHT_CAP);
2102 6924 : if (ie) {
2103 41 : tmp = max_ht20_rate(snr) + 1;
2104 41 : if (tmp > est)
2105 8 : est = tmp;
2106 :
2107 41 : ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION);
2108 82 : if (ie && ie[1] >= 2 &&
2109 41 : (ie[3] &
2110 : HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
2111 33 : tmp = max_ht40_rate(snr) + 1;
2112 33 : if (tmp > est)
2113 33 : est = tmp;
2114 : }
2115 :
2116 41 : ie = wpa_scan_get_ie(res, WLAN_EID_VHT_OPERATION);
2117 82 : if (ie && ie[1] >= 1 &&
2118 41 : (ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK)) {
2119 31 : tmp = max_vht80_rate(snr) + 1;
2120 31 : if (tmp > est)
2121 31 : est = tmp;
2122 : }
2123 : }
2124 : }
2125 :
2126 : /* TODO: channel utilization and AP load (e.g., from AP Beacon) */
2127 :
2128 6952 : res->est_throughput = est;
2129 : }
2130 :
2131 :
2132 : /**
2133 : * wpa_supplicant_get_scan_results - Get scan results
2134 : * @wpa_s: Pointer to wpa_supplicant data
2135 : * @info: Information about what was scanned or %NULL if not available
2136 : * @new_scan: Whether a new scan was performed
2137 : * Returns: Scan results, %NULL on failure
2138 : *
2139 : * This function request the current scan results from the driver and updates
2140 : * the local BSS list wpa_s->bss. The caller is responsible for freeing the
2141 : * results with wpa_scan_results_free().
2142 : */
2143 : struct wpa_scan_results *
2144 5687 : wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
2145 : struct scan_info *info, int new_scan)
2146 : {
2147 : struct wpa_scan_results *scan_res;
2148 : size_t i;
2149 5687 : int (*compar)(const void *, const void *) = wpa_scan_result_compar;
2150 :
2151 5687 : scan_res = wpa_drv_get_scan_results2(wpa_s);
2152 5687 : if (scan_res == NULL) {
2153 1 : wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
2154 1 : return NULL;
2155 : }
2156 5686 : if (scan_res->fetch_time.sec == 0) {
2157 : /*
2158 : * Make sure we have a valid timestamp if the driver wrapper
2159 : * does not set this.
2160 : */
2161 5686 : os_get_reltime(&scan_res->fetch_time);
2162 : }
2163 5686 : filter_scan_res(wpa_s, scan_res);
2164 :
2165 12628 : for (i = 0; i < scan_res->num; i++) {
2166 6942 : struct wpa_scan_res *scan_res_item = scan_res->res[i];
2167 :
2168 6942 : scan_snr(scan_res_item);
2169 6942 : scan_est_throughput(wpa_s, scan_res_item);
2170 : }
2171 :
2172 : #ifdef CONFIG_WPS
2173 5686 : if (wpas_wps_searching(wpa_s)) {
2174 723 : wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
2175 : "provisioning rules");
2176 723 : compar = wpa_scan_result_wps_compar;
2177 : }
2178 : #endif /* CONFIG_WPS */
2179 :
2180 5686 : qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
2181 : compar);
2182 5686 : dump_scan_res(scan_res);
2183 :
2184 5686 : wpa_bss_update_start(wpa_s);
2185 12628 : for (i = 0; i < scan_res->num; i++)
2186 6942 : wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
2187 : &scan_res->fetch_time);
2188 5686 : wpa_bss_update_end(wpa_s, info, new_scan);
2189 :
2190 5686 : return scan_res;
2191 : }
2192 :
2193 :
2194 : /**
2195 : * wpa_supplicant_update_scan_results - Update scan results from the driver
2196 : * @wpa_s: Pointer to wpa_supplicant data
2197 : * Returns: 0 on success, -1 on failure
2198 : *
2199 : * This function updates the BSS table within wpa_supplicant based on the
2200 : * currently available scan results from the driver without requesting a new
2201 : * scan. This is used in cases where the driver indicates an association
2202 : * (including roaming within ESS) and wpa_supplicant does not yet have the
2203 : * needed information to complete the connection (e.g., to perform validation
2204 : * steps in 4-way handshake).
2205 : */
2206 29 : int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
2207 : {
2208 : struct wpa_scan_results *scan_res;
2209 29 : scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2210 29 : if (scan_res == NULL)
2211 0 : return -1;
2212 29 : wpa_scan_results_free(scan_res);
2213 :
2214 29 : return 0;
2215 : }
2216 :
2217 :
2218 : /**
2219 : * scan_only_handler - Reports scan results
2220 : */
2221 1274 : void scan_only_handler(struct wpa_supplicant *wpa_s,
2222 : struct wpa_scan_results *scan_res)
2223 : {
2224 1274 : wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received");
2225 1274 : if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
2226 3 : wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
2227 3 : wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
2228 : wpa_s->manual_scan_id);
2229 3 : wpa_s->manual_scan_use_id = 0;
2230 : } else {
2231 1271 : wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
2232 : }
2233 1274 : wpas_notify_scan_results(wpa_s);
2234 1274 : wpas_notify_scan_done(wpa_s, 1);
2235 1274 : if (wpa_s->scan_work) {
2236 1274 : struct wpa_radio_work *work = wpa_s->scan_work;
2237 1274 : wpa_s->scan_work = NULL;
2238 1274 : radio_work_done(work);
2239 : }
2240 :
2241 1274 : if (wpa_s->wpa_state == WPA_SCANNING)
2242 1238 : wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
2243 1274 : }
2244 :
2245 :
2246 0 : int wpas_scan_scheduled(struct wpa_supplicant *wpa_s)
2247 : {
2248 0 : return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL);
2249 : }
2250 :
2251 :
2252 : struct wpa_driver_scan_params *
2253 4580 : wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
2254 : {
2255 : struct wpa_driver_scan_params *params;
2256 : size_t i;
2257 : u8 *n;
2258 :
2259 4580 : params = os_zalloc(sizeof(*params));
2260 4580 : if (params == NULL)
2261 2 : return NULL;
2262 :
2263 9137 : for (i = 0; i < src->num_ssids; i++) {
2264 4560 : if (src->ssids[i].ssid) {
2265 422 : n = os_malloc(src->ssids[i].ssid_len);
2266 422 : if (n == NULL)
2267 1 : goto failed;
2268 421 : os_memcpy(n, src->ssids[i].ssid,
2269 : src->ssids[i].ssid_len);
2270 421 : params->ssids[i].ssid = n;
2271 421 : params->ssids[i].ssid_len = src->ssids[i].ssid_len;
2272 : }
2273 : }
2274 4577 : params->num_ssids = src->num_ssids;
2275 :
2276 4577 : if (src->extra_ies) {
2277 4563 : n = os_malloc(src->extra_ies_len);
2278 4563 : if (n == NULL)
2279 1 : goto failed;
2280 4562 : os_memcpy(n, src->extra_ies, src->extra_ies_len);
2281 4562 : params->extra_ies = n;
2282 4562 : params->extra_ies_len = src->extra_ies_len;
2283 : }
2284 :
2285 4576 : if (src->freqs) {
2286 4367 : int len = int_array_len(src->freqs);
2287 4367 : params->freqs = os_malloc((len + 1) * sizeof(int));
2288 4367 : if (params->freqs == NULL)
2289 1 : goto failed;
2290 4366 : os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int));
2291 : }
2292 :
2293 4575 : if (src->filter_ssids) {
2294 2 : params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) *
2295 2 : src->num_filter_ssids);
2296 2 : if (params->filter_ssids == NULL)
2297 0 : goto failed;
2298 2 : os_memcpy(params->filter_ssids, src->filter_ssids,
2299 : sizeof(*params->filter_ssids) *
2300 : src->num_filter_ssids);
2301 2 : params->num_filter_ssids = src->num_filter_ssids;
2302 : }
2303 :
2304 4575 : params->filter_rssi = src->filter_rssi;
2305 4575 : params->p2p_probe = src->p2p_probe;
2306 4575 : params->only_new_results = src->only_new_results;
2307 4575 : params->low_priority = src->low_priority;
2308 :
2309 4575 : if (src->sched_scan_plans_num > 0) {
2310 0 : params->sched_scan_plans =
2311 0 : os_malloc(sizeof(*src->sched_scan_plans) *
2312 0 : src->sched_scan_plans_num);
2313 0 : if (!params->sched_scan_plans)
2314 0 : goto failed;
2315 :
2316 0 : os_memcpy(params->sched_scan_plans, src->sched_scan_plans,
2317 : sizeof(*src->sched_scan_plans) *
2318 : src->sched_scan_plans_num);
2319 0 : params->sched_scan_plans_num = src->sched_scan_plans_num;
2320 : }
2321 :
2322 4575 : if (src->mac_addr_rand) {
2323 3 : params->mac_addr_rand = src->mac_addr_rand;
2324 :
2325 3 : if (src->mac_addr && src->mac_addr_mask) {
2326 : u8 *mac_addr;
2327 :
2328 2 : mac_addr = os_malloc(2 * ETH_ALEN);
2329 2 : if (!mac_addr)
2330 0 : goto failed;
2331 :
2332 2 : os_memcpy(mac_addr, src->mac_addr, ETH_ALEN);
2333 2 : os_memcpy(mac_addr + ETH_ALEN, src->mac_addr_mask,
2334 : ETH_ALEN);
2335 2 : params->mac_addr = mac_addr;
2336 2 : params->mac_addr_mask = mac_addr + ETH_ALEN;
2337 : }
2338 : }
2339 :
2340 4575 : if (src->bssid) {
2341 : u8 *bssid;
2342 :
2343 8 : bssid = os_malloc(ETH_ALEN);
2344 8 : if (!bssid)
2345 0 : goto failed;
2346 8 : os_memcpy(bssid, src->bssid, ETH_ALEN);
2347 8 : params->bssid = bssid;
2348 : }
2349 :
2350 4575 : return params;
2351 :
2352 : failed:
2353 3 : wpa_scan_free_params(params);
2354 3 : return NULL;
2355 : }
2356 :
2357 :
2358 5518 : void wpa_scan_free_params(struct wpa_driver_scan_params *params)
2359 : {
2360 : size_t i;
2361 :
2362 5518 : if (params == NULL)
2363 5523 : return;
2364 :
2365 11007 : for (i = 0; i < params->num_ssids; i++)
2366 5494 : os_free((u8 *) params->ssids[i].ssid);
2367 5513 : os_free((u8 *) params->extra_ies);
2368 5513 : os_free(params->freqs);
2369 5513 : os_free(params->filter_ssids);
2370 5513 : os_free(params->sched_scan_plans);
2371 :
2372 : /*
2373 : * Note: params->mac_addr_mask points to same memory allocation and
2374 : * must not be freed separately.
2375 : */
2376 5513 : os_free((u8 *) params->mac_addr);
2377 :
2378 5513 : os_free((u8 *) params->bssid);
2379 :
2380 5513 : os_free(params);
2381 : }
2382 :
2383 :
2384 4 : int wpas_start_pno(struct wpa_supplicant *wpa_s)
2385 : {
2386 : int ret, prio;
2387 : size_t i, num_ssid, num_match_ssid;
2388 : struct wpa_ssid *ssid;
2389 : struct wpa_driver_scan_params params;
2390 : struct sched_scan_plan scan_plan;
2391 : unsigned int max_sched_scan_ssids;
2392 :
2393 4 : if (!wpa_s->sched_scan_supported)
2394 4 : return -1;
2395 :
2396 0 : if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
2397 0 : max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
2398 : else
2399 0 : max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
2400 0 : if (max_sched_scan_ssids < 1)
2401 0 : return -1;
2402 :
2403 0 : if (wpa_s->pno || wpa_s->pno_sched_pending)
2404 0 : return 0;
2405 :
2406 0 : if ((wpa_s->wpa_state > WPA_SCANNING) &&
2407 0 : (wpa_s->wpa_state <= WPA_COMPLETED)) {
2408 0 : wpa_printf(MSG_ERROR, "PNO: In assoc process");
2409 0 : return -EAGAIN;
2410 : }
2411 :
2412 0 : if (wpa_s->wpa_state == WPA_SCANNING) {
2413 0 : wpa_supplicant_cancel_scan(wpa_s);
2414 0 : if (wpa_s->sched_scanning) {
2415 0 : wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
2416 : "ongoing sched scan");
2417 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
2418 0 : wpa_s->pno_sched_pending = 1;
2419 0 : return 0;
2420 : }
2421 : }
2422 :
2423 0 : if (wpa_s->sched_scan_stop_req) {
2424 0 : wpa_printf(MSG_DEBUG,
2425 : "Schedule PNO after previous sched scan has stopped");
2426 0 : wpa_s->pno_sched_pending = 1;
2427 0 : return 0;
2428 : }
2429 :
2430 0 : os_memset(¶ms, 0, sizeof(params));
2431 :
2432 0 : num_ssid = num_match_ssid = 0;
2433 0 : ssid = wpa_s->conf->ssid;
2434 0 : while (ssid) {
2435 0 : if (!wpas_network_disabled(wpa_s, ssid)) {
2436 0 : num_match_ssid++;
2437 0 : if (ssid->scan_ssid)
2438 0 : num_ssid++;
2439 : }
2440 0 : ssid = ssid->next;
2441 : }
2442 :
2443 0 : if (num_match_ssid == 0) {
2444 0 : wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
2445 0 : return -1;
2446 : }
2447 :
2448 0 : if (num_match_ssid > num_ssid) {
2449 0 : params.num_ssids++; /* wildcard */
2450 0 : num_ssid++;
2451 : }
2452 :
2453 0 : if (num_ssid > max_sched_scan_ssids) {
2454 0 : wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
2455 : "%u", max_sched_scan_ssids, (unsigned int) num_ssid);
2456 0 : num_ssid = max_sched_scan_ssids;
2457 : }
2458 :
2459 0 : if (num_match_ssid > wpa_s->max_match_sets) {
2460 0 : num_match_ssid = wpa_s->max_match_sets;
2461 0 : wpa_dbg(wpa_s, MSG_DEBUG, "PNO: Too many SSIDs to match");
2462 : }
2463 0 : params.filter_ssids = os_calloc(num_match_ssid,
2464 : sizeof(struct wpa_driver_scan_filter));
2465 0 : if (params.filter_ssids == NULL)
2466 0 : return -1;
2467 :
2468 0 : i = 0;
2469 0 : prio = 0;
2470 0 : ssid = wpa_s->conf->pssid[prio];
2471 0 : while (ssid) {
2472 0 : if (!wpas_network_disabled(wpa_s, ssid)) {
2473 0 : if (ssid->scan_ssid && params.num_ssids < num_ssid) {
2474 0 : params.ssids[params.num_ssids].ssid =
2475 0 : ssid->ssid;
2476 0 : params.ssids[params.num_ssids].ssid_len =
2477 0 : ssid->ssid_len;
2478 0 : params.num_ssids++;
2479 : }
2480 0 : os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
2481 : ssid->ssid_len);
2482 0 : params.filter_ssids[i].ssid_len = ssid->ssid_len;
2483 0 : params.num_filter_ssids++;
2484 0 : i++;
2485 0 : if (i == num_match_ssid)
2486 0 : break;
2487 : }
2488 0 : if (ssid->pnext)
2489 0 : ssid = ssid->pnext;
2490 0 : else if (prio + 1 == wpa_s->conf->num_prio)
2491 0 : break;
2492 : else
2493 0 : ssid = wpa_s->conf->pssid[++prio];
2494 : }
2495 :
2496 0 : if (wpa_s->conf->filter_rssi)
2497 0 : params.filter_rssi = wpa_s->conf->filter_rssi;
2498 :
2499 0 : if (wpa_s->sched_scan_plans_num) {
2500 0 : params.sched_scan_plans = wpa_s->sched_scan_plans;
2501 0 : params.sched_scan_plans_num = wpa_s->sched_scan_plans_num;
2502 : } else {
2503 : /* Set one scan plan that will run infinitely */
2504 0 : if (wpa_s->conf->sched_scan_interval)
2505 0 : scan_plan.interval = wpa_s->conf->sched_scan_interval;
2506 : else
2507 0 : scan_plan.interval = 10;
2508 :
2509 0 : scan_plan.iterations = 0;
2510 0 : params.sched_scan_plans = &scan_plan;
2511 0 : params.sched_scan_plans_num = 1;
2512 : }
2513 :
2514 0 : if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
2515 0 : wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
2516 0 : params.freqs = wpa_s->manual_sched_scan_freqs;
2517 : }
2518 :
2519 0 : if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) {
2520 0 : params.mac_addr_rand = 1;
2521 0 : if (wpa_s->mac_addr_pno) {
2522 0 : params.mac_addr = wpa_s->mac_addr_pno;
2523 0 : params.mac_addr_mask = wpa_s->mac_addr_pno + ETH_ALEN;
2524 : }
2525 : }
2526 :
2527 0 : ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms);
2528 0 : os_free(params.filter_ssids);
2529 0 : if (ret == 0)
2530 0 : wpa_s->pno = 1;
2531 : else
2532 0 : wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
2533 0 : return ret;
2534 : }
2535 :
2536 :
2537 1 : int wpas_stop_pno(struct wpa_supplicant *wpa_s)
2538 : {
2539 1 : int ret = 0;
2540 :
2541 1 : if (!wpa_s->pno)
2542 1 : return 0;
2543 :
2544 0 : ret = wpa_supplicant_stop_sched_scan(wpa_s);
2545 0 : wpa_s->sched_scan_stop_req = 1;
2546 :
2547 0 : wpa_s->pno = 0;
2548 0 : wpa_s->pno_sched_pending = 0;
2549 :
2550 0 : if (wpa_s->wpa_state == WPA_SCANNING)
2551 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
2552 :
2553 0 : return ret;
2554 : }
2555 :
2556 :
2557 737 : void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s,
2558 : unsigned int type)
2559 : {
2560 737 : type &= MAC_ADDR_RAND_ALL;
2561 737 : wpa_s->mac_addr_rand_enable &= ~type;
2562 :
2563 737 : if (type & MAC_ADDR_RAND_SCAN) {
2564 737 : os_free(wpa_s->mac_addr_scan);
2565 737 : wpa_s->mac_addr_scan = NULL;
2566 : }
2567 :
2568 737 : if (type & MAC_ADDR_RAND_SCHED_SCAN) {
2569 733 : os_free(wpa_s->mac_addr_sched_scan);
2570 733 : wpa_s->mac_addr_sched_scan = NULL;
2571 : }
2572 :
2573 737 : if (type & MAC_ADDR_RAND_PNO) {
2574 733 : os_free(wpa_s->mac_addr_pno);
2575 733 : wpa_s->mac_addr_pno = NULL;
2576 : }
2577 737 : }
2578 :
2579 :
2580 3 : int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
2581 : unsigned int type, const u8 *addr,
2582 : const u8 *mask)
2583 : {
2584 3 : u8 *tmp = NULL;
2585 :
2586 3 : wpas_mac_addr_rand_scan_clear(wpa_s, type);
2587 :
2588 3 : if (addr) {
2589 2 : tmp = os_malloc(2 * ETH_ALEN);
2590 2 : if (!tmp)
2591 0 : return -1;
2592 2 : os_memcpy(tmp, addr, ETH_ALEN);
2593 2 : os_memcpy(tmp + ETH_ALEN, mask, ETH_ALEN);
2594 : }
2595 :
2596 3 : if (type == MAC_ADDR_RAND_SCAN) {
2597 3 : wpa_s->mac_addr_scan = tmp;
2598 0 : } else if (type == MAC_ADDR_RAND_SCHED_SCAN) {
2599 0 : wpa_s->mac_addr_sched_scan = tmp;
2600 0 : } else if (type == MAC_ADDR_RAND_PNO) {
2601 0 : wpa_s->mac_addr_pno = tmp;
2602 : } else {
2603 0 : wpa_printf(MSG_INFO,
2604 : "scan: Invalid MAC randomization type=0x%x",
2605 : type);
2606 0 : os_free(tmp);
2607 0 : return -1;
2608 : }
2609 :
2610 3 : wpa_s->mac_addr_rand_enable |= type;
2611 3 : return 0;
2612 : }
2613 :
2614 :
2615 11005 : int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
2616 : {
2617 11005 : int scan_work = !!wpa_s->scan_work;
2618 :
2619 : #ifdef CONFIG_P2P
2620 11005 : scan_work |= !!wpa_s->p2p_scan_work;
2621 : #endif /* CONFIG_P2P */
2622 :
2623 11005 : if (scan_work && wpa_s->own_scan_running) {
2624 60 : wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
2625 60 : return wpa_drv_abort_scan(wpa_s);
2626 : }
2627 :
2628 10945 : return 0;
2629 : }
2630 :
2631 :
2632 703 : int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd)
2633 : {
2634 703 : struct sched_scan_plan *scan_plans = NULL;
2635 703 : const char *token, *context = NULL;
2636 703 : unsigned int num = 0;
2637 :
2638 703 : if (!cmd)
2639 696 : return -1;
2640 :
2641 7 : if (!cmd[0]) {
2642 1 : wpa_printf(MSG_DEBUG, "Clear sched scan plans");
2643 1 : os_free(wpa_s->sched_scan_plans);
2644 1 : wpa_s->sched_scan_plans = NULL;
2645 1 : wpa_s->sched_scan_plans_num = 0;
2646 1 : return 0;
2647 : }
2648 :
2649 14 : while ((token = cstr_token(cmd, " ", &context))) {
2650 : int ret;
2651 : struct sched_scan_plan *scan_plan, *n;
2652 :
2653 7 : n = os_realloc_array(scan_plans, num + 1, sizeof(*scan_plans));
2654 7 : if (!n)
2655 1 : goto fail;
2656 :
2657 6 : scan_plans = n;
2658 6 : scan_plan = &scan_plans[num];
2659 6 : num++;
2660 :
2661 6 : ret = sscanf(token, "%u:%u", &scan_plan->interval,
2662 : &scan_plan->iterations);
2663 6 : if (ret <= 0 || ret > 2 || !scan_plan->interval) {
2664 1 : wpa_printf(MSG_ERROR,
2665 : "Invalid sched scan plan input: %s", token);
2666 1 : goto fail;
2667 : }
2668 :
2669 5 : if (scan_plan->interval > wpa_s->max_sched_scan_plan_interval) {
2670 0 : wpa_printf(MSG_WARNING,
2671 : "scan plan %u: Scan interval too long(%u), use the maximum allowed(%u)",
2672 : num, scan_plan->interval,
2673 : wpa_s->max_sched_scan_plan_interval);
2674 0 : scan_plan->interval =
2675 0 : wpa_s->max_sched_scan_plan_interval;
2676 : }
2677 :
2678 5 : if (ret == 1) {
2679 2 : scan_plan->iterations = 0;
2680 2 : break;
2681 : }
2682 :
2683 3 : if (!scan_plan->iterations) {
2684 1 : wpa_printf(MSG_ERROR,
2685 : "scan plan %u: Number of iterations cannot be zero",
2686 : num);
2687 1 : goto fail;
2688 : }
2689 :
2690 4 : if (scan_plan->iterations >
2691 2 : wpa_s->max_sched_scan_plan_iterations) {
2692 2 : wpa_printf(MSG_WARNING,
2693 : "scan plan %u: Too many iterations(%u), use the maximum allowed(%u)",
2694 : num, scan_plan->iterations,
2695 : wpa_s->max_sched_scan_plan_iterations);
2696 2 : scan_plan->iterations =
2697 2 : wpa_s->max_sched_scan_plan_iterations;
2698 : }
2699 :
2700 2 : wpa_printf(MSG_DEBUG,
2701 : "scan plan %u: interval=%u iterations=%u",
2702 : num, scan_plan->interval, scan_plan->iterations);
2703 : }
2704 :
2705 3 : if (!scan_plans) {
2706 1 : wpa_printf(MSG_ERROR, "Invalid scan plans entry");
2707 1 : goto fail;
2708 : }
2709 :
2710 2 : if (cstr_token(cmd, " ", &context) || scan_plans[num - 1].iterations) {
2711 1 : wpa_printf(MSG_ERROR,
2712 : "All scan plans but the last must specify a number of iterations");
2713 1 : goto fail;
2714 : }
2715 :
2716 1 : wpa_printf(MSG_DEBUG, "scan plan %u (last plan): interval=%u",
2717 1 : num, scan_plans[num - 1].interval);
2718 :
2719 1 : if (num > wpa_s->max_sched_scan_plans) {
2720 1 : wpa_printf(MSG_WARNING,
2721 : "Too many scheduled scan plans (only %u supported)",
2722 : wpa_s->max_sched_scan_plans);
2723 1 : wpa_printf(MSG_WARNING,
2724 : "Use only the first %u scan plans, and the last one (in infinite loop)",
2725 1 : wpa_s->max_sched_scan_plans - 1);
2726 1 : os_memcpy(&scan_plans[wpa_s->max_sched_scan_plans - 1],
2727 : &scan_plans[num - 1], sizeof(*scan_plans));
2728 1 : num = wpa_s->max_sched_scan_plans;
2729 : }
2730 :
2731 1 : os_free(wpa_s->sched_scan_plans);
2732 1 : wpa_s->sched_scan_plans = scan_plans;
2733 1 : wpa_s->sched_scan_plans_num = num;
2734 :
2735 1 : return 0;
2736 :
2737 : fail:
2738 5 : os_free(scan_plans);
2739 5 : wpa_printf(MSG_ERROR, "invalid scan plans list");
2740 5 : return -1;
2741 : }
2742 :
2743 :
2744 : /**
2745 : * wpas_scan_reset_sched_scan - Reset sched_scan state
2746 : * @wpa_s: Pointer to wpa_supplicant data
2747 : *
2748 : * This function is used to cancel a running scheduled scan and to reset an
2749 : * internal scan state to continue with a regular scan on the following
2750 : * wpa_supplicant_req_scan() calls.
2751 : */
2752 1434 : void wpas_scan_reset_sched_scan(struct wpa_supplicant *wpa_s)
2753 : {
2754 1434 : wpa_s->normal_scans = 0;
2755 1434 : if (wpa_s->sched_scanning) {
2756 0 : wpa_s->sched_scan_timed_out = 0;
2757 0 : wpa_s->prev_sched_ssid = NULL;
2758 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
2759 : }
2760 1434 : }
2761 :
2762 :
2763 0 : void wpas_scan_restart_sched_scan(struct wpa_supplicant *wpa_s)
2764 : {
2765 : /* simulate timeout to restart the sched scan */
2766 0 : wpa_s->sched_scan_timed_out = 1;
2767 0 : wpa_s->prev_sched_ssid = NULL;
2768 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
2769 0 : }
|