1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * hostapd / Callback functions for driver wrappers 3e5b75505Sopenharmony_ci * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "utils/includes.h" 10e5b75505Sopenharmony_ci 11e5b75505Sopenharmony_ci#include "utils/common.h" 12e5b75505Sopenharmony_ci#include "utils/eloop.h" 13e5b75505Sopenharmony_ci#include "radius/radius.h" 14e5b75505Sopenharmony_ci#include "drivers/driver.h" 15e5b75505Sopenharmony_ci#include "common/ieee802_11_defs.h" 16e5b75505Sopenharmony_ci#include "common/ieee802_11_common.h" 17e5b75505Sopenharmony_ci#include "common/wpa_ctrl.h" 18e5b75505Sopenharmony_ci#include "common/dpp.h" 19e5b75505Sopenharmony_ci#include "crypto/random.h" 20e5b75505Sopenharmony_ci#include "p2p/p2p.h" 21e5b75505Sopenharmony_ci#include "wps/wps.h" 22e5b75505Sopenharmony_ci#include "fst/fst.h" 23e5b75505Sopenharmony_ci#include "wnm_ap.h" 24e5b75505Sopenharmony_ci#include "hostapd.h" 25e5b75505Sopenharmony_ci#include "ieee802_11.h" 26e5b75505Sopenharmony_ci#include "ieee802_11_auth.h" 27e5b75505Sopenharmony_ci#include "sta_info.h" 28e5b75505Sopenharmony_ci#include "accounting.h" 29e5b75505Sopenharmony_ci#include "tkip_countermeasures.h" 30e5b75505Sopenharmony_ci#include "ieee802_1x.h" 31e5b75505Sopenharmony_ci#include "wpa_auth.h" 32e5b75505Sopenharmony_ci#include "wps_hostapd.h" 33e5b75505Sopenharmony_ci#include "ap_drv_ops.h" 34e5b75505Sopenharmony_ci#include "ap_config.h" 35e5b75505Sopenharmony_ci#include "ap_mlme.h" 36e5b75505Sopenharmony_ci#include "hw_features.h" 37e5b75505Sopenharmony_ci#include "dfs.h" 38e5b75505Sopenharmony_ci#include "beacon.h" 39e5b75505Sopenharmony_ci#include "mbo_ap.h" 40e5b75505Sopenharmony_ci#include "dpp_hostapd.h" 41e5b75505Sopenharmony_ci#include "fils_hlp.h" 42e5b75505Sopenharmony_ci#include "neighbor_db.h" 43e5b75505Sopenharmony_ci 44e5b75505Sopenharmony_ci 45e5b75505Sopenharmony_ci#ifdef CONFIG_FILS 46e5b75505Sopenharmony_civoid hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, 47e5b75505Sopenharmony_ci struct sta_info *sta) 48e5b75505Sopenharmony_ci{ 49e5b75505Sopenharmony_ci u16 reply_res = WLAN_STATUS_SUCCESS; 50e5b75505Sopenharmony_ci struct ieee802_11_elems elems; 51e5b75505Sopenharmony_ci u8 buf[IEEE80211_MAX_MMPDU_SIZE], *p = buf; 52e5b75505Sopenharmony_ci int new_assoc; 53e5b75505Sopenharmony_ci 54e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s FILS: Finish association with " MACSTR, 55e5b75505Sopenharmony_ci __func__, MAC2STR(sta->addr)); 56e5b75505Sopenharmony_ci eloop_cancel_timeout(fils_hlp_timeout, hapd, sta); 57e5b75505Sopenharmony_ci if (!sta->fils_pending_assoc_req) 58e5b75505Sopenharmony_ci return; 59e5b75505Sopenharmony_ci 60e5b75505Sopenharmony_ci ieee802_11_parse_elems(sta->fils_pending_assoc_req, 61e5b75505Sopenharmony_ci sta->fils_pending_assoc_req_len, &elems, 0); 62e5b75505Sopenharmony_ci if (!elems.fils_session) { 63e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s failed to find FILS Session element", 64e5b75505Sopenharmony_ci __func__); 65e5b75505Sopenharmony_ci return; 66e5b75505Sopenharmony_ci } 67e5b75505Sopenharmony_ci 68e5b75505Sopenharmony_ci p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p, 69e5b75505Sopenharmony_ci elems.fils_session, 70e5b75505Sopenharmony_ci sta->fils_hlp_resp); 71e5b75505Sopenharmony_ci 72e5b75505Sopenharmony_ci reply_res = hostapd_sta_assoc(hapd, sta->addr, 73e5b75505Sopenharmony_ci sta->fils_pending_assoc_is_reassoc, 74e5b75505Sopenharmony_ci WLAN_STATUS_SUCCESS, 75e5b75505Sopenharmony_ci buf, p - buf); 76e5b75505Sopenharmony_ci ap_sta_set_authorized(hapd, sta, 1); 77e5b75505Sopenharmony_ci new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; 78e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; 79e5b75505Sopenharmony_ci sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; 80e5b75505Sopenharmony_ci hostapd_set_sta_flags(hapd, sta); 81e5b75505Sopenharmony_ci wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FILS); 82e5b75505Sopenharmony_ci ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); 83e5b75505Sopenharmony_ci hostapd_new_assoc_sta(hapd, sta, !new_assoc); 84e5b75505Sopenharmony_ci os_free(sta->fils_pending_assoc_req); 85e5b75505Sopenharmony_ci sta->fils_pending_assoc_req = NULL; 86e5b75505Sopenharmony_ci sta->fils_pending_assoc_req_len = 0; 87e5b75505Sopenharmony_ci wpabuf_free(sta->fils_hlp_resp); 88e5b75505Sopenharmony_ci sta->fils_hlp_resp = NULL; 89e5b75505Sopenharmony_ci wpabuf_free(sta->hlp_dhcp_discover); 90e5b75505Sopenharmony_ci sta->hlp_dhcp_discover = NULL; 91e5b75505Sopenharmony_ci fils_hlp_deinit(hapd); 92e5b75505Sopenharmony_ci 93e5b75505Sopenharmony_ci /* 94e5b75505Sopenharmony_ci * Remove the station in case transmission of a success response fails 95e5b75505Sopenharmony_ci * (the STA was added associated to the driver) or if the station was 96e5b75505Sopenharmony_ci * previously added unassociated. 97e5b75505Sopenharmony_ci */ 98e5b75505Sopenharmony_ci if (reply_res != WLAN_STATUS_SUCCESS || sta->added_unassoc) { 99e5b75505Sopenharmony_ci hostapd_drv_sta_remove(hapd, sta->addr); 100e5b75505Sopenharmony_ci sta->added_unassoc = 0; 101e5b75505Sopenharmony_ci } 102e5b75505Sopenharmony_ci} 103e5b75505Sopenharmony_ci#endif /* CONFIG_FILS */ 104e5b75505Sopenharmony_ci 105e5b75505Sopenharmony_ci 106e5b75505Sopenharmony_ciint hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, 107e5b75505Sopenharmony_ci const u8 *req_ies, size_t req_ies_len, int reassoc) 108e5b75505Sopenharmony_ci{ 109e5b75505Sopenharmony_ci struct sta_info *sta; 110e5b75505Sopenharmony_ci int new_assoc, res; 111e5b75505Sopenharmony_ci struct ieee802_11_elems elems; 112e5b75505Sopenharmony_ci const u8 *ie; 113e5b75505Sopenharmony_ci size_t ielen; 114e5b75505Sopenharmony_ci#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS) || defined(CONFIG_OWE) 115e5b75505Sopenharmony_ci u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; 116e5b75505Sopenharmony_ci u8 *p = buf; 117e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP || CONFIG_IEEE80211W || CONFIG_FILS || CONFIG_OWE */ 118e5b75505Sopenharmony_ci u16 reason = WLAN_REASON_UNSPECIFIED; 119e5b75505Sopenharmony_ci u16 status = WLAN_STATUS_SUCCESS; 120e5b75505Sopenharmony_ci const u8 *p2p_dev_addr = NULL; 121e5b75505Sopenharmony_ci 122e5b75505Sopenharmony_ci if (addr == NULL) { 123e5b75505Sopenharmony_ci /* 124e5b75505Sopenharmony_ci * This could potentially happen with unexpected event from the 125e5b75505Sopenharmony_ci * driver wrapper. This was seen at least in one case where the 126e5b75505Sopenharmony_ci * driver ended up being set to station mode while hostapd was 127e5b75505Sopenharmony_ci * running, so better make sure we stop processing such an 128e5b75505Sopenharmony_ci * event here. 129e5b75505Sopenharmony_ci */ 130e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 131e5b75505Sopenharmony_ci "hostapd_notif_assoc: Skip event with no address"); 132e5b75505Sopenharmony_ci return -1; 133e5b75505Sopenharmony_ci } 134e5b75505Sopenharmony_ci 135e5b75505Sopenharmony_ci if (is_multicast_ether_addr(addr) || 136e5b75505Sopenharmony_ci is_zero_ether_addr(addr) || 137e5b75505Sopenharmony_ci os_memcmp(addr, hapd->own_addr, ETH_ALEN) == 0) { 138e5b75505Sopenharmony_ci /* Do not process any frames with unexpected/invalid SA so that 139e5b75505Sopenharmony_ci * we do not add any state for unexpected STA addresses or end 140e5b75505Sopenharmony_ci * up sending out frames to unexpected destination. */ 141e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: Invalid SA=" MACSTR 142e5b75505Sopenharmony_ci " in received indication - ignore this indication silently", 143e5b75505Sopenharmony_ci __func__, MAC2STR(addr)); 144e5b75505Sopenharmony_ci return 0; 145e5b75505Sopenharmony_ci } 146e5b75505Sopenharmony_ci 147e5b75505Sopenharmony_ci random_add_randomness(addr, ETH_ALEN); 148e5b75505Sopenharmony_ci 149e5b75505Sopenharmony_ci hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 150e5b75505Sopenharmony_ci HOSTAPD_LEVEL_INFO, "associated"); 151e5b75505Sopenharmony_ci 152e5b75505Sopenharmony_ci ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0); 153e5b75505Sopenharmony_ci if (elems.wps_ie) { 154e5b75505Sopenharmony_ci ie = elems.wps_ie - 2; 155e5b75505Sopenharmony_ci ielen = elems.wps_ie_len + 2; 156e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq"); 157e5b75505Sopenharmony_ci } else if (elems.rsn_ie) { 158e5b75505Sopenharmony_ci ie = elems.rsn_ie - 2; 159e5b75505Sopenharmony_ci ielen = elems.rsn_ie_len + 2; 160e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); 161e5b75505Sopenharmony_ci } else if (elems.wpa_ie) { 162e5b75505Sopenharmony_ci ie = elems.wpa_ie - 2; 163e5b75505Sopenharmony_ci ielen = elems.wpa_ie_len + 2; 164e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq"); 165e5b75505Sopenharmony_ci#ifdef CONFIG_HS20 166e5b75505Sopenharmony_ci } else if (elems.osen) { 167e5b75505Sopenharmony_ci ie = elems.osen - 2; 168e5b75505Sopenharmony_ci ielen = elems.osen_len + 2; 169e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq"); 170e5b75505Sopenharmony_ci#endif /* CONFIG_HS20 */ 171e5b75505Sopenharmony_ci } else { 172e5b75505Sopenharmony_ci ie = NULL; 173e5b75505Sopenharmony_ci ielen = 0; 174e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 175e5b75505Sopenharmony_ci "STA did not include WPS/RSN/WPA IE in (Re)AssocReq"); 176e5b75505Sopenharmony_ci } 177e5b75505Sopenharmony_ci 178e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 179e5b75505Sopenharmony_ci if (sta) { 180e5b75505Sopenharmony_ci ap_sta_no_session_timeout(hapd, sta); 181e5b75505Sopenharmony_ci accounting_sta_stop(hapd, sta); 182e5b75505Sopenharmony_ci 183e5b75505Sopenharmony_ci /* 184e5b75505Sopenharmony_ci * Make sure that the previously registered inactivity timer 185e5b75505Sopenharmony_ci * will not remove the STA immediately. 186e5b75505Sopenharmony_ci */ 187e5b75505Sopenharmony_ci sta->timeout_next = STA_NULLFUNC; 188e5b75505Sopenharmony_ci } else { 189e5b75505Sopenharmony_ci sta = ap_sta_add(hapd, addr); 190e5b75505Sopenharmony_ci if (sta == NULL) { 191e5b75505Sopenharmony_ci hostapd_drv_sta_disassoc(hapd, addr, 192e5b75505Sopenharmony_ci WLAN_REASON_DISASSOC_AP_BUSY); 193e5b75505Sopenharmony_ci return -1; 194e5b75505Sopenharmony_ci } 195e5b75505Sopenharmony_ci } 196e5b75505Sopenharmony_ci sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); 197e5b75505Sopenharmony_ci 198e5b75505Sopenharmony_ci /* 199e5b75505Sopenharmony_ci * ACL configurations to the drivers (implementing AP SME and ACL 200e5b75505Sopenharmony_ci * offload) without hostapd's knowledge, can result in a disconnection 201e5b75505Sopenharmony_ci * though the driver accepts the connection. Skip the hostapd check for 202e5b75505Sopenharmony_ci * ACL if the driver supports ACL offload to avoid potentially 203e5b75505Sopenharmony_ci * conflicting ACL rules. 204e5b75505Sopenharmony_ci */ 205e5b75505Sopenharmony_ci if (hapd->iface->drv_max_acl_mac_addrs == 0 && 206e5b75505Sopenharmony_ci hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) { 207e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect", 208e5b75505Sopenharmony_ci MAC2STR(addr)); 209e5b75505Sopenharmony_ci reason = WLAN_REASON_UNSPECIFIED; 210e5b75505Sopenharmony_ci goto fail; 211e5b75505Sopenharmony_ci } 212e5b75505Sopenharmony_ci 213e5b75505Sopenharmony_ci#ifdef CONFIG_P2P 214e5b75505Sopenharmony_ci if (elems.p2p) { 215e5b75505Sopenharmony_ci wpabuf_free(sta->p2p_ie); 216e5b75505Sopenharmony_ci sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, 217e5b75505Sopenharmony_ci P2P_IE_VENDOR_TYPE); 218e5b75505Sopenharmony_ci if (sta->p2p_ie) 219e5b75505Sopenharmony_ci p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); 220e5b75505Sopenharmony_ci } 221e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */ 222e5b75505Sopenharmony_ci 223e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211N 224e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 225e5b75505Sopenharmony_ci if (elems.ht_capabilities && 226e5b75505Sopenharmony_ci (hapd->iface->conf->ht_capab & 227e5b75505Sopenharmony_ci HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 228e5b75505Sopenharmony_ci struct ieee80211_ht_capabilities *ht_cap = 229e5b75505Sopenharmony_ci (struct ieee80211_ht_capabilities *) 230e5b75505Sopenharmony_ci elems.ht_capabilities; 231e5b75505Sopenharmony_ci 232e5b75505Sopenharmony_ci if (le_to_host16(ht_cap->ht_capabilities_info) & 233e5b75505Sopenharmony_ci HT_CAP_INFO_40MHZ_INTOLERANT) 234e5b75505Sopenharmony_ci ht40_intolerant_add(hapd->iface, sta); 235e5b75505Sopenharmony_ci } 236e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 237e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211N */ 238e5b75505Sopenharmony_ci 239e5b75505Sopenharmony_ci#ifdef CONFIG_INTERWORKING 240e5b75505Sopenharmony_ci if (elems.ext_capab && elems.ext_capab_len > 4) { 241e5b75505Sopenharmony_ci if (elems.ext_capab[4] & 0x01) 242e5b75505Sopenharmony_ci sta->qos_map_enabled = 1; 243e5b75505Sopenharmony_ci } 244e5b75505Sopenharmony_ci#endif /* CONFIG_INTERWORKING */ 245e5b75505Sopenharmony_ci 246e5b75505Sopenharmony_ci#ifdef CONFIG_HS20 247e5b75505Sopenharmony_ci wpabuf_free(sta->hs20_ie); 248e5b75505Sopenharmony_ci if (elems.hs20 && elems.hs20_len > 4) { 249e5b75505Sopenharmony_ci sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4, 250e5b75505Sopenharmony_ci elems.hs20_len - 4); 251e5b75505Sopenharmony_ci } else 252e5b75505Sopenharmony_ci sta->hs20_ie = NULL; 253e5b75505Sopenharmony_ci 254e5b75505Sopenharmony_ci wpabuf_free(sta->roaming_consortium); 255e5b75505Sopenharmony_ci if (elems.roaming_cons_sel) 256e5b75505Sopenharmony_ci sta->roaming_consortium = wpabuf_alloc_copy( 257e5b75505Sopenharmony_ci elems.roaming_cons_sel + 4, 258e5b75505Sopenharmony_ci elems.roaming_cons_sel_len - 4); 259e5b75505Sopenharmony_ci else 260e5b75505Sopenharmony_ci sta->roaming_consortium = NULL; 261e5b75505Sopenharmony_ci#endif /* CONFIG_HS20 */ 262e5b75505Sopenharmony_ci 263e5b75505Sopenharmony_ci#ifdef CONFIG_FST 264e5b75505Sopenharmony_ci wpabuf_free(sta->mb_ies); 265e5b75505Sopenharmony_ci if (hapd->iface->fst) 266e5b75505Sopenharmony_ci sta->mb_ies = mb_ies_by_info(&elems.mb_ies); 267e5b75505Sopenharmony_ci else 268e5b75505Sopenharmony_ci sta->mb_ies = NULL; 269e5b75505Sopenharmony_ci#endif /* CONFIG_FST */ 270e5b75505Sopenharmony_ci 271e5b75505Sopenharmony_ci mbo_ap_check_sta_assoc(hapd, sta, &elems); 272e5b75505Sopenharmony_ci 273e5b75505Sopenharmony_ci ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes, 274e5b75505Sopenharmony_ci elems.supp_op_classes_len); 275e5b75505Sopenharmony_ci 276e5b75505Sopenharmony_ci if (hapd->conf->wpa) { 277e5b75505Sopenharmony_ci if (ie == NULL || ielen == 0) { 278e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 279e5b75505Sopenharmony_ci if (hapd->conf->wps_state) { 280e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 281e5b75505Sopenharmony_ci "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use"); 282e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_MAYBE_WPS; 283e5b75505Sopenharmony_ci goto skip_wpa_check; 284e5b75505Sopenharmony_ci } 285e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 286e5b75505Sopenharmony_ci 287e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); 288e5b75505Sopenharmony_ci reason = WLAN_REASON_INVALID_IE; 289e5b75505Sopenharmony_ci status = WLAN_STATUS_INVALID_IE; 290e5b75505Sopenharmony_ci goto fail; 291e5b75505Sopenharmony_ci } 292e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 293e5b75505Sopenharmony_ci if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && 294e5b75505Sopenharmony_ci os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { 295e5b75505Sopenharmony_ci struct wpabuf *wps; 296e5b75505Sopenharmony_ci 297e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_WPS; 298e5b75505Sopenharmony_ci wps = ieee802_11_vendor_ie_concat(ie, ielen, 299e5b75505Sopenharmony_ci WPS_IE_VENDOR_TYPE); 300e5b75505Sopenharmony_ci if (wps) { 301e5b75505Sopenharmony_ci if (wps_is_20(wps)) { 302e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 303e5b75505Sopenharmony_ci "WPS: STA supports WPS 2.0"); 304e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_WPS2; 305e5b75505Sopenharmony_ci } 306e5b75505Sopenharmony_ci wpabuf_free(wps); 307e5b75505Sopenharmony_ci } 308e5b75505Sopenharmony_ci goto skip_wpa_check; 309e5b75505Sopenharmony_ci } 310e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 311e5b75505Sopenharmony_ci 312e5b75505Sopenharmony_ci if (sta->wpa_sm == NULL) 313e5b75505Sopenharmony_ci sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, 314e5b75505Sopenharmony_ci sta->addr, 315e5b75505Sopenharmony_ci p2p_dev_addr); 316e5b75505Sopenharmony_ci if (sta->wpa_sm == NULL) { 317e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 318e5b75505Sopenharmony_ci "Failed to initialize WPA state machine"); 319e5b75505Sopenharmony_ci return -1; 320e5b75505Sopenharmony_ci } 321e5b75505Sopenharmony_ci res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, 322e5b75505Sopenharmony_ci hapd->iface->freq, 323e5b75505Sopenharmony_ci ie, ielen, 324e5b75505Sopenharmony_ci elems.mdie, elems.mdie_len, 325e5b75505Sopenharmony_ci elems.owe_dh, elems.owe_dh_len); 326e5b75505Sopenharmony_ci if (res != WPA_IE_OK) { 327e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 328e5b75505Sopenharmony_ci "WPA/RSN information element rejected? (res %u)", 329e5b75505Sopenharmony_ci res); 330e5b75505Sopenharmony_ci wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); 331e5b75505Sopenharmony_ci if (res == WPA_INVALID_GROUP) { 332e5b75505Sopenharmony_ci reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; 333e5b75505Sopenharmony_ci status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; 334e5b75505Sopenharmony_ci } else if (res == WPA_INVALID_PAIRWISE) { 335e5b75505Sopenharmony_ci reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; 336e5b75505Sopenharmony_ci status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 337e5b75505Sopenharmony_ci } else if (res == WPA_INVALID_AKMP) { 338e5b75505Sopenharmony_ci reason = WLAN_REASON_AKMP_NOT_VALID; 339e5b75505Sopenharmony_ci status = WLAN_STATUS_AKMP_NOT_VALID; 340e5b75505Sopenharmony_ci } 341e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W 342e5b75505Sopenharmony_ci else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) { 343e5b75505Sopenharmony_ci reason = WLAN_REASON_INVALID_IE; 344e5b75505Sopenharmony_ci status = WLAN_STATUS_INVALID_IE; 345e5b75505Sopenharmony_ci } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) { 346e5b75505Sopenharmony_ci reason = WLAN_REASON_CIPHER_SUITE_REJECTED; 347e5b75505Sopenharmony_ci status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; 348e5b75505Sopenharmony_ci } 349e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */ 350e5b75505Sopenharmony_ci else { 351e5b75505Sopenharmony_ci reason = WLAN_REASON_INVALID_IE; 352e5b75505Sopenharmony_ci status = WLAN_STATUS_INVALID_IE; 353e5b75505Sopenharmony_ci } 354e5b75505Sopenharmony_ci goto fail; 355e5b75505Sopenharmony_ci } 356e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W 357e5b75505Sopenharmony_ci if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == 358e5b75505Sopenharmony_ci (WLAN_STA_ASSOC | WLAN_STA_MFP) && 359e5b75505Sopenharmony_ci !sta->sa_query_timed_out && 360e5b75505Sopenharmony_ci sta->sa_query_count > 0) 361e5b75505Sopenharmony_ci ap_check_sa_query_timeout(hapd, sta); 362e5b75505Sopenharmony_ci if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == 363e5b75505Sopenharmony_ci (WLAN_STA_ASSOC | WLAN_STA_MFP) && 364e5b75505Sopenharmony_ci !sta->sa_query_timed_out && 365e5b75505Sopenharmony_ci (sta->auth_alg != WLAN_AUTH_FT)) { 366e5b75505Sopenharmony_ci /* 367e5b75505Sopenharmony_ci * STA has already been associated with MFP and SA 368e5b75505Sopenharmony_ci * Query timeout has not been reached. Reject the 369e5b75505Sopenharmony_ci * association attempt temporarily and start SA Query, 370e5b75505Sopenharmony_ci * if one is not pending. 371e5b75505Sopenharmony_ci */ 372e5b75505Sopenharmony_ci 373e5b75505Sopenharmony_ci if (sta->sa_query_count == 0) 374e5b75505Sopenharmony_ci ap_sta_start_sa_query(hapd, sta); 375e5b75505Sopenharmony_ci 376e5b75505Sopenharmony_ci status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; 377e5b75505Sopenharmony_ci 378e5b75505Sopenharmony_ci p = hostapd_eid_assoc_comeback_time(hapd, sta, p); 379e5b75505Sopenharmony_ci 380e5b75505Sopenharmony_ci hostapd_sta_assoc(hapd, addr, reassoc, status, buf, 381e5b75505Sopenharmony_ci p - buf); 382e5b75505Sopenharmony_ci return 0; 383e5b75505Sopenharmony_ci } 384e5b75505Sopenharmony_ci 385e5b75505Sopenharmony_ci if (wpa_auth_uses_mfp(sta->wpa_sm)) 386e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_MFP; 387e5b75505Sopenharmony_ci else 388e5b75505Sopenharmony_ci sta->flags &= ~WLAN_STA_MFP; 389e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */ 390e5b75505Sopenharmony_ci 391e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211R_AP 392e5b75505Sopenharmony_ci if (sta->auth_alg == WLAN_AUTH_FT) { 393e5b75505Sopenharmony_ci status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies, 394e5b75505Sopenharmony_ci req_ies_len); 395e5b75505Sopenharmony_ci if (status != WLAN_STATUS_SUCCESS) { 396e5b75505Sopenharmony_ci if (status == WLAN_STATUS_INVALID_PMKID) 397e5b75505Sopenharmony_ci reason = WLAN_REASON_INVALID_IE; 398e5b75505Sopenharmony_ci if (status == WLAN_STATUS_INVALID_MDIE) 399e5b75505Sopenharmony_ci reason = WLAN_REASON_INVALID_IE; 400e5b75505Sopenharmony_ci if (status == WLAN_STATUS_INVALID_FTIE) 401e5b75505Sopenharmony_ci reason = WLAN_REASON_INVALID_IE; 402e5b75505Sopenharmony_ci goto fail; 403e5b75505Sopenharmony_ci } 404e5b75505Sopenharmony_ci } 405e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP */ 406e5b75505Sopenharmony_ci } else if (hapd->conf->wps_state) { 407e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 408e5b75505Sopenharmony_ci struct wpabuf *wps; 409e5b75505Sopenharmony_ci 410e5b75505Sopenharmony_ci if (req_ies) 411e5b75505Sopenharmony_ci wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, 412e5b75505Sopenharmony_ci WPS_IE_VENDOR_TYPE); 413e5b75505Sopenharmony_ci else 414e5b75505Sopenharmony_ci wps = NULL; 415e5b75505Sopenharmony_ci#ifdef CONFIG_WPS_STRICT 416e5b75505Sopenharmony_ci if (wps && wps_validate_assoc_req(wps) < 0) { 417e5b75505Sopenharmony_ci reason = WLAN_REASON_INVALID_IE; 418e5b75505Sopenharmony_ci status = WLAN_STATUS_INVALID_IE; 419e5b75505Sopenharmony_ci wpabuf_free(wps); 420e5b75505Sopenharmony_ci goto fail; 421e5b75505Sopenharmony_ci } 422e5b75505Sopenharmony_ci#endif /* CONFIG_WPS_STRICT */ 423e5b75505Sopenharmony_ci if (wps) { 424e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_WPS; 425e5b75505Sopenharmony_ci if (wps_is_20(wps)) { 426e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 427e5b75505Sopenharmony_ci "WPS: STA supports WPS 2.0"); 428e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_WPS2; 429e5b75505Sopenharmony_ci } 430e5b75505Sopenharmony_ci } else 431e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_MAYBE_WPS; 432e5b75505Sopenharmony_ci wpabuf_free(wps); 433e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 434e5b75505Sopenharmony_ci#ifdef CONFIG_HS20 435e5b75505Sopenharmony_ci } else if (hapd->conf->osen) { 436e5b75505Sopenharmony_ci if (elems.osen == NULL) { 437e5b75505Sopenharmony_ci hostapd_logger( 438e5b75505Sopenharmony_ci hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 439e5b75505Sopenharmony_ci HOSTAPD_LEVEL_INFO, 440e5b75505Sopenharmony_ci "No HS 2.0 OSEN element in association request"); 441e5b75505Sopenharmony_ci return WLAN_STATUS_INVALID_IE; 442e5b75505Sopenharmony_ci } 443e5b75505Sopenharmony_ci 444e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association"); 445e5b75505Sopenharmony_ci if (sta->wpa_sm == NULL) 446e5b75505Sopenharmony_ci sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, 447e5b75505Sopenharmony_ci sta->addr, NULL); 448e5b75505Sopenharmony_ci if (sta->wpa_sm == NULL) { 449e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 450e5b75505Sopenharmony_ci "Failed to initialize WPA state machine"); 451e5b75505Sopenharmony_ci return WLAN_STATUS_UNSPECIFIED_FAILURE; 452e5b75505Sopenharmony_ci } 453e5b75505Sopenharmony_ci if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm, 454e5b75505Sopenharmony_ci elems.osen - 2, elems.osen_len + 2) < 0) 455e5b75505Sopenharmony_ci return WLAN_STATUS_INVALID_IE; 456e5b75505Sopenharmony_ci#endif /* CONFIG_HS20 */ 457e5b75505Sopenharmony_ci } 458e5b75505Sopenharmony_ci 459e5b75505Sopenharmony_ci#ifdef CONFIG_MBO 460e5b75505Sopenharmony_ci if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) && 461e5b75505Sopenharmony_ci elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) && 462e5b75505Sopenharmony_ci hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 463e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 464e5b75505Sopenharmony_ci "MBO: Reject WPA2 association without PMF"); 465e5b75505Sopenharmony_ci return WLAN_STATUS_UNSPECIFIED_FAILURE; 466e5b75505Sopenharmony_ci } 467e5b75505Sopenharmony_ci#endif /* CONFIG_MBO */ 468e5b75505Sopenharmony_ci 469e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 470e5b75505Sopenharmony_ciskip_wpa_check: 471e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 472e5b75505Sopenharmony_ci 473e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211R_AP 474e5b75505Sopenharmony_ci p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), 475e5b75505Sopenharmony_ci sta->auth_alg, req_ies, req_ies_len); 476e5b75505Sopenharmony_ci if (!p) { 477e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); 478e5b75505Sopenharmony_ci return WLAN_STATUS_UNSPECIFIED_FAILURE; 479e5b75505Sopenharmony_ci } 480e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP */ 481e5b75505Sopenharmony_ci 482e5b75505Sopenharmony_ci#ifdef CONFIG_FILS 483e5b75505Sopenharmony_ci if (sta->auth_alg == WLAN_AUTH_FILS_SK || 484e5b75505Sopenharmony_ci sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || 485e5b75505Sopenharmony_ci sta->auth_alg == WLAN_AUTH_FILS_PK) { 486e5b75505Sopenharmony_ci int delay_assoc = 0; 487e5b75505Sopenharmony_ci 488e5b75505Sopenharmony_ci if (!req_ies) 489e5b75505Sopenharmony_ci return WLAN_STATUS_UNSPECIFIED_FAILURE; 490e5b75505Sopenharmony_ci 491e5b75505Sopenharmony_ci if (!wpa_fils_validate_fils_session(sta->wpa_sm, req_ies, 492e5b75505Sopenharmony_ci req_ies_len, 493e5b75505Sopenharmony_ci sta->fils_session)) { 494e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 495e5b75505Sopenharmony_ci "FILS: Session validation failed"); 496e5b75505Sopenharmony_ci return WLAN_STATUS_UNSPECIFIED_FAILURE; 497e5b75505Sopenharmony_ci } 498e5b75505Sopenharmony_ci 499e5b75505Sopenharmony_ci res = wpa_fils_validate_key_confirm(sta->wpa_sm, req_ies, 500e5b75505Sopenharmony_ci req_ies_len); 501e5b75505Sopenharmony_ci if (res < 0) { 502e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 503e5b75505Sopenharmony_ci "FILS: Key Confirm validation failed"); 504e5b75505Sopenharmony_ci return WLAN_STATUS_UNSPECIFIED_FAILURE; 505e5b75505Sopenharmony_ci } 506e5b75505Sopenharmony_ci 507e5b75505Sopenharmony_ci if (fils_process_hlp(hapd, sta, req_ies, req_ies_len) > 0) { 508e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 509e5b75505Sopenharmony_ci "FILS: Delaying Assoc Response (HLP)"); 510e5b75505Sopenharmony_ci delay_assoc = 1; 511e5b75505Sopenharmony_ci } else { 512e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 513e5b75505Sopenharmony_ci "FILS: Going ahead with Assoc Response (no HLP)"); 514e5b75505Sopenharmony_ci } 515e5b75505Sopenharmony_ci 516e5b75505Sopenharmony_ci if (sta) { 517e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "FILS: HLP callback cleanup"); 518e5b75505Sopenharmony_ci eloop_cancel_timeout(fils_hlp_timeout, hapd, sta); 519e5b75505Sopenharmony_ci os_free(sta->fils_pending_assoc_req); 520e5b75505Sopenharmony_ci sta->fils_pending_assoc_req = NULL; 521e5b75505Sopenharmony_ci sta->fils_pending_assoc_req_len = 0; 522e5b75505Sopenharmony_ci wpabuf_free(sta->fils_hlp_resp); 523e5b75505Sopenharmony_ci sta->fils_hlp_resp = NULL; 524e5b75505Sopenharmony_ci sta->fils_drv_assoc_finish = 0; 525e5b75505Sopenharmony_ci } 526e5b75505Sopenharmony_ci 527e5b75505Sopenharmony_ci if (sta && delay_assoc && status == WLAN_STATUS_SUCCESS) { 528e5b75505Sopenharmony_ci u8 *req_tmp; 529e5b75505Sopenharmony_ci 530e5b75505Sopenharmony_ci req_tmp = os_malloc(req_ies_len); 531e5b75505Sopenharmony_ci if (!req_tmp) { 532e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 533e5b75505Sopenharmony_ci "FILS: buffer allocation failed for assoc req"); 534e5b75505Sopenharmony_ci goto fail; 535e5b75505Sopenharmony_ci } 536e5b75505Sopenharmony_ci os_memcpy(req_tmp, req_ies, req_ies_len); 537e5b75505Sopenharmony_ci sta->fils_pending_assoc_req = req_tmp; 538e5b75505Sopenharmony_ci sta->fils_pending_assoc_req_len = req_ies_len; 539e5b75505Sopenharmony_ci sta->fils_pending_assoc_is_reassoc = reassoc; 540e5b75505Sopenharmony_ci sta->fils_drv_assoc_finish = 1; 541e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 542e5b75505Sopenharmony_ci "FILS: Waiting for HLP processing before sending (Re)Association Response frame to " 543e5b75505Sopenharmony_ci MACSTR, MAC2STR(sta->addr)); 544e5b75505Sopenharmony_ci eloop_register_timeout( 545e5b75505Sopenharmony_ci 0, hapd->conf->fils_hlp_wait_time * 1024, 546e5b75505Sopenharmony_ci fils_hlp_timeout, hapd, sta); 547e5b75505Sopenharmony_ci return 0; 548e5b75505Sopenharmony_ci } 549e5b75505Sopenharmony_ci p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p, 550e5b75505Sopenharmony_ci elems.fils_session, 551e5b75505Sopenharmony_ci sta->fils_hlp_resp); 552e5b75505Sopenharmony_ci wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)", 553e5b75505Sopenharmony_ci buf, p - buf); 554e5b75505Sopenharmony_ci } 555e5b75505Sopenharmony_ci#endif /* CONFIG_FILS */ 556e5b75505Sopenharmony_ci 557e5b75505Sopenharmony_ci#ifdef CONFIG_OWE 558e5b75505Sopenharmony_ci if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && 559e5b75505Sopenharmony_ci wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE && 560e5b75505Sopenharmony_ci elems.owe_dh) { 561e5b75505Sopenharmony_ci u8 *npos; 562e5b75505Sopenharmony_ci 563e5b75505Sopenharmony_ci npos = owe_assoc_req_process(hapd, sta, 564e5b75505Sopenharmony_ci elems.owe_dh, elems.owe_dh_len, 565e5b75505Sopenharmony_ci p, sizeof(buf) - (p - buf), 566e5b75505Sopenharmony_ci &reason); 567e5b75505Sopenharmony_ci if (npos) 568e5b75505Sopenharmony_ci p = npos; 569e5b75505Sopenharmony_ci if (!npos && 570e5b75505Sopenharmony_ci reason == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { 571e5b75505Sopenharmony_ci status = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 572e5b75505Sopenharmony_ci hostapd_sta_assoc(hapd, addr, reassoc, status, buf, 573e5b75505Sopenharmony_ci p - buf); 574e5b75505Sopenharmony_ci return 0; 575e5b75505Sopenharmony_ci } 576e5b75505Sopenharmony_ci 577e5b75505Sopenharmony_ci if (!npos || reason != WLAN_STATUS_SUCCESS) 578e5b75505Sopenharmony_ci goto fail; 579e5b75505Sopenharmony_ci } 580e5b75505Sopenharmony_ci#endif /* CONFIG_OWE */ 581e5b75505Sopenharmony_ci 582e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 583e5b75505Sopenharmony_ci dpp_pfs_free(sta->dpp_pfs); 584e5b75505Sopenharmony_ci sta->dpp_pfs = NULL; 585e5b75505Sopenharmony_ci 586e5b75505Sopenharmony_ci if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && 587e5b75505Sopenharmony_ci hapd->conf->dpp_netaccesskey && sta->wpa_sm && 588e5b75505Sopenharmony_ci wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP && 589e5b75505Sopenharmony_ci elems.owe_dh) { 590e5b75505Sopenharmony_ci sta->dpp_pfs = dpp_pfs_init( 591e5b75505Sopenharmony_ci wpabuf_head(hapd->conf->dpp_netaccesskey), 592e5b75505Sopenharmony_ci wpabuf_len(hapd->conf->dpp_netaccesskey)); 593e5b75505Sopenharmony_ci if (!sta->dpp_pfs) { 594e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 595e5b75505Sopenharmony_ci "DPP: Could not initialize PFS"); 596e5b75505Sopenharmony_ci /* Try to continue without PFS */ 597e5b75505Sopenharmony_ci goto pfs_fail; 598e5b75505Sopenharmony_ci } 599e5b75505Sopenharmony_ci 600e5b75505Sopenharmony_ci if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh, 601e5b75505Sopenharmony_ci elems.owe_dh_len) < 0) { 602e5b75505Sopenharmony_ci dpp_pfs_free(sta->dpp_pfs); 603e5b75505Sopenharmony_ci sta->dpp_pfs = NULL; 604e5b75505Sopenharmony_ci reason = WLAN_REASON_UNSPECIFIED; 605e5b75505Sopenharmony_ci goto fail; 606e5b75505Sopenharmony_ci } 607e5b75505Sopenharmony_ci } 608e5b75505Sopenharmony_ci 609e5b75505Sopenharmony_ci wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ? 610e5b75505Sopenharmony_ci sta->dpp_pfs->secret : NULL); 611e5b75505Sopenharmony_ci pfs_fail: 612e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 613e5b75505Sopenharmony_ci 614e5b75505Sopenharmony_ci#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE) 615e5b75505Sopenharmony_ci hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); 616e5b75505Sopenharmony_ci 617e5b75505Sopenharmony_ci if (sta->auth_alg == WLAN_AUTH_FT || 618e5b75505Sopenharmony_ci sta->auth_alg == WLAN_AUTH_FILS_SK || 619e5b75505Sopenharmony_ci sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || 620e5b75505Sopenharmony_ci sta->auth_alg == WLAN_AUTH_FILS_PK) 621e5b75505Sopenharmony_ci ap_sta_set_authorized(hapd, sta, 1); 622e5b75505Sopenharmony_ci#else /* CONFIG_IEEE80211R_AP || CONFIG_FILS */ 623e5b75505Sopenharmony_ci /* Keep compiler silent about unused variables */ 624e5b75505Sopenharmony_ci if (status) { 625e5b75505Sopenharmony_ci } 626e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP || CONFIG_FILS */ 627e5b75505Sopenharmony_ci 628e5b75505Sopenharmony_ci new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; 629e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; 630e5b75505Sopenharmony_ci sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; 631e5b75505Sopenharmony_ci 632e5b75505Sopenharmony_ci hostapd_set_sta_flags(hapd, sta); 633e5b75505Sopenharmony_ci 634e5b75505Sopenharmony_ci if (reassoc && (sta->auth_alg == WLAN_AUTH_FT)) 635e5b75505Sopenharmony_ci wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); 636e5b75505Sopenharmony_ci#ifdef CONFIG_FILS 637e5b75505Sopenharmony_ci else if (sta->auth_alg == WLAN_AUTH_FILS_SK || 638e5b75505Sopenharmony_ci sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || 639e5b75505Sopenharmony_ci sta->auth_alg == WLAN_AUTH_FILS_PK) 640e5b75505Sopenharmony_ci wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FILS); 641e5b75505Sopenharmony_ci#endif /* CONFIG_FILS */ 642e5b75505Sopenharmony_ci else 643e5b75505Sopenharmony_ci wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); 644e5b75505Sopenharmony_ci 645e5b75505Sopenharmony_ci hostapd_new_assoc_sta(hapd, sta, !new_assoc); 646e5b75505Sopenharmony_ci 647e5b75505Sopenharmony_ci ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); 648e5b75505Sopenharmony_ci 649e5b75505Sopenharmony_ci#ifdef CONFIG_P2P 650e5b75505Sopenharmony_ci if (req_ies) { 651e5b75505Sopenharmony_ci p2p_group_notif_assoc(hapd->p2p_group, sta->addr, 652e5b75505Sopenharmony_ci req_ies, req_ies_len); 653e5b75505Sopenharmony_ci } 654e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */ 655e5b75505Sopenharmony_ci 656e5b75505Sopenharmony_ci return 0; 657e5b75505Sopenharmony_ci 658e5b75505Sopenharmony_cifail: 659e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211R_AP 660e5b75505Sopenharmony_ci hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); 661e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP */ 662e5b75505Sopenharmony_ci hostapd_drv_sta_disassoc(hapd, sta->addr, reason); 663e5b75505Sopenharmony_ci ap_free_sta(hapd, sta); 664e5b75505Sopenharmony_ci return -1; 665e5b75505Sopenharmony_ci} 666e5b75505Sopenharmony_ci 667e5b75505Sopenharmony_ci 668e5b75505Sopenharmony_civoid hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) 669e5b75505Sopenharmony_ci{ 670e5b75505Sopenharmony_ci struct sta_info *sta; 671e5b75505Sopenharmony_ci 672e5b75505Sopenharmony_ci if (addr == NULL) { 673e5b75505Sopenharmony_ci /* 674e5b75505Sopenharmony_ci * This could potentially happen with unexpected event from the 675e5b75505Sopenharmony_ci * driver wrapper. This was seen at least in one case where the 676e5b75505Sopenharmony_ci * driver ended up reporting a station mode event while hostapd 677e5b75505Sopenharmony_ci * was running, so better make sure we stop processing such an 678e5b75505Sopenharmony_ci * event here. 679e5b75505Sopenharmony_ci */ 680e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 681e5b75505Sopenharmony_ci "hostapd_notif_disassoc: Skip event with no address"); 682e5b75505Sopenharmony_ci return; 683e5b75505Sopenharmony_ci } 684e5b75505Sopenharmony_ci 685e5b75505Sopenharmony_ci hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 686e5b75505Sopenharmony_ci HOSTAPD_LEVEL_INFO, "disassociated"); 687e5b75505Sopenharmony_ci 688e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 689e5b75505Sopenharmony_ci if (sta == NULL) { 690e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 691e5b75505Sopenharmony_ci "Disassociation notification for unknown STA " 692e5b75505Sopenharmony_ci MACSTR, MAC2STR(addr)); 693e5b75505Sopenharmony_ci return; 694e5b75505Sopenharmony_ci } 695e5b75505Sopenharmony_ci 696e5b75505Sopenharmony_ci ap_sta_set_authorized(hapd, sta, 0); 697e5b75505Sopenharmony_ci sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); 698e5b75505Sopenharmony_ci wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); 699e5b75505Sopenharmony_ci sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; 700e5b75505Sopenharmony_ci ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 701e5b75505Sopenharmony_ci ap_free_sta(hapd, sta); 702e5b75505Sopenharmony_ci} 703e5b75505Sopenharmony_ci 704e5b75505Sopenharmony_ci 705e5b75505Sopenharmony_civoid hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) 706e5b75505Sopenharmony_ci{ 707e5b75505Sopenharmony_ci struct sta_info *sta = ap_get_sta(hapd, addr); 708e5b75505Sopenharmony_ci 709e5b75505Sopenharmony_ci if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer) 710e5b75505Sopenharmony_ci return; 711e5b75505Sopenharmony_ci 712e5b75505Sopenharmony_ci hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 713e5b75505Sopenharmony_ci HOSTAPD_LEVEL_INFO, 714e5b75505Sopenharmony_ci "disconnected due to excessive missing ACKs"); 715e5b75505Sopenharmony_ci hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK); 716e5b75505Sopenharmony_ci ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK); 717e5b75505Sopenharmony_ci} 718e5b75505Sopenharmony_ci 719e5b75505Sopenharmony_ci 720e5b75505Sopenharmony_civoid hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, 721e5b75505Sopenharmony_ci enum smps_mode smps_mode, 722e5b75505Sopenharmony_ci enum chan_width chan_width, u8 rx_nss) 723e5b75505Sopenharmony_ci{ 724e5b75505Sopenharmony_ci struct sta_info *sta = ap_get_sta(hapd, addr); 725e5b75505Sopenharmony_ci const char *txt; 726e5b75505Sopenharmony_ci 727e5b75505Sopenharmony_ci if (!sta) 728e5b75505Sopenharmony_ci return; 729e5b75505Sopenharmony_ci 730e5b75505Sopenharmony_ci switch (smps_mode) { 731e5b75505Sopenharmony_ci case SMPS_AUTOMATIC: 732e5b75505Sopenharmony_ci txt = "automatic"; 733e5b75505Sopenharmony_ci break; 734e5b75505Sopenharmony_ci case SMPS_OFF: 735e5b75505Sopenharmony_ci txt = "off"; 736e5b75505Sopenharmony_ci break; 737e5b75505Sopenharmony_ci case SMPS_DYNAMIC: 738e5b75505Sopenharmony_ci txt = "dynamic"; 739e5b75505Sopenharmony_ci break; 740e5b75505Sopenharmony_ci case SMPS_STATIC: 741e5b75505Sopenharmony_ci txt = "static"; 742e5b75505Sopenharmony_ci break; 743e5b75505Sopenharmony_ci default: 744e5b75505Sopenharmony_ci txt = NULL; 745e5b75505Sopenharmony_ci break; 746e5b75505Sopenharmony_ci } 747e5b75505Sopenharmony_ci if (txt) { 748e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_SMPS_MODE_CHANGED 749e5b75505Sopenharmony_ci MACSTR " %s", MAC2STR(addr), txt); 750e5b75505Sopenharmony_ci } 751e5b75505Sopenharmony_ci 752e5b75505Sopenharmony_ci switch (chan_width) { 753e5b75505Sopenharmony_ci case CHAN_WIDTH_20_NOHT: 754e5b75505Sopenharmony_ci txt = "20(no-HT)"; 755e5b75505Sopenharmony_ci break; 756e5b75505Sopenharmony_ci case CHAN_WIDTH_20: 757e5b75505Sopenharmony_ci txt = "20"; 758e5b75505Sopenharmony_ci break; 759e5b75505Sopenharmony_ci case CHAN_WIDTH_40: 760e5b75505Sopenharmony_ci txt = "40"; 761e5b75505Sopenharmony_ci break; 762e5b75505Sopenharmony_ci case CHAN_WIDTH_80: 763e5b75505Sopenharmony_ci txt = "80"; 764e5b75505Sopenharmony_ci break; 765e5b75505Sopenharmony_ci case CHAN_WIDTH_80P80: 766e5b75505Sopenharmony_ci txt = "80+80"; 767e5b75505Sopenharmony_ci break; 768e5b75505Sopenharmony_ci case CHAN_WIDTH_160: 769e5b75505Sopenharmony_ci txt = "160"; 770e5b75505Sopenharmony_ci break; 771e5b75505Sopenharmony_ci default: 772e5b75505Sopenharmony_ci txt = NULL; 773e5b75505Sopenharmony_ci break; 774e5b75505Sopenharmony_ci } 775e5b75505Sopenharmony_ci if (txt) { 776e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_MAX_BW_CHANGED 777e5b75505Sopenharmony_ci MACSTR " %s", MAC2STR(addr), txt); 778e5b75505Sopenharmony_ci } 779e5b75505Sopenharmony_ci 780e5b75505Sopenharmony_ci if (rx_nss != 0xff) { 781e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_N_SS_CHANGED 782e5b75505Sopenharmony_ci MACSTR " %d", MAC2STR(addr), rx_nss); 783e5b75505Sopenharmony_ci } 784e5b75505Sopenharmony_ci} 785e5b75505Sopenharmony_ci 786e5b75505Sopenharmony_ci 787e5b75505Sopenharmony_civoid hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, 788e5b75505Sopenharmony_ci int offset, int width, int cf1, int cf2, 789e5b75505Sopenharmony_ci int finished) 790e5b75505Sopenharmony_ci{ 791e5b75505Sopenharmony_ci /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ 792e5b75505Sopenharmony_ci 793e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 794e5b75505Sopenharmony_ci int channel, chwidth, is_dfs; 795e5b75505Sopenharmony_ci u8 seg0_idx = 0, seg1_idx = 0; 796e5b75505Sopenharmony_ci size_t i; 797e5b75505Sopenharmony_ci 798e5b75505Sopenharmony_ci hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 799e5b75505Sopenharmony_ci HOSTAPD_LEVEL_INFO, 800e5b75505Sopenharmony_ci "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", 801e5b75505Sopenharmony_ci finished ? "had" : "starting", 802e5b75505Sopenharmony_ci freq, ht, hapd->iconf->ch_switch_vht_config, offset, 803e5b75505Sopenharmony_ci width, channel_width_to_string(width), cf1, cf2); 804e5b75505Sopenharmony_ci 805e5b75505Sopenharmony_ci if (!hapd->iface->current_mode) { 806e5b75505Sopenharmony_ci hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 807e5b75505Sopenharmony_ci HOSTAPD_LEVEL_WARNING, 808e5b75505Sopenharmony_ci "ignore channel switch since the interface is not yet ready"); 809e5b75505Sopenharmony_ci return; 810e5b75505Sopenharmony_ci } 811e5b75505Sopenharmony_ci 812e5b75505Sopenharmony_ci hapd->iface->freq = freq; 813e5b75505Sopenharmony_ci 814e5b75505Sopenharmony_ci channel = hostapd_hw_get_channel(hapd, freq); 815e5b75505Sopenharmony_ci if (!channel) { 816e5b75505Sopenharmony_ci hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 817e5b75505Sopenharmony_ci HOSTAPD_LEVEL_WARNING, 818e5b75505Sopenharmony_ci "driver switched to bad channel!"); 819e5b75505Sopenharmony_ci return; 820e5b75505Sopenharmony_ci } 821e5b75505Sopenharmony_ci 822e5b75505Sopenharmony_ci switch (width) { 823e5b75505Sopenharmony_ci case CHAN_WIDTH_80: 824e5b75505Sopenharmony_ci chwidth = CHANWIDTH_80MHZ; 825e5b75505Sopenharmony_ci break; 826e5b75505Sopenharmony_ci case CHAN_WIDTH_80P80: 827e5b75505Sopenharmony_ci chwidth = CHANWIDTH_80P80MHZ; 828e5b75505Sopenharmony_ci break; 829e5b75505Sopenharmony_ci case CHAN_WIDTH_160: 830e5b75505Sopenharmony_ci chwidth = CHANWIDTH_160MHZ; 831e5b75505Sopenharmony_ci break; 832e5b75505Sopenharmony_ci case CHAN_WIDTH_20_NOHT: 833e5b75505Sopenharmony_ci case CHAN_WIDTH_20: 834e5b75505Sopenharmony_ci case CHAN_WIDTH_40: 835e5b75505Sopenharmony_ci default: 836e5b75505Sopenharmony_ci chwidth = CHANWIDTH_USE_HT; 837e5b75505Sopenharmony_ci break; 838e5b75505Sopenharmony_ci } 839e5b75505Sopenharmony_ci 840e5b75505Sopenharmony_ci switch (hapd->iface->current_mode->mode) { 841e5b75505Sopenharmony_ci case HOSTAPD_MODE_IEEE80211A: 842e5b75505Sopenharmony_ci if (cf1 > 5000) 843e5b75505Sopenharmony_ci seg0_idx = (cf1 - 5000) / 5; 844e5b75505Sopenharmony_ci if (cf2 > 5000) 845e5b75505Sopenharmony_ci seg1_idx = (cf2 - 5000) / 5; 846e5b75505Sopenharmony_ci break; 847e5b75505Sopenharmony_ci default: 848e5b75505Sopenharmony_ci ieee80211_freq_to_chan(cf1, &seg0_idx); 849e5b75505Sopenharmony_ci ieee80211_freq_to_chan(cf2, &seg1_idx); 850e5b75505Sopenharmony_ci break; 851e5b75505Sopenharmony_ci } 852e5b75505Sopenharmony_ci 853e5b75505Sopenharmony_ci hapd->iconf->channel = channel; 854e5b75505Sopenharmony_ci hapd->iconf->ieee80211n = ht; 855e5b75505Sopenharmony_ci if (!ht) { 856e5b75505Sopenharmony_ci hapd->iconf->ieee80211ac = 0; 857e5b75505Sopenharmony_ci } else if (hapd->iconf->ch_switch_vht_config) { 858e5b75505Sopenharmony_ci /* CHAN_SWITCH VHT config */ 859e5b75505Sopenharmony_ci if (hapd->iconf->ch_switch_vht_config & 860e5b75505Sopenharmony_ci CH_SWITCH_VHT_ENABLED) 861e5b75505Sopenharmony_ci hapd->iconf->ieee80211ac = 1; 862e5b75505Sopenharmony_ci else if (hapd->iconf->ch_switch_vht_config & 863e5b75505Sopenharmony_ci CH_SWITCH_VHT_DISABLED) 864e5b75505Sopenharmony_ci hapd->iconf->ieee80211ac = 0; 865e5b75505Sopenharmony_ci } 866e5b75505Sopenharmony_ci hapd->iconf->ch_switch_vht_config = 0; 867e5b75505Sopenharmony_ci 868e5b75505Sopenharmony_ci hapd->iconf->secondary_channel = offset; 869e5b75505Sopenharmony_ci hostapd_set_oper_chwidth(hapd->iconf, chwidth); 870e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx); 871e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx); 872e5b75505Sopenharmony_ci 873e5b75505Sopenharmony_ci is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features, 874e5b75505Sopenharmony_ci hapd->iface->num_hw_features); 875e5b75505Sopenharmony_ci 876e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, 877e5b75505Sopenharmony_ci "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d", 878e5b75505Sopenharmony_ci finished ? WPA_EVENT_CHANNEL_SWITCH : 879e5b75505Sopenharmony_ci WPA_EVENT_CHANNEL_SWITCH_STARTED, 880e5b75505Sopenharmony_ci freq, ht, offset, channel_width_to_string(width), 881e5b75505Sopenharmony_ci cf1, cf2, is_dfs); 882e5b75505Sopenharmony_ci if (!finished) 883e5b75505Sopenharmony_ci return; 884e5b75505Sopenharmony_ci 885e5b75505Sopenharmony_ci if (hapd->csa_in_progress && 886e5b75505Sopenharmony_ci freq == hapd->cs_freq_params.freq) { 887e5b75505Sopenharmony_ci hostapd_cleanup_cs_params(hapd); 888e5b75505Sopenharmony_ci ieee802_11_set_beacon(hapd); 889e5b75505Sopenharmony_ci 890e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED 891e5b75505Sopenharmony_ci "freq=%d dfs=%d", freq, is_dfs); 892e5b75505Sopenharmony_ci } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { 893e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED 894e5b75505Sopenharmony_ci "freq=%d dfs=%d", freq, is_dfs); 895e5b75505Sopenharmony_ci } 896e5b75505Sopenharmony_ci 897e5b75505Sopenharmony_ci for (i = 0; i < hapd->iface->num_bss; i++) 898e5b75505Sopenharmony_ci hostapd_neighbor_set_own_report(hapd->iface->bss[i]); 899e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 900e5b75505Sopenharmony_ci} 901e5b75505Sopenharmony_ci 902e5b75505Sopenharmony_ci 903e5b75505Sopenharmony_civoid hostapd_event_connect_failed_reason(struct hostapd_data *hapd, 904e5b75505Sopenharmony_ci const u8 *addr, int reason_code) 905e5b75505Sopenharmony_ci{ 906e5b75505Sopenharmony_ci switch (reason_code) { 907e5b75505Sopenharmony_ci case MAX_CLIENT_REACHED: 908e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR, 909e5b75505Sopenharmony_ci MAC2STR(addr)); 910e5b75505Sopenharmony_ci break; 911e5b75505Sopenharmony_ci case BLOCKED_CLIENT: 912e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR, 913e5b75505Sopenharmony_ci MAC2STR(addr)); 914e5b75505Sopenharmony_ci break; 915e5b75505Sopenharmony_ci } 916e5b75505Sopenharmony_ci} 917e5b75505Sopenharmony_ci 918e5b75505Sopenharmony_ci 919e5b75505Sopenharmony_ci#ifdef CONFIG_ACS 920e5b75505Sopenharmony_civoid hostapd_acs_channel_selected(struct hostapd_data *hapd, 921e5b75505Sopenharmony_ci struct acs_selected_channels *acs_res) 922e5b75505Sopenharmony_ci{ 923e5b75505Sopenharmony_ci int ret, i; 924e5b75505Sopenharmony_ci int err = 0; 925e5b75505Sopenharmony_ci 926e5b75505Sopenharmony_ci if (hapd->iconf->channel) { 927e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "ACS: Channel was already set to %d", 928e5b75505Sopenharmony_ci hapd->iconf->channel); 929e5b75505Sopenharmony_ci return; 930e5b75505Sopenharmony_ci } 931e5b75505Sopenharmony_ci 932e5b75505Sopenharmony_ci if (!hapd->iface->current_mode) { 933e5b75505Sopenharmony_ci for (i = 0; i < hapd->iface->num_hw_features; i++) { 934e5b75505Sopenharmony_ci struct hostapd_hw_modes *mode = 935e5b75505Sopenharmony_ci &hapd->iface->hw_features[i]; 936e5b75505Sopenharmony_ci 937e5b75505Sopenharmony_ci if (mode->mode == acs_res->hw_mode) { 938e5b75505Sopenharmony_ci hapd->iface->current_mode = mode; 939e5b75505Sopenharmony_ci break; 940e5b75505Sopenharmony_ci } 941e5b75505Sopenharmony_ci } 942e5b75505Sopenharmony_ci if (!hapd->iface->current_mode) { 943e5b75505Sopenharmony_ci hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 944e5b75505Sopenharmony_ci HOSTAPD_LEVEL_WARNING, 945e5b75505Sopenharmony_ci "driver selected to bad hw_mode"); 946e5b75505Sopenharmony_ci err = 1; 947e5b75505Sopenharmony_ci goto out; 948e5b75505Sopenharmony_ci } 949e5b75505Sopenharmony_ci } 950e5b75505Sopenharmony_ci 951e5b75505Sopenharmony_ci hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel); 952e5b75505Sopenharmony_ci 953e5b75505Sopenharmony_ci if (!acs_res->pri_channel) { 954e5b75505Sopenharmony_ci hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 955e5b75505Sopenharmony_ci HOSTAPD_LEVEL_WARNING, 956e5b75505Sopenharmony_ci "driver switched to bad channel"); 957e5b75505Sopenharmony_ci err = 1; 958e5b75505Sopenharmony_ci goto out; 959e5b75505Sopenharmony_ci } 960e5b75505Sopenharmony_ci 961e5b75505Sopenharmony_ci hapd->iconf->channel = acs_res->pri_channel; 962e5b75505Sopenharmony_ci hapd->iconf->acs = 1; 963e5b75505Sopenharmony_ci 964e5b75505Sopenharmony_ci if (acs_res->sec_channel == 0) 965e5b75505Sopenharmony_ci hapd->iconf->secondary_channel = 0; 966e5b75505Sopenharmony_ci else if (acs_res->sec_channel < acs_res->pri_channel) 967e5b75505Sopenharmony_ci hapd->iconf->secondary_channel = -1; 968e5b75505Sopenharmony_ci else if (acs_res->sec_channel > acs_res->pri_channel) 969e5b75505Sopenharmony_ci hapd->iconf->secondary_channel = 1; 970e5b75505Sopenharmony_ci else { 971e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Invalid secondary channel!"); 972e5b75505Sopenharmony_ci err = 1; 973e5b75505Sopenharmony_ci goto out; 974e5b75505Sopenharmony_ci } 975e5b75505Sopenharmony_ci 976e5b75505Sopenharmony_ci if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) { 977e5b75505Sopenharmony_ci /* set defaults for backwards compatibility */ 978e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0); 979e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0); 980e5b75505Sopenharmony_ci hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_USE_HT); 981e5b75505Sopenharmony_ci if (acs_res->ch_width == 80) { 982e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg0_idx( 983e5b75505Sopenharmony_ci hapd->iconf, acs_res->vht_seg0_center_ch); 984e5b75505Sopenharmony_ci hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_80MHZ); 985e5b75505Sopenharmony_ci } else if (acs_res->ch_width == 160) { 986e5b75505Sopenharmony_ci if (acs_res->vht_seg1_center_ch == 0) { 987e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg0_idx( 988e5b75505Sopenharmony_ci hapd->iconf, 989e5b75505Sopenharmony_ci acs_res->vht_seg0_center_ch); 990e5b75505Sopenharmony_ci hostapd_set_oper_chwidth(hapd->iconf, 991e5b75505Sopenharmony_ci CHANWIDTH_160MHZ); 992e5b75505Sopenharmony_ci } else { 993e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg0_idx( 994e5b75505Sopenharmony_ci hapd->iconf, 995e5b75505Sopenharmony_ci acs_res->vht_seg0_center_ch); 996e5b75505Sopenharmony_ci hostapd_set_oper_centr_freq_seg1_idx( 997e5b75505Sopenharmony_ci hapd->iconf, 998e5b75505Sopenharmony_ci acs_res->vht_seg1_center_ch); 999e5b75505Sopenharmony_ci hostapd_set_oper_chwidth(hapd->iconf, 1000e5b75505Sopenharmony_ci CHANWIDTH_80P80MHZ); 1001e5b75505Sopenharmony_ci } 1002e5b75505Sopenharmony_ci } 1003e5b75505Sopenharmony_ci } 1004e5b75505Sopenharmony_ci 1005e5b75505Sopenharmony_ciout: 1006e5b75505Sopenharmony_ci ret = hostapd_acs_completed(hapd->iface, err); 1007e5b75505Sopenharmony_ci if (ret) { 1008e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 1009e5b75505Sopenharmony_ci "ACS: Possibly channel configuration is invalid"); 1010e5b75505Sopenharmony_ci } 1011e5b75505Sopenharmony_ci} 1012e5b75505Sopenharmony_ci#endif /* CONFIG_ACS */ 1013e5b75505Sopenharmony_ci 1014e5b75505Sopenharmony_ci 1015e5b75505Sopenharmony_ciint hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, 1016e5b75505Sopenharmony_ci const u8 *bssid, const u8 *ie, size_t ie_len, 1017e5b75505Sopenharmony_ci int ssi_signal) 1018e5b75505Sopenharmony_ci{ 1019e5b75505Sopenharmony_ci size_t i; 1020e5b75505Sopenharmony_ci int ret = 0; 1021e5b75505Sopenharmony_ci 1022e5b75505Sopenharmony_ci if (sa == NULL || ie == NULL) 1023e5b75505Sopenharmony_ci return -1; 1024e5b75505Sopenharmony_ci 1025e5b75505Sopenharmony_ci random_add_randomness(sa, ETH_ALEN); 1026e5b75505Sopenharmony_ci for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) { 1027e5b75505Sopenharmony_ci if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, 1028e5b75505Sopenharmony_ci sa, da, bssid, ie, ie_len, 1029e5b75505Sopenharmony_ci ssi_signal) > 0) { 1030e5b75505Sopenharmony_ci ret = 1; 1031e5b75505Sopenharmony_ci break; 1032e5b75505Sopenharmony_ci } 1033e5b75505Sopenharmony_ci } 1034e5b75505Sopenharmony_ci return ret; 1035e5b75505Sopenharmony_ci} 1036e5b75505Sopenharmony_ci 1037e5b75505Sopenharmony_ci 1038e5b75505Sopenharmony_ci#ifdef HOSTAPD 1039e5b75505Sopenharmony_ci 1040e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211R_AP 1041e5b75505Sopenharmony_cistatic void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst, 1042e5b75505Sopenharmony_ci const u8 *bssid, 1043e5b75505Sopenharmony_ci u16 auth_transaction, u16 status, 1044e5b75505Sopenharmony_ci const u8 *ies, size_t ies_len) 1045e5b75505Sopenharmony_ci{ 1046e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 1047e5b75505Sopenharmony_ci struct sta_info *sta; 1048e5b75505Sopenharmony_ci 1049e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, dst); 1050e5b75505Sopenharmony_ci if (sta == NULL) 1051e5b75505Sopenharmony_ci return; 1052e5b75505Sopenharmony_ci 1053e5b75505Sopenharmony_ci hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, 1054e5b75505Sopenharmony_ci HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); 1055e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_AUTH; 1056e5b75505Sopenharmony_ci 1057e5b75505Sopenharmony_ci hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len); 1058e5b75505Sopenharmony_ci} 1059e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP */ 1060e5b75505Sopenharmony_ci 1061e5b75505Sopenharmony_ci 1062e5b75505Sopenharmony_ci#ifdef CONFIG_FILS 1063e5b75505Sopenharmony_cistatic void hostapd_notify_auth_fils_finish(struct hostapd_data *hapd, 1064e5b75505Sopenharmony_ci struct sta_info *sta, u16 resp, 1065e5b75505Sopenharmony_ci struct wpabuf *data, int pub) 1066e5b75505Sopenharmony_ci{ 1067e5b75505Sopenharmony_ci if (resp == WLAN_STATUS_SUCCESS) { 1068e5b75505Sopenharmony_ci hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 1069e5b75505Sopenharmony_ci HOSTAPD_LEVEL_DEBUG, "authentication OK (FILS)"); 1070e5b75505Sopenharmony_ci sta->flags |= WLAN_STA_AUTH; 1071e5b75505Sopenharmony_ci wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); 1072e5b75505Sopenharmony_ci sta->auth_alg = WLAN_AUTH_FILS_SK; 1073e5b75505Sopenharmony_ci mlme_authenticate_indication(hapd, sta); 1074e5b75505Sopenharmony_ci } else { 1075e5b75505Sopenharmony_ci hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 1076e5b75505Sopenharmony_ci HOSTAPD_LEVEL_DEBUG, 1077e5b75505Sopenharmony_ci "authentication failed (FILS)"); 1078e5b75505Sopenharmony_ci } 1079e5b75505Sopenharmony_ci 1080e5b75505Sopenharmony_ci hostapd_sta_auth(hapd, sta->addr, 2, resp, 1081e5b75505Sopenharmony_ci data ? wpabuf_head(data) : NULL, 1082e5b75505Sopenharmony_ci data ? wpabuf_len(data) : 0); 1083e5b75505Sopenharmony_ci wpabuf_free(data); 1084e5b75505Sopenharmony_ci} 1085e5b75505Sopenharmony_ci#endif /* CONFIG_FILS */ 1086e5b75505Sopenharmony_ci 1087e5b75505Sopenharmony_ci 1088e5b75505Sopenharmony_cistatic void hostapd_notif_auth(struct hostapd_data *hapd, 1089e5b75505Sopenharmony_ci struct auth_info *rx_auth) 1090e5b75505Sopenharmony_ci{ 1091e5b75505Sopenharmony_ci struct sta_info *sta; 1092e5b75505Sopenharmony_ci u16 status = WLAN_STATUS_SUCCESS; 1093e5b75505Sopenharmony_ci u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; 1094e5b75505Sopenharmony_ci size_t resp_ies_len = 0; 1095e5b75505Sopenharmony_ci 1096e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, rx_auth->peer); 1097e5b75505Sopenharmony_ci if (!sta) { 1098e5b75505Sopenharmony_ci sta = ap_sta_add(hapd, rx_auth->peer); 1099e5b75505Sopenharmony_ci if (sta == NULL) { 1100e5b75505Sopenharmony_ci status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1101e5b75505Sopenharmony_ci goto fail; 1102e5b75505Sopenharmony_ci } 1103e5b75505Sopenharmony_ci } 1104e5b75505Sopenharmony_ci sta->flags &= ~WLAN_STA_PREAUTH; 1105e5b75505Sopenharmony_ci ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); 1106e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211R_AP 1107e5b75505Sopenharmony_ci if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) { 1108e5b75505Sopenharmony_ci sta->auth_alg = WLAN_AUTH_FT; 1109e5b75505Sopenharmony_ci if (sta->wpa_sm == NULL) 1110e5b75505Sopenharmony_ci sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, 1111e5b75505Sopenharmony_ci sta->addr, NULL); 1112e5b75505Sopenharmony_ci if (sta->wpa_sm == NULL) { 1113e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1114e5b75505Sopenharmony_ci "FT: Failed to initialize WPA state machine"); 1115e5b75505Sopenharmony_ci status = WLAN_STATUS_UNSPECIFIED_FAILURE; 1116e5b75505Sopenharmony_ci goto fail; 1117e5b75505Sopenharmony_ci } 1118e5b75505Sopenharmony_ci wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid, 1119e5b75505Sopenharmony_ci rx_auth->auth_transaction, rx_auth->ies, 1120e5b75505Sopenharmony_ci rx_auth->ies_len, 1121e5b75505Sopenharmony_ci hostapd_notify_auth_ft_finish, hapd); 1122e5b75505Sopenharmony_ci return; 1123e5b75505Sopenharmony_ci } 1124e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP */ 1125e5b75505Sopenharmony_ci 1126e5b75505Sopenharmony_ci#ifdef CONFIG_FILS 1127e5b75505Sopenharmony_ci if (rx_auth->auth_type == WLAN_AUTH_FILS_SK) { 1128e5b75505Sopenharmony_ci sta->auth_alg = WLAN_AUTH_FILS_SK; 1129e5b75505Sopenharmony_ci handle_auth_fils(hapd, sta, rx_auth->ies, rx_auth->ies_len, 1130e5b75505Sopenharmony_ci rx_auth->auth_type, rx_auth->auth_transaction, 1131e5b75505Sopenharmony_ci rx_auth->status_code, 1132e5b75505Sopenharmony_ci hostapd_notify_auth_fils_finish); 1133e5b75505Sopenharmony_ci return; 1134e5b75505Sopenharmony_ci } 1135e5b75505Sopenharmony_ci#endif /* CONFIG_FILS */ 1136e5b75505Sopenharmony_ci 1137e5b75505Sopenharmony_cifail: 1138e5b75505Sopenharmony_ci hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1, 1139e5b75505Sopenharmony_ci status, resp_ies, resp_ies_len); 1140e5b75505Sopenharmony_ci} 1141e5b75505Sopenharmony_ci 1142e5b75505Sopenharmony_ci 1143e5b75505Sopenharmony_ci#ifndef NEED_AP_MLME 1144e5b75505Sopenharmony_cistatic void hostapd_action_rx(struct hostapd_data *hapd, 1145e5b75505Sopenharmony_ci struct rx_mgmt *drv_mgmt) 1146e5b75505Sopenharmony_ci{ 1147e5b75505Sopenharmony_ci struct ieee80211_mgmt *mgmt; 1148e5b75505Sopenharmony_ci struct sta_info *sta; 1149e5b75505Sopenharmony_ci size_t plen __maybe_unused; 1150e5b75505Sopenharmony_ci u16 fc; 1151e5b75505Sopenharmony_ci u8 *action __maybe_unused; 1152e5b75505Sopenharmony_ci 1153e5b75505Sopenharmony_ci if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1) 1154e5b75505Sopenharmony_ci return; 1155e5b75505Sopenharmony_ci 1156e5b75505Sopenharmony_ci plen = drv_mgmt->frame_len - IEEE80211_HDRLEN; 1157e5b75505Sopenharmony_ci 1158e5b75505Sopenharmony_ci mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; 1159e5b75505Sopenharmony_ci fc = le_to_host16(mgmt->frame_control); 1160e5b75505Sopenharmony_ci if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION) 1161e5b75505Sopenharmony_ci return; /* handled by the driver */ 1162e5b75505Sopenharmony_ci 1163e5b75505Sopenharmony_ci action = (u8 *) &mgmt->u.action.u; 1164e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR 1165e5b75505Sopenharmony_ci " da " MACSTR " plen %d", 1166e5b75505Sopenharmony_ci mgmt->u.action.category, *action, 1167e5b75505Sopenharmony_ci MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) plen); 1168e5b75505Sopenharmony_ci 1169e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, mgmt->sa); 1170e5b75505Sopenharmony_ci if (sta == NULL) { 1171e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: station not found", __func__); 1172e5b75505Sopenharmony_ci return; 1173e5b75505Sopenharmony_ci } 1174e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211R_AP 1175e5b75505Sopenharmony_ci if (mgmt->u.action.category == WLAN_ACTION_FT) { 1176e5b75505Sopenharmony_ci wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, plen); 1177e5b75505Sopenharmony_ci return; 1178e5b75505Sopenharmony_ci } 1179e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP */ 1180e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W 1181e5b75505Sopenharmony_ci if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY) { 1182e5b75505Sopenharmony_ci ieee802_11_sa_query_action(hapd, mgmt, drv_mgmt->frame_len); 1183e5b75505Sopenharmony_ci return; 1184e5b75505Sopenharmony_ci } 1185e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */ 1186e5b75505Sopenharmony_ci#ifdef CONFIG_WNM_AP 1187e5b75505Sopenharmony_ci if (mgmt->u.action.category == WLAN_ACTION_WNM) { 1188e5b75505Sopenharmony_ci ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len); 1189e5b75505Sopenharmony_ci return; 1190e5b75505Sopenharmony_ci } 1191e5b75505Sopenharmony_ci#endif /* CONFIG_WNM_AP */ 1192e5b75505Sopenharmony_ci#ifdef CONFIG_FST 1193e5b75505Sopenharmony_ci if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) { 1194e5b75505Sopenharmony_ci fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len); 1195e5b75505Sopenharmony_ci return; 1196e5b75505Sopenharmony_ci } 1197e5b75505Sopenharmony_ci#endif /* CONFIG_FST */ 1198e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 1199e5b75505Sopenharmony_ci if (plen >= 2 + 4 && 1200e5b75505Sopenharmony_ci mgmt->u.action.u.vs_public_action.action == 1201e5b75505Sopenharmony_ci WLAN_PA_VENDOR_SPECIFIC && 1202e5b75505Sopenharmony_ci WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) == 1203e5b75505Sopenharmony_ci OUI_WFA && 1204e5b75505Sopenharmony_ci mgmt->u.action.u.vs_public_action.variable[0] == 1205e5b75505Sopenharmony_ci DPP_OUI_TYPE) { 1206e5b75505Sopenharmony_ci const u8 *pos, *end; 1207e5b75505Sopenharmony_ci 1208e5b75505Sopenharmony_ci pos = mgmt->u.action.u.vs_public_action.oui; 1209e5b75505Sopenharmony_ci end = drv_mgmt->frame + drv_mgmt->frame_len; 1210e5b75505Sopenharmony_ci hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos, 1211e5b75505Sopenharmony_ci drv_mgmt->freq); 1212e5b75505Sopenharmony_ci return; 1213e5b75505Sopenharmony_ci } 1214e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 1215e5b75505Sopenharmony_ci} 1216e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 1217e5b75505Sopenharmony_ci 1218e5b75505Sopenharmony_ci 1219e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 1220e5b75505Sopenharmony_ci 1221e5b75505Sopenharmony_ci#define HAPD_BROADCAST ((struct hostapd_data *) -1) 1222e5b75505Sopenharmony_ci 1223e5b75505Sopenharmony_cistatic struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface, 1224e5b75505Sopenharmony_ci const u8 *bssid) 1225e5b75505Sopenharmony_ci{ 1226e5b75505Sopenharmony_ci size_t i; 1227e5b75505Sopenharmony_ci 1228e5b75505Sopenharmony_ci if (bssid == NULL) 1229e5b75505Sopenharmony_ci return NULL; 1230e5b75505Sopenharmony_ci if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && 1231e5b75505Sopenharmony_ci bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) 1232e5b75505Sopenharmony_ci return HAPD_BROADCAST; 1233e5b75505Sopenharmony_ci 1234e5b75505Sopenharmony_ci for (i = 0; i < iface->num_bss; i++) { 1235e5b75505Sopenharmony_ci if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) 1236e5b75505Sopenharmony_ci return iface->bss[i]; 1237e5b75505Sopenharmony_ci } 1238e5b75505Sopenharmony_ci 1239e5b75505Sopenharmony_ci return NULL; 1240e5b75505Sopenharmony_ci} 1241e5b75505Sopenharmony_ci 1242e5b75505Sopenharmony_ci 1243e5b75505Sopenharmony_cistatic void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, 1244e5b75505Sopenharmony_ci const u8 *bssid, const u8 *addr, 1245e5b75505Sopenharmony_ci int wds) 1246e5b75505Sopenharmony_ci{ 1247e5b75505Sopenharmony_ci hapd = get_hapd_bssid(hapd->iface, bssid); 1248e5b75505Sopenharmony_ci if (hapd == NULL || hapd == HAPD_BROADCAST) 1249e5b75505Sopenharmony_ci return; 1250e5b75505Sopenharmony_ci 1251e5b75505Sopenharmony_ci ieee802_11_rx_from_unknown(hapd, addr, wds); 1252e5b75505Sopenharmony_ci} 1253e5b75505Sopenharmony_ci 1254e5b75505Sopenharmony_ci 1255e5b75505Sopenharmony_cistatic int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) 1256e5b75505Sopenharmony_ci{ 1257e5b75505Sopenharmony_ci struct hostapd_iface *iface = hapd->iface; 1258e5b75505Sopenharmony_ci const struct ieee80211_hdr *hdr; 1259e5b75505Sopenharmony_ci const u8 *bssid; 1260e5b75505Sopenharmony_ci struct hostapd_frame_info fi; 1261e5b75505Sopenharmony_ci int ret; 1262e5b75505Sopenharmony_ci 1263e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 1264e5b75505Sopenharmony_ci if (hapd->ext_mgmt_frame_handling) { 1265e5b75505Sopenharmony_ci size_t hex_len = 2 * rx_mgmt->frame_len + 1; 1266e5b75505Sopenharmony_ci char *hex = os_malloc(hex_len); 1267e5b75505Sopenharmony_ci 1268e5b75505Sopenharmony_ci if (hex) { 1269e5b75505Sopenharmony_ci wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame, 1270e5b75505Sopenharmony_ci rx_mgmt->frame_len); 1271e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex); 1272e5b75505Sopenharmony_ci os_free(hex); 1273e5b75505Sopenharmony_ci } 1274e5b75505Sopenharmony_ci return 1; 1275e5b75505Sopenharmony_ci } 1276e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 1277e5b75505Sopenharmony_ci 1278e5b75505Sopenharmony_ci hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; 1279e5b75505Sopenharmony_ci bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); 1280e5b75505Sopenharmony_ci if (bssid == NULL) 1281e5b75505Sopenharmony_ci return 0; 1282e5b75505Sopenharmony_ci 1283e5b75505Sopenharmony_ci hapd = get_hapd_bssid(iface, bssid); 1284e5b75505Sopenharmony_ci if (hapd == NULL) { 1285e5b75505Sopenharmony_ci u16 fc = le_to_host16(hdr->frame_control); 1286e5b75505Sopenharmony_ci 1287e5b75505Sopenharmony_ci /* 1288e5b75505Sopenharmony_ci * Drop frames to unknown BSSIDs except for Beacon frames which 1289e5b75505Sopenharmony_ci * could be used to update neighbor information. 1290e5b75505Sopenharmony_ci */ 1291e5b75505Sopenharmony_ci if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 1292e5b75505Sopenharmony_ci WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) 1293e5b75505Sopenharmony_ci hapd = iface->bss[0]; 1294e5b75505Sopenharmony_ci else 1295e5b75505Sopenharmony_ci return 0; 1296e5b75505Sopenharmony_ci } 1297e5b75505Sopenharmony_ci 1298e5b75505Sopenharmony_ci os_memset(&fi, 0, sizeof(fi)); 1299e5b75505Sopenharmony_ci fi.freq = rx_mgmt->freq; 1300e5b75505Sopenharmony_ci fi.datarate = rx_mgmt->datarate; 1301e5b75505Sopenharmony_ci fi.ssi_signal = rx_mgmt->ssi_signal; 1302e5b75505Sopenharmony_ci 1303e5b75505Sopenharmony_ci if (hapd == HAPD_BROADCAST) { 1304e5b75505Sopenharmony_ci size_t i; 1305e5b75505Sopenharmony_ci 1306e5b75505Sopenharmony_ci ret = 0; 1307e5b75505Sopenharmony_ci for (i = 0; i < iface->num_bss; i++) { 1308e5b75505Sopenharmony_ci /* if bss is set, driver will call this function for 1309e5b75505Sopenharmony_ci * each bss individually. */ 1310e5b75505Sopenharmony_ci if (rx_mgmt->drv_priv && 1311e5b75505Sopenharmony_ci (iface->bss[i]->drv_priv != rx_mgmt->drv_priv)) 1312e5b75505Sopenharmony_ci continue; 1313e5b75505Sopenharmony_ci 1314e5b75505Sopenharmony_ci if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, 1315e5b75505Sopenharmony_ci rx_mgmt->frame_len, &fi) > 0) 1316e5b75505Sopenharmony_ci ret = 1; 1317e5b75505Sopenharmony_ci } 1318e5b75505Sopenharmony_ci } else 1319e5b75505Sopenharmony_ci ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, 1320e5b75505Sopenharmony_ci &fi); 1321e5b75505Sopenharmony_ci 1322e5b75505Sopenharmony_ci random_add_randomness(&fi, sizeof(fi)); 1323e5b75505Sopenharmony_ci 1324e5b75505Sopenharmony_ci return ret; 1325e5b75505Sopenharmony_ci} 1326e5b75505Sopenharmony_ci 1327e5b75505Sopenharmony_ci 1328e5b75505Sopenharmony_cistatic void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, 1329e5b75505Sopenharmony_ci size_t len, u16 stype, int ok) 1330e5b75505Sopenharmony_ci{ 1331e5b75505Sopenharmony_ci struct ieee80211_hdr *hdr; 1332e5b75505Sopenharmony_ci struct hostapd_data *orig_hapd = hapd; 1333e5b75505Sopenharmony_ci 1334e5b75505Sopenharmony_ci hdr = (struct ieee80211_hdr *) buf; 1335e5b75505Sopenharmony_ci hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); 1336e5b75505Sopenharmony_ci if (!hapd) 1337e5b75505Sopenharmony_ci return; 1338e5b75505Sopenharmony_ci if (hapd == HAPD_BROADCAST) { 1339e5b75505Sopenharmony_ci if (stype != WLAN_FC_STYPE_ACTION || len <= 25 || 1340e5b75505Sopenharmony_ci buf[24] != WLAN_ACTION_PUBLIC) 1341e5b75505Sopenharmony_ci return; 1342e5b75505Sopenharmony_ci hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2); 1343e5b75505Sopenharmony_ci if (!hapd || hapd == HAPD_BROADCAST) 1344e5b75505Sopenharmony_ci return; 1345e5b75505Sopenharmony_ci /* 1346e5b75505Sopenharmony_ci * Allow processing of TX status for a Public Action frame that 1347e5b75505Sopenharmony_ci * used wildcard BBSID. 1348e5b75505Sopenharmony_ci */ 1349e5b75505Sopenharmony_ci } 1350e5b75505Sopenharmony_ci ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); 1351e5b75505Sopenharmony_ci} 1352e5b75505Sopenharmony_ci 1353e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 1354e5b75505Sopenharmony_ci 1355e5b75505Sopenharmony_ci 1356e5b75505Sopenharmony_cistatic int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) 1357e5b75505Sopenharmony_ci{ 1358e5b75505Sopenharmony_ci struct sta_info *sta = ap_get_sta(hapd, addr); 1359e5b75505Sopenharmony_ci 1360e5b75505Sopenharmony_ci if (sta) 1361e5b75505Sopenharmony_ci return 0; 1362e5b75505Sopenharmony_ci 1363e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR 1364e5b75505Sopenharmony_ci " - adding a new STA", MAC2STR(addr)); 1365e5b75505Sopenharmony_ci sta = ap_sta_add(hapd, addr); 1366e5b75505Sopenharmony_ci if (sta) { 1367e5b75505Sopenharmony_ci hostapd_new_assoc_sta(hapd, sta, 0); 1368e5b75505Sopenharmony_ci } else { 1369e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, 1370e5b75505Sopenharmony_ci MAC2STR(addr)); 1371e5b75505Sopenharmony_ci return -1; 1372e5b75505Sopenharmony_ci } 1373e5b75505Sopenharmony_ci 1374e5b75505Sopenharmony_ci return 0; 1375e5b75505Sopenharmony_ci} 1376e5b75505Sopenharmony_ci 1377e5b75505Sopenharmony_ci 1378e5b75505Sopenharmony_cistatic void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, 1379e5b75505Sopenharmony_ci const u8 *data, size_t data_len) 1380e5b75505Sopenharmony_ci{ 1381e5b75505Sopenharmony_ci struct hostapd_iface *iface = hapd->iface; 1382e5b75505Sopenharmony_ci struct sta_info *sta; 1383e5b75505Sopenharmony_ci size_t j; 1384e5b75505Sopenharmony_ci 1385e5b75505Sopenharmony_ci for (j = 0; j < iface->num_bss; j++) { 1386e5b75505Sopenharmony_ci sta = ap_get_sta(iface->bss[j], src); 1387e5b75505Sopenharmony_ci if (sta && sta->flags & WLAN_STA_ASSOC) { 1388e5b75505Sopenharmony_ci hapd = iface->bss[j]; 1389e5b75505Sopenharmony_ci break; 1390e5b75505Sopenharmony_ci } 1391e5b75505Sopenharmony_ci } 1392e5b75505Sopenharmony_ci 1393e5b75505Sopenharmony_ci ieee802_1x_receive(hapd, src, data, data_len); 1394e5b75505Sopenharmony_ci} 1395e5b75505Sopenharmony_ci 1396e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 1397e5b75505Sopenharmony_ci 1398e5b75505Sopenharmony_ci 1399e5b75505Sopenharmony_cistatic struct hostapd_channel_data * hostapd_get_mode_channel( 1400e5b75505Sopenharmony_ci struct hostapd_iface *iface, unsigned int freq) 1401e5b75505Sopenharmony_ci{ 1402e5b75505Sopenharmony_ci int i; 1403e5b75505Sopenharmony_ci struct hostapd_channel_data *chan; 1404e5b75505Sopenharmony_ci 1405e5b75505Sopenharmony_ci for (i = 0; i < iface->current_mode->num_channels; i++) { 1406e5b75505Sopenharmony_ci chan = &iface->current_mode->channels[i]; 1407e5b75505Sopenharmony_ci if ((unsigned int) chan->freq == freq) 1408e5b75505Sopenharmony_ci return chan; 1409e5b75505Sopenharmony_ci } 1410e5b75505Sopenharmony_ci 1411e5b75505Sopenharmony_ci return NULL; 1412e5b75505Sopenharmony_ci} 1413e5b75505Sopenharmony_ci 1414e5b75505Sopenharmony_ci 1415e5b75505Sopenharmony_cistatic void hostapd_update_nf(struct hostapd_iface *iface, 1416e5b75505Sopenharmony_ci struct hostapd_channel_data *chan, 1417e5b75505Sopenharmony_ci struct freq_survey *survey) 1418e5b75505Sopenharmony_ci{ 1419e5b75505Sopenharmony_ci if (!iface->chans_surveyed) { 1420e5b75505Sopenharmony_ci chan->min_nf = survey->nf; 1421e5b75505Sopenharmony_ci iface->lowest_nf = survey->nf; 1422e5b75505Sopenharmony_ci } else { 1423e5b75505Sopenharmony_ci if (dl_list_empty(&chan->survey_list)) 1424e5b75505Sopenharmony_ci chan->min_nf = survey->nf; 1425e5b75505Sopenharmony_ci else if (survey->nf < chan->min_nf) 1426e5b75505Sopenharmony_ci chan->min_nf = survey->nf; 1427e5b75505Sopenharmony_ci if (survey->nf < iface->lowest_nf) 1428e5b75505Sopenharmony_ci iface->lowest_nf = survey->nf; 1429e5b75505Sopenharmony_ci } 1430e5b75505Sopenharmony_ci} 1431e5b75505Sopenharmony_ci 1432e5b75505Sopenharmony_ci 1433e5b75505Sopenharmony_cistatic void hostapd_single_channel_get_survey(struct hostapd_iface *iface, 1434e5b75505Sopenharmony_ci struct survey_results *survey_res) 1435e5b75505Sopenharmony_ci{ 1436e5b75505Sopenharmony_ci struct hostapd_channel_data *chan; 1437e5b75505Sopenharmony_ci struct freq_survey *survey; 1438e5b75505Sopenharmony_ci u64 divisor, dividend; 1439e5b75505Sopenharmony_ci 1440e5b75505Sopenharmony_ci survey = dl_list_first(&survey_res->survey_list, struct freq_survey, 1441e5b75505Sopenharmony_ci list); 1442e5b75505Sopenharmony_ci if (!survey || !survey->freq) 1443e5b75505Sopenharmony_ci return; 1444e5b75505Sopenharmony_ci 1445e5b75505Sopenharmony_ci chan = hostapd_get_mode_channel(iface, survey->freq); 1446e5b75505Sopenharmony_ci if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED) 1447e5b75505Sopenharmony_ci return; 1448e5b75505Sopenharmony_ci 1449e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1450e5b75505Sopenharmony_ci "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)", 1451e5b75505Sopenharmony_ci survey->freq, 1452e5b75505Sopenharmony_ci (unsigned long int) survey->channel_time, 1453e5b75505Sopenharmony_ci (unsigned long int) survey->channel_time_busy); 1454e5b75505Sopenharmony_ci 1455e5b75505Sopenharmony_ci if (survey->channel_time > iface->last_channel_time && 1456e5b75505Sopenharmony_ci survey->channel_time > survey->channel_time_busy) { 1457e5b75505Sopenharmony_ci dividend = survey->channel_time_busy - 1458e5b75505Sopenharmony_ci iface->last_channel_time_busy; 1459e5b75505Sopenharmony_ci divisor = survey->channel_time - iface->last_channel_time; 1460e5b75505Sopenharmony_ci 1461e5b75505Sopenharmony_ci iface->channel_utilization = dividend * 255 / divisor; 1462e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Channel Utilization: %d", 1463e5b75505Sopenharmony_ci iface->channel_utilization); 1464e5b75505Sopenharmony_ci } 1465e5b75505Sopenharmony_ci iface->last_channel_time = survey->channel_time; 1466e5b75505Sopenharmony_ci iface->last_channel_time_busy = survey->channel_time_busy; 1467e5b75505Sopenharmony_ci} 1468e5b75505Sopenharmony_ci 1469e5b75505Sopenharmony_ci 1470e5b75505Sopenharmony_civoid hostapd_event_get_survey(struct hostapd_iface *iface, 1471e5b75505Sopenharmony_ci struct survey_results *survey_results) 1472e5b75505Sopenharmony_ci{ 1473e5b75505Sopenharmony_ci struct freq_survey *survey, *tmp; 1474e5b75505Sopenharmony_ci struct hostapd_channel_data *chan; 1475e5b75505Sopenharmony_ci 1476e5b75505Sopenharmony_ci if (dl_list_empty(&survey_results->survey_list)) { 1477e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "No survey data received"); 1478e5b75505Sopenharmony_ci return; 1479e5b75505Sopenharmony_ci } 1480e5b75505Sopenharmony_ci 1481e5b75505Sopenharmony_ci if (survey_results->freq_filter) { 1482e5b75505Sopenharmony_ci hostapd_single_channel_get_survey(iface, survey_results); 1483e5b75505Sopenharmony_ci return; 1484e5b75505Sopenharmony_ci } 1485e5b75505Sopenharmony_ci 1486e5b75505Sopenharmony_ci dl_list_for_each_safe(survey, tmp, &survey_results->survey_list, 1487e5b75505Sopenharmony_ci struct freq_survey, list) { 1488e5b75505Sopenharmony_ci chan = hostapd_get_mode_channel(iface, survey->freq); 1489e5b75505Sopenharmony_ci if (!chan) 1490e5b75505Sopenharmony_ci continue; 1491e5b75505Sopenharmony_ci if (chan->flag & HOSTAPD_CHAN_DISABLED) 1492e5b75505Sopenharmony_ci continue; 1493e5b75505Sopenharmony_ci 1494e5b75505Sopenharmony_ci dl_list_del(&survey->list); 1495e5b75505Sopenharmony_ci dl_list_add_tail(&chan->survey_list, &survey->list); 1496e5b75505Sopenharmony_ci 1497e5b75505Sopenharmony_ci hostapd_update_nf(iface, chan, survey); 1498e5b75505Sopenharmony_ci 1499e5b75505Sopenharmony_ci iface->chans_surveyed++; 1500e5b75505Sopenharmony_ci } 1501e5b75505Sopenharmony_ci} 1502e5b75505Sopenharmony_ci 1503e5b75505Sopenharmony_ci 1504e5b75505Sopenharmony_ci#ifdef HOSTAPD 1505e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 1506e5b75505Sopenharmony_ci 1507e5b75505Sopenharmony_cistatic void hostapd_event_iface_unavailable(struct hostapd_data *hapd) 1508e5b75505Sopenharmony_ci{ 1509e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped", 1510e5b75505Sopenharmony_ci hapd->conf->iface); 1511e5b75505Sopenharmony_ci 1512e5b75505Sopenharmony_ci if (hapd->csa_in_progress) { 1513e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "CSA failed (%s was stopped)", 1514e5b75505Sopenharmony_ci hapd->conf->iface); 1515e5b75505Sopenharmony_ci hostapd_switch_channel_fallback(hapd->iface, 1516e5b75505Sopenharmony_ci &hapd->cs_freq_params); 1517e5b75505Sopenharmony_ci } 1518e5b75505Sopenharmony_ci} 1519e5b75505Sopenharmony_ci 1520e5b75505Sopenharmony_ci 1521e5b75505Sopenharmony_cistatic void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd, 1522e5b75505Sopenharmony_ci struct dfs_event *radar) 1523e5b75505Sopenharmony_ci{ 1524e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); 1525e5b75505Sopenharmony_ci hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled, 1526e5b75505Sopenharmony_ci radar->chan_offset, radar->chan_width, 1527e5b75505Sopenharmony_ci radar->cf1, radar->cf2); 1528e5b75505Sopenharmony_ci} 1529e5b75505Sopenharmony_ci 1530e5b75505Sopenharmony_ci 1531e5b75505Sopenharmony_cistatic void hostapd_event_dfs_pre_cac_expired(struct hostapd_data *hapd, 1532e5b75505Sopenharmony_ci struct dfs_event *radar) 1533e5b75505Sopenharmony_ci{ 1534e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DFS Pre-CAC expired on %d MHz", radar->freq); 1535e5b75505Sopenharmony_ci hostapd_dfs_pre_cac_expired(hapd->iface, radar->freq, radar->ht_enabled, 1536e5b75505Sopenharmony_ci radar->chan_offset, radar->chan_width, 1537e5b75505Sopenharmony_ci radar->cf1, radar->cf2); 1538e5b75505Sopenharmony_ci} 1539e5b75505Sopenharmony_ci 1540e5b75505Sopenharmony_ci 1541e5b75505Sopenharmony_cistatic void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd, 1542e5b75505Sopenharmony_ci struct dfs_event *radar) 1543e5b75505Sopenharmony_ci{ 1544e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); 1545e5b75505Sopenharmony_ci hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled, 1546e5b75505Sopenharmony_ci radar->chan_offset, radar->chan_width, 1547e5b75505Sopenharmony_ci radar->cf1, radar->cf2); 1548e5b75505Sopenharmony_ci} 1549e5b75505Sopenharmony_ci 1550e5b75505Sopenharmony_ci 1551e5b75505Sopenharmony_cistatic void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd, 1552e5b75505Sopenharmony_ci struct dfs_event *radar) 1553e5b75505Sopenharmony_ci{ 1554e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); 1555e5b75505Sopenharmony_ci hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled, 1556e5b75505Sopenharmony_ci radar->chan_offset, radar->chan_width, 1557e5b75505Sopenharmony_ci radar->cf1, radar->cf2); 1558e5b75505Sopenharmony_ci} 1559e5b75505Sopenharmony_ci 1560e5b75505Sopenharmony_ci 1561e5b75505Sopenharmony_cistatic void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd, 1562e5b75505Sopenharmony_ci struct dfs_event *radar) 1563e5b75505Sopenharmony_ci{ 1564e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); 1565e5b75505Sopenharmony_ci hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled, 1566e5b75505Sopenharmony_ci radar->chan_offset, radar->chan_width, 1567e5b75505Sopenharmony_ci radar->cf1, radar->cf2); 1568e5b75505Sopenharmony_ci} 1569e5b75505Sopenharmony_ci 1570e5b75505Sopenharmony_ci 1571e5b75505Sopenharmony_cistatic void hostapd_event_dfs_cac_started(struct hostapd_data *hapd, 1572e5b75505Sopenharmony_ci struct dfs_event *radar) 1573e5b75505Sopenharmony_ci{ 1574e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq); 1575e5b75505Sopenharmony_ci hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled, 1576e5b75505Sopenharmony_ci radar->chan_offset, radar->chan_width, 1577e5b75505Sopenharmony_ci radar->cf1, radar->cf2); 1578e5b75505Sopenharmony_ci} 1579e5b75505Sopenharmony_ci 1580e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 1581e5b75505Sopenharmony_ci 1582e5b75505Sopenharmony_ci 1583e5b75505Sopenharmony_cistatic void hostapd_event_wds_sta_interface_status(struct hostapd_data *hapd, 1584e5b75505Sopenharmony_ci int istatus, 1585e5b75505Sopenharmony_ci const char *ifname, 1586e5b75505Sopenharmony_ci const u8 *addr) 1587e5b75505Sopenharmony_ci{ 1588e5b75505Sopenharmony_ci struct sta_info *sta = ap_get_sta(hapd, addr); 1589e5b75505Sopenharmony_ci 1590e5b75505Sopenharmony_ci if (sta) { 1591e5b75505Sopenharmony_ci os_free(sta->ifname_wds); 1592e5b75505Sopenharmony_ci if (istatus == INTERFACE_ADDED) 1593e5b75505Sopenharmony_ci sta->ifname_wds = os_strdup(ifname); 1594e5b75505Sopenharmony_ci else 1595e5b75505Sopenharmony_ci sta->ifname_wds = NULL; 1596e5b75505Sopenharmony_ci } 1597e5b75505Sopenharmony_ci 1598e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, "%sifname=%s sta_addr=" MACSTR, 1599e5b75505Sopenharmony_ci istatus == INTERFACE_ADDED ? 1600e5b75505Sopenharmony_ci WDS_STA_INTERFACE_ADDED : WDS_STA_INTERFACE_REMOVED, 1601e5b75505Sopenharmony_ci ifname, MAC2STR(addr)); 1602e5b75505Sopenharmony_ci} 1603e5b75505Sopenharmony_ci 1604e5b75505Sopenharmony_ci 1605e5b75505Sopenharmony_ci#ifdef CONFIG_OWE 1606e5b75505Sopenharmony_cistatic int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, 1607e5b75505Sopenharmony_ci const u8 *peer, const u8 *ie, 1608e5b75505Sopenharmony_ci size_t ie_len) 1609e5b75505Sopenharmony_ci{ 1610e5b75505Sopenharmony_ci u16 status; 1611e5b75505Sopenharmony_ci struct sta_info *sta; 1612e5b75505Sopenharmony_ci struct ieee802_11_elems elems; 1613e5b75505Sopenharmony_ci 1614e5b75505Sopenharmony_ci if (!hapd || !hapd->wpa_auth) { 1615e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "OWE: Invalid hapd context"); 1616e5b75505Sopenharmony_ci return -1; 1617e5b75505Sopenharmony_ci } 1618e5b75505Sopenharmony_ci if (!peer) { 1619e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "OWE: Peer unknown"); 1620e5b75505Sopenharmony_ci return -1; 1621e5b75505Sopenharmony_ci } 1622e5b75505Sopenharmony_ci if (!(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) { 1623e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "OWE: No OWE AKM configured"); 1624e5b75505Sopenharmony_ci status = WLAN_STATUS_AKMP_NOT_VALID; 1625e5b75505Sopenharmony_ci goto err; 1626e5b75505Sopenharmony_ci } 1627e5b75505Sopenharmony_ci if (ieee802_11_parse_elems(ie, ie_len, &elems, 1) == ParseFailed) { 1628e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "OWE: Failed to parse OWE IE for " 1629e5b75505Sopenharmony_ci MACSTR, MAC2STR(peer)); 1630e5b75505Sopenharmony_ci status = WLAN_STATUS_UNSPECIFIED_FAILURE; 1631e5b75505Sopenharmony_ci goto err; 1632e5b75505Sopenharmony_ci } 1633e5b75505Sopenharmony_ci status = owe_validate_request(hapd, peer, elems.rsn_ie, 1634e5b75505Sopenharmony_ci elems.rsn_ie_len, 1635e5b75505Sopenharmony_ci elems.owe_dh, elems.owe_dh_len); 1636e5b75505Sopenharmony_ci if (status != WLAN_STATUS_SUCCESS) 1637e5b75505Sopenharmony_ci goto err; 1638e5b75505Sopenharmony_ci 1639e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, peer); 1640e5b75505Sopenharmony_ci if (sta) { 1641e5b75505Sopenharmony_ci ap_sta_no_session_timeout(hapd, sta); 1642e5b75505Sopenharmony_ci accounting_sta_stop(hapd, sta); 1643e5b75505Sopenharmony_ci 1644e5b75505Sopenharmony_ci /* 1645e5b75505Sopenharmony_ci * Make sure that the previously registered inactivity timer 1646e5b75505Sopenharmony_ci * will not remove the STA immediately. 1647e5b75505Sopenharmony_ci */ 1648e5b75505Sopenharmony_ci sta->timeout_next = STA_NULLFUNC; 1649e5b75505Sopenharmony_ci } else { 1650e5b75505Sopenharmony_ci sta = ap_sta_add(hapd, peer); 1651e5b75505Sopenharmony_ci if (!sta) { 1652e5b75505Sopenharmony_ci status = WLAN_STATUS_UNSPECIFIED_FAILURE; 1653e5b75505Sopenharmony_ci goto err; 1654e5b75505Sopenharmony_ci } 1655e5b75505Sopenharmony_ci } 1656e5b75505Sopenharmony_ci sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); 1657e5b75505Sopenharmony_ci 1658e5b75505Sopenharmony_ci status = owe_process_rsn_ie(hapd, sta, elems.rsn_ie, 1659e5b75505Sopenharmony_ci elems.rsn_ie_len, elems.owe_dh, 1660e5b75505Sopenharmony_ci elems.owe_dh_len); 1661e5b75505Sopenharmony_ci if (status != WLAN_STATUS_SUCCESS) 1662e5b75505Sopenharmony_ci ap_free_sta(hapd, sta); 1663e5b75505Sopenharmony_ci 1664e5b75505Sopenharmony_ci return 0; 1665e5b75505Sopenharmony_cierr: 1666e5b75505Sopenharmony_ci hostapd_drv_update_dh_ie(hapd, peer, status, NULL, 0); 1667e5b75505Sopenharmony_ci return 0; 1668e5b75505Sopenharmony_ci} 1669e5b75505Sopenharmony_ci#endif /* CONFIG_OWE */ 1670e5b75505Sopenharmony_ci 1671e5b75505Sopenharmony_ci 1672e5b75505Sopenharmony_civoid wpa_supplicant_event_hapd(void *ctx, enum wpa_event_type event, 1673e5b75505Sopenharmony_ci union wpa_event_data *data) 1674e5b75505Sopenharmony_ci{ 1675e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 1676e5b75505Sopenharmony_ci#ifndef CONFIG_NO_STDOUT_DEBUG 1677e5b75505Sopenharmony_ci int level = MSG_DEBUG; 1678e5b75505Sopenharmony_ci 1679e5b75505Sopenharmony_ci if (event == EVENT_RX_MGMT && data->rx_mgmt.frame && 1680e5b75505Sopenharmony_ci data->rx_mgmt.frame_len >= 24) { 1681e5b75505Sopenharmony_ci const struct ieee80211_hdr *hdr; 1682e5b75505Sopenharmony_ci u16 fc; 1683e5b75505Sopenharmony_ci 1684e5b75505Sopenharmony_ci hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; 1685e5b75505Sopenharmony_ci fc = le_to_host16(hdr->frame_control); 1686e5b75505Sopenharmony_ci if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 1687e5b75505Sopenharmony_ci WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) 1688e5b75505Sopenharmony_ci level = MSG_EXCESSIVE; 1689e5b75505Sopenharmony_ci if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 1690e5b75505Sopenharmony_ci WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) 1691e5b75505Sopenharmony_ci level = MSG_EXCESSIVE; 1692e5b75505Sopenharmony_ci } 1693e5b75505Sopenharmony_ci 1694e5b75505Sopenharmony_ci wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", 1695e5b75505Sopenharmony_ci event_to_string(event), event); 1696e5b75505Sopenharmony_ci#endif /* CONFIG_NO_STDOUT_DEBUG */ 1697e5b75505Sopenharmony_ci 1698e5b75505Sopenharmony_ci switch (event) { 1699e5b75505Sopenharmony_ci case EVENT_MICHAEL_MIC_FAILURE: 1700e5b75505Sopenharmony_ci michael_mic_failure(hapd, data->michael_mic_failure.src, 1); 1701e5b75505Sopenharmony_ci break; 1702e5b75505Sopenharmony_ci case EVENT_SCAN_RESULTS: 1703e5b75505Sopenharmony_ci if (hapd->iface->scan_cb) 1704e5b75505Sopenharmony_ci hapd->iface->scan_cb(hapd->iface); 1705e5b75505Sopenharmony_ci break; 1706e5b75505Sopenharmony_ci case EVENT_WPS_BUTTON_PUSHED: 1707e5b75505Sopenharmony_ci hostapd_wps_button_pushed(hapd, NULL); 1708e5b75505Sopenharmony_ci break; 1709e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 1710e5b75505Sopenharmony_ci case EVENT_TX_STATUS: 1711e5b75505Sopenharmony_ci switch (data->tx_status.type) { 1712e5b75505Sopenharmony_ci case WLAN_FC_TYPE_MGMT: 1713e5b75505Sopenharmony_ci hostapd_mgmt_tx_cb(hapd, data->tx_status.data, 1714e5b75505Sopenharmony_ci data->tx_status.data_len, 1715e5b75505Sopenharmony_ci data->tx_status.stype, 1716e5b75505Sopenharmony_ci data->tx_status.ack); 1717e5b75505Sopenharmony_ci break; 1718e5b75505Sopenharmony_ci case WLAN_FC_TYPE_DATA: 1719e5b75505Sopenharmony_ci hostapd_tx_status(hapd, data->tx_status.dst, 1720e5b75505Sopenharmony_ci data->tx_status.data, 1721e5b75505Sopenharmony_ci data->tx_status.data_len, 1722e5b75505Sopenharmony_ci data->tx_status.ack); 1723e5b75505Sopenharmony_ci break; 1724e5b75505Sopenharmony_ci } 1725e5b75505Sopenharmony_ci break; 1726e5b75505Sopenharmony_ci case EVENT_EAPOL_TX_STATUS: 1727e5b75505Sopenharmony_ci hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, 1728e5b75505Sopenharmony_ci data->eapol_tx_status.data, 1729e5b75505Sopenharmony_ci data->eapol_tx_status.data_len, 1730e5b75505Sopenharmony_ci data->eapol_tx_status.ack); 1731e5b75505Sopenharmony_ci break; 1732e5b75505Sopenharmony_ci case EVENT_DRIVER_CLIENT_POLL_OK: 1733e5b75505Sopenharmony_ci hostapd_client_poll_ok(hapd, data->client_poll.addr); 1734e5b75505Sopenharmony_ci break; 1735e5b75505Sopenharmony_ci case EVENT_RX_FROM_UNKNOWN: 1736e5b75505Sopenharmony_ci hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, 1737e5b75505Sopenharmony_ci data->rx_from_unknown.addr, 1738e5b75505Sopenharmony_ci data->rx_from_unknown.wds); 1739e5b75505Sopenharmony_ci break; 1740e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 1741e5b75505Sopenharmony_ci case EVENT_RX_MGMT: 1742e5b75505Sopenharmony_ci if (!data->rx_mgmt.frame) 1743e5b75505Sopenharmony_ci break; 1744e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 1745e5b75505Sopenharmony_ci hostapd_mgmt_rx(hapd, &data->rx_mgmt); 1746e5b75505Sopenharmony_ci#else /* NEED_AP_MLME */ 1747e5b75505Sopenharmony_ci hostapd_action_rx(hapd, &data->rx_mgmt); 1748e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 1749e5b75505Sopenharmony_ci break; 1750e5b75505Sopenharmony_ci case EVENT_RX_PROBE_REQ: 1751e5b75505Sopenharmony_ci if (data->rx_probe_req.sa == NULL || 1752e5b75505Sopenharmony_ci data->rx_probe_req.ie == NULL) 1753e5b75505Sopenharmony_ci break; 1754e5b75505Sopenharmony_ci hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, 1755e5b75505Sopenharmony_ci data->rx_probe_req.da, 1756e5b75505Sopenharmony_ci data->rx_probe_req.bssid, 1757e5b75505Sopenharmony_ci data->rx_probe_req.ie, 1758e5b75505Sopenharmony_ci data->rx_probe_req.ie_len, 1759e5b75505Sopenharmony_ci data->rx_probe_req.ssi_signal); 1760e5b75505Sopenharmony_ci break; 1761e5b75505Sopenharmony_ci case EVENT_NEW_STA: 1762e5b75505Sopenharmony_ci hostapd_event_new_sta(hapd, data->new_sta.addr); 1763e5b75505Sopenharmony_ci break; 1764e5b75505Sopenharmony_ci case EVENT_EAPOL_RX: 1765e5b75505Sopenharmony_ci hostapd_event_eapol_rx(hapd, data->eapol_rx.src, 1766e5b75505Sopenharmony_ci data->eapol_rx.data, 1767e5b75505Sopenharmony_ci data->eapol_rx.data_len); 1768e5b75505Sopenharmony_ci break; 1769e5b75505Sopenharmony_ci case EVENT_ASSOC: 1770e5b75505Sopenharmony_ci if (!data) 1771e5b75505Sopenharmony_ci return; 1772e5b75505Sopenharmony_ci hostapd_notif_assoc(hapd, data->assoc_info.addr, 1773e5b75505Sopenharmony_ci data->assoc_info.req_ies, 1774e5b75505Sopenharmony_ci data->assoc_info.req_ies_len, 1775e5b75505Sopenharmony_ci data->assoc_info.reassoc); 1776e5b75505Sopenharmony_ci break; 1777e5b75505Sopenharmony_ci#ifdef CONFIG_OWE 1778e5b75505Sopenharmony_ci case EVENT_UPDATE_DH: 1779e5b75505Sopenharmony_ci if (!data) 1780e5b75505Sopenharmony_ci return; 1781e5b75505Sopenharmony_ci hostapd_notif_update_dh_ie(hapd, data->update_dh.peer, 1782e5b75505Sopenharmony_ci data->update_dh.ie, 1783e5b75505Sopenharmony_ci data->update_dh.ie_len); 1784e5b75505Sopenharmony_ci break; 1785e5b75505Sopenharmony_ci#endif /* CONFIG_OWE */ 1786e5b75505Sopenharmony_ci case EVENT_DISASSOC: 1787e5b75505Sopenharmony_ci if (data) 1788e5b75505Sopenharmony_ci hostapd_notif_disassoc(hapd, data->disassoc_info.addr); 1789e5b75505Sopenharmony_ci break; 1790e5b75505Sopenharmony_ci case EVENT_DEAUTH: 1791e5b75505Sopenharmony_ci if (data) 1792e5b75505Sopenharmony_ci hostapd_notif_disassoc(hapd, data->deauth_info.addr); 1793e5b75505Sopenharmony_ci break; 1794e5b75505Sopenharmony_ci case EVENT_STATION_LOW_ACK: 1795e5b75505Sopenharmony_ci if (!data) 1796e5b75505Sopenharmony_ci break; 1797e5b75505Sopenharmony_ci hostapd_event_sta_low_ack(hapd, data->low_ack.addr); 1798e5b75505Sopenharmony_ci break; 1799e5b75505Sopenharmony_ci case EVENT_AUTH: 1800e5b75505Sopenharmony_ci hostapd_notif_auth(hapd, &data->auth); 1801e5b75505Sopenharmony_ci break; 1802e5b75505Sopenharmony_ci case EVENT_CH_SWITCH_STARTED: 1803e5b75505Sopenharmony_ci case EVENT_CH_SWITCH: 1804e5b75505Sopenharmony_ci if (!data) 1805e5b75505Sopenharmony_ci break; 1806e5b75505Sopenharmony_ci hostapd_event_ch_switch(hapd, data->ch_switch.freq, 1807e5b75505Sopenharmony_ci data->ch_switch.ht_enabled, 1808e5b75505Sopenharmony_ci data->ch_switch.ch_offset, 1809e5b75505Sopenharmony_ci data->ch_switch.ch_width, 1810e5b75505Sopenharmony_ci data->ch_switch.cf1, 1811e5b75505Sopenharmony_ci data->ch_switch.cf2, 1812e5b75505Sopenharmony_ci event == EVENT_CH_SWITCH); 1813e5b75505Sopenharmony_ci break; 1814e5b75505Sopenharmony_ci case EVENT_CONNECT_FAILED_REASON: 1815e5b75505Sopenharmony_ci if (!data) 1816e5b75505Sopenharmony_ci break; 1817e5b75505Sopenharmony_ci hostapd_event_connect_failed_reason( 1818e5b75505Sopenharmony_ci hapd, data->connect_failed_reason.addr, 1819e5b75505Sopenharmony_ci data->connect_failed_reason.code); 1820e5b75505Sopenharmony_ci break; 1821e5b75505Sopenharmony_ci case EVENT_SURVEY: 1822e5b75505Sopenharmony_ci hostapd_event_get_survey(hapd->iface, &data->survey_results); 1823e5b75505Sopenharmony_ci break; 1824e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 1825e5b75505Sopenharmony_ci case EVENT_INTERFACE_UNAVAILABLE: 1826e5b75505Sopenharmony_ci hostapd_event_iface_unavailable(hapd); 1827e5b75505Sopenharmony_ci break; 1828e5b75505Sopenharmony_ci case EVENT_DFS_RADAR_DETECTED: 1829e5b75505Sopenharmony_ci if (!data) 1830e5b75505Sopenharmony_ci break; 1831e5b75505Sopenharmony_ci hostapd_event_dfs_radar_detected(hapd, &data->dfs_event); 1832e5b75505Sopenharmony_ci break; 1833e5b75505Sopenharmony_ci case EVENT_DFS_PRE_CAC_EXPIRED: 1834e5b75505Sopenharmony_ci if (!data) 1835e5b75505Sopenharmony_ci break; 1836e5b75505Sopenharmony_ci hostapd_event_dfs_pre_cac_expired(hapd, &data->dfs_event); 1837e5b75505Sopenharmony_ci break; 1838e5b75505Sopenharmony_ci case EVENT_DFS_CAC_FINISHED: 1839e5b75505Sopenharmony_ci if (!data) 1840e5b75505Sopenharmony_ci break; 1841e5b75505Sopenharmony_ci hostapd_event_dfs_cac_finished(hapd, &data->dfs_event); 1842e5b75505Sopenharmony_ci break; 1843e5b75505Sopenharmony_ci case EVENT_DFS_CAC_ABORTED: 1844e5b75505Sopenharmony_ci if (!data) 1845e5b75505Sopenharmony_ci break; 1846e5b75505Sopenharmony_ci hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event); 1847e5b75505Sopenharmony_ci break; 1848e5b75505Sopenharmony_ci case EVENT_DFS_NOP_FINISHED: 1849e5b75505Sopenharmony_ci if (!data) 1850e5b75505Sopenharmony_ci break; 1851e5b75505Sopenharmony_ci hostapd_event_dfs_nop_finished(hapd, &data->dfs_event); 1852e5b75505Sopenharmony_ci break; 1853e5b75505Sopenharmony_ci case EVENT_CHANNEL_LIST_CHANGED: 1854e5b75505Sopenharmony_ci /* channel list changed (regulatory?), update channel list */ 1855e5b75505Sopenharmony_ci /* TODO: check this. hostapd_get_hw_features() initializes 1856e5b75505Sopenharmony_ci * too much stuff. */ 1857e5b75505Sopenharmony_ci /* hostapd_get_hw_features(hapd->iface); */ 1858e5b75505Sopenharmony_ci hostapd_channel_list_updated( 1859e5b75505Sopenharmony_ci hapd->iface, data->channel_list_changed.initiator); 1860e5b75505Sopenharmony_ci break; 1861e5b75505Sopenharmony_ci case EVENT_DFS_CAC_STARTED: 1862e5b75505Sopenharmony_ci if (!data) 1863e5b75505Sopenharmony_ci break; 1864e5b75505Sopenharmony_ci hostapd_event_dfs_cac_started(hapd, &data->dfs_event); 1865e5b75505Sopenharmony_ci break; 1866e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 1867e5b75505Sopenharmony_ci case EVENT_INTERFACE_ENABLED: 1868e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED); 1869e5b75505Sopenharmony_ci if (hapd->disabled && hapd->started) { 1870e5b75505Sopenharmony_ci hapd->disabled = 0; 1871e5b75505Sopenharmony_ci /* 1872e5b75505Sopenharmony_ci * Try to re-enable interface if the driver stopped it 1873e5b75505Sopenharmony_ci * when the interface got disabled. 1874e5b75505Sopenharmony_ci */ 1875e5b75505Sopenharmony_ci if (hapd->wpa_auth) 1876e5b75505Sopenharmony_ci wpa_auth_reconfig_group_keys(hapd->wpa_auth); 1877e5b75505Sopenharmony_ci else 1878e5b75505Sopenharmony_ci hostapd_reconfig_encryption(hapd); 1879e5b75505Sopenharmony_ci hapd->reenable_beacon = 1; 1880e5b75505Sopenharmony_ci ieee802_11_set_beacon(hapd); 1881e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 1882e5b75505Sopenharmony_ci } else if (hapd->disabled && hapd->iface->cac_started) { 1883e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC"); 1884e5b75505Sopenharmony_ci hostapd_handle_dfs(hapd->iface); 1885e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 1886e5b75505Sopenharmony_ci } 1887e5b75505Sopenharmony_ci break; 1888e5b75505Sopenharmony_ci case EVENT_INTERFACE_DISABLED: 1889e5b75505Sopenharmony_ci hostapd_free_stas(hapd); 1890e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED); 1891e5b75505Sopenharmony_ci hapd->disabled = 1; 1892e5b75505Sopenharmony_ci break; 1893e5b75505Sopenharmony_ci#ifdef CONFIG_ACS 1894e5b75505Sopenharmony_ci case EVENT_ACS_CHANNEL_SELECTED: 1895e5b75505Sopenharmony_ci hostapd_acs_channel_selected(hapd, 1896e5b75505Sopenharmony_ci &data->acs_selected_channels); 1897e5b75505Sopenharmony_ci break; 1898e5b75505Sopenharmony_ci#endif /* CONFIG_ACS */ 1899e5b75505Sopenharmony_ci case EVENT_STATION_OPMODE_CHANGED: 1900e5b75505Sopenharmony_ci hostapd_event_sta_opmode_changed(hapd, data->sta_opmode.addr, 1901e5b75505Sopenharmony_ci data->sta_opmode.smps_mode, 1902e5b75505Sopenharmony_ci data->sta_opmode.chan_width, 1903e5b75505Sopenharmony_ci data->sta_opmode.rx_nss); 1904e5b75505Sopenharmony_ci break; 1905e5b75505Sopenharmony_ci case EVENT_WDS_STA_INTERFACE_STATUS: 1906e5b75505Sopenharmony_ci hostapd_event_wds_sta_interface_status( 1907e5b75505Sopenharmony_ci hapd, data->wds_sta_interface.istatus, 1908e5b75505Sopenharmony_ci data->wds_sta_interface.ifname, 1909e5b75505Sopenharmony_ci data->wds_sta_interface.sta_addr); 1910e5b75505Sopenharmony_ci break; 1911e5b75505Sopenharmony_ci default: 1912e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Unknown event %d", event); 1913e5b75505Sopenharmony_ci break; 1914e5b75505Sopenharmony_ci } 1915e5b75505Sopenharmony_ci} 1916e5b75505Sopenharmony_ci 1917e5b75505Sopenharmony_ci 1918e5b75505Sopenharmony_civoid wpa_supplicant_event_global_hapd(void *ctx, enum wpa_event_type event, 1919e5b75505Sopenharmony_ci union wpa_event_data *data) 1920e5b75505Sopenharmony_ci{ 1921e5b75505Sopenharmony_ci struct hapd_interfaces *interfaces = ctx; 1922e5b75505Sopenharmony_ci struct hostapd_data *hapd; 1923e5b75505Sopenharmony_ci 1924e5b75505Sopenharmony_ci if (event != EVENT_INTERFACE_STATUS) 1925e5b75505Sopenharmony_ci return; 1926e5b75505Sopenharmony_ci 1927e5b75505Sopenharmony_ci hapd = hostapd_get_iface(interfaces, data->interface_status.ifname); 1928e5b75505Sopenharmony_ci if (hapd && hapd->driver && hapd->driver->get_ifindex && 1929e5b75505Sopenharmony_ci hapd->drv_priv) { 1930e5b75505Sopenharmony_ci unsigned int ifindex; 1931e5b75505Sopenharmony_ci 1932e5b75505Sopenharmony_ci ifindex = hapd->driver->get_ifindex(hapd->drv_priv); 1933e5b75505Sopenharmony_ci if (ifindex != data->interface_status.ifindex) { 1934e5b75505Sopenharmony_ci wpa_dbg(hapd->msg_ctx, MSG_DEBUG, 1935e5b75505Sopenharmony_ci "interface status ifindex %d mismatch (%d)", 1936e5b75505Sopenharmony_ci ifindex, data->interface_status.ifindex); 1937e5b75505Sopenharmony_ci return; 1938e5b75505Sopenharmony_ci } 1939e5b75505Sopenharmony_ci } 1940e5b75505Sopenharmony_ci if (hapd) 1941e5b75505Sopenharmony_ci wpa_supplicant_event_hapd(hapd, event, data); 1942e5b75505Sopenharmony_ci} 1943e5b75505Sopenharmony_ci 1944e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 1945