static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_ssid *ssid; int scan_req = 0, ret; struct wpabuf *wps_ie = NULL; const u8 *extra_ie = NULL; size_t extra_ie_len = 0; int wps = 0; #ifdef CONFIG_WPS enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO; #endif /* CONFIG_WPS */ wpa_printf(MSG_DEBUG, "%s: scan_req = %d, ap_scan = %d", __func__, wpa_s->scan_req, wpa_s->conf->ap_scan); #if ICS_LEGACY_WLAN_SUPPORT if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { wpa_printf(MSG_DEBUG, "Skip scan - interface disabled"); return; } #endif if (wpa_s->disconnected && !wpa_s->scan_req) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); return; } if (!wpa_supplicant_enabled_networks(wpa_s->conf) && !wpa_s->scan_req) { wpa_printf(MSG_DEBUG, "No enabled networks - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); return; } scan_req = wpa_s->scan_req; wpa_s->scan_req = 0; if (wpa_s->conf->ap_scan != 0 && wpa_s->driver && IS_WIRED(wpa_s->driver)) { wpa_printf(MSG_DEBUG, "Using wired authentication - " "overriding ap_scan configuration"); wpa_s->conf->ap_scan = 0; } if (wpa_s->conf->ap_scan == 0) { wpa_supplicant_gen_assoc_event(wpa_s); return; } if (wpa_s->wpa_state == WPA_DISCONNECTED || wpa_s->wpa_state == WPA_INACTIVE) wpa_supplicant_set_state(wpa_s, WPA_SCANNING); ssid = wpa_s->conf->ssid; if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) { while (ssid) { if (ssid == wpa_s->prev_scan_ssid) { ssid = ssid->next; break; } ssid = ssid->next; } } while (ssid) { //MTK_OP01_PROTECT_START #ifdef CONFIG_CMCC_SUPPORT /* CMCC */ if ( #else //MTK_OP01_PROTECT_END if (!ssid->disabled && //MTK_OP01_PROTECT_START #endif //MTK_OP01_PROTECT_END (ssid->scan_ssid || wpa_s->conf->ap_scan == 2)) break; ssid = ssid->next; } if (scan_req != 2 && wpa_s->conf->ap_scan == 2) { /* * ap_scan=2 mode - try to associate with each SSID instead of * scanning for each scan_ssid=1 network. */ if (ssid == NULL) { wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached " "end of scan list - go back to beginning"); wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; wpa_supplicant_req_scan(wpa_s, 0, 0); return; } if (ssid->next) { /* Continue from the next SSID on the next attempt. */ wpa_s->prev_scan_ssid = ssid; } else { /* Start from the beginning of the SSID list. */ wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; } wpa_supplicant_associate(wpa_s, NULL, ssid); return; } #ifdef CONFIG_WPS wps = wpas_wps_in_use(wpa_s->conf, &req_type); #endif /* CONFIG_WPS */ if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 && !wpa_s->use_client_mlme && wps != 2) { wpa_s->scan_res_tried++; wpa_s->scan_req = scan_req; wpa_printf(MSG_DEBUG, "Trying to get current scan results " "first without requesting a new scan to speed up " "initial association"); wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL); return; } #ifdef CONFIG_WPS if (wps) { wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev, wpa_s->wps->uuid, req_type); if (wps_ie) { extra_ie = wpabuf_head(wps_ie); extra_ie_len = wpabuf_len(wps_ie); } } #endif /* CONFIG_WPS */ wpa_supplicant_notify_scanning(wpa_s, 1); wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", ssid ? "specific": "broadcast"); if (ssid) { wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", ssid->ssid, ssid->ssid_len); wpa_s->prev_scan_ssid = ssid; } else wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; if (wpa_s->use_client_mlme) { ieee80211_sta_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len); ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL, ssid ? ssid->ssid_len : 0); } else { wpa_drv_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len); ret = wpa_drv_scan(wpa_s, &ssid); } wpabuf_free(wps_ie); if (ret) { wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); wpa_supplicant_notify_scanning(wpa_s, 0); wpa_supplicant_req_scan(wpa_s, 10, 0); } else { wpa_s->scan_runs++; } }
/** * wpa_supplicant_cancel_scan - Cancel a scheduled scan request * @wpa_s: Pointer to wpa_supplicant data * * This function is used to cancel a scan request scheduled with * wpa_supplicant_req_scan(). */ void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) { wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request"); eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); wpa_supplicant_notify_scanning(wpa_s, 0); }
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { struct wpa_bss *selected; struct wpa_ssid *ssid = NULL; struct wpa_scan_results *scan_res; int ap = 0; #ifdef CONFIG_AP if (wpa_s->ap_iface) ap = 1; #endif /* CONFIG_AP */ wpa_supplicant_notify_scanning(wpa_s, 0); scan_res = wpa_supplicant_get_scan_results(wpa_s, data ? &data->scan_info : NULL, 1); if (scan_res == NULL) { if (wpa_s->conf->ap_scan == 2 || ap) return; wpa_printf(MSG_DEBUG, "Failed to get scan results - try " "scanning again"); wpa_supplicant_req_new_scan(wpa_s, 1, 0); return; } if (wpa_s->scan_res_handler) { wpa_s->scan_res_handler(wpa_s, scan_res); wpa_s->scan_res_handler = NULL; wpa_scan_results_free(scan_res); return; } if (ap) { wpa_printf(MSG_DEBUG, "Ignore scan results in AP mode"); wpa_scan_results_free(scan_res); return; } wpa_printf(MSG_DEBUG, "New scan results available"); wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); wpas_notify_scan_results(wpa_s); wpas_notify_scan_done(wpa_s, 1); if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) { wpa_scan_results_free(scan_res); return; } if (wpa_s->disconnected) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); wpa_scan_results_free(scan_res); return; } wpa_supplicant_rsn_preauth_scan_results(wpa_s, scan_res); selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid); if (selected) { int skip; skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid, scan_res); wpa_scan_results_free(scan_res); if (skip) return; wpa_supplicant_connect(wpa_s, selected, ssid); } else { wpa_scan_results_free(scan_res); wpa_printf(MSG_DEBUG, "No suitable network found"); ssid = wpa_supplicant_pick_new_network(wpa_s); if (ssid) { wpa_printf(MSG_DEBUG, "Setup a new network"); wpa_supplicant_associate(wpa_s, NULL, ssid); } else { int timeout_sec = 5; int timeout_usec = 0; #ifdef CONFIG_P2P if (wpa_s->p2p_in_provisioning) { /* * Use shorter wait during P2P Provisioning * state to speed up group formation. */ timeout_sec = 0; timeout_usec = 250000; } #endif /* CONFIG_P2P */ wpa_supplicant_req_new_scan(wpa_s, timeout_sec, timeout_usec); } } }
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) { int prio, timeout; struct wpa_scan_res *selected = NULL; struct wpa_ssid *ssid = NULL; wpa_supplicant_notify_scanning(wpa_s, 0); if (wpa_supplicant_get_scan_results(wpa_s) < 0) { if (wpa_s->conf->ap_scan == 2) return; wpa_printf(MSG_DEBUG, "Failed to get scan results - try " "scanning again"); timeout = 1; goto req_scan; } /* * Don't post the results if this was the initial cached * and there were no results. */ if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 && wpa_s->scan_res->num == 0) { wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are " "empty - not posting"); } else { wpa_printf(MSG_DEBUG, "New scan results available"); wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); wpa_supplicant_dbus_notify_scan_results(wpa_s); wpas_wps_notify_scan_results(wpa_s); } if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) return; if (wpa_s->disconnected) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); return; } while (selected == NULL) { for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { selected = wpa_supplicant_select_bss( wpa_s, wpa_s->conf->pssid[prio], &ssid); if (selected) break; } if (selected == NULL && wpa_s->blacklist) { wpa_printf(MSG_DEBUG, "No APs found - clear blacklist " "and try again"); wpa_blacklist_clear(wpa_s); wpa_s->blacklist_cleared++; } else if (selected == NULL) { break; } } if (selected) { if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) { wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP "PBC session overlap"); timeout = 10; goto req_scan; } /* Do not trigger new association unless the BSSID has changed * or if reassociation is requested. If we are in process of * associating with the selected BSSID, do not trigger new * attempt. */ if (wpa_s->reassociate || (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 && (wpa_s->wpa_state != WPA_ASSOCIATING || os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) != 0))) { if (wpa_supplicant_scard_init(wpa_s, ssid)) { wpa_supplicant_req_scan(wpa_s, 10, 0); return; } wpa_supplicant_associate(wpa_s, selected, ssid); } else { wpa_printf(MSG_DEBUG, "Already associated with the " "selected AP."); } rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res); } else { wpa_printf(MSG_DEBUG, "No suitable AP found."); timeout = 5; goto req_scan; } return; req_scan: if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1) { /* * Quick recovery if the initial scan results were not * complete when fetched before the first scan request. */ wpa_s->scan_res_tried++; timeout = 0; } else if (!wpa_supplicant_enabled_networks(wpa_s->conf)) { /* * No networks are enabled; short-circuit request so * we don't wait timeout seconds before transitioning * to INACTIVE state. */ wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); return; } wpa_supplicant_req_scan(wpa_s, timeout, 0); }
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { //struct wpa_bss *selected; //struct wpa_ssid *ssid = NULL; struct wpa_scan_results *scan_res; wpa_supplicant_notify_scanning(wpa_s, 0); scan_res = wpa_supplicant_get_scan_results(wpa_s, data ? &data->scan_info : NULL, 1); ros_scan_completed(wpa_s, scan_res); if (scan_res == NULL) { if (wpa_s->conf->ap_scan == 2) return; wpa_printf(MSG_DEBUG, "Failed to get scan results - don't bother try " "scanning again"); //wpa_supplicant_req_new_scan(wpa_s, 1, 0); return; } if (wpa_s->scan_res_handler) { wpa_s->scan_res_handler(wpa_s, scan_res); wpa_s->scan_res_handler = NULL; wpa_scan_results_free(scan_res); return; } /* * Don't post the results if this was the initial cached * and there were no results. */ if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 && scan_res->num == 0) { wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are " "empty - not posting"); } else { wpa_printf(MSG_DEBUG, "New scan results available"); wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); wpas_notify_scan_results(wpa_s); } wpas_notify_scan_done(wpa_s, 1); if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) { wpa_scan_results_free(scan_res); return; } if (wpa_s->disconnected) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); wpa_scan_results_free(scan_res); return; } if (bgscan_notify_scan(wpa_s) == 1) { wpa_scan_results_free(scan_res); return; } wpa_supplicant_rsn_preauth_scan_results(wpa_s, scan_res); /*selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid); if (selected) { int skip; wpa_s->more_bss_to_try = 1; skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid, scan_res); wpa_scan_results_free(scan_res); if (skip) return; wpa_supplicant_connect(wpa_s, selected, ssid); } else { wpa_s->more_bss_to_try = 0; wpa_scan_results_free(scan_res); wpa_printf(MSG_DEBUG, "No suitable network found"); ssid = wpa_supplicant_pick_new_network(wpa_s); if (ssid) { wpa_printf(MSG_DEBUG, "Setup a new network"); wpa_supplicant_associate(wpa_s, NULL, ssid); } else { int timeout_sec = 1; int timeout_usec = 0; wpa_supplicant_req_new_scan(wpa_s, timeout_sec, timeout_usec); } } */ }