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