/* Format one result on one text line into a buffer. */ static int wpa_supplicant_ctrl_iface_scan_result( const struct wpa_scan_res *res, char *buf, size_t buflen) { char *pos, *end; int ret; const u8 *ie, *ie2; pos = buf; end = buf + buflen; ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", MAC2STR(res->bssid), res->freq, res->level); if (ret < 0 || ret >= end - pos) return -1; pos += ret; ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); if (ie) pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); ie2 = wpa_scan_get_ie(res, WLAN_EID_RSN); if (ie2) pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); pos = wpa_supplicant_wps_ie_txt(pos, end, res); if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) { ret = os_snprintf(pos, end - pos, "[WEP]"); if (ret < 0 || ret >= end - pos) return -1; pos += ret; } /* Just to make the fields line up nicely when printed */ if (!ie && !ie2) { ret = os_snprintf(pos, end - pos, "\t"); if (ret < 0 || ret >= end - pos) return -1; pos += ret; } ie = wpa_scan_get_ie(res, WLAN_EID_SSID); if (res->caps & IEEE80211_CAP_IBSS) ret = os_snprintf(pos, end - pos, "\t%s%s", "(*)", wpa_ssid_txt(ie + 2, ie[1])); else ret = os_snprintf(pos, end - pos, "\t%s", ie ? wpa_ssid_txt(ie + 2, ie[1]) : ""); if (ret < 0 || ret >= end - pos) return -1; pos += ret; ret = os_snprintf(pos, end - pos, "\n"); if (ret < 0 || ret >= end - pos) return -1; pos += ret; return pos - buf; }
static struct wpa_bss * wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res, struct wpa_ssid *group, struct wpa_ssid **selected_ssid) { size_t i; wpa_printf(MSG_DEBUG, "Selecting BSS from priority group %d", group->priority); for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; const u8 *ie, *ssid; u8 ssid_len; *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group); if (!*selected_ssid) continue; ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ssid = ie ? ie + 2 : (u8 *) ""; ssid_len = ie ? ie[1] : 0; wpa_printf(MSG_DEBUG, " selected BSS " MACSTR " ssid='%s'", MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len)); return wpa_bss_get(wpa_s, bss->bssid, ssid, ssid_len); } return NULL; }
static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { dl_list_del(&bss->list); dl_list_del(&bss->list_id); wpa_s->num_bss--; wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR " SSID '%s'", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len)); wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id); #ifdef CONFIG_INTERWORKING wpabuf_free(bss->anqp_venue_name); wpabuf_free(bss->anqp_network_auth_type); wpabuf_free(bss->anqp_roaming_consortium); wpabuf_free(bss->anqp_ip_addr_type_availability); wpabuf_free(bss->anqp_nai_realm); wpabuf_free(bss->anqp_3gpp); wpabuf_free(bss->anqp_domain_name); #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_HS20 wpabuf_free(bss->hs20_operator_friendly_name); wpabuf_free(bss->hs20_wan_metrics); wpabuf_free(bss->hs20_connection_capability); wpabuf_free(bss->hs20_operating_class); #endif /* CONFIG_HS20 */ os_free(bss); }
static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s, const u8 *ssid, size_t ssid_len, struct wpa_scan_res *res) { struct wpa_bss *bss; bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len); if (bss == NULL) return NULL; bss->id = wpa_s->bss_next_id++; bss->last_update_idx = wpa_s->bss_update_idx; wpa_bss_copy_res(bss, res); os_memcpy(bss->ssid, ssid, ssid_len); bss->ssid_len = ssid_len; bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); wpa_bss_set_hessid(bss); dl_list_add_tail(&wpa_s->bss, &bss->list); dl_list_add_tail(&wpa_s->bss_id, &bss->list_id); wpa_s->num_bss++; wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR " SSID '%s'", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len)); wpas_notify_bss_added(wpa_s, bss->bssid, bss->id); if (wpa_s->num_bss > wpa_s->conf->bss_max_count && wpa_bss_remove_oldest(wpa_s) != 0) { wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d " "because all BSSes are in use. We should normally " "not get here!", (int) wpa_s->num_bss); wpa_s->conf->bss_max_count = wpa_s->num_bss; } return bss; }
void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, enum wpa_states new_state, enum wpa_states old_state) { /* notify the old DBus API */ wpa_supplicant_dbus_notify_state_change(wpa_s, new_state, old_state); /* notify the new DBus API */ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE); #ifdef CONFIG_P2P if (new_state == WPA_COMPLETED) wpas_p2p_notif_connected(wpa_s); else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED) wpas_p2p_notif_disconnected(wpa_s); #endif /* CONFIG_P2P */ sme_state_changed(wpa_s); #ifdef ANDROID wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE "id=%d state=%d BSSID=" MACSTR " SSID=%s", wpa_s->current_ssid ? wpa_s->current_ssid->id : -1, new_state, MAC2STR(wpa_s->bssid), wpa_s->current_ssid && wpa_s->current_ssid->ssid ? wpa_ssid_txt(wpa_s->current_ssid->ssid, wpa_s->current_ssid->ssid_len) : ""); #endif /* ANDROID */ }
static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const char *reason) { if (wpa_s->last_scan_res) { unsigned int i; for (i = 0; i < wpa_s->last_scan_res_used; i++) { if (wpa_s->last_scan_res[i] == bss) { os_memmove(&wpa_s->last_scan_res[i], &wpa_s->last_scan_res[i + 1], (wpa_s->last_scan_res_used - i - 1) * sizeof(struct wpa_bss *)); wpa_s->last_scan_res_used--; break; } } } wpa_bss_update_pending_connect(wpa_s, bss, NULL); dl_list_del(&bss->list); dl_list_del(&bss->list_id); wpa_s->num_bss--; wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR " SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), reason); wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id); wpa_bss_anqp_free(bss->anqp); os_free(bss); }
static void wpa_bss_add(struct wpa_supplicant *wpa_s, const u8 *ssid, size_t ssid_len, struct wpa_scan_res *res) { struct wpa_bss *bss; bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len); if (bss == NULL) return; bss->id = wpa_s->bss_next_id++; bss->last_update_idx = wpa_s->bss_update_idx; wpa_bss_copy_res(bss, res); os_memcpy(bss->ssid, ssid, ssid_len); bss->ssid_len = ssid_len; bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); dl_list_add_tail(&wpa_s->bss, &bss->list); dl_list_add_tail(&wpa_s->bss_id, &bss->list_id); wpa_s->num_bss++; wpa_printf(MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR " SSID '%s'", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len)); wpas_notify_bss_added(wpa_s, bss->bssid, bss->id); if (wpa_s->num_bss > wpa_s->conf->bss_max_count) { /* Remove the oldest entry */ wpa_bss_remove(wpa_s, dl_list_first(&wpa_s->bss, struct wpa_bss, list)); }
void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, const u8 *bssid, u16 auth_type) { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; os_memset(¶ms, 0, sizeof(params)); params.bssid = bssid; params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; params.freq = wpa_s->sme.freq; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? wpa_s->sme.assoc_req_ie : NULL; params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { params.wpa_ie = wpa_s->sme.ft_ies; params.wpa_ie_len = wpa_s->sme.ft_ies_len; } #endif /* CONFIG_IEEE80211R */ params.mode = mode; params.mgmt_frame_protection = wpa_s->sme.mfp; if (wpa_s->sme.prev_bssid_set) params.prev_bssid = wpa_s->sme.prev_bssid; wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", params.freq); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); if (params.wpa_ie == NULL || ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) < 0) { wpa_printf(MSG_DEBUG, "SME: Could not parse own IEs?!"); os_memset(&elems, 0, sizeof(elems)); } if (elems.rsn_ie) wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, elems.rsn_ie_len + 2); else if (elems.wpa_ie) wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, elems.wpa_ie_len + 2); else wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " "failed"); //wpa_supplicant_req_scan(wpa_s, 5, 0); ros_assoc_failed(wpa_s, bssid, "Driver request to associate failed"); return; } /* TODO: add timeout on association */ }
static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { dl_list_del(&bss->list); dl_list_del(&bss->list_id); wpa_s->num_bss--; wpa_printf(MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR " SSID '%s'", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len)); wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id); os_free(bss); }
//Start MANA static void log_ssid(const u8 *ssid, size_t ssid_len, const u8 *mac) { //Quick hack to output observed MACs & SSIDs //TODO: Fix this so it works in loud mode, right now will only log an SSID once char *mana_outfile = getenv("MANAOUTFILE"); FILE *f = fopen(mana_outfile, "a"); if (f != NULL) { int rand=0; if (mac[0] & 2) //Check if locally administered aka random MAC rand=1; fprintf(f,MACSTR ", %s, %d\n", MAC2STR(mac), wpa_ssid_txt(ssid, ssid_len), rand); fclose(f); } }
static int wpa_supplicant_ctrl_iface_list_networks( struct wpa_supplicant *wpa_s, char *buf, size_t buflen) { char *pos, *end; struct wpa_ssid *ssid; int ret; pos = buf; end = buf + buflen; ret = os_snprintf(pos, end - pos, "network id / ssid / bssid / flags\n"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; ssid = wpa_s->conf->ssid; while (ssid) { ret = os_snprintf(pos, end - pos, "%d\t%s", ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; if (ssid->bssid_set) { ret = os_snprintf(pos, end - pos, "\t" MACSTR, MAC2STR(ssid->bssid)); } else { ret = os_snprintf(pos, end - pos, "\tany"); } if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; ret = os_snprintf(pos, end - pos, "\t%s%s", ssid == wpa_s->current_ssid ? "[CURRENT]" : "", ssid->disabled ? "[DISABLED]" : ""); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; ret = os_snprintf(pos, end - pos, "\n"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; ssid = ssid->next; } return pos - buf; }
/** * wpa_config_debug_dump_networks - Debug dump of configured networks * @config: Configuration data from wpa_config_read() */ void wpa_config_debug_dump_networks(struct wpa_config *config) { int prio; struct wpa_ssid *ssid; for (prio = 0; prio < config->num_prio; prio++) { ssid = config->pssid[prio]; wpa_printf(MSG_DEBUG, "Priority group %d", ssid->priority); while (ssid) { wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); ssid = ssid->pnext; } } }
static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, const char *params, char *buf, size_t buflen) { char *pos, *end; int res, verbose; verbose = strcmp(params, "-VERBOSE") == 0; pos = buf; end = buf + buflen; pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n", MAC2STR(wpa_s->bssid)); if (wpa_s->current_ssid) { pos += snprintf(pos, end - pos, "ssid=%s\n", wpa_ssid_txt(wpa_s->current_ssid->ssid, wpa_s->current_ssid->ssid_len)); } pos += snprintf(pos, end - pos, "pairwise_cipher=%s\n" "group_cipher=%s\n" "key_mgmt=%s\n" "wpa_state=%s\n", wpa_cipher_txt(wpa_s->pairwise_cipher), wpa_cipher_txt(wpa_s->group_cipher), wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->proto), wpa_state_txt(wpa_s->wpa_state)); res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose); if (res >= 0) pos += res; if (wpa_s->preauth_eapol) { pos += snprintf(pos, end - pos, "Pre-authentication " "EAPOL state machines:\n"); res = eapol_sm_get_status(wpa_s->preauth_eapol, pos, end - pos, verbose); if (res >= 0) pos += res; } return pos - buf; }
static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, dladm_wlan_ess_t *bss, struct wpa_ssid *ssid) { uint8_t wpa_ie[IEEE80211_MAX_OPT_IE]; int wpa_ie_len; wpa_s->reassociate = 0; wpa_printf(MSG_DEBUG, "Trying to associate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(bss->we_bssid.wb_bytes), wpa_ssid_txt((char *)ssid->ssid, ssid->ssid_len), bss->we_freq); wpa_supplicant_cancel_scan(wpa_s); if (bss->we_wpa_ie_len && (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) { wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, bss->we_bssid.wb_bytes, NULL); if (wpa_s->cur_pmksa) { wpa_hexdump(MSG_DEBUG, "RSN: PMKID", wpa_s->cur_pmksa->pmkid, PMKID_LEN); } if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_ie, &wpa_ie_len)) { wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " "management and encryption suites"); return; } } else { wpa_ie_len = 0; } wpa_clear_keys(wpa_s, bss->we_bssid.wb_bytes); wpa_s->wpa_state = WPA_ASSOCIATING; wpa_s->driver->associate(wpa_s->linkid, (const char *)bss->we_bssid.wb_bytes, wpa_ie, wpa_ie_len); /* Timeout for IEEE 802.11 authentication and association */ wpa_supplicant_req_auth_timeout(wpa_s, 15, 0); }
static void wpa_supplicant_wps_event_er_ap_settings( struct wpa_supplicant *wpa_s, struct wps_event_er_ap_settings *ap_settings) { char uuid_str[100]; char key_str[65]; const struct wps_credential *cred = ap_settings->cred; key_str[0] = '\0'; if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) { if (cred->key_len >= 8 && cred->key_len <= 64) { os_memcpy(key_str, cred->key, cred->key_len); key_str[cred->key_len] = '\0'; } } uuid_bin2str(ap_settings->uuid, uuid_str, sizeof(uuid_str)); /* Use wpa_msg_ctrl to avoid showing the key in debug log */ wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_SETTINGS "uuid=%s ssid=%s auth_type=0x%04x encr_type=0x%04x " "key=%s", uuid_str, wpa_ssid_txt(cred->ssid, cred->ssid_len), cred->auth_type, cred->encr_type, key_str); }
void handle_probe_req(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len, int ssi_signal) { u8 *resp; struct ieee802_11_elems elems; const u8 *ie; size_t ie_len; size_t i, resp_len; int noack; enum ssid_match_result res; int ret; u16 csa_offs[2]; size_t csa_offs_len; ie = mgmt->u.probe_req.variable; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) return; if (hapd->iconf->track_sta_max_num) sta_track_add(hapd->iface, mgmt->sa); ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, mgmt->sa, mgmt->da, mgmt->bssid, ie, ie_len, ssi_signal) > 0) return; if (!hapd->iconf->send_probe_response) return; if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, MAC2STR(mgmt->sa)); return; } if ((!elems.ssid || !elems.supp_rates)) { wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " "without SSID or supported rates element", MAC2STR(mgmt->sa)); return; } /* * No need to reply if the Probe Request frame was sent on an adjacent * channel. IEEE Std 802.11-2012 describes this as a requirement for an * AP with dot11RadioMeasurementActivated set to true, but strictly * speaking does not allow such ignoring of Probe Request frames if * dot11RadioMeasurementActivated is false. Anyway, this can help reduce * number of unnecessary Probe Response frames for cases where the STA * is less likely to see them (Probe Request frame sent on a * neighboring, but partially overlapping, channel). */ if (elems.ds_params && hapd->iface->current_mode && (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G || hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B) && hapd->iconf->channel != elems.ds_params[0]) { wpa_printf(MSG_DEBUG, "Ignore Probe Request due to DS Params mismatch: chan=%u != ds.chan=%u", hapd->iconf->channel, elems.ds_params[0]); return; } #ifdef CONFIG_P2P if (hapd->p2p && hapd->p2p_group && elems.wps_ie) { struct wpabuf *wps; wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) { wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " "due to mismatch with Requested Device " "Type"); wpabuf_free(wps); return; } wpabuf_free(wps); } if (hapd->p2p && hapd->p2p_group && elems.p2p) { struct wpabuf *p2p; p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE); if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) { wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " "due to mismatch with Device ID"); wpabuf_free(p2p); return; } wpabuf_free(p2p); } #endif /* CONFIG_P2P */ if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 && elems.ssid_list_len == 0) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " "broadcast SSID ignored", MAC2STR(mgmt->sa)); return; } #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_GROUP_OWNER) && elems.ssid_len == P2P_WILDCARD_SSID_LEN && os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) { /* Process P2P Wildcard SSID like Wildcard SSID */ elems.ssid_len = 0; } #endif /* CONFIG_P2P */ res = ssid_match(hapd, elems.ssid, elems.ssid_len, elems.ssid_list, elems.ssid_list_len); if (res == NO_SSID_MATCH) { if (!(mgmt->da[0] & 0x01)) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for foreign SSID '%s' (DA " MACSTR ")%s", MAC2STR(mgmt->sa), wpa_ssid_txt(elems.ssid, elems.ssid_len), MAC2STR(mgmt->da), elems.ssid_list ? " (SSID list)" : ""); } return; } #ifdef CONFIG_INTERWORKING if (hapd->conf->interworking && elems.interworking && elems.interworking_len >= 1) { u8 ant = elems.interworking[0] & 0x0f; if (ant != INTERWORKING_ANT_WILDCARD && ant != hapd->conf->access_network_type) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for mismatching ANT %u ignored", MAC2STR(mgmt->sa), ant); return; } } if (hapd->conf->interworking && elems.interworking && (elems.interworking_len == 7 || elems.interworking_len == 9)) { const u8 *hessid; if (elems.interworking_len == 7) hessid = elems.interworking + 1; else hessid = elems.interworking + 1 + 2; if (!is_broadcast_ether_addr(hessid) && os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for mismatching HESSID " MACSTR " ignored", MAC2STR(mgmt->sa), MAC2STR(hessid)); return; } } #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_GROUP_OWNER) && supp_rates_11b_only(&elems)) { /* Indicates support for 11b rates only */ wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from " MACSTR " with only 802.11b rates", MAC2STR(mgmt->sa)); return; } #endif /* CONFIG_P2P */ /* TODO: verify that supp_rates contains at least one matching rate * with AP configuration */ if (hapd->conf->no_probe_resp_if_seen_on && is_multicast_ether_addr(mgmt->da) && is_multicast_ether_addr(mgmt->bssid) && sta_track_seen_on(hapd->iface, mgmt->sa, hapd->conf->no_probe_resp_if_seen_on)) { wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR " since STA has been seen on %s", hapd->conf->iface, MAC2STR(mgmt->sa), hapd->conf->no_probe_resp_if_seen_on); return; } if (hapd->conf->no_probe_resp_if_max_sta && is_multicast_ether_addr(mgmt->da) && is_multicast_ether_addr(mgmt->bssid) && hapd->num_sta >= hapd->conf->max_num_sta && !ap_get_sta(hapd, mgmt->sa)) { wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR " since no room for additional STA", hapd->conf->iface, MAC2STR(mgmt->sa)); return; } #ifdef CONFIG_TESTING_OPTIONS if (hapd->iconf->ignore_probe_probability > 0.0 && drand48() < hapd->iconf->ignore_probe_probability) { wpa_printf(MSG_INFO, "TESTING: ignoring probe request from " MACSTR, MAC2STR(mgmt->sa)); return; } #endif /* CONFIG_TESTING_OPTIONS */ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL, &resp_len); if (resp == NULL) return; /* * If this is a broadcast probe request, apply no ack policy to avoid * excessive retries. */ noack = !!(res == WILDCARD_SSID_MATCH && is_broadcast_ether_addr(mgmt->da)); csa_offs_len = 0; if (hapd->csa_in_progress) { if (hapd->cs_c_off_proberesp) csa_offs[csa_offs_len++] = hapd->cs_c_off_proberesp; if (hapd->cs_c_off_ecsa_proberesp) csa_offs[csa_offs_len++] = hapd->cs_c_off_ecsa_proberesp; } ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack, csa_offs_len ? csa_offs : NULL, csa_offs_len); if (ret < 0) wpa_printf(MSG_INFO, "handle_probe_req: send failed"); os_free(resp); wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " "SSID", MAC2STR(mgmt->sa), elems.ssid_len == 0 ? "broadcast" : "our"); }
static struct wpa_scan_res * wpa_supplicant_select_bss_wapi(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, struct wpa_ssid **selected_ssid) { struct wpa_ssid *ssid; struct wpa_scan_res *bss; size_t i; struct wpa_blacklist *e; const u8 *ie; wpa_printf(MSG_DEBUG, "Try to find WAPI-enabled AP"); for (i = 0; i < wpa_s->scan_res->num; i++) { const u8 *ssid_; u8 wapi_ie_len, ssid_len; bss = wpa_s->scan_res->res[i]; ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ssid_ = ie ? ie + 2 : (u8 *) ""; ssid_len = ie ? ie[1] : 0; //ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); //wpa_ie_len = ie ? ie[1] : 0; ie = wpa_scan_get_ie(bss, WAPI_INFO_ELEM); wapi_ie_len = ie ? ie[1] : 0; wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " "wapi_ie_len=%u caps=0x%x", (int) i, MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len), wapi_ie_len, bss->caps); e = wpa_blacklist_get(wpa_s, bss->bssid); if (e && e->count > 1) { wpa_printf(MSG_DEBUG, " skip - blacklisted"); continue; } if (ssid_len == 0) { wpa_printf(MSG_DEBUG, " skip - SSID not known"); continue; } if (wapi_ie_len == 0) { wpa_printf(MSG_DEBUG, " skip - no WAPI IE"); continue; } for (ssid = group; ssid; ssid = ssid->pnext) { int check_ssid = 1; if (ssid->disabled) { wpa_printf(MSG_DEBUG, " skip - disabled"); continue; } if (check_ssid && (ssid_len != ssid->ssid_len || os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) { wpa_printf(MSG_DEBUG, " skip - " "SSID mismatch"); continue; } if (ssid->bssid_set && os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, " skip - " "BSSID mismatch"); continue; } if (!wpa_supplicant_ssid_wapi_bss_match(wpa_s, ssid, bss)) continue; { /* Record the WAPI AP's IE, will be reported to WAPI Module */ const u8* wapi_ie; wapi_ie = wpa_scan_get_ie(bss, WAPI_INFO_ELEM); wpa_s->bss_wapi_ie_len = 2 + wapi_ie[1]; os_memcpy(wpa_s->bss_wapi_ie, wapi_ie, wpa_s->bss_wapi_ie_len); wpa_printf(MSG_DEBUG, "[WAPI-Debug ^_^] selected WAPI AP !!!!!!! Ready to connect +_+"); } wpa_printf(MSG_DEBUG, " selected WAPI AP " MACSTR " ssid='%s'", MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len)); *selected_ssid = ssid; return bss; } } return NULL; }
void sme_authenticate(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; if (bss == NULL) { wpa_printf(MSG_ERROR, "SME: No scan result available for the " "network"); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x", params.auth_alg); } for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_PSK_SHA256))) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_printf(MSG_WARNING, "SME: Failed to set WPA key " "management and encryption suites"); return; } } else if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_IEEE8021X_SHA256)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_printf(MSG_WARNING, "SME: Failed to set WPA key " "management and encryption suites (no scan " "results)"); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_printf(MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w; if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_printf(MSG_DEBUG, "WPA: Selected AP supports MFP: " "require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "Authentication request to the " "driver failed"); wpa_supplicant_req_scan(wpa_s, 1, 0); return; } /* TODO: add timeout on authentication */ /* * Association will be started based on the authentication event from * the driver. */ }
void sme_authenticate(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; #if defined(ANDROID_P2P) && defined(WIFI_EAGLE) int freq = 0; #endif /* ANDROID_P2P && WIFI_EAGLE */ if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w; if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (wpa_s->conf->hs20) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { wpas_hs20_add_indication(hs20); os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ #ifdef CONFIG_INTERWORKING if (wpa_s->conf->interworking) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + 6, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += 6; *pos++ = WLAN_EID_EXT_CAPAB; *pos++ = 4; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x80; /* Bit 31 - Interworking */ } #endif /* CONFIG_INTERWORKING */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); wpa_s->sme.auth_alg = params.auth_alg; #if defined(ANDROID_P2P) && defined(WIFI_EAGLE) /* If multichannel concurrency is not supported, check for any frequency * conflict and take appropriate action. */ wpa_printf(MSG_DEBUG, "%s EAGLE: Priority choose", __func__); if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) && ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) { wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)" , freq, params.freq); if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq) < 0) { /* Handling conflicts failed. Disable the current connect req and * notify the userspace to take appropriate action */ wpa_printf(MSG_DEBUG, "proiritize is not set. Notifying user space to handle the case"); wpa_supplicant_disable_network(wpa_s, ssid); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_FREQ_CONFLICT " id=%d", ssid->id); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); return; } } #endif /* ANDROID_P2P && WIFI_EAGLE */ if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid); wpa_supplicant_mark_disassoc(wpa_s); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ }
static struct wpa_scan_res * wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, struct wpa_ssid **selected_ssid) { struct wpa_ssid *ssid; struct wpa_scan_res *bss; size_t i; struct wpa_blacklist *e; const u8 *ie; wpa_printf(MSG_DEBUG, "Try to find non-WPA AP"); for (i = 0; i < wpa_s->scan_res->num; i++) { const u8 *ssid_; u8 wpa_ie_len, rsn_ie_len, ssid_len; bss = wpa_s->scan_res->res[i]; ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ssid_ = ie ? ie + 2 : (u8 *) ""; ssid_len = ie ? ie[1] : 0; ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; ie = wpa_scan_get_ie(bss, WLAN_EID_RSN); rsn_ie_len = ie ? ie[1] : 0; wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x", (int) i, MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len), wpa_ie_len, rsn_ie_len, bss->caps); e = wpa_blacklist_get(wpa_s, bss->bssid); if (e && e->count > 1) { wpa_printf(MSG_DEBUG, " skip - blacklisted"); continue; } if (ssid_len == 0) { wpa_printf(MSG_DEBUG, " skip - SSID not known"); continue; } for (ssid = group; ssid; ssid = ssid->pnext) { int check_ssid = ssid->ssid_len != 0; if (ssid->disabled) { wpa_printf(MSG_DEBUG, " skip - disabled"); continue; } #ifdef CONFIG_WPS if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { /* Only allow wildcard SSID match if an AP * advertises active WPS operation that matches * with our mode. */ check_ssid = 1; if (ssid->ssid_len == 0 && wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) check_ssid = 0; } #endif /* CONFIG_WPS */ if (check_ssid && (ssid_len != ssid->ssid_len || os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) { wpa_printf(MSG_DEBUG, " skip - " "SSID mismatch"); continue; } if (ssid->bssid_set && os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, " skip - " "BSSID mismatch"); continue; } if (!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { wpa_printf(MSG_DEBUG, " skip - " "non-WPA network not allowed"); continue; } if ((ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_PSK_SHA256)) && (wpa_ie_len != 0 || rsn_ie_len != 0)) { wpa_printf(MSG_DEBUG, " skip - " "WPA network"); continue; } if (!wpa_supplicant_match_privacy(bss, ssid)) { wpa_printf(MSG_DEBUG, " skip - " "privacy mismatch"); continue; } if (bss->caps & IEEE80211_CAP_IBSS) { wpa_printf(MSG_DEBUG, " skip - " "IBSS (adhoc) network"); continue; } wpa_printf(MSG_DEBUG, " selected non-WPA AP " MACSTR " ssid='%s'", MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len)); *selected_ssid = ssid; return bss; } } return NULL; }
static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, int start) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; struct wpabuf *resp = NULL; u8 ext_capab[18]; int ext_capab_len; int skip_auth; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); wpas_connect_work_done(wpa_s); return; } skip_auth = wpa_s->conf->reassoc_same_bss_optim && wpa_s->reassoc_same_bss; wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } #ifdef CONFIG_SAE wpa_s->sme.sae_pmksa_caching = 0; if (wpa_key_mgmt_sae(ssid->key_mgmt)) { const u8 *rsn; struct wpa_ie_data ied; rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); if (!rsn) { wpa_dbg(wpa_s, MSG_DEBUG, "SAE enabled, but target BSS does not advertise RSN"); } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 && wpa_key_mgmt_sae(ied.key_mgmt)) { wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); params.auth_alg = WPA_AUTH_ALG_SAE; } else { wpa_dbg(wpa_s, MSG_DEBUG, "SAE enabled, but target BSS does not advertise SAE AKM for RSN"); } } #endif /* CONFIG_SAE */ for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = (ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching) && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); wpas_connect_work_done(wpa_s); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); wpas_connect_work_done(wpa_s); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid); if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (is_hs20_network(wpa_s, ssid, bss)) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); size_t len; wpas_hs20_add_indication(hs20, pps_mo_id); len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; if (wpabuf_len(hs20) <= len) { os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); } wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, sizeof(ext_capab)); if (ext_capab_len > 0) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + ext_capab_len, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += ext_capab_len; os_memcpy(pos, ext_capab, ext_capab_len); } if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) { struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]; size_t len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; if (wpabuf_len(buf) <= len) { os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(buf), wpabuf_len(buf)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf); } } sme_auth_handle_rrm(wpa_s, bss); #ifdef CONFIG_SAE if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE && pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0) { wpa_dbg(wpa_s, MSG_DEBUG, "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication"); params.auth_alg = WPA_AUTH_ALG_OPEN; wpa_s->sme.sae_pmksa_caching = 1; } if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) { if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid); else resp = sme_auth_build_sae_confirm(wpa_s); if (resp == NULL) { wpas_connection_failed(wpa_s, bss->bssid, 1); return; } params.sae_data = wpabuf_head(resp); params.sae_data_len = wpabuf_len(resp); wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED; } #endif /* CONFIG_SAE */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); #ifdef CONFIG_P2P /* * If multi-channel concurrency is not supported, check for any * frequency conflict. In case of any frequency conflict, remove the * least prioritized connection. */ if (wpa_s->num_multichan_concurrent < 2) { int freq, num; num = get_shared_radio_freqs(wpa_s, &freq, 1); if (num > 0 && freq > 0 && freq != params.freq) { wpa_printf(MSG_DEBUG, "Conflicting frequency found (%d != %d)", freq, params.freq); if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0) { wpas_connection_failed(wpa_s, bss->bssid, 0); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); wpas_connect_work_done(wpa_s); return; } } } #endif /* CONFIG_P2P */ if (skip_auth) { wpa_msg(wpa_s, MSG_DEBUG, "SME: Skip authentication step on reassoc-to-same-BSS"); wpabuf_free(resp); sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN); return; } wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid, 1); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); wpas_connect_work_done(wpa_s); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ wpabuf_free(resp); }
int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { struct wpa_driver_associate_params params; struct hostapd_iface *hapd_iface; struct hostapd_config *conf; struct hostapd_data *hapd; size_t i; if (ssid->ssid == NULL || ssid->ssid_len == 0) { wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); return -1; } wpa_supplicant_ap_deinit(wpa_s); wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); os_memset(¶ms, 0, sizeof(params)); params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; switch (ssid->mode) { case WPAS_MODE_INFRA: params.mode = IEEE80211_MODE_INFRA; break; case WPAS_MODE_IBSS: params.mode = IEEE80211_MODE_IBSS; break; case WPAS_MODE_AP: case WPAS_MODE_P2P_GO: case WPAS_MODE_P2P_GROUP_FORMATION: params.mode = IEEE80211_MODE_AP; break; } params.freq = ssid->frequency; if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; else wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt); if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; else if (ssid->pairwise_cipher & WPA_CIPHER_TKIP) wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; else if (ssid->pairwise_cipher & WPA_CIPHER_NONE) wpa_s->pairwise_cipher = WPA_CIPHER_NONE; else { wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " "cipher."); return -1; } params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher); params.group_suite = params.pairwise_suite; #ifdef CONFIG_P2P if (ssid->mode == WPAS_MODE_P2P_GO || ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) params.p2p = 1; wpa_drv_set_intra_bss(wpa_s, wpa_s->conf->p2p_intra_bss); #endif /* CONFIG_P2P */ if (wpa_s->parent->set_ap_uapsd) params.uapsd = wpa_s->parent->ap_uapsd; else params.uapsd = -1; if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); return -1; } wpa_s->ap_iface = hapd_iface = os_zalloc(sizeof(*wpa_s->ap_iface)); if (hapd_iface == NULL) return -1; hapd_iface->owner = wpa_s; wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); if (conf == NULL) { wpa_supplicant_ap_deinit(wpa_s); return -1; } if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) { wpa_printf(MSG_ERROR, "Failed to create AP configuration"); wpa_supplicant_ap_deinit(wpa_s); return -1; } #ifdef CONFIG_P2P if (ssid->mode == WPAS_MODE_P2P_GO) conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER; else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER | P2P_GROUP_FORMATION; #endif /* CONFIG_P2P */ hapd_iface->num_bss = conf->num_bss; hapd_iface->bss = os_zalloc(conf->num_bss * sizeof(struct hostapd_data *)); if (hapd_iface->bss == NULL) { wpa_supplicant_ap_deinit(wpa_s); return -1; } for (i = 0; i < conf->num_bss; i++) { hapd_iface->bss[i] = hostapd_alloc_bss_data(hapd_iface, conf, &conf->bss[i]); if (hapd_iface->bss[i] == NULL) { wpa_supplicant_ap_deinit(wpa_s); return -1; } hapd_iface->bss[i]->msg_ctx = wpa_s; hapd_iface->bss[i]->public_action_cb = ap_public_action_rx; hapd_iface->bss[i]->public_action_cb_ctx = wpa_s; hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx; hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s; hostapd_register_probereq_cb(hapd_iface->bss[i], ap_probe_req_rx, wpa_s); hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb; hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s; hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb; hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s; hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb; hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s; #ifdef CONFIG_P2P hapd_iface->bss[i]->p2p = wpa_s->global->p2p; hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init( wpa_s, ssid->p2p_persistent_group, ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION); #endif /* CONFIG_P2P */ hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb; hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s; } os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN); hapd_iface->bss[0]->driver = wpa_s->driver; hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv; wpa_s->current_ssid = ssid; os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN); wpa_s->assoc_freq = ssid->frequency; #if defined(CONFIG_AP) && defined(CONFIG_DRIVER_AR6003) if (wpa_s->conf->p2p_max_clients > 5) { wpa_printf(MSG_ERROR, "Cannot set max_num_sta to %d, maximum value is 5. 5 will be the value used.", wpa_s->conf->p2p_max_clients); wpa_s->conf->p2p_max_clients = 5; } wpa_printf(MSG_DEBUG, "Setting max_num_sta to %d", wpa_s->conf->p2p_max_clients); ar6003_set_max_num_sta(wpa_s->drv_priv, wpa_s->conf->p2p_max_clients); #endif #ifdef CONFIG_P2P if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) { hapd = hapd_iface->bss[0]; os_memcpy(hapd->iconf->country, wpa_s->conf->country, 2); hapd->iconf->country[2] ='\0'; } #endif if (hostapd_setup_interface(wpa_s->ap_iface)) { wpa_printf(MSG_ERROR, "Failed to initialize AP interface"); wpa_supplicant_ap_deinit(wpa_s); return -1; } return 0; }
static struct wpa_scan_res * wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, struct wpa_ssid **selected_ssid) { struct wpa_ssid *ssid; struct wpa_scan_res *bss; size_t i; struct wpa_blacklist *e; const u8 *ie; wpa_printf(MSG_DEBUG, "Try to find WPA-enabled AP"); for (i = 0; i < wpa_s->scan_res->num; i++) { const u8 *ssid_; u8 wpa_ie_len, rsn_ie_len, ssid_len; bss = wpa_s->scan_res->res[i]; ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ssid_ = ie ? ie + 2 : (u8 *) ""; ssid_len = ie ? ie[1] : 0; ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; ie = wpa_scan_get_ie(bss, WLAN_EID_RSN); rsn_ie_len = ie ? ie[1] : 0; wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x", (int) i, MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len), wpa_ie_len, rsn_ie_len, bss->caps); e = wpa_blacklist_get(wpa_s, bss->bssid); if (e && e->count > 1) { wpa_printf(MSG_DEBUG, " skip - blacklisted"); continue; } if (ssid_len == 0) { wpa_printf(MSG_DEBUG, " skip - SSID not known"); continue; } if (wpa_ie_len == 0 && rsn_ie_len == 0) { wpa_printf(MSG_DEBUG, " skip - no WPA/RSN IE"); continue; } for (ssid = group; ssid; ssid = ssid->pnext) { int check_ssid = 1; if (ssid->disabled) { wpa_printf(MSG_DEBUG, " skip - disabled"); continue; } #ifdef CONFIG_WPS if (ssid->ssid_len == 0 && wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) check_ssid = 0; #endif /* CONFIG_WPS */ if (check_ssid && (ssid_len != ssid->ssid_len || os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) { wpa_printf(MSG_DEBUG, " skip - " "SSID mismatch"); continue; } if (ssid->bssid_set && os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, " skip - " "BSSID mismatch"); continue; } if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) continue; wpa_printf(MSG_DEBUG, " selected WPA AP " MACSTR " ssid='%s'", MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len)); *selected_ssid = ssid; return bss; } } return NULL; }
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_ssid *ssid; int ret; struct wpabuf *extra_ie = NULL; struct wpa_driver_scan_params params; struct wpa_driver_scan_params *scan_params; size_t max_ssids; enum wpa_states prev_state; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); wpas_p2p_continue_after_scan(wpa_s); return; } if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) { wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); wpas_p2p_continue_after_scan(wpa_s); 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_supplicant_enabled_networks(wpa_s) && wpa_s->scan_req == NORMAL_SCAN_REQ) { wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); wpas_p2p_continue_after_scan(wpa_s); return; } if (wpa_s->conf->ap_scan != 0 && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) { wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - " "overriding ap_scan configuration"); wpa_s->conf->ap_scan = 0; wpas_notify_ap_scan_changed(wpa_s); } if (wpa_s->conf->ap_scan == 0) { wpa_supplicant_gen_assoc_event(wpa_s); return; } #ifdef CONFIG_P2P 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) { wpa_dbg(wpa_s, MSG_DEBUG, "Process pending station " "mode scan during P2P search"); } else { wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan " "while P2P operation is in progress"); wpa_s->sta_scan_pending = 1; wpa_supplicant_req_scan(wpa_s, 5, 0); return; } } #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 = wpa_s->max_scan_ssids; if (max_ssids > WPAS_MAX_SCAN_SSIDS) max_ssids = WPAS_MAX_SCAN_SSIDS; } wpa_s->last_scan_req = wpa_s->scan_req; wpa_s->scan_req = NORMAL_SCAN_REQ; os_memset(¶ms, 0, sizeof(params)); prev_state = wpa_s->wpa_state; if (wpa_s->wpa_state == WPA_DISCONNECTED || wpa_s->wpa_state == WPA_INACTIVE) wpa_supplicant_set_state(wpa_s, WPA_SCANNING); /* * If autoscan has set its own scanning parameters */ if (wpa_s->autoscan_params != NULL) { scan_params = wpa_s->autoscan_params; goto 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; } wpa_s->connect_without_scan = NULL; if (ssid) { wpa_printf(MSG_DEBUG, "Start a pre-selected network " "without scan step"); wpa_supplicant_associate(wpa_s, NULL, ssid); return; } } #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 (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; goto ssid_list_set; } #endif /* CONFIG_P2P */ /* Find the starting point from which to continue scanning */ ssid = wpa_s->conf->ssid; if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) { while (ssid) { if (ssid == wpa_s->prev_scan_ssid) { ssid = ssid->next; break; } ssid = ssid->next; } } 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); return; } else if (wpa_s->conf->ap_scan == 2) { /* * User-initiated scan request in ap_scan == 2; scan with * wildcard SSID. */ ssid = NULL; } else { struct wpa_ssid *start = ssid, *tssid; int freqs_set = 0; if (ssid == NULL && max_ssids > 1) ssid = wpa_s->conf->ssid; while (ssid) { if (!wpas_network_disabled(wpa_s, ssid) && ssid->scan_ssid) { wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", ssid->ssid, ssid->ssid_len); params.ssids[params.num_ssids].ssid = ssid->ssid; params.ssids[params.num_ssids].ssid_len = ssid->ssid_len; params.num_ssids++; if (params.num_ssids + 1 >= max_ssids) break; } ssid = ssid->next; if (ssid == start) break; if (ssid == NULL && max_ssids > 1 && start != wpa_s->conf->ssid) ssid = wpa_s->conf->ssid; } for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { if (wpas_network_disabled(wpa_s, tssid)) continue; if ((params.freqs || !freqs_set) && tssid->scan_freq) { int_array_concat(¶ms.freqs, tssid->scan_freq); } else { os_free(params.freqs); params.freqs = NULL; } freqs_set = 1; } int_array_sort_unique(params.freqs); } if (ssid && max_ssids == 1) { /* * If the driver is limited to 1 SSID at a time interleave * wildcard SSID scans with specific SSID scans to avoid * waiting a long time for a wildcard scan. */ if (!wpa_s->prev_scan_wildcard) { params.ssids[0].ssid = NULL; params.ssids[0].ssid_len = 0; wpa_s->prev_scan_wildcard = 1; wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for " "wildcard SSID (Interleave with specific)"); } else { wpa_s->prev_scan_ssid = ssid; wpa_s->prev_scan_wildcard = 0; wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for specific SSID: %s", wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); } } else if (ssid) { /* max_ssids > 1 */ wpa_s->prev_scan_ssid = ssid; wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in " "the scan request"); params.num_ssids++; } else { wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; params.num_ssids++; wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard " "SSID"); } #ifdef CONFIG_P2P ssid_list_set: #endif /* CONFIG_P2P */ wpa_supplicant_optimize_freqs(wpa_s, ¶ms); extra_ie = wpa_supplicant_extra_ies(wpa_s); if (params.freqs == NULL && wpa_s->next_scan_freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously " "generated frequency list"); params.freqs = wpa_s->next_scan_freqs; } else os_free(wpa_s->next_scan_freqs); wpa_s->next_scan_freqs = NULL; wpa_setband_scan_freqs(wpa_s, ¶ms); /* See if user specified frequencies. If so, scan only those. */ if (wpa_s->conf->freq_list && !params.freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on conf->freq_list"); int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); } /* Use current associated channel? */ if (wpa_s->conf->scan_cur_freq && !params.freqs) { unsigned int num = wpa_s->num_multichan_concurrent; params.freqs = os_calloc(num + 1, sizeof(int)); if (params.freqs) { num = get_shared_radio_freqs(wpa_s, params.freqs, num); if (num > 0) { wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the " "current operating channels since " "scan_cur_freq is enabled"); } else { os_free(params.freqs); params.freqs = NULL; } } } params.filter_ssids = wpa_supplicant_build_filter_ssids( wpa_s->conf, ¶ms.num_filter_ssids); if (extra_ie) { params.extra_ies = wpabuf_head(extra_ie); params.extra_ies_len = wpabuf_len(extra_ie); } #ifdef CONFIG_P2P if (wpa_s->p2p_in_provisioning || (wpa_s->show_group_started && wpa_s->go_params)) { /* * The interface may not yet be in P2P mode, so we have to * explicitly request P2P probe to disable CCK rates. */ params.p2p_probe = 1; } #endif /* CONFIG_P2P */ scan_params = ¶ms; scan: #ifdef CONFIG_P2P /* * If the driver does not support multi-channel concurrency and a * virtual interface that shares the same radio with the wpa_s interface * is operating there may not be need to scan other channels apart from * the current operating channel on the other virtual interface. Filter * out other channels in case we are trying to find a connection for a * 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 && 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 && non_p2p_network_enabled(wpa_s)) { unsigned int num = wpa_s->num_multichan_concurrent; params.freqs = os_calloc(num + 1, sizeof(int)); if (params.freqs) { num = get_shared_radio_freqs(wpa_s, params.freqs, num); if (num > 0 && num == wpa_s->num_multichan_concurrent) { wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used"); } else { os_free(params.freqs); params.freqs = NULL; } } } #endif /* CONFIG_P2P */ ret = wpa_supplicant_trigger_scan(wpa_s, scan_params); wpabuf_free(extra_ie); os_free(params.freqs); os_free(params.filter_ssids); if (ret) { wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan"); 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 = wpa_s->last_scan_req; wpa_supplicant_req_scan(wpa_s, 1, 0); } else { wpa_s->scan_for_connection = 0; } }
void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, const u8 *bssid, u16 auth_type) { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; #ifdef CONFIG_HT_OVERRIDES struct ieee80211_ht_capabilities htcaps; struct ieee80211_ht_capabilities htcaps_mask; #endif /* CONFIG_HT_OVERRIDES */ os_memset(¶ms, 0, sizeof(params)); params.bssid = bssid; params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; params.freq = wpa_s->sme.freq; params.bg_scan_period = wpa_s->current_ssid ? wpa_s->current_ssid->bg_scan_period : -1; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? wpa_s->sme.assoc_req_ie : NULL; params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher); params.group_suite = cipher_suite2driver(wpa_s->group_cipher); #ifdef CONFIG_HT_OVERRIDES os_memset(&htcaps, 0, sizeof(htcaps)); os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); params.htcaps = (u8 *) &htcaps; params.htcaps_mask = (u8 *) &htcaps_mask; wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { params.wpa_ie = wpa_s->sme.ft_ies; params.wpa_ie_len = wpa_s->sme.ft_ies_len; } #endif /* CONFIG_IEEE80211R */ params.mode = mode; params.mgmt_frame_protection = wpa_s->sme.mfp; if (wpa_s->sme.prev_bssid_set) params.prev_bssid = wpa_s->sme.prev_bssid; wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", params.freq); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); if (params.wpa_ie == NULL || ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) < 0) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!"); os_memset(&elems, 0, sizeof(elems)); } if (elems.rsn_ie) { params.wpa_proto = WPA_PROTO_RSN; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, elems.rsn_ie_len + 2); } else if (elems.wpa_ie) { params.wpa_proto = WPA_PROTO_WPA; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, elems.wpa_ie_len + 2); } else wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) params.p2p = 1; if (wpa_s->parent->set_sta_uapsd) params.uapsd = wpa_s->parent->sta_uapsd; else params.uapsd = -1; if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the " "driver failed"); wpas_connection_failed(wpa_s, wpa_s->pending_bssid); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); return; } eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, NULL); }
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 *extra_ie; struct wpa_driver_scan_params params; size_t max_ssids; enum wpa_states prev_state; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); return; } 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_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); return; } if (wpa_s->conf->ap_scan != 0 && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) { wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - " "overriding ap_scan configuration"); wpa_s->conf->ap_scan = 0; wpas_notify_ap_scan_changed(wpa_s); } if (wpa_s->conf->ap_scan == 0) { wpa_supplicant_gen_assoc_event(wpa_s); return; } #ifdef CONFIG_P2P if (wpas_p2p_in_progress(wpa_s)) { if (wpa_s->sta_scan_pending && wpas_p2p_in_progress(wpa_s) == 2 && wpa_s->global->p2p_cb_on_scan_complete) { wpa_dbg(wpa_s, MSG_DEBUG, "Process pending station " "mode scan during P2P search"); } else { wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan " "while P2P operation is in progress"); wpa_s->sta_scan_pending = 1; wpa_supplicant_req_scan(wpa_s, 5, 0); return; } } #endif /* CONFIG_P2P */ if (wpa_s->conf->ap_scan == 2) max_ssids = 1; else { max_ssids = wpa_s->max_scan_ssids; if (max_ssids > WPAS_MAX_SCAN_SSIDS) max_ssids = WPAS_MAX_SCAN_SSIDS; } scan_req = wpa_s->scan_req; wpa_s->scan_req = 0; os_memset(¶ms, 0, sizeof(params)); prev_state = wpa_s->wpa_state; if (wpa_s->wpa_state == WPA_DISCONNECTED || wpa_s->wpa_state == WPA_INACTIVE) wpa_supplicant_set_state(wpa_s, WPA_SCANNING); if (scan_req != 2 && wpa_s->connect_without_scan) { for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { if (ssid == wpa_s->connect_without_scan) break; } wpa_s->connect_without_scan = NULL; if (ssid) { wpa_printf(MSG_DEBUG, "Start a pre-selected network " "without scan step"); wpa_supplicant_associate(wpa_s, NULL, ssid); return; } } /* Find the starting point from which to continue scanning */ ssid = wpa_s->conf->ssid; if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) { while (ssid) { if (ssid == wpa_s->prev_scan_ssid) { ssid = ssid->next; break; } ssid = ssid->next; } } if (scan_req != 2 && 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); return; #ifndef ANDROID } else if (wpa_s->conf->ap_scan == 2) { /* * User-initiated scan request in ap_scan == 2; scan with * wildcard SSID. */ ssid = NULL; #endif } else { struct wpa_ssid *start = ssid, *tssid; int freqs_set = 0; if (ssid == NULL && max_ssids > 1) ssid = wpa_s->conf->ssid; while (ssid) { if (!ssid->disabled && ssid->scan_ssid) { wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", ssid->ssid, ssid->ssid_len); params.ssids[params.num_ssids].ssid = ssid->ssid; params.ssids[params.num_ssids].ssid_len = ssid->ssid_len; params.num_ssids++; if (params.num_ssids + 1 >= max_ssids) break; } ssid = ssid->next; if (ssid == start) break; if (ssid == NULL && max_ssids > 1 && start != wpa_s->conf->ssid) ssid = wpa_s->conf->ssid; } for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { if (tssid->disabled) continue; if ((params.freqs || !freqs_set) && tssid->scan_freq) { int_array_concat(¶ms.freqs, tssid->scan_freq); } else { os_free(params.freqs); params.freqs = NULL; } freqs_set = 1; } int_array_sort_unique(params.freqs); } if (ssid && max_ssids == 1) { /* * If the driver is limited to 1 SSID at a time interleave * wildcard SSID scans with specific SSID scans to avoid * waiting a long time for a wildcard scan. */ if (!wpa_s->prev_scan_wildcard) { params.ssids[0].ssid = NULL; params.ssids[0].ssid_len = 0; wpa_s->prev_scan_wildcard = 1; wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for " "wildcard SSID (Interleave with specific)"); } else { wpa_s->prev_scan_ssid = ssid; wpa_s->prev_scan_wildcard = 0; wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for specific SSID: %s", wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); } } else if (ssid) { /* max_ssids > 1 */ wpa_s->prev_scan_ssid = ssid; wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in " "the scan request"); params.num_ssids++; } else { wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; params.num_ssids++; wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard " "SSID"); } wpa_supplicant_optimize_freqs(wpa_s, ¶ms); extra_ie = wpa_supplicant_extra_ies(wpa_s, ¶ms); #ifdef CONFIG_HS20 if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 6) == 0) wpas_hs20_add_indication(extra_ie); #endif /* CONFIG_HS20 */ if (params.freqs == NULL && wpa_s->next_scan_freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously " "generated frequency list"); params.freqs = wpa_s->next_scan_freqs; } else os_free(wpa_s->next_scan_freqs); wpa_s->next_scan_freqs = NULL; params.filter_ssids = wpa_supplicant_build_filter_ssids( wpa_s->conf, ¶ms.num_filter_ssids); if (extra_ie) { params.extra_ies = wpabuf_head(extra_ie); params.extra_ies_len = wpabuf_len(extra_ie); } #ifdef CONFIG_P2P if (wpa_s->p2p_in_provisioning) { /* * The interface may not yet be in P2P mode, so we have to * explicitly request P2P probe to disable CCK rates. */ params.p2p_probe = 1; } #endif /* CONFIG_P2P */ ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms); wpabuf_free(extra_ie); os_free(params.freqs); os_free(params.filter_ssids); if (ret) { wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan"); 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_supplicant_req_scan(wpa_s, 1, 0); } }
static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, const char *params, char *buf, size_t buflen) { char *pos, *end, tmp[30]; int res, verbose, ret; verbose = os_strcmp(params, "-VERBOSE") == 0; pos = buf; end = buf + buflen; if (wpa_s->wpa_state >= WPA_ASSOCIATED) { struct wpa_ssid *ssid = wpa_s->current_ssid; ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", MAC2STR(wpa_s->bssid)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; if (ssid) { u8 *_ssid = ssid->ssid; size_t ssid_len = ssid->ssid_len; u8 ssid_buf[MAX_SSID_LEN]; if (ssid_len == 0) { int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); if (_res < 0) ssid_len = 0; else ssid_len = _res; _ssid = ssid_buf; } ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", wpa_ssid_txt(_ssid, ssid_len), ssid->id); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; if (ssid->id_str) { ret = os_snprintf(pos, end - pos, "id_str=%s\n", ssid->id_str); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } } pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); } ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", wpa_supplicant_state_txt(wpa_s->wpa_state)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; if (wpa_s->l2 && l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose); if (res >= 0) pos += res; } res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); if (res >= 0) pos += res; return pos - buf; }
/** * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan * @wpa_s: Pointer to wpa_supplicant data * * This function is used to schedule periodic scans for neighboring * access points repeating the scan continuously. */ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) { struct wpa_driver_scan_params params; enum wpa_states prev_state; struct wpa_ssid *ssid; struct wpabuf *wps_ie = NULL; int ret; unsigned int max_sched_scan_ssids; int wildcard = 0; int need_ssids; if (!wpa_s->sched_scan_supported) return -1; if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS) max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS; else max_sched_scan_ssids = wpa_s->max_sched_scan_ssids; if (max_sched_scan_ssids < 1) return -1; if (wpa_s->sched_scanning) { wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning"); return 0; } need_ssids = 0; for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { if (!ssid->disabled && !ssid->scan_ssid) { /* Use wildcard SSID to find this network */ wildcard = 1; } else if (!ssid->disabled && ssid->ssid_len) need_ssids++; } if (wildcard) need_ssids++; if (wpa_s->normal_scans < 3 && (need_ssids <= wpa_s->max_scan_ssids || wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) { /* * When normal scan can speed up operations, use that for the * first operations before starting the sched_scan to allow * user space sleep more. We do this only if the normal scan * has functionality that is suitable for this or if the * sched_scan does not have better support for multiple SSIDs. */ wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of " "sched_scan for initial scans (normal_scans=%d)", wpa_s->normal_scans); return -1; } os_memset(¶ms, 0, sizeof(params)); /* If we can't allocate space for the filters, we just don't filter */ params.filter_ssids = os_zalloc(wpa_s->max_match_sets * sizeof(struct wpa_driver_scan_filter)); prev_state = wpa_s->wpa_state; #ifndef ANDROID_P2P if (wpa_s->wpa_state == WPA_DISCONNECTED || wpa_s->wpa_state == WPA_INACTIVE) wpa_supplicant_set_state(wpa_s, WPA_SCANNING); #endif /* Find the starting point from which to continue scanning */ ssid = wpa_s->conf->ssid; if (wpa_s->prev_sched_ssid) { while (ssid) { if (ssid == wpa_s->prev_sched_ssid) { ssid = ssid->next; break; } ssid = ssid->next; } } if (!ssid || !wpa_s->prev_sched_ssid) { wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list"); wpa_s->sched_scan_interval = 10; wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2; wpa_s->first_sched_scan = 1; ssid = wpa_s->conf->ssid; wpa_s->prev_sched_ssid = ssid; } if (wildcard) { wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan"); params.num_ssids++; } while (ssid) { if (ssid->disabled) goto next; if (params.num_filter_ssids < wpa_s->max_match_sets && params.filter_ssids && ssid->ssid && ssid->ssid_len) { wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s", wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid, ssid->ssid, ssid->ssid_len); params.filter_ssids[params.num_filter_ssids].ssid_len = ssid->ssid_len; params.num_filter_ssids++; } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len) { wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID " "filter for sched_scan - drop filter"); os_free(params.filter_ssids); params.filter_ssids = NULL; params.num_filter_ssids = 0; } if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) { if (params.num_ssids == max_sched_scan_ssids) break; /* only room for broadcast SSID */ wpa_dbg(wpa_s, MSG_DEBUG, "add to active scan ssid: %s", wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); params.ssids[params.num_ssids].ssid = ssid->ssid; params.ssids[params.num_ssids].ssid_len = ssid->ssid_len; params.num_ssids++; if (params.num_ssids >= max_sched_scan_ssids) { wpa_s->prev_sched_ssid = ssid; break; } } next: wpa_s->prev_sched_ssid = ssid; ssid = ssid->next; } if (params.num_filter_ssids == 0) { os_free(params.filter_ssids); params.filter_ssids = NULL; } if (wpa_s->wps) wps_ie = wpa_supplicant_extra_ies(wpa_s, ¶ms); if (ssid || !wpa_s->first_sched_scan) { wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan: interval %d (no timeout)", wpa_s->sched_scan_interval); } else { wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan: interval %d timeout %d", wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout); } ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, wpa_s->sched_scan_interval); wpabuf_free(wps_ie); os_free(params.filter_ssids); if (ret) { wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan"); if (prev_state != wpa_s->wpa_state) wpa_supplicant_set_state(wpa_s, prev_state); return ret; } /* If we have more SSIDs to scan, add a timeout so we scan them too */ if (ssid || !wpa_s->first_sched_scan) { wpa_s->sched_scan_timed_out = 0; eloop_register_timeout(wpa_s->sched_scan_timeout, 0, wpa_supplicant_sched_scan_timeout, wpa_s, NULL); wpa_s->first_sched_scan = 0; wpa_s->sched_scan_timeout /= 2; wpa_s->sched_scan_interval *= 2; } return 0; }
static int wpa_supplicant_ctrl_iface_scan_results( struct wpa_supplicant *wpa_s, char *buf, size_t buflen) { char *pos, *end, *retpos; struct wpa_scan_result *res; int i, ret; if (wpa_s->scan_results == NULL && wpa_supplicant_get_scan_results(wpa_s) < 0) return 0; if (wpa_s->scan_results == NULL) return 0; pos = buf; end = buf + buflen; ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " "flags / ssid\n"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; for (i = 0; i < wpa_s->num_scan_results; i++) { retpos = pos; res = &wpa_s->scan_results[i]; ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", MAC2STR(res->bssid), res->freq, res->level); if (ret < 0 || ret >= end - pos) return retpos - buf; pos += ret; if (res->wpa_ie_len) { pos = wpa_supplicant_ie_txt(pos, end, "WPA", res->wpa_ie, res->wpa_ie_len); } if (res->rsn_ie_len) { pos = wpa_supplicant_ie_txt(pos, end, "WPA2", res->rsn_ie, res->rsn_ie_len); } if (!res->wpa_ie_len && !res->rsn_ie_len && res->caps & IEEE80211_CAP_PRIVACY) { ret = os_snprintf(pos, end - pos, "[WEP]"); if (ret < 0 || ret >= end - pos) return retpos - buf; pos += ret; } if (res->caps & IEEE80211_CAP_IBSS) { ret = os_snprintf(pos, end - pos, "[IBSS]"); if (ret < 0 || ret >= end - pos) return retpos - buf; pos += ret; } if (!res->wpa_ie_len && !res->rsn_ie_len) { ret = os_snprintf(pos, end - pos, "\t"); if (ret < 0 || ret >= end - pos) return retpos - buf; pos += ret; } ret = os_snprintf(pos, end - pos, "\t%s", wpa_ssid_txt(res->ssid, res->ssid_len)); if (ret < 0 || ret >= end - pos) return retpos - buf; pos += ret; ret = os_snprintf(pos, end - pos, "\n"); if (ret < 0 || ret >= end - pos) return retpos - buf; pos += ret; } return pos - buf; }
static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int i, struct wpa_scan_res *bss, struct wpa_ssid *group) { const u8 *ssid_; u8 wpa_ie_len, rsn_ie_len, ssid_len; int wpa; struct wpa_blacklist *e; const u8 *ie; struct wpa_ssid *ssid; ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ssid_ = ie ? ie + 2 : (u8 *) ""; ssid_len = ie ? ie[1] : 0; ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; ie = wpa_scan_get_ie(bss, WLAN_EID_RSN); rsn_ie_len = ie ? ie[1] : 0; wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s", i, MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len), wpa_ie_len, rsn_ie_len, bss->caps, bss->level, wpa_scan_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : ""); e = wpa_blacklist_get(wpa_s, bss->bssid); if (e && e->count > 1) { wpa_printf(MSG_DEBUG, " skip - blacklisted"); return 0; } if (ssid_len == 0) { wpa_printf(MSG_DEBUG, " skip - SSID not known"); return 0; } wpa = wpa_ie_len > 0 || rsn_ie_len > 0; for (ssid = group; ssid; ssid = ssid->pnext) { int check_ssid = wpa ? 1 : (ssid->ssid_len != 0); if (ssid->disabled) { wpa_printf(MSG_DEBUG, " skip - disabled"); continue; } #ifdef CONFIG_WPS if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { wpa_printf(MSG_DEBUG, " skip - blacklisted (WPS)"); continue; } if (wpa && ssid->ssid_len == 0 && wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) check_ssid = 0; if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { /* Only allow wildcard SSID match if an AP * advertises active WPS operation that matches * with our mode. */ check_ssid = 1; if (ssid->ssid_len == 0 && wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) check_ssid = 0; } #endif /* CONFIG_WPS */ if (check_ssid && (ssid_len != ssid->ssid_len || os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) { wpa_printf(MSG_DEBUG, " skip - SSID mismatch"); continue; } if (ssid->bssid_set && os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, " skip - BSSID mismatch"); continue; } if (wpa && !wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) continue; if (!wpa && !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { wpa_printf(MSG_DEBUG, " skip - non-WPA network not " "allowed"); continue; } if (!wpa && !wpa_supplicant_match_privacy(bss, ssid)) { wpa_printf(MSG_DEBUG, " skip - privacy mismatch"); continue; } if (!wpa && (bss->caps & IEEE80211_CAP_IBSS)) { wpa_printf(MSG_DEBUG, " skip - IBSS (adhoc) " "network"); continue; } if (!freq_allowed(ssid->freq_list, bss->freq)) { wpa_printf(MSG_DEBUG, " skip - frequency not " "allowed"); continue; } #ifdef CONFIG_P2P /* * TODO: skip the AP if its P2P IE has Group Formation * bit set in the P2P Group Capability Bitmap and we * are not in Group Formation with that device. */ #endif /* CONFIG_P2P */ /* Matching configuration found */ return ssid; } /* No matching configuration found */ return 0; }