scan.c revision b96dad47218788efffa3db0fe7f1b54a7d19e366
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Scanning
3a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
143a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt#include "common/wpa_ctrl.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_supplicant.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_supplicant.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h"
2104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "hs20_supplicant.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "notify.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bss.h"
24051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "gas_query.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "scan.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_supplicant_get_ssid(wpa_s);
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL)
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid == NULL) {
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->current_ssid = ssid;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->current_ssid != NULL)
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_notify_network_changed(wpa_s);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_initiate_eapol(wpa_s);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"network - generating associated event");
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   enum wps_request_type *req_type)
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int wps = 0;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps = 1;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*req_type = wpas_wps_get_req_type(ssid);
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!ssid->eap.phase1)
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strstr(ssid->eap.phase1, "pbc=1"))
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 2;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
71d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p &&
72d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    !wpa_s->conf->p2p_disabled) {
73c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_s->wps->dev.p2p = 1;
74c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (!wps) {
75c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wps = 1;
76c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			*req_type = WPS_REQ_ENROLLEE_INFO;
77c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */
801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wps;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
86a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
87a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_enabled_networks - Check whether there are enabled networks
88a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
89a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 if no networks are enabled, >0 if networks are enabled
90a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
91a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to figure out whether any networks (or Interworking
92a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * with enabled credentials and auto_interworking) are present in the current
93a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * configuration.
94a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
9504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_ssid *ssid = wpa_s->conf->ssid;
98aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	int count = 0, disabled = 0;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
10004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!wpas_network_disabled(wpa_s, ssid))
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			count++;
102aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		else
103aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt			disabled++;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = ssid->next;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpa_s->conf->cred && wpa_s->conf->interworking &&
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    wpa_s->conf->auto_interworking)
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		count++;
109aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	if (count == 0 && disabled > 0) {
110aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled "
111aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt			"networks)", disabled);
112aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return count;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid)
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
12104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!wpas_network_disabled(wpa_s, ssid))
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = ssid->next;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ap_scan=2 mode - try to associate with each SSID. */
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL) {
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached "
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"end of scan list - go back to beginning");
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_req_scan(wpa_s, 0, 0);
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->next) {
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Continue from the next SSID on the next attempt. */
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->prev_scan_ssid = ssid;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from the beginning of the SSID list. */
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_associate(wpa_s, NULL, ssid);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int int_array_len(const int *a)
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; a && a[i]; i++)
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return i;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void int_array_concat(int **res, const int *a)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reslen, alen, i;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *n;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reslen = int_array_len(*res);
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	alen = int_array_len(a);
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (n == NULL) {
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(*res);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*res = NULL;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i <= alen; i++)
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		n[reslen + i] = a[i];
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*res = n;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int freq_cmp(const void *a, const void *b)
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int _a = *(int *) a;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int _b = *(int *) b;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_a == 0)
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_b == 0)
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return _a - _b;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void int_array_sort_unique(int *a)
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int alen;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, j;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (a == NULL)
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	alen = int_array_len(a);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	qsort(a, alen, sizeof(int), freq_cmp);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	i = 0;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	j = 1;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (a[i] && a[j]) {
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (a[i] == a[j]) {
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			j++;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		a[++i] = a[j++];
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (a[i])
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		i++;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	a[i] = 0;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
213a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
214a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_trigger_scan - Request driver to start a scan
215a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
216a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @params: Scan parameters
217a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure
218a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_driver_scan_params *params)
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_notify_scanning(wpa_s, 1);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ret = wpa_drv_scan(wpa_s, params);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_notify_scanning(wpa_s, 0);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_notify_scan_done(wpa_s, 0);
2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
231444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		os_get_time(&wpa_s->scan_trigger_time);
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->scan_runs++;
2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->normal_scans++;
2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return ret;
2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void
2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtwpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan");
2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_supplicant_req_sched_scan(wpa_s))
2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_supplicant_req_scan(wpa_s, 0, 0);
2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void
2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtwpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it");
2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_s->sched_scan_timed_out = 1;
2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_supplicant_cancel_sched_scan(wpa_s);
2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int
2651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtwpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				struct wpa_driver_scan_params *params,
2671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				int interval)
2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int ret;
270b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_supplicant_notify_scanning(wpa_s, 1);
2721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ret)
2741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_supplicant_notify_scanning(wpa_s, 0);
275b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt	else
2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->sched_scanning = 1;
2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return ret;
2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int ret;
2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ret = wpa_drv_stop_sched_scan(wpa_s);
2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ret) {
2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!");
2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* TODO: what to do if stopping fails? */
2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_driver_scan_filter *
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_scan_filter *ssids;
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*num_ssids = 0;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conf->filter_ssids)
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->ssid && ssid->ssid_len)
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			count++;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count == 0)
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter));
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssids == NULL)
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (ssid = conf->ssid; ssid; ssid = ssid->next) {
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!ssid->ssid || !ssid->ssid_len)
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssids[*num_ssids].ssid_len = ssid->ssid_len;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(*num_ssids)++;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ssids;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpa_supplicant_optimize_freqs(
3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params)
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (params->freqs == NULL && wpa_s->p2p_in_provisioning &&
3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    wpa_s->go_params) {
3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Optimize provisioning state scan based on GO information */
3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_s->p2p_in_provisioning < 5 &&
3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    wpa_s->go_params->freq > 0) {
3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO "
3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"preferred frequency %d MHz",
3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_s->go_params->freq);
3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params->freqs = os_zalloc(2 * sizeof(int));
3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (params->freqs)
3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				params->freqs[0] = wpa_s->go_params->freq;
3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		} else if (wpa_s->p2p_in_provisioning < 8 &&
3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   wpa_s->go_params->freq_list[0]) {
3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common "
3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"channels");
3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			int_array_concat(&params->freqs,
3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					 wpa_s->go_params->freq_list);
3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (params->freqs)
3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				int_array_sort_unique(params->freqs);
3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->p2p_in_provisioning++;
3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */
3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS
3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (params->freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * Optimize post-provisioning scan based on channel used
3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * during provisioning.
3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz "
3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"that was used during provisioning", wpa_s->wps_freq);
3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params->freqs = os_zalloc(2 * sizeof(int));
3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (params->freqs)
3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params->freqs[0] = wpa_s->wps_freq;
3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->after_wps--;
3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
372c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
373c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{
374c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		/* Optimize provisioning scan based on already known channel */
375c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz",
376c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_s->wps_freq);
377c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		params->freqs = os_zalloc(2 * sizeof(int));
378c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (params->freqs)
379c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			params->freqs[0] = wpa_s->wps_freq;
380c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_s->known_wps_freq = 0; /* only do this once */
381c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */
3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING
3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   struct wpabuf *buf)
3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->conf->interworking == 0)
3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB);
3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, 4);
3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, 0x00);
3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, 0x00);
3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, 0x00);
3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */
3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		      1 + ETH_ALEN);
4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_put_u8(buf, wpa_s->conf->access_network_type);
4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* No Venue Info */
4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!is_zero_ether_addr(wpa_s->conf->hessid))
4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN);
4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */
4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
41161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
4121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
4131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpabuf *extra_ie = NULL;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int wps = 0;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING
4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->conf->interworking &&
4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    wpabuf_resize(&extra_ie, 100) == 0)
4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpas_add_interworking_elements(wpa_s, extra_ie);
4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */
4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS
4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wps = wpas_wps_in_use(wpa_s, &req_type);
4271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wps) {
4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		struct wpabuf *wps_ie;
43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
43104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						DEV_PW_DEFAULT,
43204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						&wpa_s->wps->dev,
4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						wpa_s->wps->uuid, req_type,
4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						0, NULL);
4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wps_ie) {
4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpabuf_put_buf(extra_ie, wps_ie);
4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpabuf_free(wps_ie);
4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wps) {
4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpabuf_resize(&extra_ie, ielen) == 0)
4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpas_p2p_scan_ie(wpa_s, extra_ie);
4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */
4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */
4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
45251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#ifdef CONFIG_HS20
45351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
45451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt		wpas_hs20_add_indication(extra_ie);
45551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#endif /* CONFIG_HS20 */
45651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt
4571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return extra_ie;
4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
461d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_P2P
462d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
463d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt/*
464d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * Check whether there are any enabled networks or credentials that could be
465d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * used for a non-P2P connection.
466d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */
467d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
468d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
469d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	struct wpa_ssid *ssid;
470d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
471d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
472d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (wpas_network_disabled(wpa_s, ssid))
473d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			continue;
474d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (!ssid->p2p_group)
475d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return 1;
476d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
477d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
478d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (wpa_s->conf->cred && wpa_s->conf->interworking &&
479d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    wpa_s->conf->auto_interworking)
480d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 1;
481d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
482d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
483d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
484d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
485ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#endif /* CONFIG_P2P */
486d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
487d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
488b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
489b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					  u16 num_modes,
490b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					  enum hostapd_hw_mode mode)
491b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
492b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	u16 i;
493b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
494b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	for (i = 0; i < num_modes; i++) {
495b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		if (modes[i].mode == mode)
496b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			return &modes[i];
497b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	}
498b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
499b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	return NULL;
500b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
501b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
502b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
503b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
504b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					enum hostapd_hw_mode band,
505b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					struct wpa_driver_scan_params *params)
506b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
507b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	/* Include only supported channels for the specified band */
508b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	struct hostapd_hw_modes *mode;
509b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	int count, i;
510b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
511b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
512b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (mode == NULL) {
513b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		/* No channels supported in this band - use empty list */
514b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		params->freqs = os_zalloc(sizeof(int));
515b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
516b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	}
517b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
518b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int));
519b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (params->freqs == NULL)
520b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
521b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	for (count = 0, i = 0; i < mode->num_channels; i++) {
522b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
523b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			continue;
524b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		params->freqs[count++] = mode->channels[i].freq;
525b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	}
526b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
527b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
528b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
529b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
530b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				   struct wpa_driver_scan_params *params)
531b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
532b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (wpa_s->hw.modes == NULL)
533b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return; /* unknown what channels the driver supports */
534b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (params->freqs)
535b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return; /* already using a limited channel set */
536b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (wpa_s->setband == WPA_SETBAND_5G)
537b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
538b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					    params);
539b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	else if (wpa_s->setband == WPA_SETBAND_2G)
540b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
541b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					    params);
542b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
543b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
544b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
5461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
5481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_ssid *ssid;
549d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	enum scan_req_type scan_req = NORMAL_SCAN_REQ;
550d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int ret;
55104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpabuf *extra_ie = NULL;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_scan_params params;
55304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_driver_scan_params *scan_params;
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t max_ssids;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_states prev_state;
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
55937d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		wpas_p2p_continue_after_scan(wpa_s);
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
563d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
564aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
56637d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		wpas_p2p_continue_after_scan(wpa_s);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5695887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt#ifdef ANDROID
5705887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt	if (wpa_s->scanning) {
5715887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt		/* If we are already in scanning state, we shall ignore this new scan request*/
5725887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - already scanning");
5735887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt		return;
5745887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt	}
5755887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt#endif
57604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpa_supplicant_enabled_networks(wpa_s) &&
577d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    wpa_s->scan_req == NORMAL_SCAN_REQ) {
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
58037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		wpas_p2p_continue_after_scan(wpa_s);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->ap_scan != 0 &&
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - "
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"overriding ap_scan configuration");
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->conf->ap_scan = 0;
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_notify_ap_scan_changed(wpa_s);
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->ap_scan == 0) {
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_gen_assoc_event(wpa_s);
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
598051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (wpas_p2p_in_progress(wpa_s) || wpas_wpa_is_in_progress(wpa_s, 0)) {
59961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (wpa_s->sta_scan_pending &&
60061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    wpas_p2p_in_progress(wpa_s) == 2 &&
601dc7b71324df9788e194745e8ab9386a4619a623aJouni Malinen		    wpa_s->global->p2p_cb_on_scan_complete) {
60261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Process pending station "
60361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"mode scan during P2P search");
60461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else {
6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan "
6061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"while P2P operation is in progress");
60761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_s->sta_scan_pending = 1;
6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_supplicant_req_scan(wpa_s, 5, 0);
60961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return;
6101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */
6131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
614051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifdef CONFIG_GAS
615051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (gas_query_in_progress(wpa_s->gas)) {
616051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Delay scan while GAS query is in progress");
617051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_supplicant_req_scan(wpa_s, 1, 0);
618051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
619051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
620051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_GAS */
621051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->conf->ap_scan == 2)
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		max_ssids = 1;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		max_ssids = wpa_s->max_scan_ssids;
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (max_ssids > WPAS_MAX_SCAN_SSIDS)
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			max_ssids = WPAS_MAX_SCAN_SSIDS;
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scan_req = wpa_s->scan_req;
631d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_s->scan_req = NORMAL_SCAN_REQ;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_state = wpa_s->wpa_state;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state == WPA_DISCONNECTED ||
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->wpa_state == WPA_INACTIVE)
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
64004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	/*
64104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 * If autoscan has set its own scanning parameters
64204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 */
64304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->autoscan_params != NULL) {
64404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		scan_params = wpa_s->autoscan_params;
64504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		goto scan;
64604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
64704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
648d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (scan_req != MANUAL_SCAN_REQ && wpa_s->connect_without_scan) {
64975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
65075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			if (ssid == wpa_s->connect_without_scan)
65175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen				break;
65275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
65375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_s->connect_without_scan = NULL;
65475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (ssid) {
65575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			wpa_printf(MSG_DEBUG, "Start a pre-selected network "
65675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen				   "without scan step");
65775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			wpa_supplicant_associate(wpa_s, NULL, ssid);
65875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			return;
65975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
66075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
66175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
66204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_P2P
66304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
66404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    wpa_s->go_params) {
665cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)",
666cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			   wpa_s->p2p_in_provisioning,
667cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			   wpa_s->show_group_started);
66804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		params.ssids[0].ssid = wpa_s->go_params->ssid;
66904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		params.ssids[0].ssid_len = wpa_s->go_params->ssid_len;
67004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		params.num_ssids = 1;
67104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		goto ssid_list_set;
67204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
67304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_P2P */
67404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Find the starting point from which to continue scanning */
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_s->conf->ssid;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (ssid) {
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ssid == wpa_s->prev_scan_ssid) {
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ssid = ssid->next;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid = ssid->next;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
687d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (scan_req != MANUAL_SCAN_REQ && wpa_s->conf->ap_scan == 2) {
68875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_s->connect_without_scan = NULL;
689c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_s->prev_scan_wildcard = 0;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_assoc_try(wpa_s, ssid);
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
692e25ba1592df19d46a7a1e1a1fca1fb02ebd7be8fDmitry Shmidt#ifndef ANDROID
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_s->conf->ap_scan == 2) {
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * User-initiated scan request in ap_scan == 2; scan with
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * wildcard SSID.
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = NULL;
699e25ba1592df19d46a7a1e1a1fca1fb02ebd7be8fDmitry Shmidt#endif
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_ssid *start = ssid, *tssid;
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freqs_set = 0;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid == NULL && max_ssids > 1)
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid = wpa_s->conf->ssid;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (ssid) {
70604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (!wpas_network_disabled(wpa_s, ssid) &&
70704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    ssid->scan_ssid) {
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  ssid->ssid, ssid->ssid_len);
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				params.ssids[params.num_ssids].ssid =
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					ssid->ssid;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				params.ssids[params.num_ssids].ssid_len =
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					ssid->ssid_len;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				params.num_ssids++;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (params.num_ssids + 1 >= max_ssids)
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					break;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid = ssid->next;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ssid == start)
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ssid == NULL && max_ssids > 1 &&
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    start != wpa_s->conf->ssid)
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ssid = wpa_s->conf->ssid;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) {
72704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (wpas_network_disabled(wpa_s, tssid))
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if ((params.freqs || !freqs_set) && tssid->scan_freq) {
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				int_array_concat(&params.freqs,
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 tssid->scan_freq);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_free(params.freqs);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				params.freqs = NULL;
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freqs_set = 1;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int_array_sort_unique(params.freqs);
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
741c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (ssid && max_ssids == 1) {
742c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		/*
743c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		 * If the driver is limited to 1 SSID at a time interleave
744c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		 * wildcard SSID scans with specific SSID scans to avoid
745c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		 * waiting a long time for a wildcard scan.
746c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		 */
747c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (!wpa_s->prev_scan_wildcard) {
748c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			params.ssids[0].ssid = NULL;
749c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			params.ssids[0].ssid_len = 0;
750c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_s->prev_scan_wildcard = 1;
751c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for "
752c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"wildcard SSID (Interleave with specific)");
753c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		} else {
754c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_s->prev_scan_ssid = ssid;
755c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_s->prev_scan_wildcard = 0;
756c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG,
757c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"Starting AP scan for specific SSID: %s",
758c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
760c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else if (ssid) {
761c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		/* max_ssids > 1 */
762c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
763c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_s->prev_scan_ssid = ssid;
764c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
765c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			"the scan request");
766c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		params.num_ssids++;
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params.num_ssids++;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard "
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"SSID");
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
77304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_P2P
77404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtssid_list_set:
77504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_P2P */
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_supplicant_optimize_freqs(wpa_s, &params);
77861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	extra_ie = wpa_supplicant_extra_ies(wpa_s);
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params.freqs == NULL && wpa_s->next_scan_freqs) {
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"generated frequency list");
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params.freqs = wpa_s->next_scan_freqs;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(wpa_s->next_scan_freqs);
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->next_scan_freqs = NULL;
787b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_setband_scan_freqs(wpa_s, &params);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
78951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	/* See if user specified frequencies. If so, scan only those. */
79051b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	if (wpa_s->conf->freq_list && !params.freqs) {
79151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG,
79251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt			"Optimize scan based on conf->freq_list");
79351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt		int_array_concat(&params.freqs, wpa_s->conf->freq_list);
79451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	}
79551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt
796ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	/* Use current associated channel? */
797ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (wpa_s->conf->scan_cur_freq && !params.freqs) {
798c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		unsigned int num = wpa_s->num_multichan_concurrent;
799c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
800c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		params.freqs = os_calloc(num + 1, sizeof(int));
801c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (params.freqs) {
802c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			num = get_shared_radio_freqs(wpa_s, params.freqs, num);
803c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (num > 0) {
804c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
805c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					"current operating channels since "
806c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					"scan_cur_freq is enabled");
807c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			} else {
808c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				os_free(params.freqs);
809c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				params.freqs = NULL;
810c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			}
811ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		}
812ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	}
813ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.filter_ssids = wpa_supplicant_build_filter_ssids(
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->conf, &params.num_filter_ssids);
8161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (extra_ie) {
8171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.extra_ies = wpabuf_head(extra_ie);
8181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.extra_ies_len = wpabuf_len(extra_ie);
8191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
8201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
82204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->p2p_in_provisioning ||
82304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (wpa_s->show_group_started && wpa_s->go_params)) {
8241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
8251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The interface may not yet be in P2P mode, so we have to
8261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * explicitly request P2P probe to disable CCK rates.
8271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
8281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.p2p_probe = 1;
8291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
8301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
83204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	scan_params = &params;
83304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
83404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtscan:
835d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_P2P
836d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	/*
837d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * If the driver does not support multi-channel concurrency and a
838d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * virtual interface that shares the same radio with the wpa_s interface
839d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * is operating there may not be need to scan other channels apart from
840d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * the current operating channel on the other virtual interface. Filter
841d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * out other channels in case we are trying to find a connection for a
842d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * station interface when we are not configured to prefer station
843d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * connection and a concurrent operation is already in process.
844d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 */
845d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (wpa_s->scan_for_connection && scan_req == NORMAL_SCAN_REQ &&
846d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    !scan_params->freqs && !params.freqs &&
847d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    wpas_is_p2p_prioritized(wpa_s) &&
848d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
849d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    non_p2p_network_enabled(wpa_s)) {
850c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		unsigned int num = wpa_s->num_multichan_concurrent;
851c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
852c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		params.freqs = os_calloc(num + 1, sizeof(int));
853c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (params.freqs) {
854c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			num = get_shared_radio_freqs(wpa_s, params.freqs, num);
855c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (num > 0 && num == wpa_s->num_multichan_concurrent) {
856c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used");
857c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			} else {
858c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				os_free(params.freqs);
859c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				params.freqs = NULL;
860c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			}
861d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
862d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
863d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_P2P */
864d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
86504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpabuf_free(extra_ie);
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(params.freqs);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(params.filter_ssids);
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret) {
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (prev_state != wpa_s->wpa_state)
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_set_state(wpa_s, prev_state);
875d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/* Restore scan_req since we will try to scan again */
876d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_s->scan_req = scan_req;
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_req_scan(wpa_s, 1, 0);
878d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	} else {
879d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_s->scan_for_connection = 0;
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8844b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtvoid wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec)
8854b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{
8864b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	struct os_time remaining, new_int;
8874b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	int cancelled;
8884b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
8894b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL,
8904b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt					     &remaining);
8914b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
8924b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	new_int.sec = sec;
8934b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	new_int.usec = 0;
8944b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	if (cancelled && os_time_before(&remaining, &new_int)) {
8954b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		new_int.sec = remaining.sec;
8964b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		new_int.usec = remaining.usec;
8974b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	}
8984b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
899051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (cancelled) {
900051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		eloop_register_timeout(new_int.sec, new_int.usec,
901051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       wpa_supplicant_scan, wpa_s, NULL);
902051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
9034b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	wpa_s->scan_interval = sec;
9044b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt}
9054b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
9064b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sec: Number of seconds after which to scan
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @usec: Number of microseconds after which to scan
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to schedule a scan for neighboring access points after
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the specified time.
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
91881e9700b8fb135b898181ad3aeb44d39f0a01907Dmitry Shmidt#ifndef ANDROID
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* If there's at least one network that should be specifically scanned
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * then don't cancel the scan and reschedule.  Some drivers do
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * background scanning which generates frequent scan results, and that
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * causes the specific SSID scan to get continually pushed back and
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * never happen, which causes hidden APs to never get probe-scanned.
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) &&
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->conf->ap_scan == 1) {
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_ssid *ssid = wpa_s->conf->ssid;
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (ssid) {
93004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (!wpas_network_disabled(wpa_s, ssid) &&
93104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    ssid->scan_ssid)
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid = ssid->next;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid) {
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Not rescheduling scan to "
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			        "ensure that specific SSID scans occur");
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
94181e9700b8fb135b898181ad3aeb44d39f0a01907Dmitry Shmidt#endif
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sec, usec);
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan
9511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
9521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @sec: Number of seconds after which to scan
9531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @usec: Number of microseconds after which to scan
954a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success or -1 otherwise
9551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *
9561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to schedule periodic scans for neighboring
9571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * access points after the specified time.
9581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
9591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
9601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      int sec, int usec)
9611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
9621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!wpa_s->sched_scan_supported)
9631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
9641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(sec, usec,
9661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       wpa_supplicant_delayed_sched_scan_timeout,
9671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       wpa_s, NULL);
9681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
9701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
9711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/**
9741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
9751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
976a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 is sched_scan was started or -1 otherwise
9771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *
9781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to schedule periodic scans for neighboring
9791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * access points repeating the scan continuously.
9801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
9811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
9821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
9831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_driver_scan_params params;
98404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_driver_scan_params *scan_params;
9851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	enum wpa_states prev_state;
98604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_ssid *ssid = NULL;
98761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *extra_ie = NULL;
9881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int ret;
9891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int max_sched_scan_ssids;
9901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int wildcard = 0;
9911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int need_ssids;
9921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!wpa_s->sched_scan_supported)
9941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
9951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
9971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
9981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
9991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
100004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
10011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
10021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->sched_scanning) {
10041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
10051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
10061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	need_ssids = 0;
10091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
101004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) {
10111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			/* Use wildcard SSID to find this network */
10121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wildcard = 1;
101304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else if (!wpas_network_disabled(wpa_s, ssid) &&
101404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   ssid->ssid_len)
10151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			need_ssids++;
101604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
101704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS
101804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!wpas_network_disabled(wpa_s, ssid) &&
101904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
102004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/*
102104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * Normal scan is more reliable and faster for WPS
102204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * operations and since these are for short periods of
102304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * time, the benefit of trying to use sched_scan would
102404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * be limited.
102504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 */
102604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
102704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"sched_scan for WPS");
102804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
102904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
103004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS */
10311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wildcard)
10331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		need_ssids++;
10341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->normal_scans < 3 &&
10361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    (need_ssids <= wpa_s->max_scan_ssids ||
10371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	     wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) {
10381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
10391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * When normal scan can speed up operations, use that for the
10401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * first operations before starting the sched_scan to allow
10411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * user space sleep more. We do this only if the normal scan
10421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * has functionality that is suitable for this or if the
10431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * sched_scan does not have better support for multiple SSIDs.
10441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
10451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
10461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"sched_scan for initial scans (normal_scans=%d)",
10471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s->normal_scans);
10481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
10491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&params, 0, sizeof(params));
10521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* If we can't allocate space for the filters, we just don't filter */
10541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.filter_ssids = os_zalloc(wpa_s->max_match_sets *
10551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					sizeof(struct wpa_driver_scan_filter));
10561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	prev_state = wpa_s->wpa_state;
10581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->wpa_state == WPA_DISCONNECTED ||
10591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    wpa_s->wpa_state == WPA_INACTIVE)
10601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
10611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
106204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->autoscan_params != NULL) {
106304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		scan_params = wpa_s->autoscan_params;
106404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		goto scan;
106504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
106604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
10671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* Find the starting point from which to continue scanning */
10681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ssid = wpa_s->conf->ssid;
10691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->prev_sched_ssid) {
10701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		while (ssid) {
10711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (ssid == wpa_s->prev_sched_ssid) {
10721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				ssid = ssid->next;
10731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				break;
10741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
10751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			ssid = ssid->next;
10761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
10771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!ssid || !wpa_s->prev_sched_ssid) {
10801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
108151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt		if (wpa_s->conf->sched_scan_interval)
108251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt			wpa_s->sched_scan_interval =
108351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt				wpa_s->conf->sched_scan_interval;
108404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpa_s->sched_scan_interval == 0)
108504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->sched_scan_interval = 10;
10861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
10871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->first_sched_scan = 1;
10881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ssid = wpa_s->conf->ssid;
10891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->prev_sched_ssid = ssid;
10901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wildcard) {
10931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan");
10941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.num_ssids++;
10951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	while (ssid) {
109804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpas_network_disabled(wpa_s, ssid))
10991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			goto next;
11001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (params.num_filter_ssids < wpa_s->max_match_sets &&
11021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    params.filter_ssids && ssid->ssid && ssid->ssid_len) {
11031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s",
11041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
11051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid,
11061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  ssid->ssid, ssid->ssid_len);
11071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params.filter_ssids[params.num_filter_ssids].ssid_len =
11081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				ssid->ssid_len;
11091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params.num_filter_ssids++;
11101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		} else if (params.filter_ssids && ssid->ssid && ssid->ssid_len)
11111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		{
11121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID "
11131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"filter for sched_scan - drop filter");
11141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_free(params.filter_ssids);
11151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params.filter_ssids = NULL;
11161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params.num_filter_ssids = 0;
11171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
11181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) {
11201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (params.num_ssids == max_sched_scan_ssids)
11211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				break; /* only room for broadcast SSID */
11221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG,
11231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"add to active scan ssid: %s",
11241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
11251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params.ssids[params.num_ssids].ssid =
11261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				ssid->ssid;
11271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params.ssids[params.num_ssids].ssid_len =
11281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				ssid->ssid_len;
11291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			params.num_ssids++;
11301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (params.num_ssids >= max_sched_scan_ssids) {
11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_s->prev_sched_ssid = ssid;
113204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				do {
113304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					ssid = ssid->next;
113404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				} while (ssid &&
113504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 (wpas_network_disabled(wpa_s, ssid) ||
113604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  !ssid->scan_ssid));
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				break;
11381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	next:
11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->prev_sched_ssid = ssid;
11431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ssid = ssid->next;
11441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (params.num_filter_ssids == 0) {
11471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_free(params.filter_ssids);
11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.filter_ssids = NULL;
11491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
115161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	extra_ie = wpa_supplicant_extra_ies(wpa_s);
115261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (extra_ie) {
115361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		params.extra_ies = wpabuf_head(extra_ie);
115461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		params.extra_ies_len = wpabuf_len(extra_ie);
115561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
11561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
115704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	scan_params = &params;
115804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
115904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtscan:
11601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ssid || !wpa_s->first_sched_scan) {
11611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG,
11621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"Starting sched scan: interval %d timeout %d",
11631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout);
116404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else {
116504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG,
116604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"Starting sched scan: interval %d (no timeout)",
116704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->sched_scan_interval);
11681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1170b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_setband_scan_freqs(wpa_s, scan_params);
1171b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
117204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
11731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					      wpa_s->sched_scan_interval);
117461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(extra_ie);
11751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(params.filter_ssids);
11761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ret) {
11771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan");
11781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (prev_state != wpa_s->wpa_state)
11791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_supplicant_set_state(wpa_s, prev_state);
11801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return ret;
11811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* If we have more SSIDs to scan, add a timeout so we scan them too */
11841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ssid || !wpa_s->first_sched_scan) {
11851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->sched_scan_timed_out = 0;
11861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_register_timeout(wpa_s->sched_scan_timeout, 0,
11871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       wpa_supplicant_sched_scan_timeout,
11881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       wpa_s, NULL);
11891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->first_sched_scan = 0;
11901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->sched_scan_timeout /= 2;
11911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->sched_scan_interval *= 2;
11922f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt		if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) {
11932f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt			wpa_s->sched_scan_interval = 10;
11942f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt			wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
11952f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt		}
11961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11982f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt	/* If there is no more ssids, start next time from the beginning */
11992f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt	if (!ssid)
12002f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt		wpa_s->prev_sched_ssid = NULL;
12012f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt
12021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
12031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
12041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/**
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to cancel a scan request scheduled with
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_req_scan().
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
121737d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	wpas_p2p_continue_after_scan(wpa_s);
1218c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef ANDROID
121920df807cb700c516ff346732f1bc8f914d0d26d8Dmitry Shmidt	wpa_supplicant_notify_scanning(wpa_s, 0);
1220c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/**
1225c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan
1226c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
1227c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt *
1228c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * This function is used to stop a delayed scheduled scan.
1229c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt */
1230c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtvoid wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s)
1231c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
1232c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!wpa_s->sched_scan_supported)
1233c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return;
1234c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
1235c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan");
1236c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout,
1237c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			     wpa_s, NULL);
1238c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
1239c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
1240c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
1241c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt/**
12421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans
12431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
12441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *
12451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to stop a periodic scheduled scan.
12461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
12471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
12481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
12491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!wpa_s->sched_scanning)
12501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
12511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
12531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
12541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_supplicant_stop_sched_scan(wpa_s);
12551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
12561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1258a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1259a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_notify_scanning - Indicate possible scan state change
1260a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
1261a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @scanning: Whether scanning is currently in progress
1262a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1263a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is to generate scanning notifycations. It is called whenever
1264a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * there may have been a change in scanning (scan started, completed, stopped).
1265a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpas_notify_scanning() is called whenever the scanning state changed from the
1266a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * previously notified state.
1267a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    int scanning)
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->scanning != scanning) {
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->scanning = scanning;
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_notify_scanning(wpa_s);
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rate = 0;
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *ie;
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ie && i < ie[1]; i++) {
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((ie[i + 2] & 0x7f) > rate)
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rate = ie[i + 2] & 0x7f;
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ie && i < ie[1]; i++) {
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((ie[i + 2] & 0x7f) > rate)
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rate = ie[i + 2] & 0x7f;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return rate;
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1300a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1301a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_scan_get_ie - Fetch a specified information element from a scan result
1302a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @res: Scan result entry
1303a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @ie: Information element identitifier (WLAN_EID_*)
1304a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found
1305a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1306a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function returns the first matching information element in the scan
1307a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * result.
1308a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end, *pos;
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (res + 1);
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + res->ie_len;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < end) {
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 2 + pos[1] > end)
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == ie)
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos;
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1329a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_scan_get_vendor_ie - Fetch vendor information element from a scan result
1330a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @res: Scan result entry
1331a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @vendor_type: Vendor type (four octets starting the IE payload)
1332a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found
1333a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1334a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function returns the first matching information element in the scan
1335a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * result.
1336a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  u32 vendor_type)
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end, *pos;
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (res + 1);
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + res->ie_len;
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < end) {
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 2 + pos[1] > end)
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    vendor_type == WPA_GET_BE32(&pos[2]))
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos;
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
13599657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result
13609657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * @res: Scan result entry
13619657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * @vendor_type: Vendor type (four octets starting the IE payload)
13629657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found
13639657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt *
13649657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * This function returns the first matching information element in the scan
13659657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * result.
13669657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt *
13679657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only
13689657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * from Beacon frames instead of either Beacon or Probe Response frames.
13699657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt */
13709657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidtconst u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
13719657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt					 u32 vendor_type)
13729657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt{
13739657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	const u8 *end, *pos;
13749657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt
13759657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	if (res->beacon_ie_len == 0)
13769657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		return NULL;
13779657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt
13789657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	pos = (const u8 *) (res + 1);
13799657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	pos += res->ie_len;
13809657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	end = pos + res->beacon_ie_len;
13819657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt
13829657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	while (pos + 1 < end) {
13839657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		if (pos + 2 + pos[1] > end)
13849657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt			break;
13859657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
13869657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		    vendor_type == WPA_GET_BE32(&pos[2]))
13879657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt			return pos;
13889657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		pos += 2 + pos[1];
13899657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	}
13909657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt
13919657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	return NULL;
13929657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt}
13939657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt
13949657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt
13959657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt/**
1396a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result
1397a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @res: Scan result entry
1398a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @vendor_type: Vendor type (four octets starting the IE payload)
1399a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: Pointer to the information element payload or %NULL if not found
1400a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1401a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function returns concatenated payload of possibly fragmented vendor
1402a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * specific information elements in the scan result. The caller is responsible
1403a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * for freeing the returned buffer.
1404a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u32 vendor_type)
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end, *pos;
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(res->ie_len);
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (res + 1);
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + res->ie_len;
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < end) {
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 2 + pos[1] > end)
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    vendor_type == WPA_GET_BE32(&pos[2]))
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpabuf_len(buf) == 0) {
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(buf);
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = NULL;
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/*
14371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Channels with a great SNR can operate at full rate. What is a great SNR?
14381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
14391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * rule of thumb is that any SNR above 20 is good." This one
14401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
14411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
14421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * conservative value.
14431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
14441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define GREAT_SNR 30
14451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Compare function for sorting scan results. Return >0 if @b is considered
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * better. */
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_result_compar(const void *a, const void *b)
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define IS_5GHZ(n) (n > 4000)
14511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define MIN(a,b) a < b ? a : b
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res **_wa = (void *) a;
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res **_wb = (void *) b;
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *wa = *_wa;
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *wb = *_wb;
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int wpa_a, wpa_b, maxrate_a, maxrate_b;
14571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int snr_a, snr_b;
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* WPA/WPA2 support preferred */
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_b && !wpa_a)
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_b && wpa_a)
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* privacy support preferred */
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (wb->caps & IEEE80211_CAP_PRIVACY))
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if ((wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) &&
14791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !((wa->flags | wb->flags) & WPA_SCAN_NOISE_INVALID)) {
14801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		snr_a = MIN(wa->level - wa->noise, GREAT_SNR);
14811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		snr_b = MIN(wb->level - wb->noise, GREAT_SNR);
14821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
14831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not suitable information to calculate SNR, so use level */
14841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		snr_a = wa->level;
14851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		snr_b = wb->level;
14861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
14871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* best/max rate preferred if SNR close enough */
14891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt        if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		maxrate_a = wpa_scan_get_max_rate(wa);
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		maxrate_b = wpa_scan_get_max_rate(wb);
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (maxrate_a != maxrate_b)
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return maxrate_b - maxrate_a;
14951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
14961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return IS_5GHZ(wa->freq) ? -1 : 1;
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* use freq for channel preference */
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* all things being equal, use SNR; if SNRs are
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * identical, use quality values since some drivers may only report
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * that value and leave the signal level zero */
15041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (snr_b == snr_a)
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wb->qual - wa->qual;
15061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return snr_b - snr_a;
15071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#undef MIN
15081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#undef IS_5GHZ
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Compare function for sorting scan results when searching a WPS AP for
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * provisioning. Return >0 if @b is considered better. */
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_result_wps_compar(const void *a, const void *b)
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res **_wa = (void *) a;
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res **_wb = (void *) b;
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *wa = *_wa;
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *wb = *_wb;
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int uses_wps_a, uses_wps_b;
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *wps_a, *wps_b;
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Optimization - check WPS IE existence before allocated memory and
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * doing full reassembly. */
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (uses_wps_a && !uses_wps_b)
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!uses_wps_a && uses_wps_b)
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (uses_wps_a && uses_wps_b) {
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = wps_ap_priority_compar(wps_a, wps_b);
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(wps_a);
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(wps_b);
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res)
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return res;
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Do not use current AP security policy as a sorting criteria during
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * WPS provisioning step since the AP may get reconfigured at the
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * completion of provisioning.
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* all things being equal, use signal level; if signal levels are
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * identical, use quality values since some drivers may only report
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * that value and leave the signal level zero */
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wb->level == wa->level)
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wb->qual - wa->qual;
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wb->level - wa->level;
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void dump_scan_res(struct wpa_scan_results *scan_res)
15611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
15621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
15631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t i;
15641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (scan_res->res == NULL || scan_res->num == 0)
15661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
15671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_printf(MSG_EXCESSIVE, "Sorted scan results");
15691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; i < scan_res->num; i++) {
15711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		struct wpa_scan_res *r = scan_res->res[i];
157204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		u8 *pos;
15731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if ((r->flags & (WPA_SCAN_LEVEL_DBM | WPA_SCAN_NOISE_INVALID))
15741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    == WPA_SCAN_LEVEL_DBM) {
15751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			int snr = r->level - r->noise;
15761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1577f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   "noise=%d level=%d snr=%d%s flags=0x%x "
1578f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   "age=%u",
15791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   MAC2STR(r->bssid), r->freq, r->qual,
15801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   r->noise, r->level, snr,
1581f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   snr >= GREAT_SNR ? "*" : "", r->flags,
1582f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   r->age);
15831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		} else {
15841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
1585f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   "noise=%d level=%d flags=0x%x age=%u",
15861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   MAC2STR(r->bssid), r->freq, r->qual,
1587f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   r->noise, r->level, r->flags, r->age);
15881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
158904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos = (u8 *) (r + 1);
159004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (r->ie_len)
159104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len);
159204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos += r->ie_len;
159304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (r->beacon_ie_len)
159404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs",
159504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				    pos, r->beacon_ie_len);
15961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
15971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
15981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
15991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
16001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1601a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1602a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_filter_bssid_match - Is the specified BSSID allowed
1603a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
1604a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @bssid: BSSID to check
1605a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 if the BSSID is filtered or 1 if not
1606a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1607a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to filter out specific BSSIDs from scan reslts mainly
1608a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * for testing purposes (SET bssid_filter ctrl_iface command).
1609a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
161004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
161104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      const u8 *bssid)
161204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
161304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	size_t i;
161404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
161504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->bssid_filter == NULL)
161604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 1;
161704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
161804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	for (i = 0; i < wpa_s->bssid_filter_count; i++) {
161904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
162004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			      ETH_ALEN) == 0)
162104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
162204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
162304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
162404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
162504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
162604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
162704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
162804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void filter_scan_res(struct wpa_supplicant *wpa_s,
162904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    struct wpa_scan_results *res)
163004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
163104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	size_t i, j;
163204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
163304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->bssid_filter == NULL)
163404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
163504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
163604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	for (i = 0, j = 0; i < res->num; i++) {
163704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpa_supplicant_filter_bssid_match(wpa_s,
163804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						      res->res[i]->bssid)) {
163904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			res->res[j++] = res->res[i];
164004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else {
164104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_free(res->res[i]);
164204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			res->res[i] = NULL;
164304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
164404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
164504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
164604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (res->num != j) {
164704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "Filtered out %d scan results",
164804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   (int) (res->num - j));
164904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		res->num = j;
165004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
165104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
165204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
165304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_get_scan_results - Get scan results
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @info: Information about what was scanned or %NULL if not available
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_scan: Whether a new scan was performed
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Scan results, %NULL on failure
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function request the current scan results from the driver and updates
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the local BSS list wpa_s->bss. The caller is responsible for freeing the
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * results with wpa_scan_results_free().
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_scan_results *
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct scan_info *info, int new_scan)
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_results *scan_res;
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int (*compar)(const void *, const void *) = wpa_scan_result_compar;
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	scan_res = wpa_drv_get_scan_results2(wpa_s);
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scan_res == NULL) {
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1678f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (scan_res->fetch_time.sec == 0) {
1679f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
1680f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * Make sure we have a valid timestamp if the driver wrapper
1681f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * does not set this.
1682f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
1683f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		os_get_time(&scan_res->fetch_time);
1684f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
168504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	filter_scan_res(wpa_s, scan_res);
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_wps_in_progress(wpa_s)) {
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"provisioning rules");
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		compar = wpa_scan_result_wps_compar;
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      compar);
16971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dump_scan_res(scan_res);
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_bss_update_start(wpa_s);
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < scan_res->num; i++)
1701f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
1702f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt					&scan_res->fetch_time);
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_bss_update_end(wpa_s, info, new_scan);
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return scan_res;
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1709a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1710a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_update_scan_results - Update scan results from the driver
1711a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
1712a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure
1713a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1714a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function updates the BSS table within wpa_supplicant based on the
1715a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * currently available scan results from the driver without requesting a new
1716a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * scan. This is used in cases where the driver indicates an association
1717a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * (including roaming within ESS) and wpa_supplicant does not yet have the
1718a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * needed information to complete the connection (e.g., to perform validation
1719a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * steps in 4-way handshake).
1720a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_results *scan_res;
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scan_res == NULL)
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_scan_results_free(scan_res);
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17313a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt
17323a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt
17333a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt/**
17343a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt * scan_only_handler - Reports scan results
17353a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt */
17363a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidtvoid scan_only_handler(struct wpa_supplicant *wpa_s,
17373a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt		       struct wpa_scan_results *scan_res)
17383a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt{
17394b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received");
17403a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt	wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
17413a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt	wpas_notify_scan_results(wpa_s);
17424b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	wpas_notify_scan_done(wpa_s, 1);
17433a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt}
174437d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
174537d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
174637d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidtint wpas_scan_scheduled(struct wpa_supplicant *wpa_s)
174737d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt{
174837d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL);
174937d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt}
1750