static void ieee80211n_check_scan(struct hostapd_iface *iface) { struct wpa_scan_results *scan_res; int oper40; /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */ iface->scan_cb = NULL; scan_res = hostapd_driver_get_scan_results(iface->bss[0]); if (scan_res == NULL) { hostapd_setup_interface_complete(iface, 1); return; } if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); else oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); wpa_scan_results_free(scan_res); if (!oper40) { wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " "channel pri=%d sec=%d based on overlapping BSSes", iface->conf->channel, iface->conf->channel + iface->conf->secondary_channel * 4); iface->conf->secondary_channel = 0; iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; } hostapd_setup_interface_complete(iface, 0); }
static void ieee80211n_check_scan(struct hostapd_iface *iface) { struct wpa_scan_results *scan_res; int oper40; int res; /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ iface->scan_cb = NULL; scan_res = hostapd_driver_get_scan_results(iface->bss[0]); if (scan_res == NULL) { hostapd_setup_interface_complete(iface, 1); return; } if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); else oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); wpa_scan_results_free(scan_res); if (!oper40) { wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " "channel pri=%d sec=%d based on overlapping BSSes", iface->conf->channel, iface->conf->channel + iface->conf->secondary_channel * 4); iface->conf->secondary_channel = 0; } res = ieee80211n_allowed_ht40_channel_pair(iface); hostapd_setup_interface_complete(iface, !res); }
static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface, struct sockaddr_un *from) { struct wpa_scan_results *res; u8 *buf = NULL, *pos, *end; int val; size_t i; res = iface->driver->get_scan_results2(iface->drv_priv); if (res == NULL) goto fail; buf = os_malloc(60000); if (buf == NULL) goto fail; pos = buf; end = buf + 60000; val = res->num; os_memcpy(pos, &val, sizeof(int)); pos += sizeof(int); for (i = 0; i < res->num; i++) { struct wpa_scan_res *r = res->res[i]; val = sizeof(*r) + r->ie_len; if (end - pos < (int) sizeof(int) + val) break; os_memcpy(pos, &val, sizeof(int)); pos += sizeof(int); os_memcpy(pos, r, val); pos += val; } sendto(iface->fd, buf, pos - buf, 0, (struct sockaddr *) from, sizeof(*from)); os_free(buf); wpa_scan_results_free(res); return; fail: os_free(buf); wpa_scan_results_free(res); sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from)); }
int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) { struct wpa_scan_results *scan_res; scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); if (scan_res == NULL) return -1; wpa_scan_results_free(scan_res); return 0; }
static void ieee80211n_check_scan(struct hostapd_iface *iface) { struct wpa_scan_results *scan_res; int oper40; int res; /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ iface->scan_cb = NULL; scan_res = hostapd_driver_get_scan_results(iface->bss[0]); if (scan_res == NULL) { hostapd_setup_interface_complete(iface, 1); return; } if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); else oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); wpa_scan_results_free(scan_res); iface->secondary_ch = iface->conf->secondary_channel; if (!oper40) { wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " "channel pri=%d sec=%d based on overlapping BSSes", iface->conf->channel, iface->conf->channel + iface->conf->secondary_channel * 4); iface->conf->secondary_channel = 0; if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) { /* * TODO: Could consider scheduling another scan to check * if channel width can be changed if no coex reports * are received from associating stations. */ } } res = ieee80211n_allowed_ht40_channel_pair(iface); if (!res) { iface->conf->secondary_channel = 0; iface->conf->vht_oper_centr_freq_seg0_idx = 0; iface->conf->vht_oper_centr_freq_seg1_idx = 0; iface->conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; res = 1; wpa_printf(MSG_INFO, "Fallback to 20 MHz"); } hostapd_setup_interface_complete(iface, !res); }
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 int wnm_fetch_scan_results(struct wpa_supplicant *wpa_s) { struct wpa_scan_results *scan_res; struct wpa_bss *bss; struct wpa_ssid *ssid = wpa_s->current_ssid; u8 i, found = 0; size_t j; wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Fetch current scan results from the driver for checking transition candidates"); scan_res = wpa_drv_get_scan_results2(wpa_s); if (!scan_res) { wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Failed to get scan results"); return 0; } if (scan_res->fetch_time.sec == 0) os_get_reltime(&scan_res->fetch_time); filter_scan_res(wpa_s, scan_res); for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) { struct neighbor_report *nei; nei = &wpa_s->wnm_neighbor_report_elements[i]; if (nei->preference_present && nei->preference == 0) continue; for (j = 0; j < scan_res->num; j++) { struct wpa_scan_res *res; const u8 *ssid_ie; res = scan_res->res[j]; if (os_memcmp(nei->bssid, res->bssid, ETH_ALEN) != 0 || res->age > WNM_SCAN_RESULT_AGE * 1000) continue; bss = wpa_s->current_bss; ssid_ie = wpa_scan_get_ie(res, WLAN_EID_SSID); if (bss && ssid_ie && (bss->ssid_len != ssid_ie[1] || os_memcmp(bss->ssid, ssid_ie + 2, bss->ssid_len) != 0)) continue; /* Potential candidate found */ found = 1; scan_snr(res); scan_est_throughput(wpa_s, res); wpa_bss_update_scan_res(wpa_s, res, &scan_res->fetch_time); } } wpa_scan_results_free(scan_res); if (!found) { wpa_dbg(wpa_s, MSG_DEBUG, "WNM: No transition candidate matches existing scan results"); return 0; } bss = compare_scan_neighbor_results(wpa_s, WNM_SCAN_RESULT_AGE, NULL); if (!bss) { wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Comparison of scan results against transition candidates did not find matches"); return 0; } /* Associate to the network */ wnm_bss_tm_connect(wpa_s, bss, ssid, 0); return 1; }
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); } } */ }