Change version number to v2.6 for the release
[mech_eap.git] / wpa_supplicant / scan.c
index 8dab442..fb8ebdf 100644 (file)
@@ -36,8 +36,7 @@ static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
 
        if (wpa_s->current_ssid == NULL) {
                wpa_s->current_ssid = ssid;
-               if (wpa_s->current_ssid != NULL)
-                       wpas_notify_network_changed(wpa_s);
+               wpas_notify_network_changed(wpa_s);
        }
        wpa_supplicant_initiate_eapol(wpa_s);
        wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
@@ -60,10 +59,7 @@ static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
 
                wps = 1;
                *req_type = wpas_wps_get_req_type(ssid);
-               if (!ssid->eap.phase1)
-                       continue;
-
-               if (os_strstr(ssid->eap.phase1, "pbc=1"))
+               if (ssid->eap.phase1 && os_strstr(ssid->eap.phase1, "pbc=1"))
                        return 2;
        }
 
@@ -166,6 +162,8 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
        if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
                wpa_msg(wpa_s, MSG_INFO,
                        "Failed to assign random MAC address for a scan");
+               wpa_scan_free_params(params);
+               wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
                radio_work_done(work);
                return;
        }
@@ -229,12 +227,11 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
        }
 
        ctx = wpa_scan_clone_params(params);
-       if (ctx == NULL)
-               return -1;
-
-       if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
+       if (!ctx ||
+           radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
        {
                wpa_scan_free_params(ctx);
+               wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
                return -1;
        }
 
@@ -429,6 +426,39 @@ static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_INTERWORKING */
 
 
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
+{
+       struct wpabuf *default_ies = NULL;
+       u8 ext_capab[18];
+       int ext_capab_len;
+       enum wpa_driver_if_type type = WPA_IF_STATION;
+
+#ifdef CONFIG_P2P
+       if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+               type = WPA_IF_P2P_CLIENT;
+#endif /* CONFIG_P2P */
+
+       wpa_drv_get_ext_capa(wpa_s, type);
+
+       ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+                                            sizeof(ext_capab));
+       if (ext_capab_len > 0 &&
+           wpabuf_resize(&default_ies, ext_capab_len) == 0)
+               wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
+
+#ifdef CONFIG_MBO
+       /* Send cellular capabilities for potential MBO STAs */
+       if (wpabuf_resize(&default_ies, 9) == 0)
+               wpas_mbo_scan_ie(wpa_s, default_ies);
+#endif /* CONFIG_MBO */
+
+       if (default_ies)
+               wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
+                                            wpabuf_len(default_ies));
+       wpabuf_free(default_ies);
+}
+
+
 static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
 {
        struct wpabuf *extra_ie = NULL;
@@ -439,6 +469,13 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
        enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
 #endif /* CONFIG_WPS */
 
+#ifdef CONFIG_P2P
+       if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+               wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
+       else
+#endif /* CONFIG_P2P */
+               wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+
        ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
                                             sizeof(ext_capab));
        if (ext_capab_len > 0 &&
@@ -584,6 +621,12 @@ static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
        unsigned int i;
        struct wpa_ssid *ssid;
 
+       /*
+        * For devices with max_ssids greater than 1, leave the last slot empty
+        * for adding the wildcard scan entry.
+        */
+       max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
+
        for (i = 0; i < wpa_s->scan_id_count; i++) {
                unsigned int j;
 
@@ -838,12 +881,10 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
                 * 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;
+               if (params.freqs) {
+                       params.freqs[0] = wpa_s->assoc_freq;
+                       params.freqs[1] = 0;
                }
-               params.freqs[0] = wpa_s->assoc_freq;
-               params.freqs[1] = 0;
 
                /*
                 * Reset the reattach flag so that we fall back to full scan if
@@ -1215,6 +1256,8 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
        if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
                return -1;
 
+       wpa_s->sched_scan_stop_req = 0;
+
        if (wpa_s->sched_scanning) {
                wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
                return 0;
@@ -1513,6 +1556,9 @@ void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
        if (!wpa_s->sched_scanning)
                return;
 
+       if (wpa_s->sched_scanning)
+               wpa_s->sched_scan_stop_req = 1;
+
        wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
        eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
        wpa_supplicant_stop_sched_scan(wpa_s);
@@ -2374,6 +2420,13 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
                }
        }
 
+       if (wpa_s->sched_scan_stop_req) {
+               wpa_printf(MSG_DEBUG,
+                          "Schedule PNO after previous sched scan has stopped");
+               wpa_s->pno_sched_pending = 1;
+               return 0;
+       }
+
        os_memset(&params, 0, sizeof(params));
 
        num_ssid = num_match_ssid = 0;
@@ -2489,6 +2542,7 @@ int wpas_stop_pno(struct wpa_supplicant *wpa_s)
                return 0;
 
        ret = wpa_supplicant_stop_sched_scan(wpa_s);
+       wpa_s->sched_scan_stop_req = 1;
 
        wpa_s->pno = 0;
        wpa_s->pno_sched_pending = 0;
@@ -2612,13 +2666,6 @@ int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd)
                        goto fail;
                }
 
-               if (!scan_plan->interval) {
-                       wpa_printf(MSG_ERROR,
-                                  "scan plan %u: Interval cannot be zero",
-                                  num);
-                       goto fail;
-               }
-
                if (scan_plan->interval > wpa_s->max_sched_scan_plan_interval) {
                        wpa_printf(MSG_WARNING,
                                   "scan plan %u: Scan interval too long(%u), use the maximum allowed(%u)",
@@ -2692,3 +2739,31 @@ fail:
        wpa_printf(MSG_ERROR, "invalid scan plans list");
        return -1;
 }
+
+
+/**
+ * wpas_scan_reset_sched_scan - Reset sched_scan state
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is used to cancel a running scheduled scan and to reset an
+ * internal scan state to continue with a regular scan on the following
+ * wpa_supplicant_req_scan() calls.
+ */
+void wpas_scan_reset_sched_scan(struct wpa_supplicant *wpa_s)
+{
+       wpa_s->normal_scans = 0;
+       if (wpa_s->sched_scanning) {
+               wpa_s->sched_scan_timed_out = 0;
+               wpa_s->prev_sched_ssid = NULL;
+               wpa_supplicant_cancel_sched_scan(wpa_s);
+       }
+}
+
+
+void wpas_scan_restart_sched_scan(struct wpa_supplicant *wpa_s)
+{
+       /* simulate timeout to restart the sched scan */
+       wpa_s->sched_scan_timed_out = 1;
+       wpa_s->prev_sched_ssid = NULL;
+       wpa_supplicant_cancel_sched_scan(wpa_s);
+}