Interworking: Add optional use of network selection on normal scans
[mech_eap.git] / wpa_supplicant / scan.c
1 /*
2  * WPA Supplicant - Scanning
3  * Copyright (c) 2003-2010, 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 "config.h"
15 #include "wpa_supplicant_i.h"
16 #include "driver_i.h"
17 #include "wps_supplicant.h"
18 #include "p2p_supplicant.h"
19 #include "p2p/p2p.h"
20 #include "hs20_supplicant.h"
21 #include "notify.h"
22 #include "bss.h"
23 #include "scan.h"
24
25
26 static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
27 {
28         struct wpa_ssid *ssid;
29         union wpa_event_data data;
30
31         ssid = wpa_supplicant_get_ssid(wpa_s);
32         if (ssid == NULL)
33                 return;
34
35         if (wpa_s->current_ssid == NULL) {
36                 wpa_s->current_ssid = ssid;
37                 if (wpa_s->current_ssid != NULL)
38                         wpas_notify_network_changed(wpa_s);
39         }
40         wpa_supplicant_initiate_eapol(wpa_s);
41         wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
42                 "network - generating associated event");
43         os_memset(&data, 0, sizeof(data));
44         wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
45 }
46
47
48 #ifdef CONFIG_WPS
49 static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
50                            enum wps_request_type *req_type)
51 {
52         struct wpa_ssid *ssid;
53         int wps = 0;
54
55         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
56                 if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
57                         continue;
58
59                 wps = 1;
60                 *req_type = wpas_wps_get_req_type(ssid);
61                 if (!ssid->eap.phase1)
62                         continue;
63
64                 if (os_strstr(ssid->eap.phase1, "pbc=1"))
65                         return 2;
66         }
67
68 #ifdef CONFIG_P2P
69         if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p) {
70                 wpa_s->wps->dev.p2p = 1;
71                 if (!wps) {
72                         wps = 1;
73                         *req_type = WPS_REQ_ENROLLEE_INFO;
74                 }
75         }
76 #endif /* CONFIG_P2P */
77
78         return wps;
79 }
80 #endif /* CONFIG_WPS */
81
82
83 int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
84 {
85         struct wpa_ssid *ssid = wpa_s->conf->ssid;
86         int count = 0;
87         while (ssid) {
88                 if (!wpas_network_disabled(wpa_s, ssid))
89                         count++;
90                 ssid = ssid->next;
91         }
92         if (wpa_s->conf->cred && wpa_s->conf->interworking &&
93             wpa_s->conf->auto_interworking)
94                 count++;
95         return count;
96 }
97
98
99 static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
100                                      struct wpa_ssid *ssid)
101 {
102         while (ssid) {
103                 if (!wpas_network_disabled(wpa_s, ssid))
104                         break;
105                 ssid = ssid->next;
106         }
107
108         /* ap_scan=2 mode - try to associate with each SSID. */
109         if (ssid == NULL) {
110                 wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached "
111                         "end of scan list - go back to beginning");
112                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
113                 wpa_supplicant_req_scan(wpa_s, 0, 0);
114                 return;
115         }
116         if (ssid->next) {
117                 /* Continue from the next SSID on the next attempt. */
118                 wpa_s->prev_scan_ssid = ssid;
119         } else {
120                 /* Start from the beginning of the SSID list. */
121                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
122         }
123         wpa_supplicant_associate(wpa_s, NULL, ssid);
124 }
125
126
127 static int int_array_len(const int *a)
128 {
129         int i;
130         for (i = 0; a && a[i]; i++)
131                 ;
132         return i;
133 }
134
135
136 static void int_array_concat(int **res, const int *a)
137 {
138         int reslen, alen, i;
139         int *n;
140
141         reslen = int_array_len(*res);
142         alen = int_array_len(a);
143
144         n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
145         if (n == NULL) {
146                 os_free(*res);
147                 *res = NULL;
148                 return;
149         }
150         for (i = 0; i <= alen; i++)
151                 n[reslen + i] = a[i];
152         *res = n;
153 }
154
155
156 static int freq_cmp(const void *a, const void *b)
157 {
158         int _a = *(int *) a;
159         int _b = *(int *) b;
160
161         if (_a == 0)
162                 return 1;
163         if (_b == 0)
164                 return -1;
165         return _a - _b;
166 }
167
168
169 static void int_array_sort_unique(int *a)
170 {
171         int alen;
172         int i, j;
173
174         if (a == NULL)
175                 return;
176
177         alen = int_array_len(a);
178         qsort(a, alen, sizeof(int), freq_cmp);
179
180         i = 0;
181         j = 1;
182         while (a[i] && a[j]) {
183                 if (a[i] == a[j]) {
184                         j++;
185                         continue;
186                 }
187                 a[++i] = a[j++];
188         }
189         if (a[i])
190                 i++;
191         a[i] = 0;
192 }
193
194
195 int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
196                                 struct wpa_driver_scan_params *params)
197 {
198         int ret;
199
200         wpa_supplicant_notify_scanning(wpa_s, 1);
201
202         ret = wpa_drv_scan(wpa_s, params);
203         if (ret) {
204                 wpa_supplicant_notify_scanning(wpa_s, 0);
205                 wpas_notify_scan_done(wpa_s, 0);
206         } else {
207                 wpa_s->scan_runs++;
208                 wpa_s->normal_scans++;
209         }
210
211         return ret;
212 }
213
214
215 static void
216 wpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
217 {
218         struct wpa_supplicant *wpa_s = eloop_ctx;
219
220         wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan");
221
222         if (wpa_supplicant_req_sched_scan(wpa_s))
223                 wpa_supplicant_req_scan(wpa_s, 0, 0);
224 }
225
226
227 static void
228 wpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
229 {
230         struct wpa_supplicant *wpa_s = eloop_ctx;
231
232         wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it");
233
234         wpa_s->sched_scan_timed_out = 1;
235         wpa_supplicant_cancel_sched_scan(wpa_s);
236 }
237
238
239 static int
240 wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
241                                 struct wpa_driver_scan_params *params,
242                                 int interval)
243 {
244         int ret;
245
246         wpa_supplicant_notify_scanning(wpa_s, 1);
247         ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
248         if (ret)
249                 wpa_supplicant_notify_scanning(wpa_s, 0);
250         else
251                 wpa_s->sched_scanning = 1;
252
253         return ret;
254 }
255
256
257 static int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
258 {
259         int ret;
260
261         ret = wpa_drv_stop_sched_scan(wpa_s);
262         if (ret) {
263                 wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!");
264                 /* TODO: what to do if stopping fails? */
265                 return -1;
266         }
267
268         return ret;
269 }
270
271
272 static struct wpa_driver_scan_filter *
273 wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
274 {
275         struct wpa_driver_scan_filter *ssids;
276         struct wpa_ssid *ssid;
277         size_t count;
278
279         *num_ssids = 0;
280         if (!conf->filter_ssids)
281                 return NULL;
282
283         for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
284                 if (ssid->ssid && ssid->ssid_len)
285                         count++;
286         }
287         if (count == 0)
288                 return NULL;
289         ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter));
290         if (ssids == NULL)
291                 return NULL;
292
293         for (ssid = conf->ssid; ssid; ssid = ssid->next) {
294                 if (!ssid->ssid || !ssid->ssid_len)
295                         continue;
296                 os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
297                 ssids[*num_ssids].ssid_len = ssid->ssid_len;
298                 (*num_ssids)++;
299         }
300
301         return ssids;
302 }
303
304
305 static void wpa_supplicant_optimize_freqs(
306         struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params)
307 {
308 #ifdef CONFIG_P2P
309         if (params->freqs == NULL && wpa_s->p2p_in_provisioning &&
310             wpa_s->go_params) {
311                 /* Optimize provisioning state scan based on GO information */
312                 if (wpa_s->p2p_in_provisioning < 5 &&
313                     wpa_s->go_params->freq > 0) {
314                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO "
315                                 "preferred frequency %d MHz",
316                                 wpa_s->go_params->freq);
317                         params->freqs = os_zalloc(2 * sizeof(int));
318                         if (params->freqs)
319                                 params->freqs[0] = wpa_s->go_params->freq;
320                 } else if (wpa_s->p2p_in_provisioning < 8 &&
321                            wpa_s->go_params->freq_list[0]) {
322                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common "
323                                 "channels");
324                         int_array_concat(&params->freqs,
325                                          wpa_s->go_params->freq_list);
326                         if (params->freqs)
327                                 int_array_sort_unique(params->freqs);
328                 }
329                 wpa_s->p2p_in_provisioning++;
330         }
331 #endif /* CONFIG_P2P */
332
333 #ifdef CONFIG_WPS
334         if (params->freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
335                 /*
336                  * Optimize post-provisioning scan based on channel used
337                  * during provisioning.
338                  */
339                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz "
340                         "that was used during provisioning", wpa_s->wps_freq);
341                 params->freqs = os_zalloc(2 * sizeof(int));
342                 if (params->freqs)
343                         params->freqs[0] = wpa_s->wps_freq;
344                 wpa_s->after_wps--;
345         }
346
347         if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
348         {
349                 /* Optimize provisioning scan based on already known channel */
350                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz",
351                         wpa_s->wps_freq);
352                 params->freqs = os_zalloc(2 * sizeof(int));
353                 if (params->freqs)
354                         params->freqs[0] = wpa_s->wps_freq;
355                 wpa_s->known_wps_freq = 0; /* only do this once */
356         }
357 #endif /* CONFIG_WPS */
358 }
359
360
361 #ifdef CONFIG_INTERWORKING
362 static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
363                                            struct wpabuf *buf)
364 {
365         if (wpa_s->conf->interworking == 0)
366                 return;
367
368         wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB);
369         wpabuf_put_u8(buf, 4);
370         wpabuf_put_u8(buf, 0x00);
371         wpabuf_put_u8(buf, 0x00);
372         wpabuf_put_u8(buf, 0x00);
373         wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */
374
375         wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
376         wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
377                       1 + ETH_ALEN);
378         wpabuf_put_u8(buf, wpa_s->conf->access_network_type);
379         /* No Venue Info */
380         if (!is_zero_ether_addr(wpa_s->conf->hessid))
381                 wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN);
382 }
383 #endif /* CONFIG_INTERWORKING */
384
385
386 static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
387 {
388         struct wpabuf *extra_ie = NULL;
389 #ifdef CONFIG_WPS
390         int wps = 0;
391         enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
392 #endif /* CONFIG_WPS */
393
394 #ifdef CONFIG_INTERWORKING
395         if (wpa_s->conf->interworking &&
396             wpabuf_resize(&extra_ie, 100) == 0)
397                 wpas_add_interworking_elements(wpa_s, extra_ie);
398 #endif /* CONFIG_INTERWORKING */
399
400 #ifdef CONFIG_WPS
401         wps = wpas_wps_in_use(wpa_s, &req_type);
402
403         if (wps) {
404                 struct wpabuf *wps_ie;
405                 wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
406                                                 DEV_PW_DEFAULT,
407                                                 &wpa_s->wps->dev,
408                                                 wpa_s->wps->uuid, req_type,
409                                                 0, NULL);
410                 if (wps_ie) {
411                         if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
412                                 wpabuf_put_buf(extra_ie, wps_ie);
413                         wpabuf_free(wps_ie);
414                 }
415         }
416
417 #ifdef CONFIG_P2P
418         if (wps) {
419                 size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
420                 if (wpabuf_resize(&extra_ie, ielen) == 0)
421                         wpas_p2p_scan_ie(wpa_s, extra_ie);
422         }
423 #endif /* CONFIG_P2P */
424
425 #endif /* CONFIG_WPS */
426
427         return extra_ie;
428 }
429
430
431 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
432 {
433         struct wpa_supplicant *wpa_s = eloop_ctx;
434         struct wpa_ssid *ssid;
435         int scan_req = 0, ret;
436         struct wpabuf *extra_ie = NULL;
437         struct wpa_driver_scan_params params;
438         struct wpa_driver_scan_params *scan_params;
439         size_t max_ssids;
440         enum wpa_states prev_state;
441
442         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
443                 wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
444                 return;
445         }
446
447         if (wpa_s->disconnected && !wpa_s->scan_req) {
448                 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
449                 return;
450         }
451
452         if (!wpa_supplicant_enabled_networks(wpa_s) &&
453             !wpa_s->scan_req) {
454                 wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
455                 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
456                 return;
457         }
458
459         if (wpa_s->conf->ap_scan != 0 &&
460             (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
461                 wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - "
462                         "overriding ap_scan configuration");
463                 wpa_s->conf->ap_scan = 0;
464                 wpas_notify_ap_scan_changed(wpa_s);
465         }
466
467         if (wpa_s->conf->ap_scan == 0) {
468                 wpa_supplicant_gen_assoc_event(wpa_s);
469                 return;
470         }
471
472 #ifdef CONFIG_P2P
473         if (wpas_p2p_in_progress(wpa_s)) {
474                 if (wpa_s->sta_scan_pending &&
475                     wpas_p2p_in_progress(wpa_s) == 2 &&
476                     wpa_s->p2p_cb_on_scan_complete) {
477                         wpa_dbg(wpa_s, MSG_DEBUG, "Process pending station "
478                                 "mode scan during P2P search");
479                 } else {
480                         wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan "
481                                 "while P2P operation is in progress");
482                         wpa_s->sta_scan_pending = 1;
483                         wpa_supplicant_req_scan(wpa_s, 5, 0);
484                         return;
485                 }
486         }
487 #endif /* CONFIG_P2P */
488
489         if (wpa_s->conf->ap_scan == 2)
490                 max_ssids = 1;
491         else {
492                 max_ssids = wpa_s->max_scan_ssids;
493                 if (max_ssids > WPAS_MAX_SCAN_SSIDS)
494                         max_ssids = WPAS_MAX_SCAN_SSIDS;
495         }
496
497         scan_req = wpa_s->scan_req;
498         wpa_s->scan_req = 0;
499
500         os_memset(&params, 0, sizeof(params));
501
502         prev_state = wpa_s->wpa_state;
503         if (wpa_s->wpa_state == WPA_DISCONNECTED ||
504             wpa_s->wpa_state == WPA_INACTIVE)
505                 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
506
507         /*
508          * If autoscan has set its own scanning parameters
509          */
510         if (wpa_s->autoscan_params != NULL) {
511                 scan_params = wpa_s->autoscan_params;
512                 goto scan;
513         }
514
515         if (scan_req != 2 && wpa_s->connect_without_scan) {
516                 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
517                         if (ssid == wpa_s->connect_without_scan)
518                                 break;
519                 }
520                 wpa_s->connect_without_scan = NULL;
521                 if (ssid) {
522                         wpa_printf(MSG_DEBUG, "Start a pre-selected network "
523                                    "without scan step");
524                         wpa_supplicant_associate(wpa_s, NULL, ssid);
525                         return;
526                 }
527         }
528
529 #ifdef CONFIG_P2P
530         if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
531             wpa_s->go_params) {
532                 wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during "
533                            "P2P group formation");
534                 params.ssids[0].ssid = wpa_s->go_params->ssid;
535                 params.ssids[0].ssid_len = wpa_s->go_params->ssid_len;
536                 params.num_ssids = 1;
537                 goto ssid_list_set;
538         }
539 #endif /* CONFIG_P2P */
540
541         /* Find the starting point from which to continue scanning */
542         ssid = wpa_s->conf->ssid;
543         if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
544                 while (ssid) {
545                         if (ssid == wpa_s->prev_scan_ssid) {
546                                 ssid = ssid->next;
547                                 break;
548                         }
549                         ssid = ssid->next;
550                 }
551         }
552
553         if (scan_req != 2 && wpa_s->conf->ap_scan == 2) {
554                 wpa_s->connect_without_scan = NULL;
555                 wpa_s->prev_scan_wildcard = 0;
556                 wpa_supplicant_assoc_try(wpa_s, ssid);
557                 return;
558         } else if (wpa_s->conf->ap_scan == 2) {
559                 /*
560                  * User-initiated scan request in ap_scan == 2; scan with
561                  * wildcard SSID.
562                  */
563                 ssid = NULL;
564         } else {
565                 struct wpa_ssid *start = ssid, *tssid;
566                 int freqs_set = 0;
567                 if (ssid == NULL && max_ssids > 1)
568                         ssid = wpa_s->conf->ssid;
569                 while (ssid) {
570                         if (!wpas_network_disabled(wpa_s, ssid) &&
571                             ssid->scan_ssid) {
572                                 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
573                                                   ssid->ssid, ssid->ssid_len);
574                                 params.ssids[params.num_ssids].ssid =
575                                         ssid->ssid;
576                                 params.ssids[params.num_ssids].ssid_len =
577                                         ssid->ssid_len;
578                                 params.num_ssids++;
579                                 if (params.num_ssids + 1 >= max_ssids)
580                                         break;
581                         }
582                         ssid = ssid->next;
583                         if (ssid == start)
584                                 break;
585                         if (ssid == NULL && max_ssids > 1 &&
586                             start != wpa_s->conf->ssid)
587                                 ssid = wpa_s->conf->ssid;
588                 }
589
590                 for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) {
591                         if (wpas_network_disabled(wpa_s, tssid))
592                                 continue;
593                         if ((params.freqs || !freqs_set) && tssid->scan_freq) {
594                                 int_array_concat(&params.freqs,
595                                                  tssid->scan_freq);
596                         } else {
597                                 os_free(params.freqs);
598                                 params.freqs = NULL;
599                         }
600                         freqs_set = 1;
601                 }
602                 int_array_sort_unique(params.freqs);
603         }
604
605         if (ssid && max_ssids == 1) {
606                 /*
607                  * If the driver is limited to 1 SSID at a time interleave
608                  * wildcard SSID scans with specific SSID scans to avoid
609                  * waiting a long time for a wildcard scan.
610                  */
611                 if (!wpa_s->prev_scan_wildcard) {
612                         params.ssids[0].ssid = NULL;
613                         params.ssids[0].ssid_len = 0;
614                         wpa_s->prev_scan_wildcard = 1;
615                         wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for "
616                                 "wildcard SSID (Interleave with specific)");
617                 } else {
618                         wpa_s->prev_scan_ssid = ssid;
619                         wpa_s->prev_scan_wildcard = 0;
620                         wpa_dbg(wpa_s, MSG_DEBUG,
621                                 "Starting AP scan for specific SSID: %s",
622                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
623                 }
624         } else if (ssid) {
625                 /* max_ssids > 1 */
626
627                 wpa_s->prev_scan_ssid = ssid;
628                 wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
629                         "the scan request");
630                 params.num_ssids++;
631         } else {
632                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
633                 params.num_ssids++;
634                 wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard "
635                         "SSID");
636         }
637 #ifdef CONFIG_P2P
638 ssid_list_set:
639 #endif /* CONFIG_P2P */
640
641         wpa_supplicant_optimize_freqs(wpa_s, &params);
642         extra_ie = wpa_supplicant_extra_ies(wpa_s);
643
644 #ifdef CONFIG_HS20
645         if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 6) == 0)
646                 wpas_hs20_add_indication(extra_ie);
647 #endif /* CONFIG_HS20 */
648
649         if (params.freqs == NULL && wpa_s->next_scan_freqs) {
650                 wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
651                         "generated frequency list");
652                 params.freqs = wpa_s->next_scan_freqs;
653         } else
654                 os_free(wpa_s->next_scan_freqs);
655         wpa_s->next_scan_freqs = NULL;
656
657         params.filter_ssids = wpa_supplicant_build_filter_ssids(
658                 wpa_s->conf, &params.num_filter_ssids);
659         if (extra_ie) {
660                 params.extra_ies = wpabuf_head(extra_ie);
661                 params.extra_ies_len = wpabuf_len(extra_ie);
662         }
663
664 #ifdef CONFIG_P2P
665         if (wpa_s->p2p_in_provisioning ||
666             (wpa_s->show_group_started && wpa_s->go_params)) {
667                 /*
668                  * The interface may not yet be in P2P mode, so we have to
669                  * explicitly request P2P probe to disable CCK rates.
670                  */
671                 params.p2p_probe = 1;
672         }
673 #endif /* CONFIG_P2P */
674
675         scan_params = &params;
676
677 scan:
678         ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
679
680         wpabuf_free(extra_ie);
681         os_free(params.freqs);
682         os_free(params.filter_ssids);
683
684         if (ret) {
685                 wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
686                 if (prev_state != wpa_s->wpa_state)
687                         wpa_supplicant_set_state(wpa_s, prev_state);
688                 wpa_supplicant_req_scan(wpa_s, 1, 0);
689         }
690 }
691
692
693 /**
694  * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
695  * @wpa_s: Pointer to wpa_supplicant data
696  * @sec: Number of seconds after which to scan
697  * @usec: Number of microseconds after which to scan
698  *
699  * This function is used to schedule a scan for neighboring access points after
700  * the specified time.
701  */
702 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
703 {
704         /* If there's at least one network that should be specifically scanned
705          * then don't cancel the scan and reschedule.  Some drivers do
706          * background scanning which generates frequent scan results, and that
707          * causes the specific SSID scan to get continually pushed back and
708          * never happen, which causes hidden APs to never get probe-scanned.
709          */
710         if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) &&
711             wpa_s->conf->ap_scan == 1) {
712                 struct wpa_ssid *ssid = wpa_s->conf->ssid;
713
714                 while (ssid) {
715                         if (!wpas_network_disabled(wpa_s, ssid) &&
716                             ssid->scan_ssid)
717                                 break;
718                         ssid = ssid->next;
719                 }
720                 if (ssid) {
721                         wpa_dbg(wpa_s, MSG_DEBUG, "Not rescheduling scan to "
722                                 "ensure that specific SSID scans occur");
723                         return;
724                 }
725         }
726
727         wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
728                 sec, usec);
729         eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
730         eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
731 }
732
733
734 /**
735  * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan
736  * @wpa_s: Pointer to wpa_supplicant data
737  * @sec: Number of seconds after which to scan
738  * @usec: Number of microseconds after which to scan
739  *
740  * This function is used to schedule periodic scans for neighboring
741  * access points after the specified time.
742  */
743 int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
744                                       int sec, int usec)
745 {
746         if (!wpa_s->sched_scan_supported)
747                 return -1;
748
749         eloop_register_timeout(sec, usec,
750                                wpa_supplicant_delayed_sched_scan_timeout,
751                                wpa_s, NULL);
752
753         return 0;
754 }
755
756
757 /**
758  * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
759  * @wpa_s: Pointer to wpa_supplicant data
760  *
761  * This function is used to schedule periodic scans for neighboring
762  * access points repeating the scan continuously.
763  */
764 int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
765 {
766         struct wpa_driver_scan_params params;
767         struct wpa_driver_scan_params *scan_params;
768         enum wpa_states prev_state;
769         struct wpa_ssid *ssid = NULL;
770         struct wpabuf *extra_ie = NULL;
771         int ret;
772         unsigned int max_sched_scan_ssids;
773         int wildcard = 0;
774         int need_ssids;
775
776         if (!wpa_s->sched_scan_supported)
777                 return -1;
778
779         if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
780                 max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
781         else
782                 max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
783         if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
784                 return -1;
785
786         if (wpa_s->sched_scanning) {
787                 wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
788                 return 0;
789         }
790
791         need_ssids = 0;
792         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
793                 if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) {
794                         /* Use wildcard SSID to find this network */
795                         wildcard = 1;
796                 } else if (!wpas_network_disabled(wpa_s, ssid) &&
797                            ssid->ssid_len)
798                         need_ssids++;
799
800 #ifdef CONFIG_WPS
801                 if (!wpas_network_disabled(wpa_s, ssid) &&
802                     ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
803                         /*
804                          * Normal scan is more reliable and faster for WPS
805                          * operations and since these are for short periods of
806                          * time, the benefit of trying to use sched_scan would
807                          * be limited.
808                          */
809                         wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
810                                 "sched_scan for WPS");
811                         return -1;
812                 }
813 #endif /* CONFIG_WPS */
814         }
815         if (wildcard)
816                 need_ssids++;
817
818         if (wpa_s->normal_scans < 3 &&
819             (need_ssids <= wpa_s->max_scan_ssids ||
820              wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) {
821                 /*
822                  * When normal scan can speed up operations, use that for the
823                  * first operations before starting the sched_scan to allow
824                  * user space sleep more. We do this only if the normal scan
825                  * has functionality that is suitable for this or if the
826                  * sched_scan does not have better support for multiple SSIDs.
827                  */
828                 wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
829                         "sched_scan for initial scans (normal_scans=%d)",
830                         wpa_s->normal_scans);
831                 return -1;
832         }
833
834         os_memset(&params, 0, sizeof(params));
835
836         /* If we can't allocate space for the filters, we just don't filter */
837         params.filter_ssids = os_zalloc(wpa_s->max_match_sets *
838                                         sizeof(struct wpa_driver_scan_filter));
839
840         prev_state = wpa_s->wpa_state;
841         if (wpa_s->wpa_state == WPA_DISCONNECTED ||
842             wpa_s->wpa_state == WPA_INACTIVE)
843                 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
844
845         if (wpa_s->autoscan_params != NULL) {
846                 scan_params = wpa_s->autoscan_params;
847                 goto scan;
848         }
849
850         /* Find the starting point from which to continue scanning */
851         ssid = wpa_s->conf->ssid;
852         if (wpa_s->prev_sched_ssid) {
853                 while (ssid) {
854                         if (ssid == wpa_s->prev_sched_ssid) {
855                                 ssid = ssid->next;
856                                 break;
857                         }
858                         ssid = ssid->next;
859                 }
860         }
861
862         if (!ssid || !wpa_s->prev_sched_ssid) {
863                 wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
864
865                 if (wpa_s->sched_scan_interval == 0)
866                         wpa_s->sched_scan_interval = 10;
867                 wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
868                 wpa_s->first_sched_scan = 1;
869                 ssid = wpa_s->conf->ssid;
870                 wpa_s->prev_sched_ssid = ssid;
871         }
872
873         if (wildcard) {
874                 wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan");
875                 params.num_ssids++;
876         }
877
878         while (ssid) {
879                 if (wpas_network_disabled(wpa_s, ssid))
880                         goto next;
881
882                 if (params.num_filter_ssids < wpa_s->max_match_sets &&
883                     params.filter_ssids && ssid->ssid && ssid->ssid_len) {
884                         wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s",
885                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
886                         os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid,
887                                   ssid->ssid, ssid->ssid_len);
888                         params.filter_ssids[params.num_filter_ssids].ssid_len =
889                                 ssid->ssid_len;
890                         params.num_filter_ssids++;
891                 } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len)
892                 {
893                         wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID "
894                                 "filter for sched_scan - drop filter");
895                         os_free(params.filter_ssids);
896                         params.filter_ssids = NULL;
897                         params.num_filter_ssids = 0;
898                 }
899
900                 if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) {
901                         if (params.num_ssids == max_sched_scan_ssids)
902                                 break; /* only room for broadcast SSID */
903                         wpa_dbg(wpa_s, MSG_DEBUG,
904                                 "add to active scan ssid: %s",
905                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
906                         params.ssids[params.num_ssids].ssid =
907                                 ssid->ssid;
908                         params.ssids[params.num_ssids].ssid_len =
909                                 ssid->ssid_len;
910                         params.num_ssids++;
911                         if (params.num_ssids >= max_sched_scan_ssids) {
912                                 wpa_s->prev_sched_ssid = ssid;
913                                 do {
914                                         ssid = ssid->next;
915                                 } while (ssid &&
916                                          (wpas_network_disabled(wpa_s, ssid) ||
917                                           !ssid->scan_ssid));
918                                 break;
919                         }
920                 }
921
922         next:
923                 wpa_s->prev_sched_ssid = ssid;
924                 ssid = ssid->next;
925         }
926
927         if (params.num_filter_ssids == 0) {
928                 os_free(params.filter_ssids);
929                 params.filter_ssids = NULL;
930         }
931
932         extra_ie = wpa_supplicant_extra_ies(wpa_s);
933         if (extra_ie) {
934                 params.extra_ies = wpabuf_head(extra_ie);
935                 params.extra_ies_len = wpabuf_len(extra_ie);
936         }
937
938         scan_params = &params;
939
940 scan:
941         if (ssid || !wpa_s->first_sched_scan) {
942                 wpa_dbg(wpa_s, MSG_DEBUG,
943                         "Starting sched scan: interval %d timeout %d",
944                         wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout);
945         } else {
946                 wpa_dbg(wpa_s, MSG_DEBUG,
947                         "Starting sched scan: interval %d (no timeout)",
948                         wpa_s->sched_scan_interval);
949         }
950
951         ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
952                                               wpa_s->sched_scan_interval);
953         wpabuf_free(extra_ie);
954         os_free(params.filter_ssids);
955         if (ret) {
956                 wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan");
957                 if (prev_state != wpa_s->wpa_state)
958                         wpa_supplicant_set_state(wpa_s, prev_state);
959                 return ret;
960         }
961
962         /* If we have more SSIDs to scan, add a timeout so we scan them too */
963         if (ssid || !wpa_s->first_sched_scan) {
964                 wpa_s->sched_scan_timed_out = 0;
965                 eloop_register_timeout(wpa_s->sched_scan_timeout, 0,
966                                        wpa_supplicant_sched_scan_timeout,
967                                        wpa_s, NULL);
968                 wpa_s->first_sched_scan = 0;
969                 wpa_s->sched_scan_timeout /= 2;
970                 wpa_s->sched_scan_interval *= 2;
971         }
972
973         return 0;
974 }
975
976
977 /**
978  * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
979  * @wpa_s: Pointer to wpa_supplicant data
980  *
981  * This function is used to cancel a scan request scheduled with
982  * wpa_supplicant_req_scan().
983  */
984 void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
985 {
986         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
987         eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
988 }
989
990
991 /**
992  * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans
993  * @wpa_s: Pointer to wpa_supplicant data
994  *
995  * This function is used to stop a periodic scheduled scan.
996  */
997 void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
998 {
999         if (!wpa_s->sched_scanning)
1000                 return;
1001
1002         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
1003         eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
1004         wpa_supplicant_stop_sched_scan(wpa_s);
1005 }
1006
1007
1008 void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
1009                                     int scanning)
1010 {
1011         if (wpa_s->scanning != scanning) {
1012                 wpa_s->scanning = scanning;
1013                 wpas_notify_scanning(wpa_s);
1014         }
1015 }
1016
1017
1018 static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
1019 {
1020         int rate = 0;
1021         const u8 *ie;
1022         int i;
1023
1024         ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
1025         for (i = 0; ie && i < ie[1]; i++) {
1026                 if ((ie[i + 2] & 0x7f) > rate)
1027                         rate = ie[i + 2] & 0x7f;
1028         }
1029
1030         ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
1031         for (i = 0; ie && i < ie[1]; i++) {
1032                 if ((ie[i + 2] & 0x7f) > rate)
1033                         rate = ie[i + 2] & 0x7f;
1034         }
1035
1036         return rate;
1037 }
1038
1039
1040 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
1041 {
1042         const u8 *end, *pos;
1043
1044         pos = (const u8 *) (res + 1);
1045         end = pos + res->ie_len;
1046
1047         while (pos + 1 < end) {
1048                 if (pos + 2 + pos[1] > end)
1049                         break;
1050                 if (pos[0] == ie)
1051                         return pos;
1052                 pos += 2 + pos[1];
1053         }
1054
1055         return NULL;
1056 }
1057
1058
1059 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
1060                                   u32 vendor_type)
1061 {
1062         const u8 *end, *pos;
1063
1064         pos = (const u8 *) (res + 1);
1065         end = pos + res->ie_len;
1066
1067         while (pos + 1 < end) {
1068                 if (pos + 2 + pos[1] > end)
1069                         break;
1070                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1071                     vendor_type == WPA_GET_BE32(&pos[2]))
1072                         return pos;
1073                 pos += 2 + pos[1];
1074         }
1075
1076         return NULL;
1077 }
1078
1079
1080 struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
1081                                              u32 vendor_type)
1082 {
1083         struct wpabuf *buf;
1084         const u8 *end, *pos;
1085
1086         buf = wpabuf_alloc(res->ie_len);
1087         if (buf == NULL)
1088                 return NULL;
1089
1090         pos = (const u8 *) (res + 1);
1091         end = pos + res->ie_len;
1092
1093         while (pos + 1 < end) {
1094                 if (pos + 2 + pos[1] > end)
1095                         break;
1096                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1097                     vendor_type == WPA_GET_BE32(&pos[2]))
1098                         wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
1099                 pos += 2 + pos[1];
1100         }
1101
1102         if (wpabuf_len(buf) == 0) {
1103                 wpabuf_free(buf);
1104                 buf = NULL;
1105         }
1106
1107         return buf;
1108 }
1109
1110
1111 struct wpabuf * wpa_scan_get_vendor_ie_multi_beacon(
1112         const struct wpa_scan_res *res, u32 vendor_type)
1113 {
1114         struct wpabuf *buf;
1115         const u8 *end, *pos;
1116
1117         if (res->beacon_ie_len == 0)
1118                 return NULL;
1119         buf = wpabuf_alloc(res->beacon_ie_len);
1120         if (buf == NULL)
1121                 return NULL;
1122
1123         pos = (const u8 *) (res + 1);
1124         pos += res->ie_len;
1125         end = pos + res->beacon_ie_len;
1126
1127         while (pos + 1 < end) {
1128                 if (pos + 2 + pos[1] > end)
1129                         break;
1130                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1131                     vendor_type == WPA_GET_BE32(&pos[2]))
1132                         wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
1133                 pos += 2 + pos[1];
1134         }
1135
1136         if (wpabuf_len(buf) == 0) {
1137                 wpabuf_free(buf);
1138                 buf = NULL;
1139         }
1140
1141         return buf;
1142 }
1143
1144
1145 /*
1146  * Channels with a great SNR can operate at full rate. What is a great SNR?
1147  * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
1148  * rule of thumb is that any SNR above 20 is good." This one
1149  * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
1150  * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
1151  * conservative value.
1152  */
1153 #define GREAT_SNR 30
1154
1155 /* Compare function for sorting scan results. Return >0 if @b is considered
1156  * better. */
1157 static int wpa_scan_result_compar(const void *a, const void *b)
1158 {
1159 #define IS_5GHZ(n) (n > 4000)
1160 #define MIN(a,b) a < b ? a : b
1161         struct wpa_scan_res **_wa = (void *) a;
1162         struct wpa_scan_res **_wb = (void *) b;
1163         struct wpa_scan_res *wa = *_wa;
1164         struct wpa_scan_res *wb = *_wb;
1165         int wpa_a, wpa_b, maxrate_a, maxrate_b;
1166         int snr_a, snr_b;
1167
1168         /* WPA/WPA2 support preferred */
1169         wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
1170                 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
1171         wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
1172                 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
1173
1174         if (wpa_b && !wpa_a)
1175                 return 1;
1176         if (!wpa_b && wpa_a)
1177                 return -1;
1178
1179         /* privacy support preferred */
1180         if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
1181             (wb->caps & IEEE80211_CAP_PRIVACY))
1182                 return 1;
1183         if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
1184             (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
1185                 return -1;
1186
1187         if ((wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) &&
1188             !((wa->flags | wb->flags) & WPA_SCAN_NOISE_INVALID)) {
1189                 snr_a = MIN(wa->level - wa->noise, GREAT_SNR);
1190                 snr_b = MIN(wb->level - wb->noise, GREAT_SNR);
1191         } else {
1192                 /* Not suitable information to calculate SNR, so use level */
1193                 snr_a = wa->level;
1194                 snr_b = wb->level;
1195         }
1196
1197         /* best/max rate preferred if SNR close enough */
1198         if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
1199             (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
1200                 maxrate_a = wpa_scan_get_max_rate(wa);
1201                 maxrate_b = wpa_scan_get_max_rate(wb);
1202                 if (maxrate_a != maxrate_b)
1203                         return maxrate_b - maxrate_a;
1204                 if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
1205                         return IS_5GHZ(wa->freq) ? -1 : 1;
1206         }
1207
1208         /* use freq for channel preference */
1209
1210         /* all things being equal, use SNR; if SNRs are
1211          * identical, use quality values since some drivers may only report
1212          * that value and leave the signal level zero */
1213         if (snr_b == snr_a)
1214                 return wb->qual - wa->qual;
1215         return snr_b - snr_a;
1216 #undef MIN
1217 #undef IS_5GHZ
1218 }
1219
1220
1221 #ifdef CONFIG_WPS
1222 /* Compare function for sorting scan results when searching a WPS AP for
1223  * provisioning. Return >0 if @b is considered better. */
1224 static int wpa_scan_result_wps_compar(const void *a, const void *b)
1225 {
1226         struct wpa_scan_res **_wa = (void *) a;
1227         struct wpa_scan_res **_wb = (void *) b;
1228         struct wpa_scan_res *wa = *_wa;
1229         struct wpa_scan_res *wb = *_wb;
1230         int uses_wps_a, uses_wps_b;
1231         struct wpabuf *wps_a, *wps_b;
1232         int res;
1233
1234         /* Optimization - check WPS IE existence before allocated memory and
1235          * doing full reassembly. */
1236         uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
1237         uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
1238         if (uses_wps_a && !uses_wps_b)
1239                 return -1;
1240         if (!uses_wps_a && uses_wps_b)
1241                 return 1;
1242
1243         if (uses_wps_a && uses_wps_b) {
1244                 wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
1245                 wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
1246                 res = wps_ap_priority_compar(wps_a, wps_b);
1247                 wpabuf_free(wps_a);
1248                 wpabuf_free(wps_b);
1249                 if (res)
1250                         return res;
1251         }
1252
1253         /*
1254          * Do not use current AP security policy as a sorting criteria during
1255          * WPS provisioning step since the AP may get reconfigured at the
1256          * completion of provisioning.
1257          */
1258
1259         /* all things being equal, use signal level; if signal levels are
1260          * identical, use quality values since some drivers may only report
1261          * that value and leave the signal level zero */
1262         if (wb->level == wa->level)
1263                 return wb->qual - wa->qual;
1264         return wb->level - wa->level;
1265 }
1266 #endif /* CONFIG_WPS */
1267
1268
1269 static void dump_scan_res(struct wpa_scan_results *scan_res)
1270 {
1271 #ifndef CONFIG_NO_STDOUT_DEBUG
1272         size_t i;
1273
1274         if (scan_res->res == NULL || scan_res->num == 0)
1275                 return;
1276
1277         wpa_printf(MSG_EXCESSIVE, "Sorted scan results");
1278
1279         for (i = 0; i < scan_res->num; i++) {
1280                 struct wpa_scan_res *r = scan_res->res[i];
1281                 u8 *pos;
1282                 if ((r->flags & (WPA_SCAN_LEVEL_DBM | WPA_SCAN_NOISE_INVALID))
1283                     == WPA_SCAN_LEVEL_DBM) {
1284                         int snr = r->level - r->noise;
1285                         wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1286                                    "noise=%d level=%d snr=%d%s flags=0x%x",
1287                                    MAC2STR(r->bssid), r->freq, r->qual,
1288                                    r->noise, r->level, snr,
1289                                    snr >= GREAT_SNR ? "*" : "", r->flags);
1290                 } else {
1291                         wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1292                                    "noise=%d level=%d flags=0x%x",
1293                                    MAC2STR(r->bssid), r->freq, r->qual,
1294                                    r->noise, r->level, r->flags);
1295                 }
1296                 pos = (u8 *) (r + 1);
1297                 if (r->ie_len)
1298                         wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len);
1299                 pos += r->ie_len;
1300                 if (r->beacon_ie_len)
1301                         wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs",
1302                                     pos, r->beacon_ie_len);
1303         }
1304 #endif /* CONFIG_NO_STDOUT_DEBUG */
1305 }
1306
1307
1308 int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
1309                                       const u8 *bssid)
1310 {
1311         size_t i;
1312
1313         if (wpa_s->bssid_filter == NULL)
1314                 return 1;
1315
1316         for (i = 0; i < wpa_s->bssid_filter_count; i++) {
1317                 if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
1318                               ETH_ALEN) == 0)
1319                         return 1;
1320         }
1321
1322         return 0;
1323 }
1324
1325
1326 static void filter_scan_res(struct wpa_supplicant *wpa_s,
1327                             struct wpa_scan_results *res)
1328 {
1329         size_t i, j;
1330
1331         if (wpa_s->bssid_filter == NULL)
1332                 return;
1333
1334         for (i = 0, j = 0; i < res->num; i++) {
1335                 if (wpa_supplicant_filter_bssid_match(wpa_s,
1336                                                       res->res[i]->bssid)) {
1337                         res->res[j++] = res->res[i];
1338                 } else {
1339                         os_free(res->res[i]);
1340                         res->res[i] = NULL;
1341                 }
1342         }
1343
1344         if (res->num != j) {
1345                 wpa_printf(MSG_DEBUG, "Filtered out %d scan results",
1346                            (int) (res->num - j));
1347                 res->num = j;
1348         }
1349 }
1350
1351
1352 /**
1353  * wpa_supplicant_get_scan_results - Get scan results
1354  * @wpa_s: Pointer to wpa_supplicant data
1355  * @info: Information about what was scanned or %NULL if not available
1356  * @new_scan: Whether a new scan was performed
1357  * Returns: Scan results, %NULL on failure
1358  *
1359  * This function request the current scan results from the driver and updates
1360  * the local BSS list wpa_s->bss. The caller is responsible for freeing the
1361  * results with wpa_scan_results_free().
1362  */
1363 struct wpa_scan_results *
1364 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
1365                                 struct scan_info *info, int new_scan)
1366 {
1367         struct wpa_scan_results *scan_res;
1368         size_t i;
1369         int (*compar)(const void *, const void *) = wpa_scan_result_compar;
1370
1371         scan_res = wpa_drv_get_scan_results2(wpa_s);
1372         if (scan_res == NULL) {
1373                 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
1374                 return NULL;
1375         }
1376         filter_scan_res(wpa_s, scan_res);
1377
1378 #ifdef CONFIG_WPS
1379         if (wpas_wps_in_progress(wpa_s)) {
1380                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
1381                         "provisioning rules");
1382                 compar = wpa_scan_result_wps_compar;
1383         }
1384 #endif /* CONFIG_WPS */
1385
1386         qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
1387               compar);
1388         dump_scan_res(scan_res);
1389
1390         wpa_bss_update_start(wpa_s);
1391         for (i = 0; i < scan_res->num; i++)
1392                 wpa_bss_update_scan_res(wpa_s, scan_res->res[i]);
1393         wpa_bss_update_end(wpa_s, info, new_scan);
1394
1395         return scan_res;
1396 }
1397
1398
1399 int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
1400 {
1401         struct wpa_scan_results *scan_res;
1402         scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1403         if (scan_res == NULL)
1404                 return -1;
1405         wpa_scan_results_free(scan_res);
1406
1407         return 0;
1408 }