Cumulative patch from commit 99cd77a8c50413d44f1ebead917310468a8406de
99cd77a tests: Verify reassociate-to-same-BSS commands
e8d70a7 nl80211: Hide deauth event due to forced deauth-during-auth
0f44ec8 Add a reattach command for fast reassociate-back-to-same-BSS
cfc393a hostapd: Document interworking realm EAP Method types
7450c12 DFS: Add extra debugging messages
5d0d72a wpa_supplicant: Put upper bound on initial scan time delay
8c06db7 nl80211: Fix P2P Device handling when starting with RF-kill blocked
5e3ddf4 PNO: Change sched_scan_stopped event to handle pending PNO properly
737e7a0 PNO: Move and rename pno_start()/pno_stop()
1d91f50 hostapd: Process management frames only once per BSS
e070051 hostapd: Allow to switch to usable DFS channels
01b9999 hostapd: Allow to switch to DFS channels if available
70ee1be hostapd: Add config option chanlist for DFS channels
09eef14 Use internal FIPS 186-2 PRF if needed
3b9c517 Fix PTK derivation for CCMP-256 and GCMP-256
e6ef73f nl80211: Add debug print of KEY_DATA and KEY_SEQ
b465f5d Remove unused hostapd_wep_key_cmp()
4fb363c Fix error path handling on radius_accept_attr
Change-Id: I28ecac6cbcc6f71f19a051c12b54668ca6a66e2a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index f7eb537..1d8e8a6 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -665,6 +665,36 @@
* wildcard SSID.
*/
ssid = NULL;
+ } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
+ /*
+ * Perform single-channel single-SSID scan for
+ * reassociate-to-same-BSS operation.
+ */
+ /* Setup SSID */
+ ssid = wpa_s->current_ssid;
+ wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
+ ssid->ssid, ssid->ssid_len);
+ params.ssids[0].ssid = ssid->ssid;
+ params.ssids[0].ssid_len = ssid->ssid_len;
+ params.num_ssids = 1;
+
+ /*
+ * Allocate memory for frequency array, allocate one extra
+ * slot for the zero-terminator.
+ */
+ params.freqs = os_malloc(sizeof(int) * 2);
+ if (params.freqs == NULL) {
+ wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
+ return;
+ }
+ params.freqs[0] = wpa_s->assoc_freq;
+ params.freqs[1] = 0;
+
+ /*
+ * Reset the reattach flag so that we fall back to full scan if
+ * this scan fails.
+ */
+ wpa_s->reattach = 0;
} else {
struct wpa_ssid *start = ssid, *tssid;
int freqs_set = 0;
@@ -1813,3 +1843,110 @@
os_free(params->filter_ssids);
os_free(params);
}
+
+
+int wpas_start_pno(struct wpa_supplicant *wpa_s)
+{
+ int ret, interval;
+ size_t i, num_ssid;
+ struct wpa_ssid *ssid;
+ struct wpa_driver_scan_params params;
+
+ if (!wpa_s->sched_scan_supported)
+ return -1;
+
+ if (wpa_s->pno || wpa_s->pno_sched_pending)
+ return 0;
+
+ if ((wpa_s->wpa_state > WPA_SCANNING) &&
+ (wpa_s->wpa_state <= WPA_COMPLETED)) {
+ wpa_printf(MSG_ERROR, "PNO: In assoc process");
+ return -EAGAIN;
+ }
+
+ if (wpa_s->wpa_state == WPA_SCANNING) {
+ wpa_supplicant_cancel_scan(wpa_s);
+ if (wpa_s->sched_scanning) {
+ wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
+ "ongoing sched scan");
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_s->pno_sched_pending = 1;
+ return 0;
+ }
+ }
+
+ os_memset(¶ms, 0, sizeof(params));
+
+ num_ssid = 0;
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ if (!wpas_network_disabled(wpa_s, ssid))
+ num_ssid++;
+ ssid = ssid->next;
+ }
+ if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
+ wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
+ "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
+ num_ssid = WPAS_MAX_SCAN_SSIDS;
+ }
+
+ if (num_ssid == 0) {
+ wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
+ return -1;
+ }
+
+ params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
+ num_ssid);
+ if (params.filter_ssids == NULL)
+ return -1;
+ i = 0;
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ if (!wpas_network_disabled(wpa_s, ssid)) {
+ params.ssids[i].ssid = ssid->ssid;
+ params.ssids[i].ssid_len = ssid->ssid_len;
+ params.num_ssids++;
+ os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
+ ssid->ssid_len);
+ params.filter_ssids[i].ssid_len = ssid->ssid_len;
+ params.num_filter_ssids++;
+ i++;
+ if (i == num_ssid)
+ break;
+ }
+ ssid = ssid->next;
+ }
+
+ if (wpa_s->conf->filter_rssi)
+ params.filter_rssi = wpa_s->conf->filter_rssi;
+
+ interval = wpa_s->conf->sched_scan_interval ?
+ wpa_s->conf->sched_scan_interval : 10;
+
+ ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval);
+ os_free(params.filter_ssids);
+ if (ret == 0)
+ wpa_s->pno = 1;
+ else
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
+ return ret;
+}
+
+
+int wpas_stop_pno(struct wpa_supplicant *wpa_s)
+{
+ int ret = 0;
+
+ if (!wpa_s->pno)
+ return 0;
+
+ ret = wpa_supplicant_stop_sched_scan(wpa_s);
+
+ wpa_s->pno = 0;
+ wpa_s->pno_sched_pending = 0;
+
+ if (wpa_s->wpa_state == WPA_SCANNING)
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+ return ret;
+}