#include "hs20_supplicant.h"
#include "notify.h"
#include "bss.h"
+#include "gas_query.h"
#include "scan.h"
}
-static int int_array_len(const int *a)
-{
- int i;
- for (i = 0; a && a[i]; i++)
- ;
- return i;
-}
-
-
-static void int_array_concat(int **res, const int *a)
-{
- int reslen, alen, i;
- int *n;
-
- reslen = int_array_len(*res);
- alen = int_array_len(a);
-
- n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
- if (n == NULL) {
- os_free(*res);
- *res = NULL;
- return;
- }
- for (i = 0; i <= alen; i++)
- n[reslen + i] = a[i];
- *res = n;
-}
-
-
-static int freq_cmp(const void *a, const void *b)
-{
- int _a = *(int *) a;
- int _b = *(int *) b;
-
- if (_a == 0)
- return 1;
- if (_b == 0)
- return -1;
- return _a - _b;
-}
-
-
-static void int_array_sort_unique(int *a)
-{
- int alen;
- int i, j;
-
- if (a == NULL)
- return;
-
- alen = int_array_len(a);
- qsort(a, alen, sizeof(int), freq_cmp);
-
- i = 0;
- j = 1;
- while (a[i] && a[j]) {
- if (a[i] == a[j]) {
- j++;
- continue;
- }
- a[++i] = a[j++];
- }
- if (a[i])
- i++;
- a[i] = 0;
-}
-
-
/**
* wpa_supplicant_trigger_scan - Request driver to start a scan
* @wpa_s: Pointer to wpa_supplicant data
wpa_supplicant_notify_scanning(wpa_s, 0);
wpas_notify_scan_done(wpa_s, 0);
} else {
- os_get_time(&wpa_s->scan_trigger_time);
+ os_get_reltime(&wpa_s->scan_trigger_time);
wpa_s->scan_runs++;
wpa_s->normal_scans++;
+ wpa_s->own_scan_requested = 1;
}
return ret;
}
-static int
-wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- int interval)
+int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ int interval)
{
int ret;
}
-static int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
+int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
{
int ret;
if (params->freqs)
params->freqs[0] = wpa_s->wps_freq;
wpa_s->after_wps--;
- }
+ } else if (wpa_s->after_wps)
+ wpa_s->after_wps--;
if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
{
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct wpa_ssid *ssid;
- enum scan_req_type scan_req = NORMAL_SCAN_REQ;
int ret;
struct wpabuf *extra_ie = NULL;
struct wpa_driver_scan_params params;
return;
}
+ if (wpa_s->scanning) {
+ /*
+ * If we are already in scanning state, we shall reschedule the
+ * the incoming scan request.
+ */
+ wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req");
+ wpa_supplicant_req_scan(wpa_s, 1, 0);
+ return;
+ }
+
+ if (wpa_s->external_scan_running) {
+ struct os_reltime now, diff;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &wpa_s->scan_start_time, &diff);
+ if (diff.sec < 30) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Externally triggered scan running - Reschedule the incoming scan req");
+ wpa_supplicant_req_scan(wpa_s, 1, 0);
+ return;
+ }
+ }
+
if (!wpa_supplicant_enabled_networks(wpa_s) &&
wpa_s->scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
}
#ifdef CONFIG_P2P
- if (wpas_p2p_in_progress(wpa_s) || wpas_wpa_is_in_progress(wpa_s)) {
+ if (wpas_p2p_in_progress(wpa_s) || wpas_wpa_is_in_progress(wpa_s, 0)) {
if (wpa_s->sta_scan_pending &&
wpas_p2p_in_progress(wpa_s) == 2 &&
wpa_s->global->p2p_cb_on_scan_complete) {
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_GAS
+ if (gas_query_in_progress(wpa_s->gas)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Delay scan while GAS query is in progress");
+ wpa_supplicant_req_scan(wpa_s, 1, 0);
+ return;
+ }
+#endif /* CONFIG_GAS */
+
if (wpa_s->conf->ap_scan == 2)
max_ssids = 1;
else {
max_ssids = WPAS_MAX_SCAN_SSIDS;
}
- scan_req = wpa_s->scan_req;
+ wpa_s->last_scan_req = wpa_s->scan_req;
wpa_s->scan_req = NORMAL_SCAN_REQ;
os_memset(¶ms, 0, sizeof(params));
goto scan;
}
- if (scan_req != MANUAL_SCAN_REQ && wpa_s->connect_without_scan) {
+ if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
+ wpa_s->connect_without_scan) {
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
if (ssid == wpa_s->connect_without_scan)
break;
#ifdef CONFIG_P2P
if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
wpa_s->go_params) {
- wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during "
- "P2P group formation");
+ wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)",
+ wpa_s->p2p_in_provisioning,
+ wpa_s->show_group_started);
params.ssids[0].ssid = wpa_s->go_params->ssid;
params.ssids[0].ssid_len = wpa_s->go_params->ssid_len;
params.num_ssids = 1;
}
}
- if (scan_req != MANUAL_SCAN_REQ && wpa_s->conf->ap_scan == 2) {
+ if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
+ wpa_s->conf->ap_scan == 2) {
wpa_s->connect_without_scan = NULL;
wpa_s->prev_scan_wildcard = 0;
wpa_supplicant_assoc_try(wpa_s, ssid);
wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
"the scan request");
params.num_ssids++;
+ } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
+ wpa_s->manual_scan_passive && params.num_ssids == 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request");
} else {
wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
params.num_ssids++;
wpa_supplicant_optimize_freqs(wpa_s, ¶ms);
extra_ie = wpa_supplicant_extra_ies(wpa_s);
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
+ wpa_s->manual_scan_freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
+ params.freqs = wpa_s->manual_scan_freqs;
+ wpa_s->manual_scan_freqs = NULL;
+ }
+
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
* station interface when we are not configured to prefer station
* connection and a concurrent operation is already in process.
*/
- if (wpa_s->scan_for_connection && scan_req == NORMAL_SCAN_REQ &&
+ if (wpa_s->scan_for_connection &&
+ wpa_s->last_scan_req == NORMAL_SCAN_REQ &&
!scan_params->freqs && !params.freqs &&
wpas_is_p2p_prioritized(wpa_s) &&
wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
+ if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
+ !wpa_s->manual_scan_freqs) {
+ /* Restore manual_scan_freqs for the next attempt */
+ wpa_s->manual_scan_freqs = params.freqs;
+ params.freqs = NULL;
+ }
+
wpabuf_free(extra_ie);
os_free(params.freqs);
os_free(params.filter_ssids);
if (prev_state != wpa_s->wpa_state)
wpa_supplicant_set_state(wpa_s, prev_state);
/* Restore scan_req since we will try to scan again */
- wpa_s->scan_req = scan_req;
+ wpa_s->scan_req = wpa_s->last_scan_req;
wpa_supplicant_req_scan(wpa_s, 1, 0);
} else {
wpa_s->scan_for_connection = 0;
void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec)
{
- struct os_time remaining, new_int;
+ struct os_reltime remaining, new_int;
int cancelled;
cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL,
new_int.sec = sec;
new_int.usec = 0;
- if (cancelled && os_time_before(&remaining, &new_int)) {
+ if (cancelled && os_reltime_before(&remaining, &new_int)) {
new_int.sec = remaining.sec;
new_int.usec = remaining.usec;
}
- eloop_register_timeout(new_int.sec, new_int.usec, wpa_supplicant_scan,
- wpa_s, NULL);
+ if (cancelled) {
+ eloop_register_timeout(new_int.sec, new_int.usec,
+ wpa_supplicant_scan, wpa_s, NULL);
+ }
wpa_s->scan_interval = sec;
}
*/
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
{
- /* If there's at least one network that should be specifically scanned
- * then don't cancel the scan and reschedule. Some drivers do
- * background scanning which generates frequent scan results, and that
- * causes the specific SSID scan to get continually pushed back and
- * never happen, which causes hidden APs to never get probe-scanned.
- */
- if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) &&
- wpa_s->conf->ap_scan == 1) {
- struct wpa_ssid *ssid = wpa_s->conf->ssid;
-
- while (ssid) {
- if (!wpas_network_disabled(wpa_s, ssid) &&
- ssid->scan_ssid)
- break;
- ssid = ssid->next;
- }
- if (ssid) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Not rescheduling scan to "
- "ensure that specific SSID scans occur");
- return;
- }
+ if (eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL))
+ {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d sec %d usec",
+ sec, usec);
+ return;
}
wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
/**
+ * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result
+ * @res: Scan result entry
+ * @vendor_type: Vendor type (four octets starting the IE payload)
+ * Returns: Pointer to the information element (id field) or %NULL if not found
+ *
+ * This function returns the first matching information element in the scan
+ * result.
+ *
+ * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only
+ * from Beacon frames instead of either Beacon or Probe Response frames.
+ */
+const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
+ u32 vendor_type)
+{
+ const u8 *end, *pos;
+
+ if (res->beacon_ie_len == 0)
+ return NULL;
+
+ pos = (const u8 *) (res + 1);
+ pos += res->ie_len;
+ end = pos + res->beacon_ie_len;
+
+ while (pos + 1 < end) {
+ if (pos + 2 + pos[1] > end)
+ break;
+ if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
+ vendor_type == WPA_GET_BE32(&pos[2]))
+ return pos;
+ pos += 2 + pos[1];
+ }
+
+ return NULL;
+}
+
+
+/**
* wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result
* @res: Scan result entry
* @vendor_type: Vendor type (four octets starting the IE payload)
* Make sure we have a valid timestamp if the driver wrapper
* does not set this.
*/
- os_get_time(&scan_res->fetch_time);
+ os_get_reltime(&scan_res->fetch_time);
}
filter_scan_res(wpa_s, scan_res);
#ifdef CONFIG_WPS
- if (wpas_wps_in_progress(wpa_s)) {
+ if (wpas_wps_searching(wpa_s)) {
wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
"provisioning rules");
compar = wpa_scan_result_wps_compar;
struct wpa_scan_results *scan_res)
{
wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received");
- wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
+ wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
+ wpa_s->manual_scan_id);
+ wpa_s->manual_scan_use_id = 0;
+ } else {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
+ }
wpas_notify_scan_results(wpa_s);
wpas_notify_scan_done(wpa_s, 1);
}