1 /* 2 * wpa_supplicant - SME 3 * Copyright (c) 2009-2010, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "utils/eloop.h" 13 #include "common/ieee802_11_defs.h" 14 #include "common/ieee802_11_common.h" 15 #include "eapol_supp/eapol_supp_sm.h" 16 #include "common/wpa_common.h" 17 #include "rsn_supp/wpa.h" 18 #include "rsn_supp/pmksa_cache.h" 19 #include "config.h" 20 #include "wpa_supplicant_i.h" 21 #include "driver_i.h" 22 #include "wpas_glue.h" 23 #include "wps_supplicant.h" 24 #include "p2p_supplicant.h" 25 #include "notify.h" 26 #include "bss.h" 27 #include "scan.h" 28 #include "sme.h" 29 30 #define SME_AUTH_TIMEOUT 5 31 #define SME_ASSOC_TIMEOUT 5 32 33 static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx); 34 static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx); 35 #ifdef CONFIG_IEEE80211W 36 static void sme_stop_sa_query(struct wpa_supplicant *wpa_s); 37 #endif /* CONFIG_IEEE80211W */ 38 39 40 void sme_authenticate(struct wpa_supplicant *wpa_s, 41 struct wpa_bss *bss, struct wpa_ssid *ssid) 42 { 43 struct wpa_driver_auth_params params; 44 struct wpa_ssid *old_ssid; 45 #ifdef CONFIG_IEEE80211R 46 const u8 *ie; 47 #endif /* CONFIG_IEEE80211R */ 48 #ifdef CONFIG_IEEE80211R 49 const u8 *md = NULL; 50 #endif /* CONFIG_IEEE80211R */ 51 int i, bssid_changed; 52 53 if (bss == NULL) { 54 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " 55 "the network"); 56 return; 57 } 58 59 wpa_s->current_bss = bss; 60 61 os_memset(¶ms, 0, sizeof(params)); 62 wpa_s->reassociate = 0; 63 64 params.freq = bss->freq; 65 params.bssid = bss->bssid; 66 params.ssid = bss->ssid; 67 params.ssid_len = bss->ssid_len; 68 params.p2p = ssid->p2p_group; 69 70 if (wpa_s->sme.ssid_len != params.ssid_len || 71 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) 72 wpa_s->sme.prev_bssid_set = 0; 73 74 wpa_s->sme.freq = params.freq; 75 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); 76 wpa_s->sme.ssid_len = params.ssid_len; 77 78 params.auth_alg = WPA_AUTH_ALG_OPEN; 79 #ifdef IEEE8021X_EAPOL 80 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 81 if (ssid->leap) { 82 if (ssid->non_leap == 0) 83 params.auth_alg = WPA_AUTH_ALG_LEAP; 84 else 85 params.auth_alg |= WPA_AUTH_ALG_LEAP; 86 } 87 } 88 #endif /* IEEE8021X_EAPOL */ 89 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", 90 params.auth_alg); 91 if (ssid->auth_alg) { 92 params.auth_alg = ssid->auth_alg; 93 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " 94 "0x%x", params.auth_alg); 95 } 96 97 for (i = 0; i < NUM_WEP_KEYS; i++) { 98 if (ssid->wep_key_len[i]) 99 params.wep_key[i] = ssid->wep_key[i]; 100 params.wep_key_len[i] = ssid->wep_key_len[i]; 101 } 102 params.wep_tx_keyidx = ssid->wep_tx_keyidx; 103 104 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 105 os_memset(wpa_s->bssid, 0, ETH_ALEN); 106 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); 107 if (bssid_changed) 108 wpas_notify_bssid_changed(wpa_s); 109 110 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || 111 wpa_bss_get_ie(bss, WLAN_EID_RSN)) && 112 wpa_key_mgmt_wpa(ssid->key_mgmt)) { 113 int try_opportunistic; 114 try_opportunistic = ssid->proactive_key_caching && 115 (ssid->proto & WPA_PROTO_RSN); 116 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, 117 wpa_s->current_ssid, 118 try_opportunistic) == 0) 119 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); 120 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 121 if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 122 wpa_s->sme.assoc_req_ie, 123 &wpa_s->sme.assoc_req_ie_len)) { 124 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " 125 "key management and encryption suites"); 126 return; 127 } 128 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { 129 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 130 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, 131 wpa_s->sme.assoc_req_ie, 132 &wpa_s->sme.assoc_req_ie_len)) { 133 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " 134 "key management and encryption suites (no " 135 "scan results)"); 136 return; 137 } 138 #ifdef CONFIG_WPS 139 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 140 struct wpabuf *wps_ie; 141 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); 142 if (wps_ie && wpabuf_len(wps_ie) <= 143 sizeof(wpa_s->sme.assoc_req_ie)) { 144 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); 145 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), 146 wpa_s->sme.assoc_req_ie_len); 147 } else 148 wpa_s->sme.assoc_req_ie_len = 0; 149 wpabuf_free(wps_ie); 150 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 151 #endif /* CONFIG_WPS */ 152 } else { 153 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 154 wpa_s->sme.assoc_req_ie_len = 0; 155 } 156 157 #ifdef CONFIG_IEEE80211R 158 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 159 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) 160 md = ie + 2; 161 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); 162 if (md) { 163 /* Prepare for the next transition */ 164 wpa_ft_prepare_auth_request(wpa_s->wpa, ie); 165 } 166 167 if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { 168 if (wpa_s->sme.assoc_req_ie_len + 5 < 169 sizeof(wpa_s->sme.assoc_req_ie)) { 170 struct rsn_mdie *mdie; 171 u8 *pos = wpa_s->sme.assoc_req_ie + 172 wpa_s->sme.assoc_req_ie_len; 173 *pos++ = WLAN_EID_MOBILITY_DOMAIN; 174 *pos++ = sizeof(*mdie); 175 mdie = (struct rsn_mdie *) pos; 176 os_memcpy(mdie->mobility_domain, md, 177 MOBILITY_DOMAIN_ID_LEN); 178 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; 179 wpa_s->sme.assoc_req_ie_len += 5; 180 } 181 182 if (wpa_s->sme.ft_used && 183 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && 184 wpa_sm_has_ptk(wpa_s->wpa)) { 185 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " 186 "over-the-air"); 187 params.auth_alg = WPA_AUTH_ALG_FT; 188 params.ie = wpa_s->sme.ft_ies; 189 params.ie_len = wpa_s->sme.ft_ies_len; 190 } 191 } 192 #endif /* CONFIG_IEEE80211R */ 193 194 #ifdef CONFIG_IEEE80211W 195 wpa_s->sme.mfp = ssid->ieee80211w; 196 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 197 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 198 struct wpa_ie_data _ie; 199 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && 200 _ie.capabilities & 201 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { 202 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " 203 "MFP: require MFP"); 204 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; 205 } 206 } 207 #endif /* CONFIG_IEEE80211W */ 208 209 #ifdef CONFIG_P2P 210 if (wpa_s->global->p2p) { 211 u8 *pos; 212 size_t len; 213 int res; 214 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; 215 len = sizeof(wpa_s->sme.assoc_req_ie) - 216 wpa_s->sme.assoc_req_ie_len; 217 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, 218 ssid->p2p_group); 219 if (res >= 0) 220 wpa_s->sme.assoc_req_ie_len += res; 221 } 222 #endif /* CONFIG_P2P */ 223 224 #ifdef CONFIG_INTERWORKING 225 if (wpa_s->conf->interworking) { 226 u8 *pos = wpa_s->sme.assoc_req_ie; 227 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) 228 pos += 2 + pos[1]; 229 os_memmove(pos + 6, pos, 230 wpa_s->sme.assoc_req_ie_len - 231 (pos - wpa_s->sme.assoc_req_ie)); 232 wpa_s->sme.assoc_req_ie_len += 6; 233 *pos++ = WLAN_EID_EXT_CAPAB; 234 *pos++ = 4; 235 *pos++ = 0x00; 236 *pos++ = 0x00; 237 *pos++ = 0x00; 238 *pos++ = 0x80; /* Bit 31 - Interworking */ 239 } 240 #endif /* CONFIG_INTERWORKING */ 241 242 wpa_supplicant_cancel_sched_scan(wpa_s); 243 wpa_supplicant_cancel_scan(wpa_s); 244 245 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR 246 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 247 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); 248 249 wpa_clear_keys(wpa_s, bss->bssid); 250 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 251 old_ssid = wpa_s->current_ssid; 252 wpa_s->current_ssid = ssid; 253 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); 254 wpa_supplicant_initiate_eapol(wpa_s); 255 if (old_ssid != wpa_s->current_ssid) 256 wpas_notify_network_changed(wpa_s); 257 258 wpa_s->sme.auth_alg = params.auth_alg; 259 if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { 260 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " 261 "driver failed"); 262 wpas_connection_failed(wpa_s, bss->bssid); 263 wpa_supplicant_mark_disassoc(wpa_s); 264 return; 265 } 266 267 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, 268 NULL); 269 270 /* 271 * Association will be started based on the authentication event from 272 * the driver. 273 */ 274 } 275 276 277 void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) 278 { 279 struct wpa_ssid *ssid = wpa_s->current_ssid; 280 281 if (ssid == NULL) { 282 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " 283 "when network is not selected"); 284 return; 285 } 286 287 if (wpa_s->wpa_state != WPA_AUTHENTICATING) { 288 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " 289 "when not in authenticating state"); 290 return; 291 } 292 293 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { 294 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with " 295 "unexpected peer " MACSTR, 296 MAC2STR(data->auth.peer)); 297 return; 298 } 299 300 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR 301 " auth_type=%d status_code=%d", 302 MAC2STR(data->auth.peer), data->auth.auth_type, 303 data->auth.status_code); 304 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", 305 data->auth.ies, data->auth.ies_len); 306 307 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 308 309 if (data->auth.status_code != WLAN_STATUS_SUCCESS) { 310 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status " 311 "code %d)", data->auth.status_code); 312 313 if (data->auth.status_code != 314 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG || 315 wpa_s->sme.auth_alg == data->auth.auth_type || 316 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) { 317 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 318 return; 319 } 320 321 switch (data->auth.auth_type) { 322 case WLAN_AUTH_OPEN: 323 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED; 324 325 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth"); 326 wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 327 wpa_s->current_ssid); 328 return; 329 330 case WLAN_AUTH_SHARED_KEY: 331 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP; 332 333 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth"); 334 wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 335 wpa_s->current_ssid); 336 return; 337 338 default: 339 return; 340 } 341 } 342 343 #ifdef CONFIG_IEEE80211R 344 if (data->auth.auth_type == WLAN_AUTH_FT) { 345 union wpa_event_data edata; 346 os_memset(&edata, 0, sizeof(edata)); 347 edata.ft_ies.ies = data->auth.ies; 348 edata.ft_ies.ies_len = data->auth.ies_len; 349 os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); 350 wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); 351 } 352 #endif /* CONFIG_IEEE80211R */ 353 354 sme_associate(wpa_s, ssid->mode, data->auth.peer, 355 data->auth.auth_type); 356 } 357 358 359 void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, 360 const u8 *bssid, u16 auth_type) 361 { 362 struct wpa_driver_associate_params params; 363 struct ieee802_11_elems elems; 364 #ifdef CONFIG_HT_OVERRIDES 365 struct ieee80211_ht_capabilities htcaps; 366 struct ieee80211_ht_capabilities htcaps_mask; 367 #endif /* CONFIG_HT_OVERRIDES */ 368 369 os_memset(¶ms, 0, sizeof(params)); 370 params.bssid = bssid; 371 params.ssid = wpa_s->sme.ssid; 372 params.ssid_len = wpa_s->sme.ssid_len; 373 params.freq = wpa_s->sme.freq; 374 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? 375 wpa_s->sme.assoc_req_ie : NULL; 376 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; 377 params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher); 378 params.group_suite = cipher_suite2driver(wpa_s->group_cipher); 379 #ifdef CONFIG_HT_OVERRIDES 380 os_memset(&htcaps, 0, sizeof(htcaps)); 381 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); 382 params.htcaps = (u8 *) &htcaps; 383 params.htcaps_mask = (u8 *) &htcaps_mask; 384 wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); 385 #endif /* CONFIG_HT_OVERRIDES */ 386 #ifdef CONFIG_IEEE80211R 387 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { 388 params.wpa_ie = wpa_s->sme.ft_ies; 389 params.wpa_ie_len = wpa_s->sme.ft_ies_len; 390 } 391 #endif /* CONFIG_IEEE80211R */ 392 params.mode = mode; 393 params.mgmt_frame_protection = wpa_s->sme.mfp; 394 if (wpa_s->sme.prev_bssid_set) 395 params.prev_bssid = wpa_s->sme.prev_bssid; 396 397 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR 398 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 399 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", 400 params.freq); 401 402 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); 403 404 if (params.wpa_ie == NULL || 405 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) 406 < 0) { 407 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!"); 408 os_memset(&elems, 0, sizeof(elems)); 409 } 410 if (elems.rsn_ie) { 411 params.wpa_proto = WPA_PROTO_RSN; 412 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, 413 elems.rsn_ie_len + 2); 414 } else if (elems.wpa_ie) { 415 params.wpa_proto = WPA_PROTO_WPA; 416 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, 417 elems.wpa_ie_len + 2); 418 } else 419 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 420 if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) 421 params.p2p = 1; 422 423 if (wpa_s->parent->set_sta_uapsd) 424 params.uapsd = wpa_s->parent->sta_uapsd; 425 else 426 params.uapsd = -1; 427 428 if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 429 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the " 430 "driver failed"); 431 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 432 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 433 return; 434 } 435 436 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, 437 NULL); 438 } 439 440 441 int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, 442 const u8 *ies, size_t ies_len) 443 { 444 if (md == NULL || ies == NULL) { 445 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain"); 446 os_free(wpa_s->sme.ft_ies); 447 wpa_s->sme.ft_ies = NULL; 448 wpa_s->sme.ft_ies_len = 0; 449 wpa_s->sme.ft_used = 0; 450 return 0; 451 } 452 453 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); 454 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len); 455 os_free(wpa_s->sme.ft_ies); 456 wpa_s->sme.ft_ies = os_malloc(ies_len); 457 if (wpa_s->sme.ft_ies == NULL) 458 return -1; 459 os_memcpy(wpa_s->sme.ft_ies, ies, ies_len); 460 wpa_s->sme.ft_ies_len = ies_len; 461 return 0; 462 } 463 464 465 static void sme_deauth(struct wpa_supplicant *wpa_s) 466 { 467 int bssid_changed; 468 469 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 470 471 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, 472 WLAN_REASON_DEAUTH_LEAVING) < 0) { 473 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver " 474 "failed"); 475 } 476 wpa_s->sme.prev_bssid_set = 0; 477 478 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 479 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 480 os_memset(wpa_s->bssid, 0, ETH_ALEN); 481 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 482 if (bssid_changed) 483 wpas_notify_bssid_changed(wpa_s); 484 } 485 486 487 void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, 488 union wpa_event_data *data) 489 { 490 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: " 491 "status code %d", MAC2STR(wpa_s->pending_bssid), 492 data->assoc_reject.status_code); 493 494 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 495 496 /* 497 * For now, unconditionally terminate the previous authentication. In 498 * theory, this should not be needed, but mac80211 gets quite confused 499 * if the authentication is left pending.. Some roaming cases might 500 * benefit from using the previous authentication, so this could be 501 * optimized in the future. 502 */ 503 sme_deauth(wpa_s); 504 } 505 506 507 void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, 508 union wpa_event_data *data) 509 { 510 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out"); 511 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 512 wpa_supplicant_mark_disassoc(wpa_s); 513 } 514 515 516 void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, 517 union wpa_event_data *data) 518 { 519 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out"); 520 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 521 wpa_supplicant_mark_disassoc(wpa_s); 522 } 523 524 525 void sme_event_disassoc(struct wpa_supplicant *wpa_s, 526 union wpa_event_data *data) 527 { 528 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received"); 529 if (wpa_s->sme.prev_bssid_set) { 530 /* 531 * cfg80211/mac80211 can get into somewhat confused state if 532 * the AP only disassociates us and leaves us in authenticated 533 * state. For now, force the state to be cleared to avoid 534 * confusing errors if we try to associate with the AP again. 535 */ 536 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear " 537 "driver state"); 538 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid, 539 WLAN_REASON_DEAUTH_LEAVING); 540 } 541 } 542 543 544 static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx) 545 { 546 struct wpa_supplicant *wpa_s = eloop_ctx; 547 if (wpa_s->wpa_state == WPA_AUTHENTICATING) { 548 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout"); 549 sme_deauth(wpa_s); 550 } 551 } 552 553 554 static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx) 555 { 556 struct wpa_supplicant *wpa_s = eloop_ctx; 557 if (wpa_s->wpa_state == WPA_ASSOCIATING) { 558 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout"); 559 sme_deauth(wpa_s); 560 } 561 } 562 563 564 void sme_state_changed(struct wpa_supplicant *wpa_s) 565 { 566 /* Make sure timers are cleaned up appropriately. */ 567 if (wpa_s->wpa_state != WPA_ASSOCIATING) 568 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 569 if (wpa_s->wpa_state != WPA_AUTHENTICATING) 570 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 571 } 572 573 574 void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, 575 const u8 *prev_pending_bssid) 576 { 577 /* 578 * mac80211-workaround to force deauth on failed auth cmd, 579 * requires us to remain in authenticating state to allow the 580 * second authentication attempt to be continued properly. 581 */ 582 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication " 583 "to proceed after disconnection event"); 584 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 585 os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN); 586 587 /* 588 * Re-arm authentication timer in case auth fails for whatever reason. 589 */ 590 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 591 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, 592 NULL); 593 } 594 595 596 void sme_deinit(struct wpa_supplicant *wpa_s) 597 { 598 os_free(wpa_s->sme.ft_ies); 599 wpa_s->sme.ft_ies = NULL; 600 wpa_s->sme.ft_ies_len = 0; 601 #ifdef CONFIG_IEEE80211W 602 sme_stop_sa_query(wpa_s); 603 #endif /* CONFIG_IEEE80211W */ 604 605 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 606 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 607 } 608 609 610 #ifdef CONFIG_IEEE80211W 611 612 static const unsigned int sa_query_max_timeout = 1000; 613 static const unsigned int sa_query_retry_timeout = 201; 614 615 static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s) 616 { 617 u32 tu; 618 struct os_time now, passed; 619 os_get_time(&now); 620 os_time_sub(&now, &wpa_s->sme.sa_query_start, &passed); 621 tu = (passed.sec * 1000000 + passed.usec) / 1024; 622 if (sa_query_max_timeout < tu) { 623 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out"); 624 sme_stop_sa_query(wpa_s); 625 wpa_supplicant_deauthenticate( 626 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID); 627 return 1; 628 } 629 630 return 0; 631 } 632 633 634 static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s, 635 const u8 *trans_id) 636 { 637 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN]; 638 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to " 639 MACSTR, MAC2STR(wpa_s->bssid)); 640 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID", 641 trans_id, WLAN_SA_QUERY_TR_ID_LEN); 642 req[0] = WLAN_ACTION_SA_QUERY; 643 req[1] = WLAN_SA_QUERY_REQUEST; 644 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN); 645 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 646 wpa_s->own_addr, wpa_s->bssid, 647 req, sizeof(req), 0) < 0) 648 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query " 649 "Request"); 650 } 651 652 653 static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx) 654 { 655 struct wpa_supplicant *wpa_s = eloop_ctx; 656 unsigned int timeout, sec, usec; 657 u8 *trans_id, *nbuf; 658 659 if (wpa_s->sme.sa_query_count > 0 && 660 sme_check_sa_query_timeout(wpa_s)) 661 return; 662 663 nbuf = os_realloc(wpa_s->sme.sa_query_trans_id, 664 (wpa_s->sme.sa_query_count + 1) * 665 WLAN_SA_QUERY_TR_ID_LEN); 666 if (nbuf == NULL) 667 return; 668 if (wpa_s->sme.sa_query_count == 0) { 669 /* Starting a new SA Query procedure */ 670 os_get_time(&wpa_s->sme.sa_query_start); 671 } 672 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; 673 wpa_s->sme.sa_query_trans_id = nbuf; 674 wpa_s->sme.sa_query_count++; 675 676 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); 677 678 timeout = sa_query_retry_timeout; 679 sec = ((timeout / 1000) * 1024) / 1000; 680 usec = (timeout % 1000) * 1024; 681 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL); 682 683 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d", 684 wpa_s->sme.sa_query_count); 685 686 sme_send_sa_query_req(wpa_s, trans_id); 687 } 688 689 690 static void sme_start_sa_query(struct wpa_supplicant *wpa_s) 691 { 692 sme_sa_query_timer(wpa_s, NULL); 693 } 694 695 696 static void sme_stop_sa_query(struct wpa_supplicant *wpa_s) 697 { 698 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL); 699 os_free(wpa_s->sme.sa_query_trans_id); 700 wpa_s->sme.sa_query_trans_id = NULL; 701 wpa_s->sme.sa_query_count = 0; 702 } 703 704 705 void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, 706 const u8 *da, u16 reason_code) 707 { 708 struct wpa_ssid *ssid; 709 710 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) 711 return; 712 if (wpa_s->wpa_state != WPA_COMPLETED) 713 return; 714 ssid = wpa_s->current_ssid; 715 if (ssid == NULL || ssid->ieee80211w == 0) 716 return; 717 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) 718 return; 719 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA && 720 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA) 721 return; 722 if (wpa_s->sme.sa_query_count > 0) 723 return; 724 725 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - " 726 "possible AP/STA state mismatch - trigger SA Query"); 727 sme_start_sa_query(wpa_s); 728 } 729 730 731 void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, 732 const u8 *data, size_t len) 733 { 734 int i; 735 736 if (wpa_s->sme.sa_query_trans_id == NULL || 737 len < 1 + WLAN_SA_QUERY_TR_ID_LEN || 738 data[0] != WLAN_SA_QUERY_RESPONSE) 739 return; 740 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from " 741 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]); 742 743 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) 744 return; 745 746 for (i = 0; i < wpa_s->sme.sa_query_count; i++) { 747 if (os_memcmp(wpa_s->sme.sa_query_trans_id + 748 i * WLAN_SA_QUERY_TR_ID_LEN, 749 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0) 750 break; 751 } 752 753 if (i >= wpa_s->sme.sa_query_count) { 754 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query " 755 "transaction identifier found"); 756 return; 757 } 758 759 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received " 760 "from " MACSTR, MAC2STR(sa)); 761 sme_stop_sa_query(wpa_s); 762 } 763 764 #endif /* CONFIG_IEEE80211W */ 765