3 * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "utils/eloop.h"
13 #include "common/ieee802_11_defs.h"
14 #include "common/ieee802_11_common.h"
15 #include "common/ocv.h"
16 #include "eapol_supp/eapol_supp_sm.h"
17 #include "common/wpa_common.h"
18 #include "common/sae.h"
19 #include "rsn_supp/wpa.h"
20 #include "rsn_supp/pmksa_cache.h"
22 #include "wpa_supplicant_i.h"
24 #include "wpas_glue.h"
25 #include "wps_supplicant.h"
26 #include "p2p_supplicant.h"
31 #include "hs20_supplicant.h"
33 #define SME_AUTH_TIMEOUT 5
34 #define SME_ASSOC_TIMEOUT 5
36 static void sme_auth_timer(void *eloop_ctx
, void *timeout_ctx
);
37 static void sme_assoc_timer(void *eloop_ctx
, void *timeout_ctx
);
38 static void sme_obss_scan_timeout(void *eloop_ctx
, void *timeout_ctx
);
39 #ifdef CONFIG_IEEE80211W
40 static void sme_stop_sa_query(struct wpa_supplicant
*wpa_s
);
41 #endif /* CONFIG_IEEE80211W */
46 static int index_within_array(const int *array
, int idx
)
49 for (i
= 0; i
< idx
; i
++) {
57 static int sme_set_sae_group(struct wpa_supplicant
*wpa_s
)
59 int *groups
= wpa_s
->conf
->sae_groups
;
60 int default_groups
[] = { 19, 20, 21, 0 };
62 if (!groups
|| groups
[0] <= 0)
63 groups
= default_groups
;
65 /* Configuration may have changed, so validate current index */
66 if (!index_within_array(groups
, wpa_s
->sme
.sae_group_index
))
70 int group
= groups
[wpa_s
->sme
.sae_group_index
];
73 if (sae_set_group(&wpa_s
->sme
.sae
, group
) == 0) {
74 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Selected SAE group %d",
75 wpa_s
->sme
.sae
.group
);
78 wpa_s
->sme
.sae_group_index
++;
85 static struct wpabuf
* sme_auth_build_sae_commit(struct wpa_supplicant
*wpa_s
,
86 struct wpa_ssid
*ssid
,
87 const u8
*bssid
, int external
,
94 #ifdef CONFIG_TESTING_OPTIONS
95 if (wpa_s
->sae_commit_override
) {
96 wpa_printf(MSG_DEBUG
, "SAE: TESTING - commit override");
97 buf
= wpabuf_alloc(4 + wpabuf_len(wpa_s
->sae_commit_override
));
100 wpabuf_put_le16(buf
, 1); /* Transaction seq# */
101 wpabuf_put_le16(buf
, WLAN_STATUS_SUCCESS
);
102 wpabuf_put_buf(buf
, wpa_s
->sae_commit_override
);
105 #endif /* CONFIG_TESTING_OPTIONS */
107 password
= ssid
->sae_password
;
109 password
= ssid
->passphrase
;
111 wpa_printf(MSG_DEBUG
, "SAE: No password available");
115 if (reuse
&& wpa_s
->sme
.sae
.tmp
&&
116 os_memcmp(bssid
, wpa_s
->sme
.sae
.tmp
->bssid
, ETH_ALEN
) == 0) {
117 wpa_printf(MSG_DEBUG
,
118 "SAE: Reuse previously generated PWE on a retry with the same AP");
121 if (sme_set_sae_group(wpa_s
) < 0) {
122 wpa_printf(MSG_DEBUG
, "SAE: Failed to select group");
126 if (sae_prepare_commit(wpa_s
->own_addr
, bssid
,
127 (u8
*) password
, os_strlen(password
),
128 ssid
->sae_password_id
,
129 &wpa_s
->sme
.sae
) < 0) {
130 wpa_printf(MSG_DEBUG
, "SAE: Could not pick PWE");
133 if (wpa_s
->sme
.sae
.tmp
)
134 os_memcpy(wpa_s
->sme
.sae
.tmp
->bssid
, bssid
, ETH_ALEN
);
137 len
= wpa_s
->sme
.sae_token
? wpabuf_len(wpa_s
->sme
.sae_token
) : 0;
138 if (ssid
->sae_password_id
)
139 len
+= 4 + os_strlen(ssid
->sae_password_id
);
140 buf
= wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN
+ len
);
144 wpabuf_put_le16(buf
, 1); /* Transaction seq# */
145 wpabuf_put_le16(buf
, WLAN_STATUS_SUCCESS
);
147 sae_write_commit(&wpa_s
->sme
.sae
, buf
, wpa_s
->sme
.sae_token
,
148 ssid
->sae_password_id
);
154 static struct wpabuf
* sme_auth_build_sae_confirm(struct wpa_supplicant
*wpa_s
,
159 buf
= wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN
);
164 wpabuf_put_le16(buf
, 2); /* Transaction seq# */
165 wpabuf_put_le16(buf
, WLAN_STATUS_SUCCESS
);
167 sae_write_confirm(&wpa_s
->sme
.sae
, buf
);
172 #endif /* CONFIG_SAE */
176 * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
177 * @wpa_s: Pointer to wpa_supplicant data
178 * @bss: Pointer to the bss which is the target of authentication attempt
180 static void sme_auth_handle_rrm(struct wpa_supplicant
*wpa_s
,
183 const u8 rrm_ie_len
= 5;
187 wpa_s
->rrm
.rrm_used
= 0;
189 wpa_printf(MSG_DEBUG
,
190 "RRM: Determining whether RRM can be used - device support: 0x%x",
191 wpa_s
->drv_rrm_flags
);
193 rrm_ie
= wpa_bss_get_ie(bss
, WLAN_EID_RRM_ENABLED_CAPABILITIES
);
194 if (!rrm_ie
|| !(bss
->caps
& IEEE80211_CAP_RRM
)) {
195 wpa_printf(MSG_DEBUG
, "RRM: No RRM in network");
199 if (!((wpa_s
->drv_rrm_flags
&
200 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES
) &&
201 (wpa_s
->drv_rrm_flags
& WPA_DRIVER_FLAGS_QUIET
)) &&
202 !(wpa_s
->drv_rrm_flags
& WPA_DRIVER_FLAGS_SUPPORT_RRM
)) {
203 wpa_printf(MSG_DEBUG
,
204 "RRM: Insufficient RRM support in driver - do not use RRM");
208 if (sizeof(wpa_s
->sme
.assoc_req_ie
) <
209 wpa_s
->sme
.assoc_req_ie_len
+ rrm_ie_len
+ 2) {
211 "RRM: Unable to use RRM, no room for RRM IE");
215 wpa_printf(MSG_DEBUG
, "RRM: Adding RRM IE to Association Request");
216 pos
= wpa_s
->sme
.assoc_req_ie
+ wpa_s
->sme
.assoc_req_ie_len
;
217 os_memset(pos
, 0, 2 + rrm_ie_len
);
218 *pos
++ = WLAN_EID_RRM_ENABLED_CAPABILITIES
;
221 /* Set supported capabilites flags */
222 if (wpa_s
->drv_rrm_flags
& WPA_DRIVER_FLAGS_TX_POWER_INSERTION
)
223 *pos
|= WLAN_RRM_CAPS_LINK_MEASUREMENT
;
225 *pos
|= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE
|
226 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE
|
227 WLAN_RRM_CAPS_BEACON_REPORT_TABLE
;
230 pos
[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT
;
232 wpa_s
->sme
.assoc_req_ie_len
+= rrm_ie_len
+ 2;
233 wpa_s
->rrm
.rrm_used
= 1;
237 static void sme_send_authentication(struct wpa_supplicant
*wpa_s
,
238 struct wpa_bss
*bss
, struct wpa_ssid
*ssid
,
241 struct wpa_driver_auth_params params
;
242 struct wpa_ssid
*old_ssid
;
243 #ifdef CONFIG_IEEE80211R
245 #endif /* CONFIG_IEEE80211R */
246 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
248 #endif /* CONFIG_IEEE80211R || CONFIG_FILS */
249 int i
, bssid_changed
;
250 struct wpabuf
*resp
= NULL
;
258 #endif /* CONFIG_MBO */
261 wpa_msg(wpa_s
, MSG_ERROR
, "SME: No scan result available for "
263 wpas_connect_work_done(wpa_s
);
267 skip_auth
= wpa_s
->conf
->reassoc_same_bss_optim
&&
268 wpa_s
->reassoc_same_bss
;
269 wpa_s
->current_bss
= bss
;
271 os_memset(¶ms
, 0, sizeof(params
));
272 wpa_s
->reassociate
= 0;
274 params
.freq
= bss
->freq
;
275 params
.bssid
= bss
->bssid
;
276 params
.ssid
= bss
->ssid
;
277 params
.ssid_len
= bss
->ssid_len
;
278 params
.p2p
= ssid
->p2p_group
;
280 if (wpa_s
->sme
.ssid_len
!= params
.ssid_len
||
281 os_memcmp(wpa_s
->sme
.ssid
, params
.ssid
, params
.ssid_len
) != 0)
282 wpa_s
->sme
.prev_bssid_set
= 0;
284 wpa_s
->sme
.freq
= params
.freq
;
285 os_memcpy(wpa_s
->sme
.ssid
, params
.ssid
, params
.ssid_len
);
286 wpa_s
->sme
.ssid_len
= params
.ssid_len
;
288 params
.auth_alg
= WPA_AUTH_ALG_OPEN
;
289 #ifdef IEEE8021X_EAPOL
290 if (ssid
->key_mgmt
& WPA_KEY_MGMT_IEEE8021X_NO_WPA
) {
292 if (ssid
->non_leap
== 0)
293 params
.auth_alg
= WPA_AUTH_ALG_LEAP
;
295 params
.auth_alg
|= WPA_AUTH_ALG_LEAP
;
298 #endif /* IEEE8021X_EAPOL */
299 wpa_dbg(wpa_s
, MSG_DEBUG
, "Automatic auth_alg selection: 0x%x",
301 if (ssid
->auth_alg
) {
302 params
.auth_alg
= ssid
->auth_alg
;
303 wpa_dbg(wpa_s
, MSG_DEBUG
, "Overriding auth_alg selection: "
304 "0x%x", params
.auth_alg
);
307 wpa_s
->sme
.sae_pmksa_caching
= 0;
308 if (wpa_key_mgmt_sae(ssid
->key_mgmt
)) {
310 struct wpa_ie_data ied
;
312 rsn
= wpa_bss_get_ie(bss
, WLAN_EID_RSN
);
314 wpa_dbg(wpa_s
, MSG_DEBUG
,
315 "SAE enabled, but target BSS does not advertise RSN");
316 } else if (wpa_parse_wpa_ie(rsn
, 2 + rsn
[1], &ied
) == 0 &&
317 wpa_key_mgmt_sae(ied
.key_mgmt
)) {
318 wpa_dbg(wpa_s
, MSG_DEBUG
, "Using SAE auth_alg");
319 params
.auth_alg
= WPA_AUTH_ALG_SAE
;
321 wpa_dbg(wpa_s
, MSG_DEBUG
,
322 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
325 #endif /* CONFIG_SAE */
327 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
328 if (ssid
->wep_key_len
[i
])
329 params
.wep_key
[i
] = ssid
->wep_key
[i
];
330 params
.wep_key_len
[i
] = ssid
->wep_key_len
[i
];
332 params
.wep_tx_keyidx
= ssid
->wep_tx_keyidx
;
334 bssid_changed
= !is_zero_ether_addr(wpa_s
->bssid
);
335 os_memset(wpa_s
->bssid
, 0, ETH_ALEN
);
336 os_memcpy(wpa_s
->pending_bssid
, bss
->bssid
, ETH_ALEN
);
338 wpas_notify_bssid_changed(wpa_s
);
340 if ((wpa_bss_get_vendor_ie(bss
, WPA_IE_VENDOR_TYPE
) ||
341 wpa_bss_get_ie(bss
, WLAN_EID_RSN
)) &&
342 wpa_key_mgmt_wpa(ssid
->key_mgmt
)) {
343 int try_opportunistic
;
344 const u8
*cache_id
= NULL
;
346 try_opportunistic
= (ssid
->proactive_key_caching
< 0 ?
348 ssid
->proactive_key_caching
) &&
349 (ssid
->proto
& WPA_PROTO_RSN
);
351 if (wpa_key_mgmt_fils(ssid
->key_mgmt
))
352 cache_id
= wpa_bss_get_fils_cache_id(bss
);
353 #endif /* CONFIG_FILS */
354 if (pmksa_cache_set_current(wpa_s
->wpa
, NULL
, bss
->bssid
,
356 try_opportunistic
, cache_id
,
358 eapol_sm_notify_pmkid_attempt(wpa_s
->eapol
);
359 wpa_s
->sme
.assoc_req_ie_len
= sizeof(wpa_s
->sme
.assoc_req_ie
);
360 if (wpa_supplicant_set_suites(wpa_s
, bss
, ssid
,
361 wpa_s
->sme
.assoc_req_ie
,
362 &wpa_s
->sme
.assoc_req_ie_len
)) {
363 wpa_msg(wpa_s
, MSG_WARNING
, "SME: Failed to set WPA "
364 "key management and encryption suites");
365 wpas_connect_work_done(wpa_s
);
369 } else if (wpa_bss_get_vendor_ie(bss
, OSEN_IE_VENDOR_TYPE
) &&
370 (ssid
->key_mgmt
& WPA_KEY_MGMT_OSEN
)) {
371 /* No PMKSA caching, but otherwise similar to RSN/WPA */
372 wpa_s
->sme
.assoc_req_ie_len
= sizeof(wpa_s
->sme
.assoc_req_ie
);
373 if (wpa_supplicant_set_suites(wpa_s
, bss
, ssid
,
374 wpa_s
->sme
.assoc_req_ie
,
375 &wpa_s
->sme
.assoc_req_ie_len
)) {
376 wpa_msg(wpa_s
, MSG_WARNING
, "SME: Failed to set WPA "
377 "key management and encryption suites");
378 wpas_connect_work_done(wpa_s
);
381 #endif /* CONFIG_HS20 */
382 } else if ((ssid
->key_mgmt
& WPA_KEY_MGMT_IEEE8021X_NO_WPA
) &&
383 wpa_key_mgmt_wpa_ieee8021x(ssid
->key_mgmt
)) {
385 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
386 * use non-WPA since the scan results did not indicate that the
387 * AP is using WPA or WPA2.
389 wpa_supplicant_set_non_wpa_policy(wpa_s
, ssid
);
390 wpa_s
->sme
.assoc_req_ie_len
= 0;
391 } else if (wpa_key_mgmt_wpa_any(ssid
->key_mgmt
)) {
392 wpa_s
->sme
.assoc_req_ie_len
= sizeof(wpa_s
->sme
.assoc_req_ie
);
393 if (wpa_supplicant_set_suites(wpa_s
, NULL
, ssid
,
394 wpa_s
->sme
.assoc_req_ie
,
395 &wpa_s
->sme
.assoc_req_ie_len
)) {
396 wpa_msg(wpa_s
, MSG_WARNING
, "SME: Failed to set WPA "
397 "key management and encryption suites (no "
399 wpas_connect_work_done(wpa_s
);
403 } else if (ssid
->key_mgmt
& WPA_KEY_MGMT_WPS
) {
404 struct wpabuf
*wps_ie
;
405 wps_ie
= wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid
));
406 if (wps_ie
&& wpabuf_len(wps_ie
) <=
407 sizeof(wpa_s
->sme
.assoc_req_ie
)) {
408 wpa_s
->sme
.assoc_req_ie_len
= wpabuf_len(wps_ie
);
409 os_memcpy(wpa_s
->sme
.assoc_req_ie
, wpabuf_head(wps_ie
),
410 wpa_s
->sme
.assoc_req_ie_len
);
412 wpa_s
->sme
.assoc_req_ie_len
= 0;
414 wpa_supplicant_set_non_wpa_policy(wpa_s
, ssid
);
415 #endif /* CONFIG_WPS */
417 wpa_supplicant_set_non_wpa_policy(wpa_s
, ssid
);
418 wpa_s
->sme
.assoc_req_ie_len
= 0;
421 /* In case the WPA vendor IE is used, it should be placed after all the
422 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
423 * defined in the standard. Store the WPA IE so it can later be
424 * inserted at the correct location.
428 if (wpa_s
->wpa_proto
== WPA_PROTO_WPA
) {
429 wpa_ie
= os_memdup(wpa_s
->sme
.assoc_req_ie
,
430 wpa_s
->sme
.assoc_req_ie_len
);
432 wpa_dbg(wpa_s
, MSG_DEBUG
, "WPA: Storing WPA IE");
434 wpa_ie_len
= wpa_s
->sme
.assoc_req_ie_len
;
435 wpa_s
->sme
.assoc_req_ie_len
= 0;
437 wpa_msg(wpa_s
, MSG_WARNING
, "WPA: Failed copy WPA IE");
438 wpas_connect_work_done(wpa_s
);
443 #ifdef CONFIG_IEEE80211R
444 ie
= wpa_bss_get_ie(bss
, WLAN_EID_MOBILITY_DOMAIN
);
445 if (ie
&& ie
[1] >= MOBILITY_DOMAIN_ID_LEN
)
447 wpa_sm_set_ft_params(wpa_s
->wpa
, ie
, ie
? 2 + ie
[1] : 0);
449 /* Prepare for the next transition */
450 wpa_ft_prepare_auth_request(wpa_s
->wpa
, ie
);
453 if (md
&& !wpa_key_mgmt_ft(ssid
->key_mgmt
))
456 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: FT mobility domain %02x%02x",
459 if (wpa_s
->sme
.assoc_req_ie_len
+ 5 <
460 sizeof(wpa_s
->sme
.assoc_req_ie
)) {
461 struct rsn_mdie
*mdie
;
462 u8
*pos
= wpa_s
->sme
.assoc_req_ie
+
463 wpa_s
->sme
.assoc_req_ie_len
;
464 *pos
++ = WLAN_EID_MOBILITY_DOMAIN
;
465 *pos
++ = sizeof(*mdie
);
466 mdie
= (struct rsn_mdie
*) pos
;
467 os_memcpy(mdie
->mobility_domain
, md
,
468 MOBILITY_DOMAIN_ID_LEN
);
469 mdie
->ft_capab
= md
[MOBILITY_DOMAIN_ID_LEN
];
470 wpa_s
->sme
.assoc_req_ie_len
+= 5;
473 if (wpa_s
->sme
.prev_bssid_set
&& wpa_s
->sme
.ft_used
&&
474 os_memcmp(md
, wpa_s
->sme
.mobility_domain
, 2) == 0 &&
475 wpa_sm_has_ptk(wpa_s
->wpa
)) {
476 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Trying to use FT "
478 params
.auth_alg
= WPA_AUTH_ALG_FT
;
479 params
.ie
= wpa_s
->sme
.ft_ies
;
480 params
.ie_len
= wpa_s
->sme
.ft_ies_len
;
483 #endif /* CONFIG_IEEE80211R */
485 #ifdef CONFIG_IEEE80211W
486 wpa_s
->sme
.mfp
= wpas_get_ssid_pmf(wpa_s
, ssid
);
487 if (wpa_s
->sme
.mfp
!= NO_MGMT_FRAME_PROTECTION
) {
488 const u8
*rsn
= wpa_bss_get_ie(bss
, WLAN_EID_RSN
);
489 struct wpa_ie_data _ie
;
490 if (rsn
&& wpa_parse_wpa_ie(rsn
, 2 + rsn
[1], &_ie
) == 0 &&
492 (WPA_CAPABILITY_MFPC
| WPA_CAPABILITY_MFPR
)) {
493 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Selected AP supports "
495 wpa_s
->sme
.mfp
= MGMT_FRAME_PROTECTION_REQUIRED
;
498 #endif /* CONFIG_IEEE80211W */
501 if (wpa_s
->global
->p2p
) {
505 pos
= wpa_s
->sme
.assoc_req_ie
+ wpa_s
->sme
.assoc_req_ie_len
;
506 len
= sizeof(wpa_s
->sme
.assoc_req_ie
) -
507 wpa_s
->sme
.assoc_req_ie_len
;
508 res
= wpas_p2p_assoc_req_ie(wpa_s
, bss
, pos
, len
,
511 wpa_s
->sme
.assoc_req_ie_len
+= res
;
513 #endif /* CONFIG_P2P */
516 if (wpa_s
->fst_ies
) {
517 int fst_ies_len
= wpabuf_len(wpa_s
->fst_ies
);
519 if (wpa_s
->sme
.assoc_req_ie_len
+ fst_ies_len
<=
520 sizeof(wpa_s
->sme
.assoc_req_ie
)) {
521 os_memcpy(wpa_s
->sme
.assoc_req_ie
+
522 wpa_s
->sme
.assoc_req_ie_len
,
523 wpabuf_head(wpa_s
->fst_ies
),
525 wpa_s
->sme
.assoc_req_ie_len
+= fst_ies_len
;
528 #endif /* CONFIG_FST */
530 sme_auth_handle_rrm(wpa_s
, bss
);
532 wpa_s
->sme
.assoc_req_ie_len
+= wpas_supp_op_class_ie(
533 wpa_s
, ssid
, bss
->freq
,
534 wpa_s
->sme
.assoc_req_ie
+ wpa_s
->sme
.assoc_req_ie_len
,
535 sizeof(wpa_s
->sme
.assoc_req_ie
) - wpa_s
->sme
.assoc_req_ie_len
);
538 wpa_drv_get_ext_capa(wpa_s
, WPA_IF_P2P_CLIENT
);
540 wpa_drv_get_ext_capa(wpa_s
, WPA_IF_STATION
);
542 ext_capab_len
= wpas_build_ext_capab(wpa_s
, ext_capab
,
544 if (ext_capab_len
> 0) {
545 u8
*pos
= wpa_s
->sme
.assoc_req_ie
;
546 if (wpa_s
->sme
.assoc_req_ie_len
> 0 && pos
[0] == WLAN_EID_RSN
)
548 os_memmove(pos
+ ext_capab_len
, pos
,
549 wpa_s
->sme
.assoc_req_ie_len
-
550 (pos
- wpa_s
->sme
.assoc_req_ie
));
551 wpa_s
->sme
.assoc_req_ie_len
+= ext_capab_len
;
552 os_memcpy(pos
, ext_capab
, ext_capab_len
);
556 if (is_hs20_network(wpa_s
, ssid
, bss
)) {
559 hs20
= wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN
);
561 int pps_mo_id
= hs20_get_pps_mo_id(wpa_s
, ssid
);
564 wpas_hs20_add_indication(hs20
, pps_mo_id
,
565 get_hs20_version(bss
));
566 wpas_hs20_add_roam_cons_sel(hs20
, ssid
);
567 len
= sizeof(wpa_s
->sme
.assoc_req_ie
) -
568 wpa_s
->sme
.assoc_req_ie_len
;
569 if (wpabuf_len(hs20
) <= len
) {
570 os_memcpy(wpa_s
->sme
.assoc_req_ie
+
571 wpa_s
->sme
.assoc_req_ie_len
,
572 wpabuf_head(hs20
), wpabuf_len(hs20
));
573 wpa_s
->sme
.assoc_req_ie_len
+= wpabuf_len(hs20
);
578 #endif /* CONFIG_HS20 */
583 wpa_dbg(wpa_s
, MSG_DEBUG
, "WPA: Reinsert WPA IE");
585 len
= sizeof(wpa_s
->sme
.assoc_req_ie
) -
586 wpa_s
->sme
.assoc_req_ie_len
;
588 if (len
> wpa_ie_len
) {
589 os_memcpy(wpa_s
->sme
.assoc_req_ie
+
590 wpa_s
->sme
.assoc_req_ie_len
,
592 wpa_s
->sme
.assoc_req_ie_len
+= wpa_ie_len
;
594 wpa_dbg(wpa_s
, MSG_DEBUG
, "WPA: Failed to add WPA IE");
600 if (wpa_s
->vendor_elem
[VENDOR_ELEM_ASSOC_REQ
]) {
601 struct wpabuf
*buf
= wpa_s
->vendor_elem
[VENDOR_ELEM_ASSOC_REQ
];
604 len
= sizeof(wpa_s
->sme
.assoc_req_ie
) -
605 wpa_s
->sme
.assoc_req_ie_len
;
606 if (wpabuf_len(buf
) <= len
) {
607 os_memcpy(wpa_s
->sme
.assoc_req_ie
+
608 wpa_s
->sme
.assoc_req_ie_len
,
609 wpabuf_head(buf
), wpabuf_len(buf
));
610 wpa_s
->sme
.assoc_req_ie_len
+= wpabuf_len(buf
);
615 mbo_ie
= wpa_bss_get_vendor_ie(bss
, MBO_IE_VENDOR_TYPE
);
619 len
= wpas_mbo_ie(wpa_s
, wpa_s
->sme
.assoc_req_ie
+
620 wpa_s
->sme
.assoc_req_ie_len
,
621 sizeof(wpa_s
->sme
.assoc_req_ie
) -
622 wpa_s
->sme
.assoc_req_ie_len
,
623 !!mbo_attr_from_mbo_ie(mbo_ie
,
624 OCE_ATTR_ID_CAPA_IND
));
626 wpa_s
->sme
.assoc_req_ie_len
+= len
;
628 #endif /* CONFIG_MBO */
631 if (!skip_auth
&& params
.auth_alg
== WPA_AUTH_ALG_SAE
&&
632 pmksa_cache_set_current(wpa_s
->wpa
, NULL
, bss
->bssid
, ssid
, 0,
633 NULL
, WPA_KEY_MGMT_SAE
) == 0) {
634 wpa_dbg(wpa_s
, MSG_DEBUG
,
635 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
636 wpa_sm_set_pmk_from_pmksa(wpa_s
->wpa
);
637 params
.auth_alg
= WPA_AUTH_ALG_OPEN
;
638 wpa_s
->sme
.sae_pmksa_caching
= 1;
641 if (!skip_auth
&& params
.auth_alg
== WPA_AUTH_ALG_SAE
) {
643 resp
= sme_auth_build_sae_commit(wpa_s
, ssid
,
647 resp
= sme_auth_build_sae_confirm(wpa_s
, 0);
649 wpas_connection_failed(wpa_s
, bss
->bssid
);
652 params
.auth_data
= wpabuf_head(resp
);
653 params
.auth_data_len
= wpabuf_len(resp
);
654 wpa_s
->sme
.sae
.state
= start
? SAE_COMMITTED
: SAE_CONFIRMED
;
656 #endif /* CONFIG_SAE */
658 old_ssid
= wpa_s
->current_ssid
;
659 wpa_s
->current_ssid
= ssid
;
660 wpa_supplicant_rsn_supp_set_config(wpa_s
, wpa_s
->current_ssid
);
661 wpa_supplicant_initiate_eapol(wpa_s
);
664 /* TODO: FILS operations can in some cases be done between different
665 * network_ctx (i.e., same credentials can be used with multiple
667 if (params
.auth_alg
== WPA_AUTH_ALG_OPEN
&&
668 wpa_key_mgmt_fils(ssid
->key_mgmt
)) {
671 const u8
*realm
, *username
, *rrk
;
672 size_t realm_len
, username_len
, rrk_len
;
676 * Check FILS Indication element (FILS Information field) bits
677 * indicating supported authentication algorithms against local
678 * configuration (ssid->fils_dh_group). Try to use FILS
679 * authentication only if the AP supports the combination in the
680 * network profile. */
681 indic
= wpa_bss_get_ie(bss
, WLAN_EID_FILS_INDICATION
);
682 if (!indic
|| indic
[1] < 2) {
683 wpa_printf(MSG_DEBUG
, "SME: " MACSTR
684 " does not include FILS Indication element - cannot use FILS authentication with it",
685 MAC2STR(bss
->bssid
));
689 fils_info
= WPA_GET_LE16(indic
+ 2);
690 if (ssid
->fils_dh_group
== 0 && !(fils_info
& BIT(9))) {
691 wpa_printf(MSG_DEBUG
, "SME: " MACSTR
692 " does not support FILS SK without PFS - cannot use FILS authentication with it",
693 MAC2STR(bss
->bssid
));
696 if (ssid
->fils_dh_group
!= 0 && !(fils_info
& BIT(10))) {
697 wpa_printf(MSG_DEBUG
, "SME: " MACSTR
698 " does not support FILS SK with PFS - cannot use FILS authentication with it",
699 MAC2STR(bss
->bssid
));
703 if (wpa_s
->last_con_fail_realm
&&
704 eapol_sm_get_erp_info(wpa_s
->eapol
, &ssid
->eap
,
705 &username
, &username_len
,
706 &realm
, &realm_len
, &next_seq_num
,
707 &rrk
, &rrk_len
) == 0 &&
708 realm
&& realm_len
== wpa_s
->last_con_fail_realm_len
&&
709 os_memcmp(realm
, wpa_s
->last_con_fail_realm
,
711 wpa_printf(MSG_DEBUG
,
712 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
716 if (pmksa_cache_set_current(wpa_s
->wpa
, NULL
, bss
->bssid
,
718 wpa_bss_get_fils_cache_id(bss
),
720 wpa_printf(MSG_DEBUG
,
721 "SME: Try to use FILS with PMKSA caching");
722 resp
= fils_build_auth(wpa_s
->wpa
, ssid
->fils_dh_group
, md
);
726 if (ssid
->fils_dh_group
)
727 wpa_printf(MSG_DEBUG
,
728 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
729 ssid
->fils_dh_group
);
731 wpa_printf(MSG_DEBUG
,
732 "SME: Try to use FILS SK authentication without PFS");
733 auth_alg
= ssid
->fils_dh_group
?
734 WPA_AUTH_ALG_FILS_SK_PFS
: WPA_AUTH_ALG_FILS
;
735 params
.auth_alg
= auth_alg
;
736 params
.auth_data
= wpabuf_head(resp
);
737 params
.auth_data_len
= wpabuf_len(resp
);
738 wpa_s
->sme
.auth_alg
= auth_alg
;
742 #endif /* CONFIG_FILS */
744 wpa_supplicant_cancel_sched_scan(wpa_s
);
745 wpa_supplicant_cancel_scan(wpa_s
);
747 wpa_msg(wpa_s
, MSG_INFO
, "SME: Trying to authenticate with " MACSTR
748 " (SSID='%s' freq=%d MHz)", MAC2STR(params
.bssid
),
749 wpa_ssid_txt(params
.ssid
, params
.ssid_len
), params
.freq
);
751 eapol_sm_notify_portValid(wpa_s
->eapol
, FALSE
);
752 wpa_clear_keys(wpa_s
, bss
->bssid
);
753 wpa_supplicant_set_state(wpa_s
, WPA_AUTHENTICATING
);
754 if (old_ssid
!= wpa_s
->current_ssid
)
755 wpas_notify_network_changed(wpa_s
);
758 hs20_configure_frame_filters(wpa_s
);
759 #endif /* CONFIG_HS20 */
763 * If multi-channel concurrency is not supported, check for any
764 * frequency conflict. In case of any frequency conflict, remove the
765 * least prioritized connection.
767 if (wpa_s
->num_multichan_concurrent
< 2) {
769 num
= get_shared_radio_freqs(wpa_s
, &freq
, 1);
770 if (num
> 0 && freq
> 0 && freq
!= params
.freq
) {
771 wpa_printf(MSG_DEBUG
,
772 "Conflicting frequency found (%d != %d)",
774 if (wpas_p2p_handle_frequency_conflicts(wpa_s
,
777 wpas_connection_failed(wpa_s
, bss
->bssid
);
778 wpa_supplicant_mark_disassoc(wpa_s
);
780 wpas_connect_work_done(wpa_s
);
785 #endif /* CONFIG_P2P */
788 wpa_msg(wpa_s
, MSG_DEBUG
,
789 "SME: Skip authentication step on reassoc-to-same-BSS");
791 sme_associate(wpa_s
, ssid
->mode
, bss
->bssid
, WLAN_AUTH_OPEN
);
796 wpa_s
->sme
.auth_alg
= params
.auth_alg
;
797 if (wpa_drv_authenticate(wpa_s
, ¶ms
) < 0) {
798 wpa_msg(wpa_s
, MSG_INFO
, "SME: Authentication request to the "
800 wpas_connection_failed(wpa_s
, bss
->bssid
);
801 wpa_supplicant_mark_disassoc(wpa_s
);
803 wpas_connect_work_done(wpa_s
);
807 eloop_register_timeout(SME_AUTH_TIMEOUT
, 0, sme_auth_timer
, wpa_s
,
811 * Association will be started based on the authentication event from
819 static void sme_auth_start_cb(struct wpa_radio_work
*work
, int deinit
)
821 struct wpa_connect_work
*cwork
= work
->ctx
;
822 struct wpa_supplicant
*wpa_s
= work
->wpa_s
;
826 wpa_s
->connect_work
= NULL
;
828 wpas_connect_work_free(cwork
);
832 wpa_s
->connect_work
= work
;
834 if (cwork
->bss_removed
||
835 !wpas_valid_bss_ssid(wpa_s
, cwork
->bss
, cwork
->ssid
) ||
836 wpas_network_disabled(wpa_s
, cwork
->ssid
)) {
837 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
838 wpas_connect_work_done(wpa_s
);
842 /* Starting new connection, so clear the possibly used WPA IE from the
843 * previous association. */
844 wpa_sm_set_assoc_wpa_ie(wpa_s
->wpa
, NULL
, 0);
846 sme_send_authentication(wpa_s
, cwork
->bss
, cwork
->ssid
, 1);
850 void sme_authenticate(struct wpa_supplicant
*wpa_s
,
851 struct wpa_bss
*bss
, struct wpa_ssid
*ssid
)
853 struct wpa_connect_work
*cwork
;
855 if (bss
== NULL
|| ssid
== NULL
)
857 if (wpa_s
->connect_work
) {
858 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Reject sme_authenticate() call since connect_work exist");
862 if (radio_work_pending(wpa_s
, "sme-connect")) {
864 * The previous sme-connect work might no longer be valid due to
865 * the fact that the BSS list was updated. In addition, it makes
866 * sense to adhere to the 'newer' decision.
868 wpa_dbg(wpa_s
, MSG_DEBUG
,
869 "SME: Remove previous pending sme-connect");
870 radio_remove_works(wpa_s
, "sme-connect", 0);
873 wpas_abort_ongoing_scan(wpa_s
);
875 cwork
= os_zalloc(sizeof(*cwork
));
883 wpa_s
->sme
.sae
.state
= SAE_NOTHING
;
884 wpa_s
->sme
.sae
.send_confirm
= 0;
885 wpa_s
->sme
.sae_group_index
= 0;
886 #endif /* CONFIG_SAE */
888 if (radio_add_work(wpa_s
, bss
->freq
, "sme-connect", 1,
889 sme_auth_start_cb
, cwork
) < 0)
890 wpas_connect_work_free(cwork
);
896 static int sme_external_auth_build_buf(struct wpabuf
*buf
,
897 struct wpabuf
*params
,
898 const u8
*sa
, const u8
*da
,
899 u16 auth_transaction
, u16 seq_num
)
901 struct ieee80211_mgmt
*resp
;
903 resp
= wpabuf_put(buf
, offsetof(struct ieee80211_mgmt
,
906 resp
->frame_control
= host_to_le16((WLAN_FC_TYPE_MGMT
<< 2) |
907 (WLAN_FC_STYPE_AUTH
<< 4));
908 os_memcpy(resp
->da
, da
, ETH_ALEN
);
909 os_memcpy(resp
->sa
, sa
, ETH_ALEN
);
910 os_memcpy(resp
->bssid
, da
, ETH_ALEN
);
911 resp
->u
.auth
.auth_alg
= host_to_le16(WLAN_AUTH_SAE
);
912 resp
->seq_ctrl
= host_to_le16(seq_num
<< 4);
913 resp
->u
.auth
.auth_transaction
= host_to_le16(auth_transaction
);
914 resp
->u
.auth
.status_code
= host_to_le16(WLAN_STATUS_SUCCESS
);
916 wpabuf_put_buf(buf
, params
);
922 static void sme_external_auth_send_sae_commit(struct wpa_supplicant
*wpa_s
,
924 struct wpa_ssid
*ssid
)
926 struct wpabuf
*resp
, *buf
;
928 resp
= sme_auth_build_sae_commit(wpa_s
, ssid
, bssid
, 1, 0);
932 wpa_s
->sme
.sae
.state
= SAE_COMMITTED
;
933 buf
= wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN
+ wpabuf_len(resp
));
939 wpa_s
->sme
.seq_num
++;
940 sme_external_auth_build_buf(buf
, resp
, wpa_s
->own_addr
,
941 bssid
, 1, wpa_s
->sme
.seq_num
);
942 wpa_drv_send_mlme(wpa_s
, wpabuf_head(buf
), wpabuf_len(buf
), 1, 0);
948 static void sme_send_external_auth_status(struct wpa_supplicant
*wpa_s
,
951 struct external_auth params
;
953 os_memset(¶ms
, 0, sizeof(params
));
954 params
.status
= status
;
955 os_memcpy(params
.ssid
, wpa_s
->sme
.ext_auth
.ssid
,
956 wpa_s
->sme
.ext_auth
.ssid_len
);
957 params
.ssid_len
= wpa_s
->sme
.ext_auth
.ssid_len
;
958 os_memcpy(params
.bssid
, wpa_s
->sme
.ext_auth
.bssid
, ETH_ALEN
);
959 wpa_drv_send_external_auth_status(wpa_s
, ¶ms
);
963 static void sme_handle_external_auth_start(struct wpa_supplicant
*wpa_s
,
964 union wpa_event_data
*data
)
966 struct wpa_ssid
*ssid
;
967 size_t ssid_str_len
= data
->external_auth
.ssid_len
;
968 u8
*ssid_str
= data
->external_auth
.ssid
;
970 /* Get the SSID conf from the ssid string obtained */
971 for (ssid
= wpa_s
->conf
->ssid
; ssid
; ssid
= ssid
->next
) {
972 if (!wpas_network_disabled(wpa_s
, ssid
) &&
973 ssid_str_len
== ssid
->ssid_len
&&
974 os_memcmp(ssid_str
, ssid
->ssid
, ssid_str_len
) == 0 &&
975 (ssid
->key_mgmt
& WPA_KEY_MGMT_SAE
))
979 sme_external_auth_send_sae_commit(wpa_s
,
980 data
->external_auth
.bssid
,
983 sme_send_external_auth_status(wpa_s
,
984 WLAN_STATUS_UNSPECIFIED_FAILURE
);
988 static void sme_external_auth_send_sae_confirm(struct wpa_supplicant
*wpa_s
,
991 struct wpabuf
*resp
, *buf
;
993 resp
= sme_auth_build_sae_confirm(wpa_s
, 1);
995 wpa_printf(MSG_DEBUG
, "SAE: Confirm message buf alloc failure");
999 wpa_s
->sme
.sae
.state
= SAE_CONFIRMED
;
1000 buf
= wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN
+ wpabuf_len(resp
));
1002 wpa_printf(MSG_DEBUG
, "SAE: Auth Confirm buf alloc failure");
1006 wpa_s
->sme
.seq_num
++;
1007 sme_external_auth_build_buf(buf
, resp
, wpa_s
->own_addr
,
1008 da
, 2, wpa_s
->sme
.seq_num
);
1009 wpa_drv_send_mlme(wpa_s
, wpabuf_head(buf
), wpabuf_len(buf
), 1, 0);
1015 void sme_external_auth_trigger(struct wpa_supplicant
*wpa_s
,
1016 union wpa_event_data
*data
)
1018 if (RSN_SELECTOR_GET(&data
->external_auth
.key_mgmt_suite
) !=
1019 RSN_AUTH_KEY_MGMT_SAE
)
1022 if (data
->external_auth
.action
== EXT_AUTH_START
) {
1023 os_memcpy(&wpa_s
->sme
.ext_auth
, data
,
1024 sizeof(struct external_auth
));
1025 wpa_s
->sme
.seq_num
= 0;
1026 wpa_s
->sme
.sae
.state
= SAE_NOTHING
;
1027 wpa_s
->sme
.sae
.send_confirm
= 0;
1028 wpa_s
->sme
.sae_group_index
= 0;
1029 sme_handle_external_auth_start(wpa_s
, data
);
1030 } else if (data
->external_auth
.action
== EXT_AUTH_ABORT
) {
1031 /* Report failure to driver for the wrong trigger */
1032 sme_send_external_auth_status(wpa_s
,
1033 WLAN_STATUS_UNSPECIFIED_FAILURE
);
1038 static int sme_sae_auth(struct wpa_supplicant
*wpa_s
, u16 auth_transaction
,
1039 u16 status_code
, const u8
*data
, size_t len
,
1040 int external
, const u8
*sa
)
1044 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: SAE authentication transaction %u "
1045 "status code %u", auth_transaction
, status_code
);
1047 if (auth_transaction
== 1 &&
1048 status_code
== WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ
&&
1049 wpa_s
->sme
.sae
.state
== SAE_COMMITTED
&&
1050 (external
|| wpa_s
->current_bss
) && wpa_s
->current_ssid
) {
1051 int default_groups
[] = { 19, 20, 21, 0 };
1054 groups
= wpa_s
->conf
->sae_groups
;
1055 if (!groups
|| groups
[0] <= 0)
1056 groups
= default_groups
;
1058 if (len
< sizeof(le16
)) {
1059 wpa_dbg(wpa_s
, MSG_DEBUG
,
1060 "SME: Too short SAE anti-clogging token request");
1063 group
= WPA_GET_LE16(data
);
1064 wpa_dbg(wpa_s
, MSG_DEBUG
,
1065 "SME: SAE anti-clogging token requested (group %u)",
1067 if (sae_group_allowed(&wpa_s
->sme
.sae
, groups
, group
) !=
1068 WLAN_STATUS_SUCCESS
) {
1069 wpa_dbg(wpa_s
, MSG_ERROR
,
1070 "SME: SAE group %u of anti-clogging request is invalid",
1074 wpabuf_free(wpa_s
->sme
.sae_token
);
1075 wpa_s
->sme
.sae_token
= wpabuf_alloc_copy(data
+ sizeof(le16
),
1076 len
- sizeof(le16
));
1078 sme_send_authentication(wpa_s
, wpa_s
->current_bss
,
1079 wpa_s
->current_ssid
, 2);
1081 sme_external_auth_send_sae_commit(
1082 wpa_s
, wpa_s
->sme
.ext_auth
.bssid
,
1083 wpa_s
->current_ssid
);
1087 if (auth_transaction
== 1 &&
1088 status_code
== WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED
&&
1089 wpa_s
->sme
.sae
.state
== SAE_COMMITTED
&&
1090 (external
|| wpa_s
->current_bss
) && wpa_s
->current_ssid
) {
1091 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: SAE group not supported");
1092 wpa_s
->sme
.sae_group_index
++;
1093 if (sme_set_sae_group(wpa_s
) < 0)
1094 return -1; /* no other groups enabled */
1095 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Try next enabled SAE group");
1097 sme_send_authentication(wpa_s
, wpa_s
->current_bss
,
1098 wpa_s
->current_ssid
, 1);
1100 sme_external_auth_send_sae_commit(
1101 wpa_s
, wpa_s
->sme
.ext_auth
.bssid
,
1102 wpa_s
->current_ssid
);
1106 if (auth_transaction
== 1 &&
1107 status_code
== WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER
) {
1108 const u8
*bssid
= sa
? sa
: wpa_s
->pending_bssid
;
1110 wpa_msg(wpa_s
, MSG_INFO
,
1111 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR
,
1116 if (status_code
!= WLAN_STATUS_SUCCESS
)
1119 if (auth_transaction
== 1) {
1122 groups
= wpa_s
->conf
->sae_groups
;
1124 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME SAE commit");
1125 if ((!external
&& wpa_s
->current_bss
== NULL
) ||
1126 wpa_s
->current_ssid
== NULL
)
1128 if (wpa_s
->sme
.sae
.state
!= SAE_COMMITTED
)
1130 if (groups
&& groups
[0] <= 0)
1132 res
= sae_parse_commit(&wpa_s
->sme
.sae
, data
, len
, NULL
, NULL
,
1134 if (res
== SAE_SILENTLY_DISCARD
) {
1135 wpa_printf(MSG_DEBUG
,
1136 "SAE: Drop commit message due to reflection attack");
1139 if (res
!= WLAN_STATUS_SUCCESS
)
1142 if (sae_process_commit(&wpa_s
->sme
.sae
) < 0) {
1143 wpa_printf(MSG_DEBUG
, "SAE: Failed to process peer "
1148 wpabuf_free(wpa_s
->sme
.sae_token
);
1149 wpa_s
->sme
.sae_token
= NULL
;
1151 sme_send_authentication(wpa_s
, wpa_s
->current_bss
,
1152 wpa_s
->current_ssid
, 0);
1154 sme_external_auth_send_sae_confirm(wpa_s
, sa
);
1156 } else if (auth_transaction
== 2) {
1157 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME SAE confirm");
1158 if (wpa_s
->sme
.sae
.state
!= SAE_CONFIRMED
)
1160 if (sae_check_confirm(&wpa_s
->sme
.sae
, data
, len
) < 0)
1162 wpa_s
->sme
.sae
.state
= SAE_ACCEPTED
;
1163 sae_clear_temp_data(&wpa_s
->sme
.sae
);
1166 /* Report success to driver */
1167 sme_send_external_auth_status(wpa_s
,
1168 WLAN_STATUS_SUCCESS
);
1178 void sme_external_auth_mgmt_rx(struct wpa_supplicant
*wpa_s
,
1179 const u8
*auth_frame
, size_t len
)
1181 const struct ieee80211_mgmt
*header
;
1184 header
= (const struct ieee80211_mgmt
*) auth_frame
;
1185 auth_length
= IEEE80211_HDRLEN
+ sizeof(header
->u
.auth
);
1187 if (len
< auth_length
) {
1188 /* Notify failure to the driver */
1189 sme_send_external_auth_status(wpa_s
,
1190 WLAN_STATUS_UNSPECIFIED_FAILURE
);
1194 if (le_to_host16(header
->u
.auth
.auth_alg
) == WLAN_AUTH_SAE
) {
1198 wpa_s
, le_to_host16(header
->u
.auth
.auth_transaction
),
1199 le_to_host16(header
->u
.auth
.status_code
),
1200 header
->u
.auth
.variable
,
1201 len
- auth_length
, 1, header
->sa
);
1203 /* Notify failure to the driver */
1204 sme_send_external_auth_status(
1205 wpa_s
, WLAN_STATUS_UNSPECIFIED_FAILURE
);
1211 wpa_printf(MSG_DEBUG
,
1212 "SME: SAE completed - setting PMK for 4-way handshake");
1213 wpa_sm_set_pmk(wpa_s
->wpa
, wpa_s
->sme
.sae
.pmk
, PMK_LEN
,
1214 wpa_s
->sme
.sae
.pmkid
, wpa_s
->pending_bssid
);
1218 #endif /* CONFIG_SAE */
1221 void sme_event_auth(struct wpa_supplicant
*wpa_s
, union wpa_event_data
*data
)
1223 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
1226 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Ignore authentication event "
1227 "when network is not selected");
1231 if (wpa_s
->wpa_state
!= WPA_AUTHENTICATING
) {
1232 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Ignore authentication event "
1233 "when not in authenticating state");
1237 if (os_memcmp(wpa_s
->pending_bssid
, data
->auth
.peer
, ETH_ALEN
) != 0) {
1238 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Ignore authentication with "
1239 "unexpected peer " MACSTR
,
1240 MAC2STR(data
->auth
.peer
));
1244 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Authentication response: peer=" MACSTR
1245 " auth_type=%d auth_transaction=%d status_code=%d",
1246 MAC2STR(data
->auth
.peer
), data
->auth
.auth_type
,
1247 data
->auth
.auth_transaction
, data
->auth
.status_code
);
1248 wpa_hexdump(MSG_MSGDUMP
, "SME: Authentication response IEs",
1249 data
->auth
.ies
, data
->auth
.ies_len
);
1251 eloop_cancel_timeout(sme_auth_timer
, wpa_s
, NULL
);
1254 if (data
->auth
.auth_type
== WLAN_AUTH_SAE
) {
1256 res
= sme_sae_auth(wpa_s
, data
->auth
.auth_transaction
,
1257 data
->auth
.status_code
, data
->auth
.ies
,
1258 data
->auth
.ies_len
, 0, NULL
);
1260 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1261 wpa_supplicant_set_state(wpa_s
, WPA_DISCONNECTED
);
1267 wpa_printf(MSG_DEBUG
, "SME: SAE completed - setting PMK for "
1269 wpa_sm_set_pmk(wpa_s
->wpa
, wpa_s
->sme
.sae
.pmk
, PMK_LEN
,
1270 wpa_s
->sme
.sae
.pmkid
, wpa_s
->pending_bssid
);
1272 #endif /* CONFIG_SAE */
1274 if (data
->auth
.status_code
!= WLAN_STATUS_SUCCESS
) {
1275 char *ie_txt
= NULL
;
1277 if (data
->auth
.ies
&& data
->auth
.ies_len
) {
1278 size_t buflen
= 2 * data
->auth
.ies_len
+ 1;
1279 ie_txt
= os_malloc(buflen
);
1281 wpa_snprintf_hex(ie_txt
, buflen
, data
->auth
.ies
,
1282 data
->auth
.ies_len
);
1285 wpa_msg(wpa_s
, MSG_INFO
, WPA_EVENT_AUTH_REJECT MACSTR
1286 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
1287 MAC2STR(data
->auth
.peer
), data
->auth
.auth_type
,
1288 data
->auth
.auth_transaction
, data
->auth
.status_code
,
1289 ie_txt
? " ie=" : "",
1290 ie_txt
? ie_txt
: "");
1294 if (wpa_s
->sme
.auth_alg
== WPA_AUTH_ALG_FILS
||
1295 wpa_s
->sme
.auth_alg
== WPA_AUTH_ALG_FILS_SK_PFS
)
1296 fils_connection_failure(wpa_s
);
1297 #endif /* CONFIG_FILS */
1299 if (data
->auth
.status_code
!=
1300 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG
||
1301 wpa_s
->sme
.auth_alg
== data
->auth
.auth_type
||
1302 wpa_s
->current_ssid
->auth_alg
== WPA_AUTH_ALG_LEAP
) {
1303 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1304 wpa_supplicant_set_state(wpa_s
, WPA_DISCONNECTED
);
1308 wpas_connect_work_done(wpa_s
);
1310 switch (data
->auth
.auth_type
) {
1311 case WLAN_AUTH_OPEN
:
1312 wpa_s
->current_ssid
->auth_alg
= WPA_AUTH_ALG_SHARED
;
1314 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Trying SHARED auth");
1315 wpa_supplicant_associate(wpa_s
, wpa_s
->current_bss
,
1316 wpa_s
->current_ssid
);
1319 case WLAN_AUTH_SHARED_KEY
:
1320 wpa_s
->current_ssid
->auth_alg
= WPA_AUTH_ALG_LEAP
;
1322 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Trying LEAP auth");
1323 wpa_supplicant_associate(wpa_s
, wpa_s
->current_bss
,
1324 wpa_s
->current_ssid
);
1332 #ifdef CONFIG_IEEE80211R
1333 if (data
->auth
.auth_type
== WLAN_AUTH_FT
) {
1334 const u8
*ric_ies
= NULL
;
1335 size_t ric_ies_len
= 0;
1337 if (wpa_s
->ric_ies
) {
1338 ric_ies
= wpabuf_head(wpa_s
->ric_ies
);
1339 ric_ies_len
= wpabuf_len(wpa_s
->ric_ies
);
1341 if (wpa_ft_process_response(wpa_s
->wpa
, data
->auth
.ies
,
1342 data
->auth
.ies_len
, 0,
1344 ric_ies
, ric_ies_len
) < 0) {
1345 wpa_dbg(wpa_s
, MSG_DEBUG
,
1346 "SME: FT Authentication response processing failed");
1347 wpa_msg(wpa_s
, MSG_INFO
, WPA_EVENT_DISCONNECTED
"bssid="
1349 " reason=%d locally_generated=1",
1350 MAC2STR(wpa_s
->pending_bssid
),
1351 WLAN_REASON_DEAUTH_LEAVING
);
1352 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1353 wpa_supplicant_mark_disassoc(wpa_s
);
1357 #endif /* CONFIG_IEEE80211R */
1360 if (data
->auth
.auth_type
== WLAN_AUTH_FILS_SK
||
1361 data
->auth
.auth_type
== WLAN_AUTH_FILS_SK_PFS
) {
1362 u16 expect_auth_type
;
1364 expect_auth_type
= wpa_s
->sme
.auth_alg
==
1365 WPA_AUTH_ALG_FILS_SK_PFS
? WLAN_AUTH_FILS_SK_PFS
:
1367 if (data
->auth
.auth_type
!= expect_auth_type
) {
1368 wpa_dbg(wpa_s
, MSG_DEBUG
,
1369 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
1370 data
->auth
.auth_type
, expect_auth_type
);
1371 wpa_msg(wpa_s
, MSG_INFO
, WPA_EVENT_DISCONNECTED
"bssid="
1373 " reason=%d locally_generated=1",
1374 MAC2STR(wpa_s
->pending_bssid
),
1375 WLAN_REASON_DEAUTH_LEAVING
);
1376 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1377 wpa_supplicant_mark_disassoc(wpa_s
);
1381 if (fils_process_auth(wpa_s
->wpa
, wpa_s
->pending_bssid
,
1382 data
->auth
.ies
, data
->auth
.ies_len
) < 0) {
1383 wpa_dbg(wpa_s
, MSG_DEBUG
,
1384 "SME: FILS Authentication response processing failed");
1385 wpa_msg(wpa_s
, MSG_INFO
, WPA_EVENT_DISCONNECTED
"bssid="
1387 " reason=%d locally_generated=1",
1388 MAC2STR(wpa_s
->pending_bssid
),
1389 WLAN_REASON_DEAUTH_LEAVING
);
1390 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1391 wpa_supplicant_mark_disassoc(wpa_s
);
1395 #endif /* CONFIG_FILS */
1397 sme_associate(wpa_s
, ssid
->mode
, data
->auth
.peer
,
1398 data
->auth
.auth_type
);
1402 #ifdef CONFIG_IEEE80211R
1403 static void remove_ie(u8
*buf
, size_t *len
, u8 eid
)
1405 u8
*pos
, *next
, *end
;
1407 pos
= (u8
*) get_ie(buf
, *len
, eid
);
1409 next
= pos
+ 2 + pos
[1];
1412 os_memmove(pos
, next
, end
- next
);
1415 #endif /* CONFIG_IEEE80211R */
1418 void sme_associate(struct wpa_supplicant
*wpa_s
, enum wpas_mode mode
,
1419 const u8
*bssid
, u16 auth_type
)
1421 struct wpa_driver_associate_params params
;
1422 struct ieee802_11_elems elems
;
1424 u8 nonces
[2 * FILS_NONCE_LEN
];
1425 #endif /* CONFIG_FILS */
1426 #ifdef CONFIG_HT_OVERRIDES
1427 struct ieee80211_ht_capabilities htcaps
;
1428 struct ieee80211_ht_capabilities htcaps_mask
;
1429 #endif /* CONFIG_HT_OVERRIDES */
1430 #ifdef CONFIG_VHT_OVERRIDES
1431 struct ieee80211_vht_capabilities vhtcaps
;
1432 struct ieee80211_vht_capabilities vhtcaps_mask
;
1433 #endif /* CONFIG_VHT_OVERRIDES */
1435 os_memset(¶ms
, 0, sizeof(params
));
1438 if (auth_type
== WLAN_AUTH_FILS_SK
||
1439 auth_type
== WLAN_AUTH_FILS_SK_PFS
) {
1441 const u8
*snonce
, *anonce
;
1442 const unsigned int max_hlp
= 20;
1443 struct wpabuf
*hlp
[max_hlp
];
1444 unsigned int i
, num_hlp
= 0;
1445 struct fils_hlp_req
*req
;
1447 dl_list_for_each(req
, &wpa_s
->fils_hlp_req
, struct fils_hlp_req
,
1449 hlp
[num_hlp
] = wpabuf_alloc(2 * ETH_ALEN
+ 6 +
1450 wpabuf_len(req
->pkt
));
1453 wpabuf_put_data(hlp
[num_hlp
], req
->dst
, ETH_ALEN
);
1454 wpabuf_put_data(hlp
[num_hlp
], wpa_s
->own_addr
,
1456 wpabuf_put_data(hlp
[num_hlp
],
1457 "\xaa\xaa\x03\x00\x00\x00", 6);
1458 wpabuf_put_buf(hlp
[num_hlp
], req
->pkt
);
1460 if (num_hlp
>= max_hlp
)
1464 buf
= fils_build_assoc_req(wpa_s
->wpa
, ¶ms
.fils_kek
,
1465 ¶ms
.fils_kek_len
, &snonce
,
1467 (const struct wpabuf
**) hlp
,
1469 for (i
= 0; i
< num_hlp
; i
++)
1470 wpabuf_free(hlp
[i
]);
1473 wpa_hexdump(MSG_DEBUG
, "FILS: assoc_req before FILS elements",
1474 wpa_s
->sme
.assoc_req_ie
,
1475 wpa_s
->sme
.assoc_req_ie_len
);
1476 #ifdef CONFIG_IEEE80211R
1477 if (wpa_key_mgmt_ft(wpa_s
->key_mgmt
)) {
1478 /* Remove RSNE and MDE to allow them to be overridden
1479 * with FILS+FT specific values from
1480 * fils_build_assoc_req(). */
1481 remove_ie(wpa_s
->sme
.assoc_req_ie
,
1482 &wpa_s
->sme
.assoc_req_ie_len
,
1484 wpa_hexdump(MSG_DEBUG
,
1485 "FILS: assoc_req after RSNE removal",
1486 wpa_s
->sme
.assoc_req_ie
,
1487 wpa_s
->sme
.assoc_req_ie_len
);
1488 remove_ie(wpa_s
->sme
.assoc_req_ie
,
1489 &wpa_s
->sme
.assoc_req_ie_len
,
1490 WLAN_EID_MOBILITY_DOMAIN
);
1491 wpa_hexdump(MSG_DEBUG
,
1492 "FILS: assoc_req after MDE removal",
1493 wpa_s
->sme
.assoc_req_ie
,
1494 wpa_s
->sme
.assoc_req_ie_len
);
1496 #endif /* CONFIG_IEEE80211R */
1497 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
1498 if (wpa_s
->sme
.assoc_req_ie_len
+ wpabuf_len(buf
) >
1499 sizeof(wpa_s
->sme
.assoc_req_ie
)) {
1500 wpa_printf(MSG_ERROR
,
1501 "FILS: Not enough buffer room for own AssocReq elements");
1505 os_memcpy(wpa_s
->sme
.assoc_req_ie
+ wpa_s
->sme
.assoc_req_ie_len
,
1506 wpabuf_head(buf
), wpabuf_len(buf
));
1507 wpa_s
->sme
.assoc_req_ie_len
+= wpabuf_len(buf
);
1509 wpa_hexdump(MSG_DEBUG
, "FILS: assoc_req after FILS elements",
1510 wpa_s
->sme
.assoc_req_ie
,
1511 wpa_s
->sme
.assoc_req_ie_len
);
1513 os_memcpy(nonces
, snonce
, FILS_NONCE_LEN
);
1514 os_memcpy(nonces
+ FILS_NONCE_LEN
, anonce
, FILS_NONCE_LEN
);
1515 params
.fils_nonces
= nonces
;
1516 params
.fils_nonces_len
= sizeof(nonces
);
1518 #endif /* CONFIG_FILS */
1521 #ifdef CONFIG_TESTING_OPTIONS
1522 if (get_ie_ext(wpa_s
->sme
.assoc_req_ie
, wpa_s
->sme
.assoc_req_ie_len
,
1523 WLAN_EID_EXT_OWE_DH_PARAM
)) {
1524 wpa_printf(MSG_INFO
, "TESTING: Override OWE DH element");
1526 #endif /* CONFIG_TESTING_OPTIONS */
1527 if (auth_type
== WLAN_AUTH_OPEN
&&
1528 wpa_s
->key_mgmt
== WPA_KEY_MGMT_OWE
) {
1529 struct wpabuf
*owe_ie
;
1532 if (wpa_s
->current_ssid
&& wpa_s
->current_ssid
->owe_group
) {
1533 group
= wpa_s
->current_ssid
->owe_group
;
1534 } else if (wpa_s
->assoc_status_code
==
1535 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED
) {
1536 if (wpa_s
->last_owe_group
== 19)
1538 else if (wpa_s
->last_owe_group
== 20)
1541 group
= OWE_DH_GROUP
;
1543 group
= OWE_DH_GROUP
;
1546 wpa_s
->last_owe_group
= group
;
1547 wpa_printf(MSG_DEBUG
, "OWE: Try to use group %u", group
);
1548 owe_ie
= owe_build_assoc_req(wpa_s
->wpa
, group
);
1550 wpa_printf(MSG_ERROR
,
1551 "OWE: Failed to build IE for Association Request frame");
1554 if (wpa_s
->sme
.assoc_req_ie_len
+ wpabuf_len(owe_ie
) >
1555 sizeof(wpa_s
->sme
.assoc_req_ie
)) {
1556 wpa_printf(MSG_ERROR
,
1557 "OWE: Not enough buffer room for own Association Request frame elements");
1558 wpabuf_free(owe_ie
);
1561 os_memcpy(wpa_s
->sme
.assoc_req_ie
+ wpa_s
->sme
.assoc_req_ie_len
,
1562 wpabuf_head(owe_ie
), wpabuf_len(owe_ie
));
1563 wpa_s
->sme
.assoc_req_ie_len
+= wpabuf_len(owe_ie
);
1564 wpabuf_free(owe_ie
);
1566 #endif /* CONFIG_OWE */
1568 if (wpa_s
->current_ssid
&& wpa_s
->current_ssid
->multi_ap_backhaul_sta
) {
1569 size_t multi_ap_ie_len
;
1571 multi_ap_ie_len
= add_multi_ap_ie(
1572 wpa_s
->sme
.assoc_req_ie
+ wpa_s
->sme
.assoc_req_ie_len
,
1573 sizeof(wpa_s
->sme
.assoc_req_ie
) -
1574 wpa_s
->sme
.assoc_req_ie_len
,
1575 MULTI_AP_BACKHAUL_STA
);
1576 if (multi_ap_ie_len
== 0) {
1577 wpa_printf(MSG_ERROR
,
1578 "Multi-AP: Failed to build Multi-AP IE");
1581 wpa_s
->sme
.assoc_req_ie_len
+= multi_ap_ie_len
;
1584 params
.bssid
= bssid
;
1585 params
.ssid
= wpa_s
->sme
.ssid
;
1586 params
.ssid_len
= wpa_s
->sme
.ssid_len
;
1587 params
.freq
.freq
= wpa_s
->sme
.freq
;
1588 params
.bg_scan_period
= wpa_s
->current_ssid
?
1589 wpa_s
->current_ssid
->bg_scan_period
: -1;
1590 params
.wpa_ie
= wpa_s
->sme
.assoc_req_ie_len
?
1591 wpa_s
->sme
.assoc_req_ie
: NULL
;
1592 params
.wpa_ie_len
= wpa_s
->sme
.assoc_req_ie_len
;
1593 wpa_hexdump(MSG_DEBUG
, "SME: Association Request IEs",
1594 params
.wpa_ie
, params
.wpa_ie_len
);
1595 params
.pairwise_suite
= wpa_s
->pairwise_cipher
;
1596 params
.group_suite
= wpa_s
->group_cipher
;
1597 params
.mgmt_group_suite
= wpa_s
->mgmt_group_cipher
;
1598 params
.key_mgmt_suite
= wpa_s
->key_mgmt
;
1599 params
.wpa_proto
= wpa_s
->wpa_proto
;
1600 #ifdef CONFIG_HT_OVERRIDES
1601 os_memset(&htcaps
, 0, sizeof(htcaps
));
1602 os_memset(&htcaps_mask
, 0, sizeof(htcaps_mask
));
1603 params
.htcaps
= (u8
*) &htcaps
;
1604 params
.htcaps_mask
= (u8
*) &htcaps_mask
;
1605 wpa_supplicant_apply_ht_overrides(wpa_s
, wpa_s
->current_ssid
, ¶ms
);
1606 #endif /* CONFIG_HT_OVERRIDES */
1607 #ifdef CONFIG_VHT_OVERRIDES
1608 os_memset(&vhtcaps
, 0, sizeof(vhtcaps
));
1609 os_memset(&vhtcaps_mask
, 0, sizeof(vhtcaps_mask
));
1610 params
.vhtcaps
= &vhtcaps
;
1611 params
.vhtcaps_mask
= &vhtcaps_mask
;
1612 wpa_supplicant_apply_vht_overrides(wpa_s
, wpa_s
->current_ssid
, ¶ms
);
1613 #endif /* CONFIG_VHT_OVERRIDES */
1614 #ifdef CONFIG_IEEE80211R
1615 if (auth_type
== WLAN_AUTH_FT
&& wpa_s
->sme
.ft_ies
&&
1616 get_ie(wpa_s
->sme
.ft_ies
, wpa_s
->sme
.ft_ies_len
,
1617 WLAN_EID_RIC_DATA
)) {
1618 /* There seems to be a pretty inconvenient bug in the Linux
1619 * kernel IE splitting functionality when RIC is used. For now,
1620 * skip correct behavior in IE construction here (i.e., drop the
1621 * additional non-FT-specific IEs) to avoid kernel issues. This
1622 * is fine since RIC is used only for testing purposes in the
1623 * current implementation. */
1624 wpa_printf(MSG_INFO
,
1625 "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
1626 params
.wpa_ie
= wpa_s
->sme
.ft_ies
;
1627 params
.wpa_ie_len
= wpa_s
->sme
.ft_ies_len
;
1628 } else if (auth_type
== WLAN_AUTH_FT
&& wpa_s
->sme
.ft_ies
) {
1629 const u8
*rm_en
, *pos
, *end
;
1630 size_t rm_en_len
= 0;
1631 u8
*rm_en_dup
= NULL
, *wpos
;
1633 /* Remove RSNE, MDE, FTE to allow them to be overridden with
1634 * FT specific values */
1635 remove_ie(wpa_s
->sme
.assoc_req_ie
,
1636 &wpa_s
->sme
.assoc_req_ie_len
,
1638 remove_ie(wpa_s
->sme
.assoc_req_ie
,
1639 &wpa_s
->sme
.assoc_req_ie_len
,
1640 WLAN_EID_MOBILITY_DOMAIN
);
1641 remove_ie(wpa_s
->sme
.assoc_req_ie
,
1642 &wpa_s
->sme
.assoc_req_ie_len
,
1643 WLAN_EID_FAST_BSS_TRANSITION
);
1644 rm_en
= get_ie(wpa_s
->sme
.assoc_req_ie
,
1645 wpa_s
->sme
.assoc_req_ie_len
,
1646 WLAN_EID_RRM_ENABLED_CAPABILITIES
);
1648 /* Need to remove RM Enabled Capabilities element as
1649 * well temporarily, so that it can be placed between
1651 rm_en_len
= 2 + rm_en
[1];
1652 rm_en_dup
= os_memdup(rm_en
, rm_en_len
);
1653 remove_ie(wpa_s
->sme
.assoc_req_ie
,
1654 &wpa_s
->sme
.assoc_req_ie_len
,
1655 WLAN_EID_RRM_ENABLED_CAPABILITIES
);
1657 wpa_hexdump(MSG_DEBUG
,
1658 "SME: Association Request IEs after FT IE removal",
1659 wpa_s
->sme
.assoc_req_ie
,
1660 wpa_s
->sme
.assoc_req_ie_len
);
1661 if (wpa_s
->sme
.assoc_req_ie_len
+ wpa_s
->sme
.ft_ies_len
+
1662 rm_en_len
> sizeof(wpa_s
->sme
.assoc_req_ie
)) {
1663 wpa_printf(MSG_ERROR
,
1664 "SME: Not enough buffer room for FT IEs in Association Request frame");
1669 os_memmove(wpa_s
->sme
.assoc_req_ie
+ wpa_s
->sme
.ft_ies_len
+
1671 wpa_s
->sme
.assoc_req_ie
,
1672 wpa_s
->sme
.assoc_req_ie_len
);
1673 pos
= wpa_s
->sme
.ft_ies
;
1674 end
= pos
+ wpa_s
->sme
.ft_ies_len
;
1675 wpos
= wpa_s
->sme
.assoc_req_ie
;
1676 if (*pos
== WLAN_EID_RSN
) {
1677 os_memcpy(wpos
, pos
, 2 + pos
[1]);
1682 os_memcpy(wpos
, rm_en_dup
, rm_en_len
);
1686 os_memcpy(wpos
, pos
, end
- pos
);
1687 wpa_s
->sme
.assoc_req_ie_len
+= wpa_s
->sme
.ft_ies_len
+
1689 params
.wpa_ie
= wpa_s
->sme
.assoc_req_ie
;
1690 params
.wpa_ie_len
= wpa_s
->sme
.assoc_req_ie_len
;
1691 wpa_hexdump(MSG_DEBUG
,
1692 "SME: Association Request IEs after FT override",
1693 params
.wpa_ie
, params
.wpa_ie_len
);
1695 #endif /* CONFIG_IEEE80211R */
1697 params
.mgmt_frame_protection
= wpa_s
->sme
.mfp
;
1698 params
.rrm_used
= wpa_s
->rrm
.rrm_used
;
1699 if (wpa_s
->sme
.prev_bssid_set
)
1700 params
.prev_bssid
= wpa_s
->sme
.prev_bssid
;
1702 wpa_msg(wpa_s
, MSG_INFO
, "Trying to associate with " MACSTR
1703 " (SSID='%s' freq=%d MHz)", MAC2STR(params
.bssid
),
1704 params
.ssid
? wpa_ssid_txt(params
.ssid
, params
.ssid_len
) : "",
1707 wpa_supplicant_set_state(wpa_s
, WPA_ASSOCIATING
);
1709 if (params
.wpa_ie
== NULL
||
1710 ieee802_11_parse_elems(params
.wpa_ie
, params
.wpa_ie_len
, &elems
, 0)
1712 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Could not parse own IEs?!");
1713 os_memset(&elems
, 0, sizeof(elems
));
1716 params
.wpa_proto
= WPA_PROTO_RSN
;
1717 wpa_sm_set_assoc_wpa_ie(wpa_s
->wpa
, elems
.rsn_ie
- 2,
1718 elems
.rsn_ie_len
+ 2);
1719 } else if (elems
.wpa_ie
) {
1720 params
.wpa_proto
= WPA_PROTO_WPA
;
1721 wpa_sm_set_assoc_wpa_ie(wpa_s
->wpa
, elems
.wpa_ie
- 2,
1722 elems
.wpa_ie_len
+ 2);
1723 } else if (elems
.osen
) {
1724 params
.wpa_proto
= WPA_PROTO_OSEN
;
1725 wpa_sm_set_assoc_wpa_ie(wpa_s
->wpa
, elems
.osen
- 2,
1726 elems
.osen_len
+ 2);
1728 wpa_sm_set_assoc_wpa_ie(wpa_s
->wpa
, NULL
, 0);
1729 if (wpa_s
->current_ssid
&& wpa_s
->current_ssid
->p2p_group
)
1732 if (wpa_s
->p2pdev
->set_sta_uapsd
)
1733 params
.uapsd
= wpa_s
->p2pdev
->sta_uapsd
;
1737 if (wpa_drv_associate(wpa_s
, ¶ms
) < 0) {
1738 wpa_msg(wpa_s
, MSG_INFO
, "SME: Association request to the "
1740 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1741 wpa_supplicant_set_state(wpa_s
, WPA_DISCONNECTED
);
1742 os_memset(wpa_s
->pending_bssid
, 0, ETH_ALEN
);
1746 eloop_register_timeout(SME_ASSOC_TIMEOUT
, 0, sme_assoc_timer
, wpa_s
,
1749 #ifdef CONFIG_TESTING_OPTIONS
1750 wpabuf_free(wpa_s
->last_assoc_req_wpa_ie
);
1751 wpa_s
->last_assoc_req_wpa_ie
= NULL
;
1753 wpa_s
->last_assoc_req_wpa_ie
=
1754 wpabuf_alloc_copy(params
.wpa_ie
, params
.wpa_ie_len
);
1755 #endif /* CONFIG_TESTING_OPTIONS */
1759 int sme_update_ft_ies(struct wpa_supplicant
*wpa_s
, const u8
*md
,
1760 const u8
*ies
, size_t ies_len
)
1762 if (md
== NULL
|| ies
== NULL
) {
1763 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Remove mobility domain");
1764 os_free(wpa_s
->sme
.ft_ies
);
1765 wpa_s
->sme
.ft_ies
= NULL
;
1766 wpa_s
->sme
.ft_ies_len
= 0;
1767 wpa_s
->sme
.ft_used
= 0;
1771 os_memcpy(wpa_s
->sme
.mobility_domain
, md
, MOBILITY_DOMAIN_ID_LEN
);
1772 wpa_hexdump(MSG_DEBUG
, "SME: FT IEs", ies
, ies_len
);
1773 os_free(wpa_s
->sme
.ft_ies
);
1774 wpa_s
->sme
.ft_ies
= os_memdup(ies
, ies_len
);
1775 if (wpa_s
->sme
.ft_ies
== NULL
)
1777 wpa_s
->sme
.ft_ies_len
= ies_len
;
1782 static void sme_deauth(struct wpa_supplicant
*wpa_s
)
1786 bssid_changed
= !is_zero_ether_addr(wpa_s
->bssid
);
1788 if (wpa_drv_deauthenticate(wpa_s
, wpa_s
->pending_bssid
,
1789 WLAN_REASON_DEAUTH_LEAVING
) < 0) {
1790 wpa_msg(wpa_s
, MSG_INFO
, "SME: Deauth request to the driver "
1793 wpa_s
->sme
.prev_bssid_set
= 0;
1795 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1796 wpa_supplicant_set_state(wpa_s
, WPA_DISCONNECTED
);
1797 os_memset(wpa_s
->bssid
, 0, ETH_ALEN
);
1798 os_memset(wpa_s
->pending_bssid
, 0, ETH_ALEN
);
1800 wpas_notify_bssid_changed(wpa_s
);
1804 void sme_event_assoc_reject(struct wpa_supplicant
*wpa_s
,
1805 union wpa_event_data
*data
)
1807 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Association with " MACSTR
" failed: "
1808 "status code %d", MAC2STR(wpa_s
->pending_bssid
),
1809 data
->assoc_reject
.status_code
);
1811 eloop_cancel_timeout(sme_assoc_timer
, wpa_s
, NULL
);
1814 if (wpa_s
->sme
.sae_pmksa_caching
&& wpa_s
->current_ssid
&&
1815 wpa_key_mgmt_sae(wpa_s
->current_ssid
->key_mgmt
)) {
1816 wpa_dbg(wpa_s
, MSG_DEBUG
,
1817 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
1818 wpa_sm_aborted_cached(wpa_s
->wpa
);
1819 wpa_sm_pmksa_cache_flush(wpa_s
->wpa
, wpa_s
->current_ssid
);
1820 if (wpa_s
->current_bss
) {
1821 struct wpa_bss
*bss
= wpa_s
->current_bss
;
1822 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
1824 wpa_drv_deauthenticate(wpa_s
, wpa_s
->pending_bssid
,
1825 WLAN_REASON_DEAUTH_LEAVING
);
1826 wpas_connect_work_done(wpa_s
);
1827 wpa_supplicant_mark_disassoc(wpa_s
);
1828 wpa_supplicant_connect(wpa_s
, bss
, ssid
);
1832 #endif /* CONFIG_SAE */
1835 * For now, unconditionally terminate the previous authentication. In
1836 * theory, this should not be needed, but mac80211 gets quite confused
1837 * if the authentication is left pending.. Some roaming cases might
1838 * benefit from using the previous authentication, so this could be
1839 * optimized in the future.
1845 void sme_event_auth_timed_out(struct wpa_supplicant
*wpa_s
,
1846 union wpa_event_data
*data
)
1848 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Authentication timed out");
1849 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1850 wpa_supplicant_mark_disassoc(wpa_s
);
1854 void sme_event_assoc_timed_out(struct wpa_supplicant
*wpa_s
,
1855 union wpa_event_data
*data
)
1857 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Association timed out");
1858 wpas_connection_failed(wpa_s
, wpa_s
->pending_bssid
);
1859 wpa_supplicant_mark_disassoc(wpa_s
);
1863 void sme_event_disassoc(struct wpa_supplicant
*wpa_s
,
1864 struct disassoc_info
*info
)
1866 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Disassociation event received");
1867 if (wpa_s
->sme
.prev_bssid_set
) {
1869 * cfg80211/mac80211 can get into somewhat confused state if
1870 * the AP only disassociates us and leaves us in authenticated
1871 * state. For now, force the state to be cleared to avoid
1872 * confusing errors if we try to associate with the AP again.
1874 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Deauthenticate to clear "
1876 wpa_drv_deauthenticate(wpa_s
, wpa_s
->sme
.prev_bssid
,
1877 WLAN_REASON_DEAUTH_LEAVING
);
1882 static void sme_auth_timer(void *eloop_ctx
, void *timeout_ctx
)
1884 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
1885 if (wpa_s
->wpa_state
== WPA_AUTHENTICATING
) {
1886 wpa_msg(wpa_s
, MSG_DEBUG
, "SME: Authentication timeout");
1892 static void sme_assoc_timer(void *eloop_ctx
, void *timeout_ctx
)
1894 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
1895 if (wpa_s
->wpa_state
== WPA_ASSOCIATING
) {
1896 wpa_msg(wpa_s
, MSG_DEBUG
, "SME: Association timeout");
1902 void sme_state_changed(struct wpa_supplicant
*wpa_s
)
1904 /* Make sure timers are cleaned up appropriately. */
1905 if (wpa_s
->wpa_state
!= WPA_ASSOCIATING
)
1906 eloop_cancel_timeout(sme_assoc_timer
, wpa_s
, NULL
);
1907 if (wpa_s
->wpa_state
!= WPA_AUTHENTICATING
)
1908 eloop_cancel_timeout(sme_auth_timer
, wpa_s
, NULL
);
1912 void sme_disassoc_while_authenticating(struct wpa_supplicant
*wpa_s
,
1913 const u8
*prev_pending_bssid
)
1916 * mac80211-workaround to force deauth on failed auth cmd,
1917 * requires us to remain in authenticating state to allow the
1918 * second authentication attempt to be continued properly.
1920 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Allow pending authentication "
1921 "to proceed after disconnection event");
1922 wpa_supplicant_set_state(wpa_s
, WPA_AUTHENTICATING
);
1923 os_memcpy(wpa_s
->pending_bssid
, prev_pending_bssid
, ETH_ALEN
);
1926 * Re-arm authentication timer in case auth fails for whatever reason.
1928 eloop_cancel_timeout(sme_auth_timer
, wpa_s
, NULL
);
1929 eloop_register_timeout(SME_AUTH_TIMEOUT
, 0, sme_auth_timer
, wpa_s
,
1934 void sme_clear_on_disassoc(struct wpa_supplicant
*wpa_s
)
1936 wpa_s
->sme
.prev_bssid_set
= 0;
1938 wpabuf_free(wpa_s
->sme
.sae_token
);
1939 wpa_s
->sme
.sae_token
= NULL
;
1940 sae_clear_data(&wpa_s
->sme
.sae
);
1941 #endif /* CONFIG_SAE */
1942 #ifdef CONFIG_IEEE80211R
1943 if (wpa_s
->sme
.ft_ies
|| wpa_s
->sme
.ft_used
)
1944 sme_update_ft_ies(wpa_s
, NULL
, NULL
, 0);
1945 #endif /* CONFIG_IEEE80211R */
1949 void sme_deinit(struct wpa_supplicant
*wpa_s
)
1951 os_free(wpa_s
->sme
.ft_ies
);
1952 wpa_s
->sme
.ft_ies
= NULL
;
1953 wpa_s
->sme
.ft_ies_len
= 0;
1954 #ifdef CONFIG_IEEE80211W
1955 sme_stop_sa_query(wpa_s
);
1956 #endif /* CONFIG_IEEE80211W */
1957 sme_clear_on_disassoc(wpa_s
);
1959 eloop_cancel_timeout(sme_assoc_timer
, wpa_s
, NULL
);
1960 eloop_cancel_timeout(sme_auth_timer
, wpa_s
, NULL
);
1961 eloop_cancel_timeout(sme_obss_scan_timeout
, wpa_s
, NULL
);
1965 static void sme_send_2040_bss_coex(struct wpa_supplicant
*wpa_s
,
1966 const u8
*chan_list
, u8 num_channels
,
1969 struct ieee80211_2040_bss_coex_ie
*bc_ie
;
1970 struct ieee80211_2040_intol_chan_report
*ic_report
;
1973 wpa_printf(MSG_DEBUG
, "SME: Send 20/40 BSS Coexistence to " MACSTR
1974 " (num_channels=%u num_intol=%u)",
1975 MAC2STR(wpa_s
->bssid
), num_channels
, num_intol
);
1976 wpa_hexdump(MSG_DEBUG
, "SME: 20/40 BSS Intolerant Channels",
1977 chan_list
, num_channels
);
1979 buf
= wpabuf_alloc(2 + /* action.category + action_code */
1980 sizeof(struct ieee80211_2040_bss_coex_ie
) +
1981 sizeof(struct ieee80211_2040_intol_chan_report
) +
1986 wpabuf_put_u8(buf
, WLAN_ACTION_PUBLIC
);
1987 wpabuf_put_u8(buf
, WLAN_PA_20_40_BSS_COEX
);
1989 bc_ie
= wpabuf_put(buf
, sizeof(*bc_ie
));
1990 bc_ie
->element_id
= WLAN_EID_20_40_BSS_COEXISTENCE
;
1993 bc_ie
->coex_param
|= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ
;
1995 if (num_channels
> 0) {
1996 ic_report
= wpabuf_put(buf
, sizeof(*ic_report
));
1997 ic_report
->element_id
= WLAN_EID_20_40_BSS_INTOLERANT
;
1998 ic_report
->length
= num_channels
+ 1;
1999 ic_report
->op_class
= 0;
2000 os_memcpy(wpabuf_put(buf
, num_channels
), chan_list
,
2004 if (wpa_drv_send_action(wpa_s
, wpa_s
->assoc_freq
, 0, wpa_s
->bssid
,
2005 wpa_s
->own_addr
, wpa_s
->bssid
,
2006 wpabuf_head(buf
), wpabuf_len(buf
), 0) < 0) {
2007 wpa_msg(wpa_s
, MSG_INFO
,
2008 "SME: Failed to send 20/40 BSS Coexistence frame");
2015 int sme_proc_obss_scan(struct wpa_supplicant
*wpa_s
)
2017 struct wpa_bss
*bss
;
2020 u8 chan_list
[P2P_MAX_CHANNELS
], channel
;
2021 u8 num_channels
= 0, num_intol
= 0, i
;
2023 if (!wpa_s
->sme
.sched_obss_scan
)
2026 wpa_s
->sme
.sched_obss_scan
= 0;
2027 if (!wpa_s
->current_bss
|| wpa_s
->wpa_state
!= WPA_COMPLETED
)
2031 * Check whether AP uses regulatory triplet or channel triplet in
2032 * country info. Right now the operating class of the BSS channel
2033 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
2034 * based on the assumption that operating class triplet is not used in
2035 * beacon frame. If the First Channel Number/Operating Extension
2036 * Identifier octet has a positive integer value of 201 or greater,
2037 * then its operating class triplet.
2039 * TODO: If Supported Operating Classes element is present in beacon
2040 * frame, have to lookup operating class in Annex E and fill them in
2043 ie
= wpa_bss_get_ie(wpa_s
->current_bss
, WLAN_EID_COUNTRY
);
2044 if (ie
&& (ie
[1] >= 6) && (ie
[5] >= 201))
2047 os_memset(chan_list
, 0, sizeof(chan_list
));
2049 dl_list_for_each(bss
, &wpa_s
->bss
, struct wpa_bss
, list
) {
2050 /* Skip other band bss */
2051 enum hostapd_hw_mode mode
;
2052 mode
= ieee80211_freq_to_chan(bss
->freq
, &channel
);
2053 if (mode
!= HOSTAPD_MODE_IEEE80211G
&&
2054 mode
!= HOSTAPD_MODE_IEEE80211B
)
2057 ie
= wpa_bss_get_ie(bss
, WLAN_EID_HT_CAP
);
2058 ht_cap
= (ie
&& (ie
[1] == 26)) ? WPA_GET_LE16(ie
+ 2) : 0;
2059 wpa_printf(MSG_DEBUG
, "SME OBSS scan BSS " MACSTR
2060 " freq=%u chan=%u ht_cap=0x%x",
2061 MAC2STR(bss
->bssid
), bss
->freq
, channel
, ht_cap
);
2063 if (!ht_cap
|| (ht_cap
& HT_CAP_INFO_40MHZ_INTOLERANT
)) {
2064 if (ht_cap
& HT_CAP_INFO_40MHZ_INTOLERANT
)
2067 /* Check whether the channel is already considered */
2068 for (i
= 0; i
< num_channels
; i
++) {
2069 if (channel
== chan_list
[i
])
2072 if (i
!= num_channels
)
2075 chan_list
[num_channels
++] = channel
;
2079 sme_send_2040_bss_coex(wpa_s
, chan_list
, num_channels
, num_intol
);
2084 static void wpa_obss_scan_freqs_list(struct wpa_supplicant
*wpa_s
,
2085 struct wpa_driver_scan_params
*params
)
2087 /* Include only affected channels */
2088 struct hostapd_hw_modes
*mode
;
2092 mode
= get_mode(wpa_s
->hw
.modes
, wpa_s
->hw
.num_modes
,
2093 HOSTAPD_MODE_IEEE80211G
);
2095 /* No channels supported in this band - use empty list */
2096 params
->freqs
= os_zalloc(sizeof(int));
2100 if (wpa_s
->sme
.ht_sec_chan
== HT_SEC_CHAN_UNKNOWN
&&
2101 wpa_s
->current_bss
) {
2104 ie
= wpa_bss_get_ie(wpa_s
->current_bss
, WLAN_EID_HT_OPERATION
);
2105 if (ie
&& ie
[1] >= 2) {
2108 o
= ie
[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK
;
2109 if (o
== HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE
)
2110 wpa_s
->sme
.ht_sec_chan
= HT_SEC_CHAN_ABOVE
;
2111 else if (o
== HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW
)
2112 wpa_s
->sme
.ht_sec_chan
= HT_SEC_CHAN_BELOW
;
2116 start
= wpa_s
->assoc_freq
- 10;
2117 end
= wpa_s
->assoc_freq
+ 10;
2118 switch (wpa_s
->sme
.ht_sec_chan
) {
2119 case HT_SEC_CHAN_UNKNOWN
:
2120 /* HT40+ possible on channels 1..9 */
2121 if (wpa_s
->assoc_freq
<= 2452)
2123 /* HT40- possible on channels 5-13 */
2124 if (wpa_s
->assoc_freq
>= 2432)
2127 case HT_SEC_CHAN_ABOVE
:
2130 case HT_SEC_CHAN_BELOW
:
2134 wpa_printf(MSG_DEBUG
,
2135 "OBSS: assoc_freq %d possible affected range %d-%d",
2136 wpa_s
->assoc_freq
, start
, end
);
2138 params
->freqs
= os_calloc(mode
->num_channels
+ 1, sizeof(int));
2139 if (params
->freqs
== NULL
)
2141 for (count
= 0, i
= 0; i
< mode
->num_channels
; i
++) {
2144 if (mode
->channels
[i
].flag
& HOSTAPD_CHAN_DISABLED
)
2146 freq
= mode
->channels
[i
].freq
;
2147 if (freq
- 10 >= end
|| freq
+ 10 <= start
)
2148 continue; /* not affected */
2149 params
->freqs
[count
++] = freq
;
2154 static void sme_obss_scan_timeout(void *eloop_ctx
, void *timeout_ctx
)
2156 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
2157 struct wpa_driver_scan_params params
;
2159 if (!wpa_s
->current_bss
) {
2160 wpa_printf(MSG_DEBUG
, "SME OBSS: Ignore scan request");
2164 os_memset(¶ms
, 0, sizeof(params
));
2165 wpa_obss_scan_freqs_list(wpa_s
, ¶ms
);
2166 params
.low_priority
= 1;
2167 wpa_printf(MSG_DEBUG
, "SME OBSS: Request an OBSS scan");
2169 if (wpa_supplicant_trigger_scan(wpa_s
, ¶ms
))
2170 wpa_printf(MSG_DEBUG
, "SME OBSS: Failed to trigger scan");
2172 wpa_s
->sme
.sched_obss_scan
= 1;
2173 os_free(params
.freqs
);
2175 eloop_register_timeout(wpa_s
->sme
.obss_scan_int
, 0,
2176 sme_obss_scan_timeout
, wpa_s
, NULL
);
2180 void sme_sched_obss_scan(struct wpa_supplicant
*wpa_s
, int enable
)
2183 struct wpa_bss
*bss
= wpa_s
->current_bss
;
2184 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
2185 struct hostapd_hw_modes
*hw_mode
= NULL
;
2188 eloop_cancel_timeout(sme_obss_scan_timeout
, wpa_s
, NULL
);
2189 wpa_s
->sme
.sched_obss_scan
= 0;
2190 wpa_s
->sme
.ht_sec_chan
= HT_SEC_CHAN_UNKNOWN
;
2195 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
2196 * or it expects OBSS scan to be performed by wpa_supplicant.
2198 if (!((wpa_s
->drv_flags
& WPA_DRIVER_FLAGS_SME
) ||
2199 (wpa_s
->drv_flags
& WPA_DRIVER_FLAGS_OBSS_SCAN
)) ||
2200 ssid
== NULL
|| ssid
->mode
!= IEEE80211_MODE_INFRA
)
2203 if (!wpa_s
->hw
.modes
)
2206 /* only HT caps in 11g mode are relevant */
2207 for (i
= 0; i
< wpa_s
->hw
.num_modes
; i
++) {
2208 hw_mode
= &wpa_s
->hw
.modes
[i
];
2209 if (hw_mode
->mode
== HOSTAPD_MODE_IEEE80211G
)
2213 /* Driver does not support HT40 for 11g or doesn't have 11g. */
2214 if (i
== wpa_s
->hw
.num_modes
|| !hw_mode
||
2215 !(hw_mode
->ht_capab
& HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
2218 if (bss
== NULL
|| bss
->freq
< 2400 || bss
->freq
> 2500)
2219 return; /* Not associated on 2.4 GHz band */
2221 /* Check whether AP supports HT40 */
2222 ie
= wpa_bss_get_ie(wpa_s
->current_bss
, WLAN_EID_HT_CAP
);
2223 if (!ie
|| ie
[1] < 2 ||
2224 !(WPA_GET_LE16(ie
+ 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
2225 return; /* AP does not support HT40 */
2227 ie
= wpa_bss_get_ie(wpa_s
->current_bss
,
2228 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS
);
2229 if (!ie
|| ie
[1] < 14)
2230 return; /* AP does not request OBSS scans */
2232 wpa_s
->sme
.obss_scan_int
= WPA_GET_LE16(ie
+ 6);
2233 if (wpa_s
->sme
.obss_scan_int
< 10) {
2234 wpa_printf(MSG_DEBUG
, "SME: Invalid OBSS Scan Interval %u "
2235 "replaced with the minimum 10 sec",
2236 wpa_s
->sme
.obss_scan_int
);
2237 wpa_s
->sme
.obss_scan_int
= 10;
2239 wpa_printf(MSG_DEBUG
, "SME: OBSS Scan Interval %u sec",
2240 wpa_s
->sme
.obss_scan_int
);
2241 eloop_register_timeout(wpa_s
->sme
.obss_scan_int
, 0,
2242 sme_obss_scan_timeout
, wpa_s
, NULL
);
2246 #ifdef CONFIG_IEEE80211W
2248 static const unsigned int sa_query_max_timeout
= 1000;
2249 static const unsigned int sa_query_retry_timeout
= 201;
2250 static const unsigned int sa_query_ch_switch_max_delay
= 5000; /* in usec */
2252 static int sme_check_sa_query_timeout(struct wpa_supplicant
*wpa_s
)
2255 struct os_reltime now
, passed
;
2256 os_get_reltime(&now
);
2257 os_reltime_sub(&now
, &wpa_s
->sme
.sa_query_start
, &passed
);
2258 tu
= (passed
.sec
* 1000000 + passed
.usec
) / 1024;
2259 if (sa_query_max_timeout
< tu
) {
2260 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: SA Query timed out");
2261 sme_stop_sa_query(wpa_s
);
2262 wpa_supplicant_deauthenticate(
2263 wpa_s
, WLAN_REASON_PREV_AUTH_NOT_VALID
);
2271 static void sme_send_sa_query_req(struct wpa_supplicant
*wpa_s
,
2274 u8 req
[2 + WLAN_SA_QUERY_TR_ID_LEN
+ OCV_OCI_EXTENDED_LEN
];
2275 u8 req_len
= 2 + WLAN_SA_QUERY_TR_ID_LEN
;
2277 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Sending SA Query Request to "
2278 MACSTR
, MAC2STR(wpa_s
->bssid
));
2279 wpa_hexdump(MSG_DEBUG
, "SME: SA Query Transaction ID",
2280 trans_id
, WLAN_SA_QUERY_TR_ID_LEN
);
2281 req
[0] = WLAN_ACTION_SA_QUERY
;
2282 req
[1] = WLAN_SA_QUERY_REQUEST
;
2283 os_memcpy(req
+ 2, trans_id
, WLAN_SA_QUERY_TR_ID_LEN
);
2286 if (wpa_sm_ocv_enabled(wpa_s
->wpa
)) {
2287 struct wpa_channel_info ci
;
2289 if (wpa_drv_channel_info(wpa_s
, &ci
) != 0) {
2290 wpa_printf(MSG_WARNING
,
2291 "Failed to get channel info for OCI element in SA Query Request frame");
2295 if (ocv_insert_extended_oci(&ci
, req
+ req_len
) < 0)
2298 req_len
+= OCV_OCI_EXTENDED_LEN
;
2300 #endif /* CONFIG_OCV */
2302 if (wpa_drv_send_action(wpa_s
, wpa_s
->assoc_freq
, 0, wpa_s
->bssid
,
2303 wpa_s
->own_addr
, wpa_s
->bssid
,
2304 req
, req_len
, 0) < 0)
2305 wpa_msg(wpa_s
, MSG_INFO
, "SME: Failed to send SA Query "
2310 static void sme_sa_query_timer(void *eloop_ctx
, void *timeout_ctx
)
2312 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
2313 unsigned int timeout
, sec
, usec
;
2314 u8
*trans_id
, *nbuf
;
2316 if (wpa_s
->sme
.sa_query_count
> 0 &&
2317 sme_check_sa_query_timeout(wpa_s
))
2320 nbuf
= os_realloc_array(wpa_s
->sme
.sa_query_trans_id
,
2321 wpa_s
->sme
.sa_query_count
+ 1,
2322 WLAN_SA_QUERY_TR_ID_LEN
);
2324 sme_stop_sa_query(wpa_s
);
2327 if (wpa_s
->sme
.sa_query_count
== 0) {
2328 /* Starting a new SA Query procedure */
2329 os_get_reltime(&wpa_s
->sme
.sa_query_start
);
2331 trans_id
= nbuf
+ wpa_s
->sme
.sa_query_count
* WLAN_SA_QUERY_TR_ID_LEN
;
2332 wpa_s
->sme
.sa_query_trans_id
= nbuf
;
2333 wpa_s
->sme
.sa_query_count
++;
2335 if (os_get_random(trans_id
, WLAN_SA_QUERY_TR_ID_LEN
) < 0) {
2336 wpa_printf(MSG_DEBUG
, "Could not generate SA Query ID");
2337 sme_stop_sa_query(wpa_s
);
2341 timeout
= sa_query_retry_timeout
;
2342 sec
= ((timeout
/ 1000) * 1024) / 1000;
2343 usec
= (timeout
% 1000) * 1024;
2344 eloop_register_timeout(sec
, usec
, sme_sa_query_timer
, wpa_s
, NULL
);
2346 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Association SA Query attempt %d",
2347 wpa_s
->sme
.sa_query_count
);
2349 sme_send_sa_query_req(wpa_s
, trans_id
);
2353 static void sme_start_sa_query(struct wpa_supplicant
*wpa_s
)
2355 sme_sa_query_timer(wpa_s
, NULL
);
2359 static void sme_stop_sa_query(struct wpa_supplicant
*wpa_s
)
2361 eloop_cancel_timeout(sme_sa_query_timer
, wpa_s
, NULL
);
2362 os_free(wpa_s
->sme
.sa_query_trans_id
);
2363 wpa_s
->sme
.sa_query_trans_id
= NULL
;
2364 wpa_s
->sme
.sa_query_count
= 0;
2368 void sme_event_unprot_disconnect(struct wpa_supplicant
*wpa_s
, const u8
*sa
,
2369 const u8
*da
, u16 reason_code
)
2371 struct wpa_ssid
*ssid
;
2372 struct os_reltime now
;
2374 if (wpa_s
->wpa_state
!= WPA_COMPLETED
)
2376 ssid
= wpa_s
->current_ssid
;
2377 if (wpas_get_ssid_pmf(wpa_s
, ssid
) == NO_MGMT_FRAME_PROTECTION
)
2379 if (os_memcmp(sa
, wpa_s
->bssid
, ETH_ALEN
) != 0)
2381 if (reason_code
!= WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA
&&
2382 reason_code
!= WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA
)
2384 if (wpa_s
->sme
.sa_query_count
> 0)
2387 os_get_reltime(&now
);
2388 if (wpa_s
->sme
.last_unprot_disconnect
.sec
&&
2389 !os_reltime_expired(&now
, &wpa_s
->sme
.last_unprot_disconnect
, 10))
2390 return; /* limit SA Query procedure frequency */
2391 wpa_s
->sme
.last_unprot_disconnect
= now
;
2393 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Unprotected disconnect dropped - "
2394 "possible AP/STA state mismatch - trigger SA Query");
2395 sme_start_sa_query(wpa_s
);
2399 void sme_event_ch_switch(struct wpa_supplicant
*wpa_s
)
2404 if (wpa_s
->wpa_state
!= WPA_COMPLETED
||
2405 !wpa_sm_ocv_enabled(wpa_s
->wpa
))
2408 wpa_dbg(wpa_s
, MSG_DEBUG
,
2409 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
2410 sme_stop_sa_query(wpa_s
);
2412 if (os_get_random((u8
*) &_rand
, sizeof(_rand
)) < 0)
2413 _rand
= os_random();
2414 usec
= _rand
% (sa_query_ch_switch_max_delay
+ 1);
2415 eloop_register_timeout(0, usec
, sme_sa_query_timer
, wpa_s
, NULL
);
2419 static void sme_process_sa_query_request(struct wpa_supplicant
*wpa_s
,
2420 const u8
*sa
, const u8
*data
,
2423 u8 resp
[2 + WLAN_SA_QUERY_TR_ID_LEN
+ OCV_OCI_EXTENDED_LEN
];
2424 u8 resp_len
= 2 + WLAN_SA_QUERY_TR_ID_LEN
;
2426 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Sending SA Query Response to "
2427 MACSTR
, MAC2STR(wpa_s
->bssid
));
2429 resp
[0] = WLAN_ACTION_SA_QUERY
;
2430 resp
[1] = WLAN_SA_QUERY_RESPONSE
;
2431 os_memcpy(resp
+ 2, data
+ 1, WLAN_SA_QUERY_TR_ID_LEN
);
2434 if (wpa_sm_ocv_enabled(wpa_s
->wpa
)) {
2435 struct wpa_channel_info ci
;
2437 if (wpa_drv_channel_info(wpa_s
, &ci
) != 0) {
2438 wpa_printf(MSG_WARNING
,
2439 "Failed to get channel info for OCI element in SA Query Response frame");
2443 if (ocv_insert_extended_oci(&ci
, resp
+ resp_len
) < 0)
2446 resp_len
+= OCV_OCI_EXTENDED_LEN
;
2448 #endif /* CONFIG_OCV */
2450 if (wpa_drv_send_action(wpa_s
, wpa_s
->assoc_freq
, 0, wpa_s
->bssid
,
2451 wpa_s
->own_addr
, wpa_s
->bssid
,
2452 resp
, resp_len
, 0) < 0)
2453 wpa_msg(wpa_s
, MSG_INFO
,
2454 "SME: Failed to send SA Query Response");
2458 static void sme_process_sa_query_response(struct wpa_supplicant
*wpa_s
,
2459 const u8
*sa
, const u8
*data
,
2464 if (!wpa_s
->sme
.sa_query_trans_id
)
2467 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Received SA Query response from "
2468 MACSTR
" (trans_id %02x%02x)", MAC2STR(sa
), data
[1], data
[2]);
2470 if (os_memcmp(sa
, wpa_s
->bssid
, ETH_ALEN
) != 0)
2473 for (i
= 0; i
< wpa_s
->sme
.sa_query_count
; i
++) {
2474 if (os_memcmp(wpa_s
->sme
.sa_query_trans_id
+
2475 i
* WLAN_SA_QUERY_TR_ID_LEN
,
2476 data
+ 1, WLAN_SA_QUERY_TR_ID_LEN
) == 0)
2480 if (i
>= wpa_s
->sme
.sa_query_count
) {
2481 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: No matching SA Query "
2482 "transaction identifier found");
2486 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Reply to pending SA Query received "
2487 "from " MACSTR
, MAC2STR(sa
));
2488 sme_stop_sa_query(wpa_s
);
2492 void sme_sa_query_rx(struct wpa_supplicant
*wpa_s
, const u8
*sa
,
2493 const u8
*data
, size_t len
)
2495 if (len
< 1 + WLAN_SA_QUERY_TR_ID_LEN
)
2498 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Received SA Query frame from "
2499 MACSTR
" (trans_id %02x%02x)", MAC2STR(sa
), data
[1], data
[2]);
2502 if (wpa_sm_ocv_enabled(wpa_s
->wpa
)) {
2503 struct ieee802_11_elems elems
;
2504 struct wpa_channel_info ci
;
2506 if (ieee802_11_parse_elems(data
+ 1 + WLAN_SA_QUERY_TR_ID_LEN
,
2507 len
- 1 - WLAN_SA_QUERY_TR_ID_LEN
,
2508 &elems
, 1) == ParseFailed
) {
2509 wpa_printf(MSG_DEBUG
,
2510 "SA Query: Failed to parse elements");
2514 if (wpa_drv_channel_info(wpa_s
, &ci
) != 0) {
2515 wpa_printf(MSG_WARNING
,
2516 "Failed to get channel info to validate received OCI in SA Query Action frame");
2520 if (ocv_verify_tx_params(elems
.oci
, elems
.oci_len
, &ci
,
2521 channel_width_to_int(ci
.chanwidth
),
2522 ci
.seg1_idx
) != 0) {
2523 wpa_printf(MSG_WARNING
, "%s", ocv_errorstr
);
2527 #endif /* CONFIG_OCV */
2529 if (data
[0] == WLAN_SA_QUERY_REQUEST
)
2530 sme_process_sa_query_request(wpa_s
, sa
, data
, len
);
2531 else if (data
[0] == WLAN_SA_QUERY_RESPONSE
)
2532 sme_process_sa_query_response(wpa_s
, sa
, data
, len
);
2535 #endif /* CONFIG_IEEE80211W */