#include "common/wpa_ctrl.h"
#include "common/ieee802_11_defs.h"
#include "common/hw_features_common.h"
+#include "common/gas_server.h"
#include "p2p/p2p.h"
#include "fst/fst.h"
#include "blacklist.h"
#include "wnm_sta.h"
#include "wpas_kay.h"
#include "mesh.h"
+#include "dpp_supplicant.h"
+#ifdef CONFIG_MESH
+#include "ap/ap_config.h"
+#include "ap/hostapd.h"
+#endif /* CONFIG_MESH */
const char *const wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
"\n";
#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
+
+
/* Configure default/group WEP keys for static WEP */
int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
dl_list_del(&bss->list);
os_free(bss);
}
wpa_s->l2_test = NULL;
os_free(wpa_s->get_pref_freq_list_override);
wpa_s->get_pref_freq_list_override = NULL;
+ wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
+ wpa_s->last_assoc_req_wpa_ie = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->conf != NULL) {
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = NULL;
os_free(wpa_s->manual_sched_scan_freqs);
wpa_s->manual_sched_scan_freqs = NULL;
radio_remove_works(wpa_s, "gas-query", 0);
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
+ gas_server_deinit(wpa_s->gas_server);
+ wpa_s->gas_server = NULL;
free_hw_features(wpa_s);
wpabuf_free(wpa_s->ric_ies);
wpa_s->ric_ies = NULL;
+
+#ifdef CONFIG_DPP
+ wpas_dpp_deinit(wpa_s);
+#endif /* CONFIG_DPP */
}
if (state == WPA_COMPLETED && wpa_s->new_connection) {
struct wpa_ssid *ssid = wpa_s->current_ssid;
+ int fils_hlp_sent = 0;
+
+#ifdef CONFIG_SME
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_auth_alg_fils(wpa_s->sme.auth_alg))
+ fils_hlp_sent = 1;
+#endif /* CONFIG_SME */
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_auth_alg_fils(wpa_s->auth_alg))
+ fils_hlp_sent = 1;
+
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
- MACSTR " completed [id=%d id_str=%s]",
+ MACSTR " completed [id=%d id_str=%s%s]",
MAC2STR(wpa_s->bssid),
ssid ? ssid->id : -1,
- ssid && ssid->id_str ? ssid->id_str : "");
+ ssid && ssid->id_str ? ssid->id_str : "",
+ fils_hlp_sent ? " FILS_HLP_SENT" : "");
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
wpas_clear_temp_disabled(wpa_s, ssid, 1);
wpa_blacklist_clear(wpa_s);
wpas_p2p_completed(wpa_s);
sme_sched_obss_scan(wpa_s, 1);
+
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+ if (!fils_hlp_sent && ssid && ssid->eap.erp)
+ wpas_update_fils_connect_params(wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
state == WPA_ASSOCIATED) {
wpa_s->new_connection = 1;
* TODO: should notify EAPOL SM about changes in opensc_engine_path,
* pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
*/
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
/*
* Clear forced success to clear EAP state for next
* authentication.
ie.pairwise_cipher = ssid->pairwise_cipher;
ie.key_mgmt = ssid->key_mgmt;
#ifdef CONFIG_IEEE80211W
- ie.mgmt_group_cipher =
- ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
- WPA_CIPHER_AES_128_CMAC : 0;
+ ie.mgmt_group_cipher = 0;
+ if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_GMAC_256)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_GMAC_256;
+ else if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_CMAC_256)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_CMAC_256;
+ else if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_GMAC_128)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_GMAC_128;
+ else
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_AES_128_CMAC;
+ }
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+ !ssid->owe_only &&
+ !bss_wpa && !bss_rsn && !bss_osen) {
+ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
+ wpa_s->wpa_proto = 0;
+ return 0;
+ }
+#endif /* CONFIG_OWE */
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
"based on configuration");
} else
wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_OWE
+ } else if (sel & WPA_KEY_MGMT_OWE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ } else if (sel & WPA_KEY_MGMT_DPP) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
+#endif /* CONFIG_DPP */
} else {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
"authenticated key management type");
#ifdef CONFIG_IEEE80211W
sel = ie.mgmt_group_cipher;
+ if (ssid->group_mgmt_cipher)
+ sel &= ssid->group_mgmt_cipher;
if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
!(ie.capabilities & WPA_CAPABILITY_MFPC))
sel = 0;
NULL);
psk_set = 1;
}
+
+ if (wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password)
+ psk_set = 1;
+
#ifndef CONFIG_NO_PBKDF2
if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
ssid->passphrase) {
"No PSK available for association");
return -1;
}
+#ifdef CONFIG_OWE
+ } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
+ /* OWE Diffie-Hellman exchange in (Re)Association
+ * Request/Response frames set the PMK, so do not override it
+ * here. */
+#endif /* CONFIG_OWE */
} else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
break;
case 9: /* Bits 72-79 */
#ifdef CONFIG_FILS
- *pos |= 0x01;
+ if (!wpa_s->disable_fils)
+ *pos |= 0x01;
#endif /* CONFIG_FILS */
break;
}
wmm_ac_clear_saved_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 0;
wpa_s->reassoc_same_ess = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+ wpa_s->testing_resend_assoc = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
ssid->id);
+ wpas_notify_mesh_group_started(wpa_s, ssid);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
return;
}
+ /*
+ * Set WPA state machine configuration to match the selected network now
+ * so that the information is available before wpas_start_assoc_cb()
+ * gets called. This is needed at least for RSN pre-authentication where
+ * candidate APs are added to a list based on scan result processing
+ * before completion of the first association.
+ */
+ wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
+
+#ifdef CONFIG_DPP
+ if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
+ return;
+#endif /* CONFIG_DPP */
+
#ifdef CONFIG_TDLS
if (bss)
wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
}
-static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+#ifdef CONFIG_FILS
+static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
+ size_t ie_buf_len)
{
- struct wpa_connect_work *cwork = work->ctx;
- struct wpa_bss *bss = cwork->bss;
- struct wpa_ssid *ssid = cwork->ssid;
- struct wpa_supplicant *wpa_s = work->wpa_s;
- u8 wpa_ie[200];
- size_t wpa_ie_len;
- int use_crypt, ret, i, bssid_changed;
- int algs = WPA_AUTH_ALG_OPEN;
- unsigned int cipher_pairwise, cipher_group;
- struct wpa_driver_associate_params params;
- int wep_keys_set = 0;
- int assoc_failed = 0;
- struct wpa_ssid *old_ssid;
- u8 prev_bssid[ETH_ALEN];
-#ifdef CONFIG_HT_OVERRIDES
- struct ieee80211_ht_capabilities htcaps;
- struct ieee80211_ht_capabilities htcaps_mask;
-#endif /* CONFIG_HT_OVERRIDES */
-#ifdef CONFIG_VHT_OVERRIDES
- struct ieee80211_vht_capabilities vhtcaps;
- struct ieee80211_vht_capabilities vhtcaps_mask;
-#endif /* CONFIG_VHT_OVERRIDES */
-
- if (deinit) {
- if (work->started) {
- wpa_s->connect_work = NULL;
-
- /* cancel possible auth. timeout */
- eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
- NULL);
+ struct fils_hlp_req *req;
+ size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
+ const u8 *pos;
+ u8 *buf = ie_buf;
+
+ dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list) {
+ rem_len = ie_buf_len - ie_len;
+ pos = wpabuf_head(req->pkt);
+ hdr_len = 1 + 2 * ETH_ALEN + 6;
+ hlp_len = wpabuf_len(req->pkt);
+
+ if (rem_len < 2 + hdr_len + hlp_len) {
+ wpa_printf(MSG_ERROR,
+ "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
+ (unsigned long) rem_len,
+ (unsigned long) (2 + hdr_len + hlp_len));
+ break;
}
- wpas_connect_work_free(cwork);
- return;
- }
-
- wpa_s->connect_work = work;
- if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
- wpas_network_disabled(wpa_s, ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
- wpas_connect_work_done(wpa_s);
- return;
- }
-
- os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
- os_memset(¶ms, 0, sizeof(params));
- wpa_s->reassociate = 0;
- wpa_s->eap_expected_failure = 0;
- if (bss &&
- (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
-#ifdef CONFIG_IEEE80211R
- const u8 *ie, *md = NULL;
-#endif /* CONFIG_IEEE80211R */
- wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
- " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
- wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
- 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);
-#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);
+ len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
+ /* Element ID */
+ *buf++ = WLAN_EID_EXTENSION;
+ /* Length */
+ *buf++ = len;
+ /* Element ID Extension */
+ *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
+ /* Destination MAC address */
+ os_memcpy(buf, req->dst, ETH_ALEN);
+ buf += ETH_ALEN;
+ /* Source MAC address */
+ os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
+ buf += ETH_ALEN;
+ /* LLC/SNAP Header */
+ os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
+ buf += 6;
+ /* HLP Packet */
+ os_memcpy(buf, pos, len - hdr_len);
+ buf += len - hdr_len;
+ pos += len - hdr_len;
+
+ hlp_len -= len - hdr_len;
+ ie_len += 2 + len;
+ rem_len -= 2 + len;
+
+ while (hlp_len) {
+ len = (hlp_len > 255) ? 255 : hlp_len;
+ if (rem_len < 2 + len)
+ break;
+ *buf++ = WLAN_EID_FRAGMENT;
+ *buf++ = len;
+ os_memcpy(buf, pos, len);
+ buf += len;
+ pos += len;
+
+ hlp_len -= len;
+ ie_len += 2 + len;
+ rem_len -= 2 + len;
}
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_WPS
- } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
- wpa_s->conf->ap_scan == 2 &&
- (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
- /* Use ap_scan==1 style network selection to find the network
- */
- wpas_connect_work_done(wpa_s);
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- return;
-#endif /* CONFIG_WPS */
- } else {
- wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- if (bss)
- os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
- else
- os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
}
- if (!wpa_s->pno)
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_cancel_scan(wpa_s);
+ return ie_len;
+}
+#endif /* CONFIG_FILS */
- /* Starting new association, so clear the possibly used WPA IE from the
- * previous association. */
- wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
-#ifdef IEEE8021X_EAPOL
- if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
- if (ssid->leap) {
- if (ssid->non_leap == 0)
- algs = WPA_AUTH_ALG_LEAP;
- else
- algs |= WPA_AUTH_ALG_LEAP;
- }
+static u8 * wpas_populate_assoc_ies(
+ struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, struct wpa_ssid *ssid,
+ struct wpa_driver_associate_params *params,
+ enum wpa_drv_update_connect_params_mask *mask)
+{
+ u8 *wpa_ie;
+ size_t max_wpa_ie_len = 500;
+ size_t wpa_ie_len;
+ int algs = WPA_AUTH_ALG_OPEN;
+#ifdef CONFIG_FILS
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+ struct fils_hlp_req *req;
+
+ dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list) {
+ max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
+ 2 + 2 * wpabuf_len(req->pkt) / 255;
}
-#endif /* IEEE8021X_EAPOL */
- wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
- if (ssid->auth_alg) {
- algs = ssid->auth_alg;
- wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
- "0x%x", algs);
+#endif /* CONFIG_FILS */
+
+ wpa_ie = os_malloc(max_wpa_ie_len);
+ if (!wpa_ie) {
+ wpa_printf(MSG_ERROR,
+ "Failed to allocate connect IE buffer for %lu bytes",
+ (unsigned long) max_wpa_ie_len);
+ return NULL;
}
if (bss && (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;
+ const u8 *cache_id = NULL;
+
try_opportunistic = (ssid->proactive_key_caching < 0 ?
wpa_s->conf->okc :
ssid->proactive_key_caching) &&
(ssid->proto & WPA_PROTO_RSN);
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(ssid->key_mgmt))
+ cache_id = wpa_bss_get_fils_cache_id(bss);
+#endif /* CONFIG_FILS */
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
- ssid, try_opportunistic, NULL) == 0)
+ ssid, try_opportunistic,
+ cache_id) == 0)
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
- wpa_ie_len = sizeof(wpa_ie);
+ wpa_ie_len = max_wpa_ie_len;
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
"key management and encryption suites");
- wpas_connect_work_done(wpa_s);
- return;
+ os_free(wpa_ie);
+ return NULL;
}
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
wpa_ie_len = 0;
wpa_s->wpa_proto = 0;
} else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
- wpa_ie_len = sizeof(wpa_ie);
+ wpa_ie_len = max_wpa_ie_len;
if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
"key management and encryption suites (no "
"scan results)");
- wpas_connect_work_done(wpa_s);
- return;
+ os_free(wpa_ie);
+ return NULL;
}
#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_ie)) {
+ if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
wpa_ie_len = wpabuf_len(wps_ie);
os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
} else
wpabuf_free(wps_ie);
wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
- params.wps = WPS_MODE_PRIVACY;
+ params->wps = WPS_MODE_PRIVACY;
else
- params.wps = WPS_MODE_OPEN;
+ params->wps = WPS_MODE_OPEN;
wpa_s->wpa_proto = 0;
#endif /* CONFIG_WPS */
} else {
wpa_s->wpa_proto = 0;
}
+#ifdef IEEE8021X_EAPOL
+ if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+ if (ssid->leap) {
+ if (ssid->non_leap == 0)
+ algs = WPA_AUTH_ALG_LEAP;
+ else
+ algs |= WPA_AUTH_ALG_LEAP;
+ }
+ }
+
+#ifdef CONFIG_FILS
+ /* Clear FILS association */
+ wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
+
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
+ ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
+ eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
+ &username_len, &realm, &realm_len,
+ &next_seq_num, &rrk, &rrk_len) == 0) {
+ algs = WPA_AUTH_ALG_FILS;
+ params->fils_erp_username = username;
+ params->fils_erp_username_len = username_len;
+ params->fils_erp_realm = realm;
+ params->fils_erp_realm_len = realm_len;
+ params->fils_erp_next_seq_num = next_seq_num;
+ params->fils_erp_rrk = rrk;
+ params->fils_erp_rrk_len = rrk_len;
+
+ if (mask)
+ *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
+ }
+#endif /* CONFIG_FILS */
+#endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_SAE
+ if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
+ algs = WPA_AUTH_ALG_SAE;
+#endif /* CONFIG_SAE */
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
+ if (ssid->auth_alg) {
+ algs = ssid->auth_alg;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Overriding auth_alg selection: 0x%x", algs);
+ }
+
#ifdef CONFIG_P2P
if (wpa_s->global->p2p) {
u8 *pos;
size_t len;
int res;
pos = wpa_ie + wpa_ie_len;
- len = sizeof(wpa_ie) - wpa_ie_len;
+ len = max_wpa_ie_len - wpa_ie_len;
res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
ssid->p2p_group);
if (res >= 0)
if (bss) {
wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
wpa_ie + wpa_ie_len,
- sizeof(wpa_ie) -
+ max_wpa_ie_len -
wpa_ie_len);
}
int ext_capab_len;
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab));
- if (ext_capab_len > 0) {
+ if (ext_capab_len > 0 &&
+ wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
u8 *pos = wpa_ie;
if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
pos += 2 + pos[1];
size_t len;
wpas_hs20_add_indication(hs20, pps_mo_id);
- len = sizeof(wpa_ie) - wpa_ie_len;
+ len = max_wpa_ie_len - wpa_ie_len;
if (wpabuf_len(hs20) <= len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(hs20), wpabuf_len(hs20));
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
- len = sizeof(wpa_ie) - wpa_ie_len;
+ len = max_wpa_ie_len - wpa_ie_len;
if (wpabuf_len(buf) <= len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(buf), wpabuf_len(buf));
if (wpa_s->fst_ies) {
int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
- if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
+ if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(wpa_s->fst_ies), fst_ies_len);
wpa_ie_len += fst_ies_len;
int len;
len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
- sizeof(wpa_ie) - wpa_ie_len);
+ max_wpa_ie_len - wpa_ie_len);
if (len >= 0)
wpa_ie_len += len;
}
#endif /* CONFIG_MBO */
+#ifdef CONFIG_FILS
+ if (algs == WPA_AUTH_ALG_FILS) {
+ size_t len;
+
+ len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
+ max_wpa_ie_len - wpa_ie_len);
+ wpa_ie_len += len;
+ }
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+#ifdef CONFIG_TESTING_OPTIONS
+ if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
+ wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (algs == WPA_AUTH_ALG_OPEN &&
+ ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
+ struct wpabuf *owe_ie;
+ u16 group;
+
+ if (ssid->owe_group) {
+ group = ssid->owe_group;
+ } else {
+ if (wpa_s->last_owe_group == 19)
+ group = 20;
+ else if (wpa_s->last_owe_group == 20)
+ group = 21;
+ else
+ group = OWE_DH_GROUP;
+ }
+ wpa_s->last_owe_group = group;
+ wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
+ owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
+ if (owe_ie &&
+ wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(owe_ie), wpabuf_len(owe_ie));
+ wpa_ie_len += wpabuf_len(owe_ie);
+ wpabuf_free(owe_ie);
+ }
+ }
+#endif /* CONFIG_OWE */
+
+ params->wpa_ie = wpa_ie;
+ params->wpa_ie_len = wpa_ie_len;
+ params->auth_alg = algs;
+ if (mask)
+ *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
+
+ return wpa_ie;
+}
+
+
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_driver_associate_params params;
+ enum wpa_drv_update_connect_params_mask mask = 0;
+ u8 *wpa_ie;
+
+ if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
+ return; /* nothing to do */
+
+ os_memset(¶ms, 0, sizeof(params));
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, ¶ms, &mask);
+ if (!wpa_ie)
+ return;
+
+ if (params.auth_alg != WPA_AUTH_ALG_FILS) {
+ os_free(wpa_ie);
+ return;
+ }
+
+ wpa_s->auth_alg = params.auth_alg;
+ wpa_drv_update_connect_params(wpa_s, ¶ms, mask);
+ os_free(wpa_ie);
+}
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
+
+
+static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_connect_work *cwork = work->ctx;
+ struct wpa_bss *bss = cwork->bss;
+ struct wpa_ssid *ssid = cwork->ssid;
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ u8 *wpa_ie;
+ int use_crypt, ret, i, bssid_changed;
+ unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
+ struct wpa_driver_associate_params params;
+ int wep_keys_set = 0;
+ int assoc_failed = 0;
+ struct wpa_ssid *old_ssid;
+ u8 prev_bssid[ETH_ALEN];
+#ifdef CONFIG_HT_OVERRIDES
+ struct ieee80211_ht_capabilities htcaps;
+ struct ieee80211_ht_capabilities htcaps_mask;
+#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ struct ieee80211_vht_capabilities vhtcaps;
+ struct ieee80211_vht_capabilities vhtcaps_mask;
+#endif /* CONFIG_VHT_OVERRIDES */
+
+ if (deinit) {
+ if (work->started) {
+ wpa_s->connect_work = NULL;
+
+ /* cancel possible auth. timeout */
+ eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
+ NULL);
+ }
+ wpas_connect_work_free(cwork);
+ return;
+ }
+
+ wpa_s->connect_work = work;
+
+ if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
+ wpas_network_disabled(wpa_s, ssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
+ os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
+ os_memset(¶ms, 0, sizeof(params));
+ wpa_s->reassociate = 0;
+ wpa_s->eap_expected_failure = 0;
+ if (bss &&
+ (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
+#ifdef CONFIG_IEEE80211R
+ const u8 *ie, *md = NULL;
+#endif /* CONFIG_IEEE80211R */
+ wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
+ " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
+ wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
+ 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);
+#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);
+ }
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_WPS
+ } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
+ wpa_s->conf->ap_scan == 2 &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
+ /* Use ap_scan==1 style network selection to find the network
+ */
+ wpas_connect_work_done(wpa_s);
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ return;
+#endif /* CONFIG_WPS */
+ } else {
+ wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+ if (bss)
+ os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+ else
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ }
+ if (!wpa_s->pno)
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+
+ wpa_supplicant_cancel_scan(wpa_s);
+
+ /* Starting new association, so clear the possibly used WPA IE from the
+ * previous association. */
+ wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, ¶ms, NULL);
+ if (!wpa_ie) {
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
cipher_group = wpa_s->group_cipher;
+ cipher_group_mgmt = wpa_s->mgmt_group_cipher;
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
params.freq_hint = bss->freq;
params.pbss = bss_is_pbss(bss);
} else {
+ if (ssid->bssid_hint_set)
+ params.bssid_hint = ssid->bssid_hint;
+
params.ssid = ssid->ssid;
params.ssid_len = ssid->ssid_len;
params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
params.beacon_int = wpa_s->conf->beacon_int;
}
- params.wpa_ie = wpa_ie;
- params.wpa_ie_len = wpa_ie_len;
params.pairwise_suite = cipher_pairwise;
params.group_suite = cipher_group;
+ params.mgmt_group_suite = cipher_group_mgmt;
params.key_mgmt_suite = wpa_s->key_mgmt;
params.wpa_proto = wpa_s->wpa_proto;
- params.auth_alg = algs;
+ wpa_s->auth_alg = params.auth_alg;
params.mode = ssid->mode;
params.bg_scan_period = ssid->bg_scan_period;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (wpas_p2p_handle_frequency_conflicts(
wpa_s, params.freq.freq, ssid) < 0) {
wpas_connect_work_done(wpa_s);
+ os_free(wpa_ie);
return;
}
}
params.prev_bssid = prev_bssid;
ret = wpa_drv_associate(wpa_s, ¶ms);
+ os_free(wpa_ie);
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
"failed");
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
+ struct mesh_conf *mconf;
+
+ mconf = wpa_s->ifmsh->mconf;
wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
wpa_s->ifname);
+ wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
+ mconf->meshid_len, reason_code);
wpa_supplicant_leave_mesh(wpa_s);
}
#endif /* CONFIG_MESH */
wpas_notify_network_enabled_changed(
wpa_s, other_ssid);
}
- if (wpa_s->current_ssid)
+ if (wpa_s->current_ssid) {
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
} else if (ssid->disabled != 2) {
- if (ssid == wpa_s->current_ssid)
+ if (ssid == wpa_s->current_ssid) {
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
was_disabled = ssid->disabled;
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
+ wpa_s->last_owe_group = 0;
if (wpa_s->connect_without_scan ||
wpa_supplicant_fast_associate(wpa_s) != 1) {
}
+#ifdef CONFIG_OWE
+static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *entry_ssid, size_t entry_ssid_len)
+{
+ const u8 *owe, *pos, *end;
+ u8 ssid_len;
+ struct wpa_bss *bss;
+
+ /* Check network profile SSID aganst the SSID in the
+ * OWE Transition Mode element. */
+
+ bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+ if (!bss)
+ return 0;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe)
+ return 0;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return 0;
+ pos += ETH_ALEN;
+ ssid_len = *pos++;
+ if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ return 0;
+
+ return entry_ssid_len == ssid_len &&
+ os_memcmp(pos, entry_ssid, ssid_len) == 0;
+}
+#endif /* CONFIG_OWE */
+
+
/**
* wpa_supplicant_get_ssid - Get a pointer to the current network structure
* @wpa_s: Pointer to wpa_supplicant data
return entry;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if (!wpas_network_disabled(wpa_s, entry) &&
+ owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
+ entry->ssid_len) &&
+ (!entry->bssid_set ||
+ os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+ return entry;
+#endif /* CONFIG_OWE */
+
if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
entry->ssid_len == 0 &&
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
}
#endif /* CONFIG_TESTING_OPTIONS */
-#ifdef CONFIG_PEERKEY
- if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
- wpa_s->current_ssid->peerkey &&
- !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
- wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
- wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
- return;
- }
-#endif /* CONFIG_PEERKEY */
-
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
(wpa_s->last_eapol_matches_bssid &&
#ifdef CONFIG_AP
os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
return;
wpa_drv_poll(wpa_s);
if (work->started) {
work->wpa_s->radio->num_active_works--;
wpa_dbg(work->wpa_s, MSG_DEBUG,
- "radio_work_free('%s'@%p: num_active_works --> %u",
+ "radio_work_free('%s'@%p): num_active_works --> %u",
work->type, work,
work->wpa_s->radio->num_active_works);
}
}
+#ifdef CONFIG_GAS_SERVER
+
+static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result)
+{
+ wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
+ " result=%s",
+ freq, MAC2STR(dst),
+ result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
+ (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
+ "FAILED"));
+ gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
+ result == OFFCHANNEL_SEND_ACTION_SUCCESS);
+}
+
+
+static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
+ struct wpabuf *buf, unsigned int wait_time)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ if (wait_time > wpa_s->max_remain_on_chan)
+ wait_time = wpa_s->max_remain_on_chan;
+
+ offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
+ wpabuf_head(buf), wpabuf_len(buf),
+ wait_time, wpas_gas_server_tx_status, 0);
+}
+
+#endif /* CONFIG_GAS_SERVER */
+
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
struct wpa_interface *iface)
{
struct wpa_driver_capa capa;
int capa_res;
+ u8 dfs_domain;
wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
"'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
&wpa_s->hw.num_modes,
- &wpa_s->hw.flags);
+ &wpa_s->hw.flags,
+ &dfs_domain);
if (wpa_s->hw.modes) {
u16 i;
if (wpas_wps_init(wpa_s))
return -1;
+#ifdef CONFIG_GAS_SERVER
+ wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
+ if (!wpa_s->gas_server) {
+ wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
+ return -1;
+ }
+#endif /* CONFIG_GAS_SERVER */
+
+#ifdef CONFIG_DPP
+ if (wpas_dpp_init(wpa_s) < 0)
+ return -1;
+#endif /* CONFIG_DPP */
+
if (wpa_supplicant_init_eapol(wpa_s) < 0)
return -1;
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
#ifdef CONFIG_EAP_PROXY
{
size_t len;
- wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
- &len);
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
+ wpa_s->imsi, &len);
if (wpa_s->mnc_len > 0) {
wpa_s->imsi[len] = '\0';
wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
hs20_init(wpa_s);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
+ if (wpa_s->conf->oce) {
+ if ((wpa_s->conf->oce & OCE_STA) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
+ wpa_s->enable_oce = OCE_STA;
+ if ((wpa_s->conf->oce & OCE_STA_CFON) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
+ /* TODO: Need to add STA-CFON support */
+ wpa_printf(MSG_ERROR,
+ "OCE STA-CFON feature is not yet supported");
+ }
+ }
wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
#endif /* CONFIG_MBO */
if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
+ struct wpa_driver_capa capa;
+ int res = wpa_drv_get_capa(wpa_s, &capa);
+
+ if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
+ wpa_printf(MSG_ERROR,
+ "Failed to update wowlan_triggers to '%s'",
+ wpa_s->conf->wowlan_triggers);
+ }
+
#ifdef CONFIG_WPS
wpas_wps_update_config(wpa_s);
#endif /* CONFIG_WPS */
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
(!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
+ !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
!ssid->mem_only_psk)
return 1;
wpa_s->extra_blacklist_count = 0;
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
+ wpa_s->last_owe_group = 0;
if (wpa_supplicant_fast_associate(wpa_s) != 1)
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
+static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss_tmp_disallowed *tmp;
+ unsigned int num_bssid = 0;
+ u8 *bssids;
+ int ret;
+
+ bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
+ if (!bssids)
+ return -1;
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
+ ETH_ALEN);
+ num_bssid++;
+ }
+ ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
+ os_free(bssids);
+ return ret;
+}
+
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
+
+ /* Make sure the bss is not already freed */
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (bss == tmp) {
+ dl_list_del(&tmp->list);
+ os_free(tmp);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+ break;
+ }
+ }
+}
+
+
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
unsigned int sec)
{
struct wpa_bss_tmp_disallowed *bss;
- struct os_reltime until;
-
- os_get_reltime(&until);
- until.sec += sec;
bss = wpas_get_disallowed_bss(wpa_s, bssid);
if (bss) {
- bss->disallowed_until = until;
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
+ eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
+ wpa_s, bss);
return;
}
return;
}
- bss->disallowed_until = until;
os_memcpy(bss->bssid, bssid, ETH_ALEN);
dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+ eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
+ wpa_s, bss);
}
int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
- struct os_reltime now, age;
-
- os_get_reltime(&now);
dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
- if (!os_reltime_before(&now, &tmp->disallowed_until)) {
- /* This BSS is not disallowed anymore */
- dl_list_del(&tmp->list);
- os_free(tmp);
- continue;
- }
if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
bss = tmp;
break;
if (!bss)
return 0;
- os_reltime_sub(&bss->disallowed_until, &now, &age);
- wpa_printf(MSG_DEBUG,
- "BSS " MACSTR " disabled for %ld.%0ld seconds",
- MAC2STR(bss->bssid), age.sec, age.usec);
return 1;
}