blob: 233984f7cb487a09424784fc42a3fbb400699726 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * hostapd / Callback functions for driver wrappers
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003 * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
Dmitry Shmidt7832adb2014-04-29 10:53:02 -070012#include "utils/eloop.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013#include "radius/radius.h"
14#include "drivers/driver.h"
15#include "common/ieee802_11_defs.h"
16#include "common/ieee802_11_common.h"
Dmitry Shmidtf8623282013-02-20 14:34:59 -080017#include "common/wpa_ctrl.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070018#include "common/dpp.h"
Hai Shalomc3565922019-10-28 11:58:20 -070019#include "common/sae.h"
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080020#include "common/hw_features_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "crypto/random.h"
22#include "p2p/p2p.h"
23#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080024#include "fst/fst.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070025#include "wnm_ap.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "hostapd.h"
27#include "ieee802_11.h"
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080028#include "ieee802_11_auth.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070029#include "sta_info.h"
30#include "accounting.h"
31#include "tkip_countermeasures.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032#include "ieee802_1x.h"
33#include "wpa_auth.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034#include "wps_hostapd.h"
35#include "ap_drv_ops.h"
36#include "ap_config.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070037#include "ap_mlme.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070038#include "hw_features.h"
Dmitry Shmidt051af732013-10-22 13:52:46 -070039#include "dfs.h"
Dmitry Shmidt7832adb2014-04-29 10:53:02 -070040#include "beacon.h"
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080041#include "mbo_ap.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070042#include "dpp_hostapd.h"
43#include "fils_hlp.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080044#include "neighbor_db.h"
Sunil Ravib0ac25f2024-07-12 01:42:03 +000045#include "nan_usd_ap.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070046
47
48#ifdef CONFIG_FILS
49void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
50 struct sta_info *sta)
51{
52 u16 reply_res = WLAN_STATUS_SUCCESS;
53 struct ieee802_11_elems elems;
54 u8 buf[IEEE80211_MAX_MMPDU_SIZE], *p = buf;
55 int new_assoc;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000056 bool updated;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070057
58 wpa_printf(MSG_DEBUG, "%s FILS: Finish association with " MACSTR,
59 __func__, MAC2STR(sta->addr));
60 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
61 if (!sta->fils_pending_assoc_req)
62 return;
63
Sunil Ravi2a14cf12023-11-21 00:54:38 +000064 if (ieee802_11_parse_elems(sta->fils_pending_assoc_req,
65 sta->fils_pending_assoc_req_len, &elems,
66 0) == ParseFailed ||
67 !elems.fils_session) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070068 wpa_printf(MSG_DEBUG, "%s failed to find FILS Session element",
69 __func__);
70 return;
71 }
72
73 p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
74 elems.fils_session,
75 sta->fils_hlp_resp);
76
77 reply_res = hostapd_sta_assoc(hapd, sta->addr,
78 sta->fils_pending_assoc_is_reassoc,
79 WLAN_STATUS_SUCCESS,
80 buf, p - buf);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000081 updated = ap_sta_set_authorized_flag(hapd, sta, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070082 new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
83 sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
84 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
85 hostapd_set_sta_flags(hapd, sta);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000086 if (updated)
87 ap_sta_set_authorized_event(hapd, sta, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070088 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FILS);
89 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
90 hostapd_new_assoc_sta(hapd, sta, !new_assoc);
91 os_free(sta->fils_pending_assoc_req);
92 sta->fils_pending_assoc_req = NULL;
93 sta->fils_pending_assoc_req_len = 0;
94 wpabuf_free(sta->fils_hlp_resp);
95 sta->fils_hlp_resp = NULL;
96 wpabuf_free(sta->hlp_dhcp_discover);
97 sta->hlp_dhcp_discover = NULL;
98 fils_hlp_deinit(hapd);
99
100 /*
101 * Remove the station in case transmission of a success response fails
102 * (the STA was added associated to the driver) or if the station was
103 * previously added unassociated.
104 */
105 if (reply_res != WLAN_STATUS_SUCCESS || sta->added_unassoc) {
106 hostapd_drv_sta_remove(hapd, sta->addr);
107 sta->added_unassoc = 0;
108 }
109}
110#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700111
112
Hai Shalom899fcc72020-10-19 14:38:18 -0700113static bool check_sa_query_need(struct hostapd_data *hapd, struct sta_info *sta)
114{
115 if ((sta->flags &
116 (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) !=
117 (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED))
118 return false;
119
120 if (!sta->sa_query_timed_out && sta->sa_query_count > 0)
121 ap_check_sa_query_timeout(hapd, sta);
122
123 if (!sta->sa_query_timed_out && (sta->auth_alg != WLAN_AUTH_FT)) {
124 /*
125 * STA has already been associated with MFP and SA Query timeout
126 * has not been reached. Reject the association attempt
127 * temporarily and start SA Query, if one is not pending.
128 */
129 if (sta->sa_query_count == 0)
130 ap_sta_start_sa_query(hapd, sta);
131
132 return true;
133 }
134
135 return false;
136}
137
138
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000139#ifdef CONFIG_IEEE80211BE
140static int hostapd_update_sta_links_status(struct hostapd_data *hapd,
141 struct sta_info *sta,
142 const u8 *resp_ies,
143 size_t resp_ies_len)
144{
145 struct mld_info *info = &sta->mld_info;
146 struct wpabuf *mlebuf;
147 const u8 *mle, *pos;
148 struct ieee802_11_elems elems;
149 size_t mle_len, rem_len;
150 int ret = 0;
151
152 if (!resp_ies) {
153 wpa_printf(MSG_DEBUG,
154 "MLO: (Re)Association Response frame elements not available");
155 return -1;
156 }
157
158 if (ieee802_11_parse_elems(resp_ies, resp_ies_len, &elems, 0) ==
159 ParseFailed) {
160 wpa_printf(MSG_DEBUG,
161 "MLO: Failed to parse (Re)Association Response frame elements");
162 return -1;
163 }
164
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000165 mlebuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000166 if (!mlebuf) {
167 wpa_printf(MSG_ERROR,
168 "MLO: Basic Multi-Link element not found in (Re)Association Response frame");
169 return -1;
170 }
171
172 mle = wpabuf_head(mlebuf);
173 mle_len = wpabuf_len(mlebuf);
174 if (mle_len < MULTI_LINK_CONTROL_LEN + 1 ||
175 mle_len - MULTI_LINK_CONTROL_LEN < mle[MULTI_LINK_CONTROL_LEN]) {
176 wpa_printf(MSG_ERROR,
177 "MLO: Invalid Multi-Link element in (Re)Association Response frame");
178 ret = -1;
179 goto out;
180 }
181
182 /* Skip Common Info */
183 pos = mle + MULTI_LINK_CONTROL_LEN + mle[MULTI_LINK_CONTROL_LEN];
184 rem_len = mle_len -
185 (MULTI_LINK_CONTROL_LEN + mle[MULTI_LINK_CONTROL_LEN]);
186
187 /* Parse Subelements */
188 while (rem_len > 2) {
189 size_t ie_len = 2 + pos[1];
190
191 if (rem_len < ie_len)
192 break;
193
194 if (pos[0] == MULTI_LINK_SUB_ELEM_ID_PER_STA_PROFILE) {
195 u8 link_id;
196 const u8 *sta_profile;
197 size_t sta_profile_len;
198 u16 sta_ctrl;
199
200 if (pos[1] < BASIC_MLE_STA_CTRL_LEN + 1) {
201 wpa_printf(MSG_DEBUG,
202 "MLO: Invalid per-STA profile IE");
203 goto next_subelem;
204 }
205
206 sta_profile_len = pos[1];
207 sta_profile = &pos[2];
208 sta_ctrl = WPA_GET_LE16(sta_profile);
209 link_id = sta_ctrl & BASIC_MLE_STA_CTRL_LINK_ID_MASK;
210 if (link_id >= MAX_NUM_MLD_LINKS) {
211 wpa_printf(MSG_DEBUG,
212 "MLO: Invalid link ID in per-STA profile IE");
213 goto next_subelem;
214 }
215
216 /* Skip STA Control and STA Info */
217 if (sta_profile_len - BASIC_MLE_STA_CTRL_LEN <
218 sta_profile[BASIC_MLE_STA_CTRL_LEN]) {
219 wpa_printf(MSG_DEBUG,
220 "MLO: Invalid STA info in per-STA profile IE");
221 goto next_subelem;
222 }
223
224 sta_profile_len = sta_profile_len -
225 (BASIC_MLE_STA_CTRL_LEN +
226 sta_profile[BASIC_MLE_STA_CTRL_LEN]);
227 sta_profile = sta_profile + BASIC_MLE_STA_CTRL_LEN +
228 sta_profile[BASIC_MLE_STA_CTRL_LEN];
229
230 /* Skip Capabilities Information field */
231 if (sta_profile_len < 2)
232 goto next_subelem;
233 sta_profile_len -= 2;
234 sta_profile += 2;
235
236 /* Get status of the link */
237 info->links[link_id].status = WPA_GET_LE16(sta_profile);
238 }
239next_subelem:
240 pos += ie_len;
241 rem_len -= ie_len;
242 }
243
244out:
245 wpabuf_free(mlebuf);
246 return ret;
247}
248#endif /* CONFIG_IEEE80211BE */
249
250
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700251int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000252 const u8 *req_ies, size_t req_ies_len,
253 const u8 *resp_ies, size_t resp_ies_len,
254 const u8 *link_addr, int reassoc)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255{
256 struct sta_info *sta;
Hai Shalomfdcde762020-04-02 11:19:20 -0700257 int new_assoc;
258 enum wpa_validate_result res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700259 struct ieee802_11_elems elems;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800260 const u8 *ie;
261 size_t ielen;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700262 u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
263 u8 *p = buf;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800264 u16 reason = WLAN_REASON_UNSPECIFIED;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700265 int status = WLAN_STATUS_SUCCESS;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700266 const u8 *p2p_dev_addr = NULL;
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000267#ifdef CONFIG_OWE
268 struct hostapd_iface *iface = hapd->iface;
269#endif /* CONFIG_OWE */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000270 bool updated = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271
272 if (addr == NULL) {
273 /*
274 * This could potentially happen with unexpected event from the
275 * driver wrapper. This was seen at least in one case where the
276 * driver ended up being set to station mode while hostapd was
277 * running, so better make sure we stop processing such an
278 * event here.
279 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800280 wpa_printf(MSG_DEBUG,
281 "hostapd_notif_assoc: Skip event with no address");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700282 return -1;
283 }
Hai Shalomc3565922019-10-28 11:58:20 -0700284
285 if (is_multicast_ether_addr(addr) ||
286 is_zero_ether_addr(addr) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000287 ether_addr_equal(addr, hapd->own_addr)) {
Hai Shalomc3565922019-10-28 11:58:20 -0700288 /* Do not process any frames with unexpected/invalid SA so that
289 * we do not add any state for unexpected STA addresses or end
290 * up sending out frames to unexpected destination. */
291 wpa_printf(MSG_DEBUG, "%s: Invalid SA=" MACSTR
292 " in received indication - ignore this indication silently",
293 __func__, MAC2STR(addr));
294 return 0;
295 }
296
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700297 random_add_randomness(addr, ETH_ALEN);
298
299 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
300 HOSTAPD_LEVEL_INFO, "associated");
301
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000302 if (ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0) ==
303 ParseFailed) {
304 wpa_printf(MSG_DEBUG, "%s: Could not parse elements", __func__);
305 return -1;
306 }
307
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700308 if (elems.wps_ie) {
309 ie = elems.wps_ie - 2;
310 ielen = elems.wps_ie_len + 2;
311 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
312 } else if (elems.rsn_ie) {
313 ie = elems.rsn_ie - 2;
314 ielen = elems.rsn_ie_len + 2;
315 wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
316 } else if (elems.wpa_ie) {
317 ie = elems.wpa_ie - 2;
318 ielen = elems.wpa_ie_len + 2;
319 wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800320#ifdef CONFIG_HS20
321 } else if (elems.osen) {
322 ie = elems.osen - 2;
323 ielen = elems.osen_len + 2;
324 wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq");
325#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326 } else {
327 ie = NULL;
328 ielen = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800329 wpa_printf(MSG_DEBUG,
330 "STA did not include WPS/RSN/WPA IE in (Re)AssocReq");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331 }
332
333 sta = ap_get_sta(hapd, addr);
334 if (sta) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700335 ap_sta_no_session_timeout(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700336 accounting_sta_stop(hapd, sta);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700337
338 /*
339 * Make sure that the previously registered inactivity timer
340 * will not remove the STA immediately.
341 */
342 sta->timeout_next = STA_NULLFUNC;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700343 } else {
344 sta = ap_sta_add(hapd, addr);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700345 if (sta == NULL) {
346 hostapd_drv_sta_disassoc(hapd, addr,
347 WLAN_REASON_DISASSOC_AP_BUSY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700348 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700349 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700350 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000351
352 if (hapd->conf->wpa && check_sa_query_need(hapd, sta)) {
353 status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
354 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
355 hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
356
357 return 0;
358 }
359
360#ifdef CONFIG_IEEE80211BE
361 if (link_addr) {
362 struct mld_info *info = &sta->mld_info;
363 int i, num_valid_links = 0;
364 u8 link_id = hapd->mld_link_id;
365
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000366 ap_sta_set_mld(sta, true);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000367 sta->mld_assoc_link_id = link_id;
368 os_memcpy(info->common_info.mld_addr, addr, ETH_ALEN);
369 info->links[link_id].valid = true;
370 os_memcpy(info->links[link_id].peer_addr, link_addr, ETH_ALEN);
371 os_memcpy(info->links[link_id].local_addr, hapd->own_addr,
372 ETH_ALEN);
373
374 if (!elems.basic_mle ||
375 hostapd_process_ml_assoc_req(hapd, &elems, sta) !=
376 WLAN_STATUS_SUCCESS) {
377 reason = WLAN_REASON_UNSPECIFIED;
378 wpa_printf(MSG_DEBUG,
379 "Failed to get STA non-assoc links info");
380 goto fail;
381 }
382
383 for (i = 0 ; i < MAX_NUM_MLD_LINKS; i++) {
384 if (info->links[i].valid)
385 num_valid_links++;
386 }
387 if (num_valid_links > 1 &&
388 hostapd_update_sta_links_status(hapd, sta, resp_ies,
389 resp_ies_len)) {
390 wpa_printf(MSG_DEBUG,
391 "Failed to get STA non-assoc links status info");
392 reason = WLAN_REASON_UNSPECIFIED;
393 goto fail;
394 }
395 }
396#endif /* CONFIG_IEEE80211BE */
397
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800398 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700400 /*
401 * ACL configurations to the drivers (implementing AP SME and ACL
402 * offload) without hostapd's knowledge, can result in a disconnection
403 * though the driver accepts the connection. Skip the hostapd check for
404 * ACL if the driver supports ACL offload to avoid potentially
405 * conflicting ACL rules.
406 */
407 if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
408 hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800409 wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
410 MAC2STR(addr));
411 reason = WLAN_REASON_UNSPECIFIED;
412 goto fail;
413 }
414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415#ifdef CONFIG_P2P
416 if (elems.p2p) {
417 wpabuf_free(sta->p2p_ie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800418 sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 P2P_IE_VENDOR_TYPE);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700420 if (sta->p2p_ie)
421 p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422 }
423#endif /* CONFIG_P2P */
424
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700425#ifdef NEED_AP_MLME
426 if (elems.ht_capabilities &&
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700427 (hapd->iface->conf->ht_capab &
428 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
429 struct ieee80211_ht_capabilities *ht_cap =
430 (struct ieee80211_ht_capabilities *)
431 elems.ht_capabilities;
432
433 if (le_to_host16(ht_cap->ht_capabilities_info) &
434 HT_CAP_INFO_40MHZ_INTOLERANT)
435 ht40_intolerant_add(hapd->iface, sta);
436 }
437#endif /* NEED_AP_MLME */
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700438
Sunil Ravia04bd252022-05-02 22:54:18 -0700439 check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
Dmitry Shmidt051af732013-10-22 13:52:46 -0700440
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800441#ifdef CONFIG_HS20
442 wpabuf_free(sta->hs20_ie);
443 if (elems.hs20 && elems.hs20_len > 4) {
444 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
445 elems.hs20_len - 4);
446 } else
447 sta->hs20_ie = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700448
449 wpabuf_free(sta->roaming_consortium);
450 if (elems.roaming_cons_sel)
451 sta->roaming_consortium = wpabuf_alloc_copy(
452 elems.roaming_cons_sel + 4,
453 elems.roaming_cons_sel_len - 4);
454 else
455 sta->roaming_consortium = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800456#endif /* CONFIG_HS20 */
457
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800458#ifdef CONFIG_FST
459 wpabuf_free(sta->mb_ies);
460 if (hapd->iface->fst)
461 sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
462 else
463 sta->mb_ies = NULL;
464#endif /* CONFIG_FST */
465
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800466 mbo_ap_check_sta_assoc(hapd, sta, &elems);
467
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800468 ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
469 elems.supp_op_classes_len);
470
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700471 if (hapd->conf->wpa) {
472 if (ie == NULL || ielen == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800473#ifdef CONFIG_WPS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700474 if (hapd->conf->wps_state) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800475 wpa_printf(MSG_DEBUG,
476 "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700477 sta->flags |= WLAN_STA_MAYBE_WPS;
478 goto skip_wpa_check;
479 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800480#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700481
482 wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700483 reason = WLAN_REASON_INVALID_IE;
484 status = WLAN_STATUS_INVALID_IE;
485 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800487#ifdef CONFIG_WPS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700488 if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
489 os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800490 struct wpabuf *wps;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800491
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700492 sta->flags |= WLAN_STA_WPS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800493 wps = ieee802_11_vendor_ie_concat(ie, ielen,
494 WPS_IE_VENDOR_TYPE);
495 if (wps) {
496 if (wps_is_20(wps)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800497 wpa_printf(MSG_DEBUG,
498 "WPS: STA supports WPS 2.0");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800499 sta->flags |= WLAN_STA_WPS2;
500 }
501 wpabuf_free(wps);
502 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700503 goto skip_wpa_check;
504 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800505#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700506
507 if (sta->wpa_sm == NULL)
508 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700509 sta->addr,
510 p2p_dev_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700511 if (sta->wpa_sm == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800512 wpa_printf(MSG_ERROR,
513 "Failed to initialize WPA state machine");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700514 return -1;
515 }
Sunil Ravi7f769292024-07-23 22:21:32 +0000516 wpa_auth_set_rsn_override(sta->wpa_sm,
517 elems.rsne_override != NULL);
518 wpa_auth_set_rsn_override_2(sta->wpa_sm,
519 elems.rsne_override_2 != NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000520#ifdef CONFIG_IEEE80211BE
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000521 if (ap_sta_is_mld(hapd, sta)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000522 wpa_printf(MSG_DEBUG,
523 "MLD: Set ML info in RSN Authenticator");
Sunil Ravi7f769292024-07-23 22:21:32 +0000524 wpa_auth_set_ml_info(sta->wpa_sm,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000525 sta->mld_assoc_link_id,
526 &sta->mld_info);
527 }
528#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
Hai Shalom021b0b52019-04-10 11:17:58 -0700530 hapd->iface->freq,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700531 ie, ielen,
Hai Shalomc3565922019-10-28 11:58:20 -0700532 elems.rsnxe ? elems.rsnxe - 2 : NULL,
533 elems.rsnxe ? elems.rsnxe_len + 2 : 0,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700534 elems.mdie, elems.mdie_len,
Sunil Ravi7f769292024-07-23 22:21:32 +0000535 elems.owe_dh, elems.owe_dh_len, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700536 reason = WLAN_REASON_INVALID_IE;
537 status = WLAN_STATUS_INVALID_IE;
538 switch (res) {
539 case WPA_IE_OK:
540 reason = WLAN_REASON_UNSPECIFIED;
541 status = WLAN_STATUS_SUCCESS;
542 break;
543 case WPA_INVALID_IE:
544 reason = WLAN_REASON_INVALID_IE;
545 status = WLAN_STATUS_INVALID_IE;
546 break;
547 case WPA_INVALID_GROUP:
548 reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
549 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
550 break;
551 case WPA_INVALID_PAIRWISE:
552 reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
553 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
554 break;
555 case WPA_INVALID_AKMP:
556 reason = WLAN_REASON_AKMP_NOT_VALID;
557 status = WLAN_STATUS_AKMP_NOT_VALID;
558 break;
559 case WPA_NOT_ENABLED:
560 reason = WLAN_REASON_INVALID_IE;
561 status = WLAN_STATUS_INVALID_IE;
562 break;
563 case WPA_ALLOC_FAIL:
564 reason = WLAN_REASON_UNSPECIFIED;
565 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
566 break;
567 case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
568 reason = WLAN_REASON_INVALID_IE;
569 status = WLAN_STATUS_INVALID_IE;
570 break;
571 case WPA_INVALID_MGMT_GROUP_CIPHER:
572 reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
573 status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
574 break;
575 case WPA_INVALID_MDIE:
576 reason = WLAN_REASON_INVALID_MDE;
577 status = WLAN_STATUS_INVALID_MDIE;
578 break;
579 case WPA_INVALID_PROTO:
580 reason = WLAN_REASON_INVALID_IE;
581 status = WLAN_STATUS_INVALID_IE;
582 break;
583 case WPA_INVALID_PMKID:
584 reason = WLAN_REASON_INVALID_PMKID;
585 status = WLAN_STATUS_INVALID_PMKID;
586 break;
587 case WPA_DENIED_OTHER_REASON:
588 reason = WLAN_REASON_UNSPECIFIED;
589 status = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
590 break;
591 }
592 if (status != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800593 wpa_printf(MSG_DEBUG,
594 "WPA/RSN information element rejected? (res %u)",
595 res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596 wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800597 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598 }
Hai Shalomc3565922019-10-28 11:58:20 -0700599
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700600 if (wpa_auth_uses_mfp(sta->wpa_sm))
601 sta->flags |= WLAN_STA_MFP;
602 else
603 sta->flags &= ~WLAN_STA_MFP;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700604
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800605#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700606 if (sta->auth_alg == WLAN_AUTH_FT) {
607 status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
608 req_ies_len);
609 if (status != WLAN_STATUS_SUCCESS) {
610 if (status == WLAN_STATUS_INVALID_PMKID)
611 reason = WLAN_REASON_INVALID_IE;
612 if (status == WLAN_STATUS_INVALID_MDIE)
613 reason = WLAN_REASON_INVALID_IE;
614 if (status == WLAN_STATUS_INVALID_FTIE)
615 reason = WLAN_REASON_INVALID_IE;
616 goto fail;
617 }
618 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800619#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomc3565922019-10-28 11:58:20 -0700620#ifdef CONFIG_SAE
Sunil Ravi77d572f2023-01-17 23:58:31 +0000621 if (hapd->conf->sae_pwe == SAE_PWE_BOTH &&
Hai Shalomc3565922019-10-28 11:58:20 -0700622 sta->auth_alg == WLAN_AUTH_SAE &&
Hai Shalom899fcc72020-10-19 14:38:18 -0700623 sta->sae && !sta->sae->h2e &&
Hai Shaloma20dcd72022-02-04 13:43:00 -0800624 ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
625 WLAN_RSNX_CAPAB_SAE_H2E)) {
Hai Shalomc3565922019-10-28 11:58:20 -0700626 wpa_printf(MSG_INFO, "SAE: " MACSTR
627 " indicates support for SAE H2E, but did not use it",
628 MAC2STR(sta->addr));
629 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
630 reason = WLAN_REASON_UNSPECIFIED;
631 goto fail;
632 }
633#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700634 } else if (hapd->conf->wps_state) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800635#ifdef CONFIG_WPS
636 struct wpabuf *wps;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800637
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800638 if (req_ies)
639 wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700640 WPS_IE_VENDOR_TYPE);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800641 else
642 wps = NULL;
643#ifdef CONFIG_WPS_STRICT
644 if (wps && wps_validate_assoc_req(wps) < 0) {
645 reason = WLAN_REASON_INVALID_IE;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700646 status = WLAN_STATUS_INVALID_IE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700647 wpabuf_free(wps);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800648 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700649 }
650#endif /* CONFIG_WPS_STRICT */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800651 if (wps) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700652 sta->flags |= WLAN_STA_WPS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800653 if (wps_is_20(wps)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800654 wpa_printf(MSG_DEBUG,
655 "WPS: STA supports WPS 2.0");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800656 sta->flags |= WLAN_STA_WPS2;
657 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700658 } else
659 sta->flags |= WLAN_STA_MAYBE_WPS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800660 wpabuf_free(wps);
661#endif /* CONFIG_WPS */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800662#ifdef CONFIG_HS20
663 } else if (hapd->conf->osen) {
664 if (elems.osen == NULL) {
665 hostapd_logger(
666 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
667 HOSTAPD_LEVEL_INFO,
668 "No HS 2.0 OSEN element in association request");
669 return WLAN_STATUS_INVALID_IE;
670 }
671
672 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
673 if (sta->wpa_sm == NULL)
674 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
675 sta->addr, NULL);
676 if (sta->wpa_sm == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800677 wpa_printf(MSG_WARNING,
678 "Failed to initialize WPA state machine");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800679 return WLAN_STATUS_UNSPECIFIED_FAILURE;
680 }
681 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
682 elems.osen - 2, elems.osen_len + 2) < 0)
683 return WLAN_STATUS_INVALID_IE;
684#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700686#ifdef CONFIG_WPS
687skip_wpa_check:
688#endif /* CONFIG_WPS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800689
690#ifdef CONFIG_MBO
691 if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
692 elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
693 hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
694 wpa_printf(MSG_INFO,
695 "MBO: Reject WPA2 association without PMF");
696 return WLAN_STATUS_UNSPECIFIED_FAILURE;
697 }
698#endif /* CONFIG_MBO */
699
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800700#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700701 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
Hai Shalomfdcde762020-04-02 11:19:20 -0700702 sta->auth_alg, req_ies, req_ies_len,
703 !elems.rsnxe);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700704 if (!p) {
705 wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
706 return WLAN_STATUS_UNSPECIFIED_FAILURE;
707 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700708#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700709
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700710#ifdef CONFIG_FILS
711 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
712 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
713 sta->auth_alg == WLAN_AUTH_FILS_PK) {
714 int delay_assoc = 0;
715
716 if (!req_ies)
717 return WLAN_STATUS_UNSPECIFIED_FAILURE;
718
719 if (!wpa_fils_validate_fils_session(sta->wpa_sm, req_ies,
720 req_ies_len,
721 sta->fils_session)) {
722 wpa_printf(MSG_DEBUG,
723 "FILS: Session validation failed");
724 return WLAN_STATUS_UNSPECIFIED_FAILURE;
725 }
726
727 res = wpa_fils_validate_key_confirm(sta->wpa_sm, req_ies,
728 req_ies_len);
729 if (res < 0) {
730 wpa_printf(MSG_DEBUG,
731 "FILS: Key Confirm validation failed");
732 return WLAN_STATUS_UNSPECIFIED_FAILURE;
733 }
734
735 if (fils_process_hlp(hapd, sta, req_ies, req_ies_len) > 0) {
736 wpa_printf(MSG_DEBUG,
737 "FILS: Delaying Assoc Response (HLP)");
738 delay_assoc = 1;
739 } else {
740 wpa_printf(MSG_DEBUG,
741 "FILS: Going ahead with Assoc Response (no HLP)");
742 }
743
744 if (sta) {
745 wpa_printf(MSG_DEBUG, "FILS: HLP callback cleanup");
746 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
747 os_free(sta->fils_pending_assoc_req);
748 sta->fils_pending_assoc_req = NULL;
749 sta->fils_pending_assoc_req_len = 0;
750 wpabuf_free(sta->fils_hlp_resp);
751 sta->fils_hlp_resp = NULL;
752 sta->fils_drv_assoc_finish = 0;
753 }
754
755 if (sta && delay_assoc && status == WLAN_STATUS_SUCCESS) {
756 u8 *req_tmp;
757
758 req_tmp = os_malloc(req_ies_len);
759 if (!req_tmp) {
760 wpa_printf(MSG_DEBUG,
761 "FILS: buffer allocation failed for assoc req");
762 goto fail;
763 }
764 os_memcpy(req_tmp, req_ies, req_ies_len);
765 sta->fils_pending_assoc_req = req_tmp;
766 sta->fils_pending_assoc_req_len = req_ies_len;
767 sta->fils_pending_assoc_is_reassoc = reassoc;
768 sta->fils_drv_assoc_finish = 1;
769 wpa_printf(MSG_DEBUG,
770 "FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
771 MACSTR, MAC2STR(sta->addr));
772 eloop_register_timeout(
773 0, hapd->conf->fils_hlp_wait_time * 1024,
774 fils_hlp_timeout, hapd, sta);
775 return 0;
776 }
777 p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
778 elems.fils_session,
779 sta->fils_hlp_resp);
780 wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
781 buf, p - buf);
782 }
783#endif /* CONFIG_FILS */
784
Roshan Pius3a1667e2018-07-03 15:17:14 -0700785#ifdef CONFIG_OWE
786 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000787 !(iface->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_AP) &&
Roshan Pius3a1667e2018-07-03 15:17:14 -0700788 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
789 elems.owe_dh) {
790 u8 *npos;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700791 u16 ret_status;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700792
793 npos = owe_assoc_req_process(hapd, sta,
794 elems.owe_dh, elems.owe_dh_len,
795 p, sizeof(buf) - (p - buf),
Hai Shalomb755a2a2020-04-23 21:49:02 -0700796 &ret_status);
797 status = ret_status;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700798 if (npos)
799 p = npos;
Hai Shalomfdcde762020-04-02 11:19:20 -0700800
Roshan Pius3a1667e2018-07-03 15:17:14 -0700801 if (!npos &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700802 status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Hai Shalomb755a2a2020-04-23 21:49:02 -0700803 hostapd_sta_assoc(hapd, addr, reassoc, ret_status, buf,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700804 p - buf);
805 return 0;
806 }
807
Hai Shalomfdcde762020-04-02 11:19:20 -0700808 if (!npos || status != WLAN_STATUS_SUCCESS)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700809 goto fail;
810 }
811#endif /* CONFIG_OWE */
812
Hai Shalom021b0b52019-04-10 11:17:58 -0700813#ifdef CONFIG_DPP2
814 dpp_pfs_free(sta->dpp_pfs);
815 sta->dpp_pfs = NULL;
816
817 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
818 hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
819 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
820 elems.owe_dh) {
821 sta->dpp_pfs = dpp_pfs_init(
822 wpabuf_head(hapd->conf->dpp_netaccesskey),
823 wpabuf_len(hapd->conf->dpp_netaccesskey));
824 if (!sta->dpp_pfs) {
825 wpa_printf(MSG_DEBUG,
826 "DPP: Could not initialize PFS");
827 /* Try to continue without PFS */
828 goto pfs_fail;
829 }
830
831 if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh,
832 elems.owe_dh_len) < 0) {
833 dpp_pfs_free(sta->dpp_pfs);
834 sta->dpp_pfs = NULL;
835 reason = WLAN_REASON_UNSPECIFIED;
836 goto fail;
837 }
838 }
839
840 wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ?
841 sta->dpp_pfs->secret : NULL);
842 pfs_fail:
843#endif /* CONFIG_DPP2 */
844
Hai Shalomfdcde762020-04-02 11:19:20 -0700845 if (elems.rrm_enabled &&
846 elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
847 os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
848 sizeof(sta->rrm_enabled_capa));
849
Roshan Pius3a1667e2018-07-03 15:17:14 -0700850#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700851 hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700853 if (sta->auth_alg == WLAN_AUTH_FT ||
854 sta->auth_alg == WLAN_AUTH_FILS_SK ||
855 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
856 sta->auth_alg == WLAN_AUTH_FILS_PK)
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000857 updated = ap_sta_set_authorized_flag(hapd, sta, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700858#else /* CONFIG_IEEE80211R_AP || CONFIG_FILS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700859 /* Keep compiler silent about unused variables */
860 if (status) {
861 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700862#endif /* CONFIG_IEEE80211R_AP || CONFIG_FILS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700863
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000864#ifdef CONFIG_IEEE80211BE
865 if (hostapd_process_assoc_ml_info(hapd, sta, req_ies, req_ies_len,
866 !!reassoc, WLAN_STATUS_SUCCESS,
867 true)) {
868 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
869 reason = WLAN_REASON_UNSPECIFIED;
870 goto fail;
871 }
872#endif /* CONFIG_IEEE80211BE */
873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874 new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
875 sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800876 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700877
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700878 hostapd_set_sta_flags(hapd, sta);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000879 if (updated)
880 ap_sta_set_authorized_event(hapd, sta, 1);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700881
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700882 if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
883 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700884#ifdef CONFIG_FILS
885 else if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
886 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
887 sta->auth_alg == WLAN_AUTH_FILS_PK)
888 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FILS);
889#endif /* CONFIG_FILS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700890 else
891 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892
893 hostapd_new_assoc_sta(hapd, sta, !new_assoc);
894
895 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
896
897#ifdef CONFIG_P2P
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800898 if (req_ies) {
899 p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
900 req_ies, req_ies_len);
901 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902#endif /* CONFIG_P2P */
903
904 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800905
906fail:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800907#ifdef CONFIG_IEEE80211R_AP
Hai Shalomb755a2a2020-04-23 21:49:02 -0700908 if (status >= 0)
909 hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800910#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800911 hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
912 ap_free_sta(hapd, sta);
913 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700914}
915
916
Sunil Ravi99c035e2024-07-12 01:42:03 +0000917static void hostapd_remove_sta(struct hostapd_data *hapd, struct sta_info *sta)
918{
919 ap_sta_set_authorized(hapd, sta, 0);
920 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
921 hostapd_set_sta_flags(hapd, sta);
922 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
923 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
924 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
925 ap_free_sta(hapd, sta);
926}
927
928
929#ifdef CONFIG_IEEE80211BE
930static void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
931 struct sta_info *sta,
932 const u8 *addr)
933{
934 unsigned int link_id, i;
935 struct hostapd_data *tmp_hapd;
936 struct hapd_interfaces *interfaces = assoc_hapd->iface->interfaces;
937
938 /* Remove STA entry in non-assoc links */
939 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
940 if (!sta->mld_info.links[link_id].valid)
941 continue;
942
943 for (i = 0; i < interfaces->count; i++) {
944 struct sta_info *tmp_sta;
945
946 tmp_hapd = interfaces->iface[i]->bss[0];
947
948 if (!tmp_hapd->conf->mld_ap ||
949 assoc_hapd == tmp_hapd ||
950 assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
951 continue;
952
953 tmp_sta = ap_get_sta(tmp_hapd, addr);
954 if (tmp_sta)
955 ap_free_sta(tmp_hapd, tmp_sta);
956 }
957 }
958
959 /* Remove STA in assoc link */
960 hostapd_remove_sta(assoc_hapd, sta);
961}
962#endif /* CONFIG_IEEE80211BE */
963
964
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700965void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
966{
967 struct sta_info *sta;
968
969 if (addr == NULL) {
970 /*
971 * This could potentially happen with unexpected event from the
972 * driver wrapper. This was seen at least in one case where the
973 * driver ended up reporting a station mode event while hostapd
974 * was running, so better make sure we stop processing such an
975 * event here.
976 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800977 wpa_printf(MSG_DEBUG,
978 "hostapd_notif_disassoc: Skip event with no address");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 return;
980 }
981
982 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
983 HOSTAPD_LEVEL_INFO, "disassociated");
984
985 sta = ap_get_sta(hapd, addr);
Sunil Ravi99c035e2024-07-12 01:42:03 +0000986#ifdef CONFIG_IEEE80211BE
987 if (hostapd_is_mld_ap(hapd)) {
988 struct hostapd_data *assoc_hapd;
989 unsigned int i;
990
991 if (!sta) {
992 /* Find non-MLO cases from any of the affiliated AP
993 * links. */
994 for (i = 0; i < hapd->iface->interfaces->count; ++i) {
995 struct hostapd_iface *h =
996 hapd->iface->interfaces->iface[i];
997 struct hostapd_data *h_hapd = h->bss[0];
998 struct hostapd_bss_config *hconf = h_hapd->conf;
999
1000 if (!hconf->mld_ap ||
1001 hconf->mld_id != hapd->conf->mld_id)
1002 continue;
1003
1004 sta = ap_get_sta(h_hapd, addr);
1005 if (sta) {
1006 if (!sta->mld_info.mld_sta) {
1007 hapd = h_hapd;
1008 goto legacy;
1009 }
1010 break;
1011 }
1012 }
1013 } else if (!sta->mld_info.mld_sta) {
1014 goto legacy;
1015 }
1016 if (!sta) {
1017 wpa_printf(MSG_DEBUG,
1018 "Disassociation notification for unknown STA "
1019 MACSTR, MAC2STR(addr));
1020 return;
1021 }
1022 sta = hostapd_ml_get_assoc_sta(hapd, sta, &assoc_hapd);
1023 if (sta)
1024 hostapd_notif_disassoc_mld(assoc_hapd, sta, addr);
1025 return;
1026 }
1027
1028legacy:
1029#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 if (sta == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001031 wpa_printf(MSG_DEBUG,
1032 "Disassociation notification for unknown STA "
1033 MACSTR, MAC2STR(addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 return;
1035 }
1036
Sunil Ravi99c035e2024-07-12 01:42:03 +00001037 hostapd_remove_sta(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001038}
1039
1040
1041void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
1042{
1043 struct sta_info *sta = ap_get_sta(hapd, addr);
1044
Roshan Pius3a1667e2018-07-03 15:17:14 -07001045 if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 return;
1047
1048 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001049 HOSTAPD_LEVEL_INFO,
1050 "disconnected due to excessive missing ACKs");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051 hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001052 ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053}
1054
1055
Roshan Pius3a1667e2018-07-03 15:17:14 -07001056void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
1057 enum smps_mode smps_mode,
1058 enum chan_width chan_width, u8 rx_nss)
1059{
1060 struct sta_info *sta = ap_get_sta(hapd, addr);
1061 const char *txt;
1062
1063 if (!sta)
1064 return;
1065
1066 switch (smps_mode) {
1067 case SMPS_AUTOMATIC:
1068 txt = "automatic";
1069 break;
1070 case SMPS_OFF:
1071 txt = "off";
1072 break;
1073 case SMPS_DYNAMIC:
1074 txt = "dynamic";
1075 break;
1076 case SMPS_STATIC:
1077 txt = "static";
1078 break;
1079 default:
1080 txt = NULL;
1081 break;
1082 }
1083 if (txt) {
1084 wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_SMPS_MODE_CHANGED
1085 MACSTR " %s", MAC2STR(addr), txt);
1086 }
1087
1088 switch (chan_width) {
1089 case CHAN_WIDTH_20_NOHT:
1090 txt = "20(no-HT)";
1091 break;
1092 case CHAN_WIDTH_20:
1093 txt = "20";
1094 break;
1095 case CHAN_WIDTH_40:
1096 txt = "40";
1097 break;
1098 case CHAN_WIDTH_80:
1099 txt = "80";
1100 break;
1101 case CHAN_WIDTH_80P80:
1102 txt = "80+80";
1103 break;
1104 case CHAN_WIDTH_160:
1105 txt = "160";
1106 break;
Sunil8cd6f4d2022-06-28 18:40:46 +00001107 case CHAN_WIDTH_320:
1108 txt = "320";
1109 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001110 default:
1111 txt = NULL;
1112 break;
1113 }
1114 if (txt) {
1115 wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_MAX_BW_CHANGED
1116 MACSTR " %s", MAC2STR(addr), txt);
1117 }
1118
1119 if (rx_nss != 0xff) {
1120 wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_N_SS_CHANGED
1121 MACSTR " %d", MAC2STR(addr), rx_nss);
1122 }
1123}
1124
1125
Dmitry Shmidt04949592012-07-19 12:16:46 -07001126void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
Hai Shalom81f62d82019-07-22 12:10:00 -07001127 int offset, int width, int cf1, int cf2,
Sunil Ravi036cec52023-03-29 11:35:17 -07001128 u16 punct_bitmap, int finished)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001129{
1130#ifdef NEED_AP_MLME
Sunil Ravi77d572f2023-01-17 23:58:31 +00001131 int channel, chwidth, is_dfs0, is_dfs;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001132 u8 seg0_idx = 0, seg1_idx = 0, op_class, chan_no;
Hai Shalom74f70d42019-02-11 14:42:39 -08001133 size_t i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001134
1135 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001136 HOSTAPD_LEVEL_INFO,
Sunil Ravi036cec52023-03-29 11:35:17 -07001137 "driver %s channel switch: iface->freq=%d, freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d, puncturing_bitmap=0x%x",
Hai Shalom81f62d82019-07-22 12:10:00 -07001138 finished ? "had" : "starting",
Sunil Ravi77d572f2023-01-17 23:58:31 +00001139 hapd->iface->freq,
Hai Shalom60840252021-02-19 19:02:11 -08001140 freq, ht, hapd->iconf->ch_switch_vht_config,
Sunil Ravia04bd252022-05-02 22:54:18 -07001141 hapd->iconf->ch_switch_he_config,
1142 hapd->iconf->ch_switch_eht_config, offset,
Sunil Ravi036cec52023-03-29 11:35:17 -07001143 width, channel_width_to_string(width), cf1, cf2,
1144 punct_bitmap);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001145
Hai Shalom1dc4d202019-04-29 16:22:27 -07001146 if (!hapd->iface->current_mode) {
1147 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1148 HOSTAPD_LEVEL_WARNING,
1149 "ignore channel switch since the interface is not yet ready");
1150 return;
1151 }
1152
Sunil Ravi77d572f2023-01-17 23:58:31 +00001153 /* Check if any of configured channels require DFS */
1154 is_dfs0 = hostapd_is_dfs_required(hapd->iface);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001155 hapd->iface->freq = freq;
1156
1157 channel = hostapd_hw_get_channel(hapd, freq);
1158 if (!channel) {
1159 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001160 HOSTAPD_LEVEL_WARNING,
1161 "driver switched to bad channel!");
Dmitry Shmidt04949592012-07-19 12:16:46 -07001162 return;
1163 }
1164
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001165 switch (width) {
1166 case CHAN_WIDTH_80:
Sunil8cd6f4d2022-06-28 18:40:46 +00001167 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001168 break;
1169 case CHAN_WIDTH_80P80:
Sunil8cd6f4d2022-06-28 18:40:46 +00001170 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001171 break;
1172 case CHAN_WIDTH_160:
Sunil8cd6f4d2022-06-28 18:40:46 +00001173 chwidth = CONF_OPER_CHWIDTH_160MHZ;
1174 break;
1175 case CHAN_WIDTH_320:
1176 chwidth = CONF_OPER_CHWIDTH_320MHZ;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001177 break;
1178 case CHAN_WIDTH_20_NOHT:
1179 case CHAN_WIDTH_20:
1180 case CHAN_WIDTH_40:
1181 default:
Sunil8cd6f4d2022-06-28 18:40:46 +00001182 chwidth = CONF_OPER_CHWIDTH_USE_HT;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001183 break;
1184 }
1185
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001186 /* The operating channel changed when CSA finished, so need to update
1187 * hw_mode for all following operations to cover the cases where the
1188 * driver changed the operating band. */
1189 if (finished && hostapd_csa_update_hwmode(hapd->iface))
1190 return;
1191
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001192 switch (hapd->iface->current_mode->mode) {
1193 case HOSTAPD_MODE_IEEE80211A:
Hai Shalom899fcc72020-10-19 14:38:18 -07001194 if (cf1 == 5935)
1195 seg0_idx = (cf1 - 5925) / 5;
1196 else if (cf1 > 5950)
1197 seg0_idx = (cf1 - 5950) / 5;
1198 else if (cf1 > 5000)
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001199 seg0_idx = (cf1 - 5000) / 5;
Hai Shalom899fcc72020-10-19 14:38:18 -07001200
1201 if (cf2 == 5935)
1202 seg1_idx = (cf2 - 5925) / 5;
1203 else if (cf2 > 5950)
1204 seg1_idx = (cf2 - 5950) / 5;
1205 else if (cf2 > 5000)
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001206 seg1_idx = (cf2 - 5000) / 5;
1207 break;
1208 default:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001209 ieee80211_freq_to_chan(cf1, &seg0_idx);
1210 ieee80211_freq_to_chan(cf2, &seg1_idx);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001211 break;
1212 }
1213
Dmitry Shmidt04949592012-07-19 12:16:46 -07001214 hapd->iconf->channel = channel;
1215 hapd->iconf->ieee80211n = ht;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001216 if (!ht)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001217 hapd->iconf->ieee80211ac = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001218 if (hapd->iconf->ch_switch_vht_config) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001219 /* CHAN_SWITCH VHT config */
1220 if (hapd->iconf->ch_switch_vht_config &
1221 CH_SWITCH_VHT_ENABLED)
1222 hapd->iconf->ieee80211ac = 1;
1223 else if (hapd->iconf->ch_switch_vht_config &
1224 CH_SWITCH_VHT_DISABLED)
1225 hapd->iconf->ieee80211ac = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001226 }
1227 if (hapd->iconf->ch_switch_he_config) {
Hai Shalom60840252021-02-19 19:02:11 -08001228 /* CHAN_SWITCH HE config */
1229 if (hapd->iconf->ch_switch_he_config &
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001230 CH_SWITCH_HE_ENABLED) {
Hai Shalom60840252021-02-19 19:02:11 -08001231 hapd->iconf->ieee80211ax = 1;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001232 if (hapd->iface->freq > 4000 &&
1233 hapd->iface->freq < 5895)
1234 hapd->iconf->ieee80211ac = 1;
1235 }
Hai Shalom60840252021-02-19 19:02:11 -08001236 else if (hapd->iconf->ch_switch_he_config &
1237 CH_SWITCH_HE_DISABLED)
1238 hapd->iconf->ieee80211ax = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001239 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001240#ifdef CONFIG_IEEE80211BE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001241 if (hapd->iconf->ch_switch_eht_config) {
Sunil Ravia04bd252022-05-02 22:54:18 -07001242 /* CHAN_SWITCH EHT config */
1243 if (hapd->iconf->ch_switch_eht_config &
1244 CH_SWITCH_EHT_ENABLED) {
1245 hapd->iconf->ieee80211be = 1;
1246 hapd->iconf->ieee80211ax = 1;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001247 if (!is_6ghz_freq(hapd->iface->freq) &&
1248 hapd->iface->freq > 4000)
Sunil Ravia04bd252022-05-02 22:54:18 -07001249 hapd->iconf->ieee80211ac = 1;
1250 } else if (hapd->iconf->ch_switch_eht_config &
1251 CH_SWITCH_EHT_DISABLED)
1252 hapd->iconf->ieee80211be = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001253 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001254#endif /* CONFIG_IEEE80211BE */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001255 hapd->iconf->ch_switch_vht_config = 0;
Hai Shalom60840252021-02-19 19:02:11 -08001256 hapd->iconf->ch_switch_he_config = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07001257 hapd->iconf->ch_switch_eht_config = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001258
Hai Shaloma20dcd72022-02-04 13:43:00 -08001259 if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 ||
Sunil Ravi640215c2023-06-28 23:08:09 +00001260 width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160 ||
1261 width == CHAN_WIDTH_320)
Hai Shaloma20dcd72022-02-04 13:43:00 -08001262 hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1263 else if (width == CHAN_WIDTH_20 || width == CHAN_WIDTH_20_NOHT)
1264 hapd->iconf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1265
Dmitry Shmidt04949592012-07-19 12:16:46 -07001266 hapd->iconf->secondary_channel = offset;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001267 if (ieee80211_freq_to_channel_ext(freq, offset, chwidth,
1268 &op_class, &chan_no) !=
1269 NUM_HOSTAPD_MODES)
1270 hapd->iconf->op_class = op_class;
Hai Shalom81f62d82019-07-22 12:10:00 -07001271 hostapd_set_oper_chwidth(hapd->iconf, chwidth);
1272 hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
1273 hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001274 /* Auto-detect new bw320_offset */
1275 hostapd_set_and_check_bw320_offset(hapd->iconf, 0);
Sunil Ravi036cec52023-03-29 11:35:17 -07001276#ifdef CONFIG_IEEE80211BE
1277 hapd->iconf->punct_bitmap = punct_bitmap;
1278#endif /* CONFIG_IEEE80211BE */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001279 if (hapd->iconf->ieee80211ac) {
1280 hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK;
Sunil8cd6f4d2022-06-28 18:40:46 +00001281 if (chwidth == CONF_OPER_CHWIDTH_160MHZ)
Hai Shaloma20dcd72022-02-04 13:43:00 -08001282 hapd->iconf->vht_capab |=
1283 VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Sunil8cd6f4d2022-06-28 18:40:46 +00001284 else if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Hai Shaloma20dcd72022-02-04 13:43:00 -08001285 hapd->iconf->vht_capab |=
1286 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1287 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001288
Roshan Pius3a1667e2018-07-03 15:17:14 -07001289 is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features,
1290 hapd->iface->num_hw_features);
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001291
Hai Shalom81f62d82019-07-22 12:10:00 -07001292 wpa_msg(hapd->msg_ctx, MSG_INFO,
Sunil Ravi036cec52023-03-29 11:35:17 -07001293 "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d is_dfs0=%d dfs=%d puncturing_bitmap=0x%04x",
Hai Shalom81f62d82019-07-22 12:10:00 -07001294 finished ? WPA_EVENT_CHANNEL_SWITCH :
1295 WPA_EVENT_CHANNEL_SWITCH_STARTED,
1296 freq, ht, offset, channel_width_to_string(width),
Sunil Ravi036cec52023-03-29 11:35:17 -07001297 cf1, cf2, is_dfs0, is_dfs, punct_bitmap);
Hai Shalom81f62d82019-07-22 12:10:00 -07001298 if (!finished)
1299 return;
1300
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001301 if (hapd->csa_in_progress &&
1302 freq == hapd->cs_freq_params.freq) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001303 hostapd_cleanup_cs_params(hapd);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001304 ieee802_11_set_beacon(hapd);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001305
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001306 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
1307 "freq=%d dfs=%d", freq, is_dfs);
1308 } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00001309 /* Complete AP configuration for the first bring up. */
1310 if (is_dfs0 > 0 &&
1311 hostapd_is_dfs_required(hapd->iface) <= 0 &&
1312 hapd->iface->state != HAPD_IFACE_ENABLED) {
1313 /* Fake a CAC start bit to skip setting channel */
1314 hapd->iface->cac_started = 1;
1315 hostapd_setup_interface_complete(hapd->iface, 0);
1316 }
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001317 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
1318 "freq=%d dfs=%d", freq, is_dfs);
Hai Shalomfdcde762020-04-02 11:19:20 -07001319 } else if (is_dfs &&
1320 hostapd_is_dfs_required(hapd->iface) &&
1321 !hostapd_is_dfs_chan_available(hapd->iface) &&
1322 !hapd->iface->cac_started) {
1323 hostapd_disable_iface(hapd->iface);
1324 hostapd_enable_iface(hapd->iface);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001325 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001326
1327 for (i = 0; i < hapd->iface->num_bss; i++)
1328 hostapd_neighbor_set_own_report(hapd->iface->bss[i]);
Hai Shalom899fcc72020-10-19 14:38:18 -07001329
1330#ifdef CONFIG_OCV
Sunil Ravia04bd252022-05-02 22:54:18 -07001331 if (hapd->conf->ocv &&
1332 !(hapd->iface->drv_flags2 &
1333 WPA_DRIVER_FLAGS2_SA_QUERY_OFFLOAD_AP)) {
Hai Shalom899fcc72020-10-19 14:38:18 -07001334 struct sta_info *sta;
1335 bool check_sa_query = false;
1336
1337 for (sta = hapd->sta_list; sta; sta = sta->next) {
1338 if (wpa_auth_uses_ocv(sta->wpa_sm) &&
1339 !(sta->flags & WLAN_STA_WNM_SLEEP_MODE)) {
1340 sta->post_csa_sa_query = 1;
1341 check_sa_query = true;
1342 }
1343 }
1344
1345 if (check_sa_query) {
1346 wpa_printf(MSG_DEBUG,
1347 "OCV: Check post-CSA SA Query initiation in 15 seconds");
1348 eloop_register_timeout(15, 0,
1349 hostapd_ocv_check_csa_sa_query,
1350 hapd, NULL);
1351 }
1352 }
1353#endif /* CONFIG_OCV */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001354#endif /* NEED_AP_MLME */
1355}
1356
1357
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001358void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
1359 const u8 *addr, int reason_code)
1360{
1361 switch (reason_code) {
1362 case MAX_CLIENT_REACHED:
1363 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR,
1364 MAC2STR(addr));
1365 break;
1366 case BLOCKED_CLIENT:
1367 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR,
1368 MAC2STR(addr));
1369 break;
1370 }
1371}
1372
1373
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001374#ifdef CONFIG_ACS
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08001375void hostapd_acs_channel_selected(struct hostapd_data *hapd,
1376 struct acs_selected_channels *acs_res)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001377{
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07001378 int ret, i;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001379 int err = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001380 struct hostapd_channel_data *pri_chan;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001381
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001382#ifdef CONFIG_IEEE80211BE
1383 if (acs_res->link_id != -1) {
1384 hapd = hostapd_mld_get_link_bss(hapd, acs_res->link_id);
1385 if (!hapd) {
1386 wpa_printf(MSG_ERROR,
1387 "MLD: Failed to get link BSS for EVENT_ACS_CHANNEL_SELECTED link_id=%d",
1388 acs_res->link_id);
1389 return;
1390 }
1391 }
1392#endif /* CONFIG_IEEE80211BE */
1393
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001394 if (hapd->iconf->channel) {
1395 wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
1396 hapd->iconf->channel);
1397 return;
1398 }
1399
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001400 hapd->iface->freq = acs_res->pri_freq;
1401
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07001402 if (!hapd->iface->current_mode) {
1403 for (i = 0; i < hapd->iface->num_hw_features; i++) {
1404 struct hostapd_hw_modes *mode =
1405 &hapd->iface->hw_features[i];
1406
1407 if (mode->mode == acs_res->hw_mode) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001408 if (hapd->iface->freq > 0 &&
1409 !hw_get_chan(mode->mode,
1410 hapd->iface->freq,
1411 hapd->iface->hw_features,
1412 hapd->iface->num_hw_features))
1413 continue;
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07001414 hapd->iface->current_mode = mode;
1415 break;
1416 }
1417 }
1418 if (!hapd->iface->current_mode) {
1419 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1420 HOSTAPD_LEVEL_WARNING,
1421 "driver selected to bad hw_mode");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001422 err = 1;
1423 goto out;
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07001424 }
1425 }
1426
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001427 if (!acs_res->pri_freq) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001428 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1429 HOSTAPD_LEVEL_WARNING,
1430 "driver switched to bad channel");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001431 err = 1;
1432 goto out;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001433 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001434 pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode,
1435 acs_res->pri_freq, NULL,
1436 hapd->iface->hw_features,
1437 hapd->iface->num_hw_features);
1438 if (!pri_chan) {
1439 wpa_printf(MSG_ERROR,
1440 "ACS: Could not determine primary channel number from pri_freq %u",
1441 acs_res->pri_freq);
1442 err = 1;
1443 goto out;
1444 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001445
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001446 hapd->iconf->channel = pri_chan->chan;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07001447 hapd->iconf->acs = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001448
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001449 if (acs_res->sec_freq == 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001450 hapd->iconf->secondary_channel = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001451 else if (acs_res->sec_freq < acs_res->pri_freq)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001452 hapd->iconf->secondary_channel = -1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001453 else if (acs_res->sec_freq > acs_res->pri_freq)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001454 hapd->iconf->secondary_channel = 1;
1455 else {
1456 wpa_printf(MSG_ERROR, "Invalid secondary channel!");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001457 err = 1;
1458 goto out;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001459 }
1460
Hai Shalomfdcde762020-04-02 11:19:20 -07001461 hapd->iconf->edmg_channel = acs_res->edmg_channel;
1462
Hai Shalom81f62d82019-07-22 12:10:00 -07001463 if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) {
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07001464 /* set defaults for backwards compatibility */
Hai Shalom81f62d82019-07-22 12:10:00 -07001465 hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
1466 hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0);
Sunil8cd6f4d2022-06-28 18:40:46 +00001467 hostapd_set_oper_chwidth(hapd->iconf, CONF_OPER_CHWIDTH_USE_HT);
Hai Shalomfdcde762020-04-02 11:19:20 -07001468 if (acs_res->ch_width == 40) {
1469 if (is_6ghz_freq(acs_res->pri_freq))
1470 hostapd_set_oper_centr_freq_seg0_idx(
1471 hapd->iconf,
1472 acs_res->vht_seg0_center_ch);
1473 } else if (acs_res->ch_width == 80) {
Hai Shalom81f62d82019-07-22 12:10:00 -07001474 hostapd_set_oper_centr_freq_seg0_idx(
1475 hapd->iconf, acs_res->vht_seg0_center_ch);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07001476 if (acs_res->vht_seg1_center_ch == 0) {
Sunil8cd6f4d2022-06-28 18:40:46 +00001477 hostapd_set_oper_chwidth(
1478 hapd->iconf, CONF_OPER_CHWIDTH_80MHZ);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07001479 } else {
Sunil8cd6f4d2022-06-28 18:40:46 +00001480 hostapd_set_oper_chwidth(
1481 hapd->iconf,
1482 CONF_OPER_CHWIDTH_80P80MHZ);
Hai Shalom81f62d82019-07-22 12:10:00 -07001483 hostapd_set_oper_centr_freq_seg1_idx(
1484 hapd->iconf,
1485 acs_res->vht_seg1_center_ch);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07001486 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001487 } else if (acs_res->ch_width == 160) {
Sunil8cd6f4d2022-06-28 18:40:46 +00001488 hostapd_set_oper_chwidth(hapd->iconf,
1489 CONF_OPER_CHWIDTH_160MHZ);
Hai Shalomfdcde762020-04-02 11:19:20 -07001490 hostapd_set_oper_centr_freq_seg0_idx(
1491 hapd->iconf, acs_res->vht_seg1_center_ch);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07001492 }
1493 }
1494
Sunil8cd6f4d2022-06-28 18:40:46 +00001495#ifdef CONFIG_IEEE80211BE
1496 if (hapd->iface->conf->ieee80211be && acs_res->ch_width == 320) {
1497 hostapd_set_oper_chwidth(hapd->iconf, CONF_OPER_CHWIDTH_320MHZ);
1498 hostapd_set_oper_centr_freq_seg0_idx(
1499 hapd->iconf, acs_res->vht_seg1_center_ch);
1500 hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
1501 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001502
1503 if (hapd->iface->conf->ieee80211be && acs_res->puncture_bitmap)
1504 hapd->iconf->punct_bitmap = acs_res->puncture_bitmap;
Sunil8cd6f4d2022-06-28 18:40:46 +00001505#endif /* CONFIG_IEEE80211BE */
1506
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001507out:
1508 ret = hostapd_acs_completed(hapd->iface, err);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001509 if (ret) {
1510 wpa_printf(MSG_ERROR,
1511 "ACS: Possibly channel configuration is invalid");
1512 }
1513}
1514#endif /* CONFIG_ACS */
1515
1516
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001517int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001518 const u8 *bssid, const u8 *ie, size_t ie_len,
1519 int ssi_signal)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001520{
1521 size_t i;
1522 int ret = 0;
1523
1524 if (sa == NULL || ie == NULL)
1525 return -1;
1526
1527 random_add_randomness(sa, ETH_ALEN);
1528 for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
1529 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001530 sa, da, bssid, ie, ie_len,
1531 ssi_signal) > 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001532 ret = 1;
1533 break;
1534 }
1535 }
1536 return ret;
1537}
1538
1539
1540#ifdef HOSTAPD
1541
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001542#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001543static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001544 u16 auth_transaction, u16 status,
1545 const u8 *ies, size_t ies_len)
1546{
1547 struct hostapd_data *hapd = ctx;
1548 struct sta_info *sta;
1549
1550 sta = ap_get_sta(hapd, dst);
1551 if (sta == NULL)
1552 return;
1553
1554 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
1555 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
1556 sta->flags |= WLAN_STA_AUTH;
1557
1558 hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len);
1559}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001560#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001561
1562
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001563#ifdef CONFIG_FILS
1564static void hostapd_notify_auth_fils_finish(struct hostapd_data *hapd,
1565 struct sta_info *sta, u16 resp,
1566 struct wpabuf *data, int pub)
1567{
1568 if (resp == WLAN_STATUS_SUCCESS) {
1569 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1570 HOSTAPD_LEVEL_DEBUG, "authentication OK (FILS)");
1571 sta->flags |= WLAN_STA_AUTH;
1572 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
1573 sta->auth_alg = WLAN_AUTH_FILS_SK;
1574 mlme_authenticate_indication(hapd, sta);
1575 } else {
1576 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1577 HOSTAPD_LEVEL_DEBUG,
1578 "authentication failed (FILS)");
1579 }
1580
1581 hostapd_sta_auth(hapd, sta->addr, 2, resp,
1582 data ? wpabuf_head(data) : NULL,
1583 data ? wpabuf_len(data) : 0);
1584 wpabuf_free(data);
1585}
1586#endif /* CONFIG_FILS */
1587
1588
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001589static void hostapd_notif_auth(struct hostapd_data *hapd,
1590 struct auth_info *rx_auth)
1591{
1592 struct sta_info *sta;
1593 u16 status = WLAN_STATUS_SUCCESS;
1594 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
1595 size_t resp_ies_len = 0;
1596
1597 sta = ap_get_sta(hapd, rx_auth->peer);
1598 if (!sta) {
1599 sta = ap_sta_add(hapd, rx_auth->peer);
1600 if (sta == NULL) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07001601 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001602 goto fail;
1603 }
1604 }
1605 sta->flags &= ~WLAN_STA_PREAUTH;
1606 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001607#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001608 if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) {
1609 sta->auth_alg = WLAN_AUTH_FT;
1610 if (sta->wpa_sm == NULL)
1611 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001612 sta->addr, NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001613 if (sta->wpa_sm == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001614 wpa_printf(MSG_DEBUG,
1615 "FT: Failed to initialize WPA state machine");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001616 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1617 goto fail;
1618 }
Sunil Ravi7f769292024-07-23 22:21:32 +00001619 wpa_ft_process_auth(sta->wpa_sm,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001620 rx_auth->auth_transaction, rx_auth->ies,
1621 rx_auth->ies_len,
1622 hostapd_notify_auth_ft_finish, hapd);
1623 return;
1624 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001625#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001626
1627#ifdef CONFIG_FILS
1628 if (rx_auth->auth_type == WLAN_AUTH_FILS_SK) {
1629 sta->auth_alg = WLAN_AUTH_FILS_SK;
1630 handle_auth_fils(hapd, sta, rx_auth->ies, rx_auth->ies_len,
1631 rx_auth->auth_type, rx_auth->auth_transaction,
1632 rx_auth->status_code,
1633 hostapd_notify_auth_fils_finish);
1634 return;
1635 }
1636#endif /* CONFIG_FILS */
1637
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001638fail:
1639 hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
1640 status, resp_ies, resp_ies_len);
1641}
1642
1643
Hai Shalom021b0b52019-04-10 11:17:58 -07001644#ifndef NEED_AP_MLME
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001645static void hostapd_action_rx(struct hostapd_data *hapd,
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001646 struct rx_mgmt *drv_mgmt)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001647{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001648 struct ieee80211_mgmt *mgmt;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001649 struct sta_info *sta;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001650 size_t plen __maybe_unused;
1651 u16 fc;
Hai Shalom74f70d42019-02-11 14:42:39 -08001652 u8 *action __maybe_unused;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001653
Hai Shalom74f70d42019-02-11 14:42:39 -08001654 if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001655 return;
1656
Hai Shalom021b0b52019-04-10 11:17:58 -07001657 plen = drv_mgmt->frame_len - IEEE80211_HDRLEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001658
1659 mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
1660 fc = le_to_host16(mgmt->frame_control);
1661 if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
1662 return; /* handled by the driver */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001663
Hai Shalom74f70d42019-02-11 14:42:39 -08001664 action = (u8 *) &mgmt->u.action.u;
1665 wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR
1666 " da " MACSTR " plen %d",
1667 mgmt->u.action.category, *action,
1668 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) plen);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001669
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001670 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001671 if (sta == NULL) {
1672 wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
1673 return;
1674 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001675#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001676 if (mgmt->u.action.category == WLAN_ACTION_FT) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001677 wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, plen);
1678 return;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001679 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001680#endif /* CONFIG_IEEE80211R_AP */
Hai Shalom021b0b52019-04-10 11:17:58 -07001681 if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001682 ieee802_11_sa_query_action(hapd, mgmt, drv_mgmt->frame_len);
Hai Shalom021b0b52019-04-10 11:17:58 -07001683 return;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001684 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001685#ifdef CONFIG_WNM_AP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001686 if (mgmt->u.action.category == WLAN_ACTION_WNM) {
1687 ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
Hai Shalom021b0b52019-04-10 11:17:58 -07001688 return;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001689 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001690#endif /* CONFIG_WNM_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001691#ifdef CONFIG_FST
1692 if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) {
1693 fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len);
1694 return;
1695 }
1696#endif /* CONFIG_FST */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001697#ifdef CONFIG_DPP
Hai Shalom021b0b52019-04-10 11:17:58 -07001698 if (plen >= 2 + 4 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001699 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001700 mgmt->u.action.u.vs_public_action.action ==
1701 WLAN_PA_VENDOR_SPECIFIC &&
1702 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
1703 OUI_WFA &&
1704 mgmt->u.action.u.vs_public_action.variable[0] ==
1705 DPP_OUI_TYPE) {
1706 const u8 *pos, *end;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001707
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001708 pos = mgmt->u.action.u.vs_public_action.oui;
1709 end = drv_mgmt->frame + drv_mgmt->frame_len;
1710 hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos,
1711 drv_mgmt->freq);
1712 return;
1713 }
1714#endif /* CONFIG_DPP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001715#ifdef CONFIG_NAN_USD
1716 if (mgmt->u.action.category == WLAN_ACTION_PUBLIC && plen >= 5 &&
1717 mgmt->u.action.u.vs_public_action.action ==
1718 WLAN_PA_VENDOR_SPECIFIC &&
1719 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
1720 OUI_WFA &&
1721 mgmt->u.action.u.vs_public_action.variable[0] == NAN_OUI_TYPE) {
1722 const u8 *pos, *end;
1723
1724 pos = mgmt->u.action.u.vs_public_action.variable;
1725 end = drv_mgmt->frame + drv_mgmt->frame_len;
1726 pos++;
1727 hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, drv_mgmt->freq,
1728 pos, end - pos);
1729 return;
1730 }
1731#endif /* CONFIG_NAN_USD */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001732}
Hai Shalom021b0b52019-04-10 11:17:58 -07001733#endif /* NEED_AP_MLME */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001734
1735
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736#ifdef NEED_AP_MLME
1737
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001738static struct hostapd_data *
1739switch_link_hapd(struct hostapd_data *hapd, int link_id)
1740{
1741#ifdef CONFIG_IEEE80211BE
1742 if (hapd->conf->mld_ap && link_id >= 0) {
1743 struct hostapd_data *link_bss;
1744
1745 link_bss = hostapd_mld_get_link_bss(hapd, link_id);
1746 if (link_bss)
1747 return link_bss;
1748 }
1749#endif /* CONFIG_IEEE80211BE */
1750
1751 return hapd;
1752}
1753
1754
Sunil Ravi99c035e2024-07-12 01:42:03 +00001755static struct hostapd_data *
1756switch_link_scan(struct hostapd_data *hapd, u64 scan_cookie)
1757{
1758#ifdef CONFIG_IEEE80211BE
1759 if (hapd->conf->mld_ap && scan_cookie != 0) {
1760 unsigned int i;
1761
1762 for (i = 0; i < hapd->iface->interfaces->count; i++) {
1763 struct hostapd_iface *h;
1764 struct hostapd_data *h_hapd;
1765
1766 h = hapd->iface->interfaces->iface[i];
1767 h_hapd = h->bss[0];
1768 if (!hostapd_is_ml_partner(hapd, h_hapd))
1769 continue;
1770
1771 if (h_hapd->scan_cookie == scan_cookie) {
1772 h_hapd->scan_cookie = 0;
1773 return h_hapd;
1774 }
1775 }
1776 }
1777#endif /* CONFIG_IEEE80211BE */
1778
1779 return hapd;
1780}
1781
1782
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001783#define HAPD_BROADCAST ((struct hostapd_data *) -1)
1784
1785static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
Sunil Ravi7f769292024-07-23 22:21:32 +00001786 const u8 *bssid, int link_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787{
1788 size_t i;
1789
1790 if (bssid == NULL)
1791 return NULL;
1792 if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
1793 bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
1794 return HAPD_BROADCAST;
1795
1796 for (i = 0; i < iface->num_bss; i++) {
Sunil Ravi7f769292024-07-23 22:21:32 +00001797 struct hostapd_data *hapd;
1798#ifdef CONFIG_IEEE80211BE
1799 struct hostapd_data *p_hapd;
1800#endif /* CONFIG_IEEE80211BE */
1801
1802 hapd = iface->bss[i];
1803 if (ether_addr_equal(bssid, hapd->own_addr))
1804 return hapd;
1805
1806#ifdef CONFIG_IEEE80211BE
1807 if (ether_addr_equal(bssid, hapd->own_addr) ||
1808 (hapd->conf->mld_ap &&
1809 ether_addr_equal(bssid, hapd->mld->mld_addr) &&
1810 link_id == hapd->mld_link_id))
1811 return hapd;
1812
1813 if (!hapd->conf->mld_ap)
1814 continue;
1815
1816 for_each_mld_link(p_hapd, hapd) {
1817 if (p_hapd == hapd)
1818 continue;
1819
1820 if (ether_addr_equal(bssid, p_hapd->own_addr) ||
1821 (ether_addr_equal(bssid, p_hapd->mld->mld_addr) &&
1822 link_id == p_hapd->mld_link_id))
1823 return p_hapd;
1824 }
1825#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 }
1827
1828 return NULL;
1829}
1830
1831
1832static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001833 const u8 *bssid, const u8 *addr,
1834 int wds)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001835{
Sunil Ravi7f769292024-07-23 22:21:32 +00001836 hapd = get_hapd_bssid(hapd->iface, bssid, -1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001837 if (hapd == NULL || hapd == HAPD_BROADCAST)
1838 return;
1839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001840 ieee802_11_rx_from_unknown(hapd, addr, wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841}
1842
1843
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001844static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001845{
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001846 struct hostapd_iface *iface;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001847 const struct ieee80211_hdr *hdr;
1848 const u8 *bssid;
1849 struct hostapd_frame_info fi;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001850 int ret;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001851
Sunil Ravi7f769292024-07-23 22:21:32 +00001852 if (rx_mgmt->ctx)
1853 hapd = rx_mgmt->ctx;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001854 hapd = switch_link_hapd(hapd, rx_mgmt->link_id);
1855 iface = hapd->iface;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001857#ifdef CONFIG_TESTING_OPTIONS
1858 if (hapd->ext_mgmt_frame_handling) {
1859 size_t hex_len = 2 * rx_mgmt->frame_len + 1;
1860 char *hex = os_malloc(hex_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001861
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001862 if (hex) {
1863 wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame,
1864 rx_mgmt->frame_len);
1865 wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex);
1866 os_free(hex);
1867 }
1868 return 1;
1869 }
1870#endif /* CONFIG_TESTING_OPTIONS */
1871
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001872 hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
1873 bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
1874 if (bssid == NULL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001875 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876
Sunil Ravi7f769292024-07-23 22:21:32 +00001877 hapd = get_hapd_bssid(iface, bssid, rx_mgmt->link_id);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001878
1879 if (!hapd) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001880 u16 fc = le_to_host16(hdr->frame_control);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881
1882 /*
1883 * Drop frames to unknown BSSIDs except for Beacon frames which
1884 * could be used to update neighbor information.
1885 */
1886 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
1887 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
1888 hapd = iface->bss[0];
1889 else
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001890 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 }
1892
1893 os_memset(&fi, 0, sizeof(fi));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001894 fi.freq = rx_mgmt->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001895 fi.datarate = rx_mgmt->datarate;
1896 fi.ssi_signal = rx_mgmt->ssi_signal;
1897
1898 if (hapd == HAPD_BROADCAST) {
1899 size_t i;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001900
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001901 ret = 0;
1902 for (i = 0; i < iface->num_bss; i++) {
Dmitry Shmidt98660862014-03-11 17:26:21 -07001903 /* if bss is set, driver will call this function for
1904 * each bss individually. */
1905 if (rx_mgmt->drv_priv &&
1906 (iface->bss[i]->drv_priv != rx_mgmt->drv_priv))
1907 continue;
1908
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001909 if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
1910 rx_mgmt->frame_len, &fi) > 0)
1911 ret = 1;
1912 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001913 } else
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001914 ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len,
1915 &fi);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001916
1917 random_add_randomness(&fi, sizeof(fi));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001918
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001919 return ret;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001920}
1921
1922
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001924 size_t len, u16 stype, int ok, int link_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001925{
1926 struct ieee80211_hdr *hdr;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001927 struct hostapd_data *orig_hapd, *tmp_hapd;
1928
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001929 orig_hapd = hapd;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001930
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001931 hdr = (struct ieee80211_hdr *) buf;
Sunil Ravi7f769292024-07-23 22:21:32 +00001932 hapd = switch_link_hapd(hapd, link_id);
1933 tmp_hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len), link_id);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001934 if (tmp_hapd) {
1935 hapd = tmp_hapd;
1936#ifdef CONFIG_IEEE80211BE
1937 } else if (hapd->conf->mld_ap &&
Sunil Ravi99c035e2024-07-12 01:42:03 +00001938 ether_addr_equal(hapd->mld->mld_addr,
1939 get_hdr_bssid(hdr, len))) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001940 /* AP MLD address match - use hapd pointer as-is */
1941#endif /* CONFIG_IEEE80211BE */
1942 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001943 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001944 }
1945
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001946 if (hapd == HAPD_BROADCAST) {
1947 if (stype != WLAN_FC_STYPE_ACTION || len <= 25 ||
1948 buf[24] != WLAN_ACTION_PUBLIC)
1949 return;
Sunil Ravi7f769292024-07-23 22:21:32 +00001950 hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2, link_id);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001951 if (!hapd || hapd == HAPD_BROADCAST)
1952 return;
1953 /*
1954 * Allow processing of TX status for a Public Action frame that
1955 * used wildcard BBSID.
1956 */
1957 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001958 ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
1959}
1960
1961#endif /* NEED_AP_MLME */
1962
1963
1964static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
1965{
1966 struct sta_info *sta = ap_get_sta(hapd, addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968 if (sta)
1969 return 0;
1970
1971 wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
1972 " - adding a new STA", MAC2STR(addr));
1973 sta = ap_sta_add(hapd, addr);
1974 if (sta) {
1975 hostapd_new_assoc_sta(hapd, sta, 0);
1976 } else {
1977 wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
1978 MAC2STR(addr));
1979 return -1;
1980 }
1981
1982 return 0;
1983}
1984
1985
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001986static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
Sunil Ravi7f769292024-07-23 22:21:32 +00001987 const u8 *src, bool rsn,
1988 struct sta_info **sta_ret)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001989{
Sunil Ravi7f769292024-07-23 22:21:32 +00001990 struct hostapd_data *hapd;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001991 struct sta_info *sta;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001992 unsigned int j;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993
Sunil Ravi7f769292024-07-23 22:21:32 +00001994 if (sta_ret)
1995 *sta_ret = NULL;
1996
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001997 for (j = 0; j < iface->num_bss; j++) {
Sunil Ravi7f769292024-07-23 22:21:32 +00001998 hapd = iface->bss[j];
1999 sta = ap_get_sta(hapd, src);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002000 if (sta && (sta->flags & WLAN_STA_ASSOC) &&
Sunil Ravi7f769292024-07-23 22:21:32 +00002001 (!rsn || sta->wpa_sm)) {
2002 if (sta_ret)
2003 *sta_ret = sta;
2004 return hapd;
2005 }
2006#ifdef CONFIG_IEEE80211BE
2007 if (hapd->conf->mld_ap) {
2008 struct hostapd_data *p_hapd;
2009
2010 for_each_mld_link(p_hapd, hapd) {
2011 if (p_hapd == hapd)
2012 continue;
2013
2014 sta = ap_get_sta(p_hapd, src);
2015 if (sta && (sta->flags & WLAN_STA_ASSOC) &&
2016 (!rsn || sta->wpa_sm)) {
2017 if (sta_ret)
2018 *sta_ret = sta;
2019 return p_hapd;
2020 }
2021 }
2022 }
2023#endif /* CONFIG_IEEE80211BE */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002024 }
2025
2026 return NULL;
2027}
2028
2029
2030static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
2031 const u8 *data, size_t data_len,
2032 enum frame_encryption encrypted,
2033 int link_id)
2034{
2035 struct hostapd_data *orig_hapd = hapd;
2036
2037#ifdef CONFIG_IEEE80211BE
Sunil Ravi7f769292024-07-23 22:21:32 +00002038 hapd = switch_link_hapd(hapd, link_id);
2039 hapd = hostapd_find_by_sta(hapd->iface, src, true, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002040#else /* CONFIG_IEEE80211BE */
Sunil Ravi7f769292024-07-23 22:21:32 +00002041 hapd = hostapd_find_by_sta(hapd->iface, src, false, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002042#endif /* CONFIG_IEEE80211BE */
2043
2044 if (!hapd) {
2045 /* WLAN cases need to have an existing association, but non-WLAN
2046 * cases (mainly, wired IEEE 802.1X) need to be able to process
2047 * EAPOL frames from new devices that do not yet have a STA
2048 * entry and as such, do not get a match in
2049 * hostapd_find_by_sta(). */
2050 wpa_printf(MSG_DEBUG,
2051 "No STA-specific hostapd instance for EAPOL RX found - fall back to initial context");
2052 hapd = orig_hapd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 }
2054
Sunil8cd6f4d2022-06-28 18:40:46 +00002055 ieee802_1x_receive(hapd, src, data, data_len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056}
2057
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08002058#endif /* HOSTAPD */
2059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060
Hai Shalomfdcde762020-04-02 11:19:20 -07002061static struct hostapd_channel_data *
2062hostapd_get_mode_chan(struct hostapd_hw_modes *mode, unsigned int freq)
2063{
2064 int i;
2065 struct hostapd_channel_data *chan;
2066
2067 for (i = 0; i < mode->num_channels; i++) {
2068 chan = &mode->channels[i];
2069 if ((unsigned int) chan->freq == freq)
2070 return chan;
2071 }
2072
2073 return NULL;
2074}
2075
2076
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002077static struct hostapd_channel_data * hostapd_get_mode_channel(
2078 struct hostapd_iface *iface, unsigned int freq)
2079{
2080 int i;
2081 struct hostapd_channel_data *chan;
2082
Hai Shalomfdcde762020-04-02 11:19:20 -07002083 for (i = 0; i < iface->num_hw_features; i++) {
2084 if (hostapd_hw_skip_mode(iface, &iface->hw_features[i]))
2085 continue;
2086 chan = hostapd_get_mode_chan(&iface->hw_features[i], freq);
2087 if (chan)
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002088 return chan;
2089 }
2090
2091 return NULL;
2092}
2093
2094
2095static void hostapd_update_nf(struct hostapd_iface *iface,
2096 struct hostapd_channel_data *chan,
2097 struct freq_survey *survey)
2098{
2099 if (!iface->chans_surveyed) {
2100 chan->min_nf = survey->nf;
2101 iface->lowest_nf = survey->nf;
2102 } else {
2103 if (dl_list_empty(&chan->survey_list))
2104 chan->min_nf = survey->nf;
2105 else if (survey->nf < chan->min_nf)
2106 chan->min_nf = survey->nf;
2107 if (survey->nf < iface->lowest_nf)
2108 iface->lowest_nf = survey->nf;
2109 }
2110}
2111
2112
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002113static void hostapd_single_channel_get_survey(struct hostapd_iface *iface,
2114 struct survey_results *survey_res)
2115{
2116 struct hostapd_channel_data *chan;
2117 struct freq_survey *survey;
2118 u64 divisor, dividend;
2119
2120 survey = dl_list_first(&survey_res->survey_list, struct freq_survey,
2121 list);
2122 if (!survey || !survey->freq)
2123 return;
2124
2125 chan = hostapd_get_mode_channel(iface, survey->freq);
2126 if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED)
2127 return;
2128
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002129 wpa_printf(MSG_DEBUG,
2130 "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002131 survey->freq,
2132 (unsigned long int) survey->channel_time,
2133 (unsigned long int) survey->channel_time_busy);
2134
2135 if (survey->channel_time > iface->last_channel_time &&
2136 survey->channel_time > survey->channel_time_busy) {
2137 dividend = survey->channel_time_busy -
2138 iface->last_channel_time_busy;
2139 divisor = survey->channel_time - iface->last_channel_time;
2140
2141 iface->channel_utilization = dividend * 255 / divisor;
2142 wpa_printf(MSG_DEBUG, "Channel Utilization: %d",
2143 iface->channel_utilization);
2144 }
2145 iface->last_channel_time = survey->channel_time;
2146 iface->last_channel_time_busy = survey->channel_time_busy;
2147}
2148
2149
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08002150void hostapd_event_get_survey(struct hostapd_iface *iface,
2151 struct survey_results *survey_results)
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002152{
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002153 struct freq_survey *survey, *tmp;
2154 struct hostapd_channel_data *chan;
2155
2156 if (dl_list_empty(&survey_results->survey_list)) {
2157 wpa_printf(MSG_DEBUG, "No survey data received");
2158 return;
2159 }
2160
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002161 if (survey_results->freq_filter) {
2162 hostapd_single_channel_get_survey(iface, survey_results);
2163 return;
2164 }
2165
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002166 dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
2167 struct freq_survey, list) {
2168 chan = hostapd_get_mode_channel(iface, survey->freq);
2169 if (!chan)
2170 continue;
2171 if (chan->flag & HOSTAPD_CHAN_DISABLED)
2172 continue;
2173
2174 dl_list_del(&survey->list);
2175 dl_list_add_tail(&chan->survey_list, &survey->list);
2176
2177 hostapd_update_nf(iface, chan, survey);
2178
2179 iface->chans_surveyed++;
2180 }
2181}
2182
2183
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08002184#ifdef HOSTAPD
Dmitry Shmidt051af732013-10-22 13:52:46 -07002185#ifdef NEED_AP_MLME
2186
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002187static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
2188{
2189 wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped",
2190 hapd->conf->iface);
2191
2192 if (hapd->csa_in_progress) {
2193 wpa_printf(MSG_INFO, "CSA failed (%s was stopped)",
2194 hapd->conf->iface);
2195 hostapd_switch_channel_fallback(hapd->iface,
2196 &hapd->cs_freq_params);
2197 }
Yu Ouyang378d3c42021-08-20 17:31:08 +08002198
2199 // inform framework that interface is unavailable
2200 hostapd_disable_iface(hapd->iface);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002201}
2202
2203
Dmitry Shmidt051af732013-10-22 13:52:46 -07002204static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
2205 struct dfs_event *radar)
2206{
2207 wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002208 hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled,
Dmitry Shmidt051af732013-10-22 13:52:46 -07002209 radar->chan_offset, radar->chan_width,
2210 radar->cf1, radar->cf2);
2211}
2212
2213
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002214static void hostapd_event_dfs_pre_cac_expired(struct hostapd_data *hapd,
2215 struct dfs_event *radar)
2216{
2217 wpa_printf(MSG_DEBUG, "DFS Pre-CAC expired on %d MHz", radar->freq);
2218 hostapd_dfs_pre_cac_expired(hapd->iface, radar->freq, radar->ht_enabled,
2219 radar->chan_offset, radar->chan_width,
2220 radar->cf1, radar->cf2);
2221}
2222
2223
Dmitry Shmidt051af732013-10-22 13:52:46 -07002224static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd,
2225 struct dfs_event *radar)
2226{
2227 wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002228 hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled,
Dmitry Shmidt051af732013-10-22 13:52:46 -07002229 radar->chan_offset, radar->chan_width,
2230 radar->cf1, radar->cf2);
2231}
2232
2233
2234static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd,
2235 struct dfs_event *radar)
2236{
2237 wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002238 hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled,
Dmitry Shmidt051af732013-10-22 13:52:46 -07002239 radar->chan_offset, radar->chan_width,
2240 radar->cf1, radar->cf2);
2241}
2242
2243
2244static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
2245 struct dfs_event *radar)
2246{
2247 wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002248 hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled,
Dmitry Shmidt051af732013-10-22 13:52:46 -07002249 radar->chan_offset, radar->chan_width,
2250 radar->cf1, radar->cf2);
2251}
2252
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002253
2254static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
2255 struct dfs_event *radar)
2256{
2257 wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
2258 hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
2259 radar->chan_offset, radar->chan_width,
2260 radar->cf1, radar->cf2);
2261}
2262
Dmitry Shmidt051af732013-10-22 13:52:46 -07002263#endif /* NEED_AP_MLME */
2264
2265
Roshan Pius3a1667e2018-07-03 15:17:14 -07002266static void hostapd_event_wds_sta_interface_status(struct hostapd_data *hapd,
2267 int istatus,
2268 const char *ifname,
2269 const u8 *addr)
2270{
2271 struct sta_info *sta = ap_get_sta(hapd, addr);
2272
2273 if (sta) {
2274 os_free(sta->ifname_wds);
2275 if (istatus == INTERFACE_ADDED)
2276 sta->ifname_wds = os_strdup(ifname);
2277 else
2278 sta->ifname_wds = NULL;
2279 }
2280
2281 wpa_msg(hapd->msg_ctx, MSG_INFO, "%sifname=%s sta_addr=" MACSTR,
2282 istatus == INTERFACE_ADDED ?
2283 WDS_STA_INTERFACE_ADDED : WDS_STA_INTERFACE_REMOVED,
2284 ifname, MAC2STR(addr));
2285}
2286
2287
Hai Shalom81f62d82019-07-22 12:10:00 -07002288#ifdef CONFIG_OWE
2289static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd,
2290 const u8 *peer, const u8 *ie,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002291 size_t ie_len, const u8 *link_addr)
Hai Shalom81f62d82019-07-22 12:10:00 -07002292{
2293 u16 status;
2294 struct sta_info *sta;
2295 struct ieee802_11_elems elems;
2296
2297 if (!hapd || !hapd->wpa_auth) {
2298 wpa_printf(MSG_DEBUG, "OWE: Invalid hapd context");
2299 return -1;
2300 }
2301 if (!peer) {
2302 wpa_printf(MSG_DEBUG, "OWE: Peer unknown");
2303 return -1;
2304 }
2305 if (!(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) {
2306 wpa_printf(MSG_DEBUG, "OWE: No OWE AKM configured");
2307 status = WLAN_STATUS_AKMP_NOT_VALID;
2308 goto err;
2309 }
2310 if (ieee802_11_parse_elems(ie, ie_len, &elems, 1) == ParseFailed) {
2311 wpa_printf(MSG_DEBUG, "OWE: Failed to parse OWE IE for "
2312 MACSTR, MAC2STR(peer));
2313 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
2314 goto err;
2315 }
2316 status = owe_validate_request(hapd, peer, elems.rsn_ie,
2317 elems.rsn_ie_len,
2318 elems.owe_dh, elems.owe_dh_len);
2319 if (status != WLAN_STATUS_SUCCESS)
2320 goto err;
2321
2322 sta = ap_get_sta(hapd, peer);
2323 if (sta) {
2324 ap_sta_no_session_timeout(hapd, sta);
2325 accounting_sta_stop(hapd, sta);
2326
2327 /*
2328 * Make sure that the previously registered inactivity timer
2329 * will not remove the STA immediately.
2330 */
2331 sta->timeout_next = STA_NULLFUNC;
2332 } else {
2333 sta = ap_sta_add(hapd, peer);
2334 if (!sta) {
2335 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
2336 goto err;
2337 }
2338 }
2339 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
2340
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002341#ifdef CONFIG_IEEE80211BE
2342 if (link_addr) {
2343 struct mld_info *info = &sta->mld_info;
2344 u8 link_id = hapd->mld_link_id;
2345
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002346 ap_sta_set_mld(sta, true);
2347 sta->mld_assoc_link_id = link_id;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002348 os_memcpy(info->common_info.mld_addr, peer, ETH_ALEN);
2349 info->links[link_id].valid = true;
2350 os_memcpy(info->links[link_id].local_addr, hapd->own_addr,
2351 ETH_ALEN);
2352 os_memcpy(info->links[link_id].peer_addr, link_addr, ETH_ALEN);
2353 }
2354#endif /* CONFIG_IEEE80211BE */
2355
Hai Shalom81f62d82019-07-22 12:10:00 -07002356 status = owe_process_rsn_ie(hapd, sta, elems.rsn_ie,
2357 elems.rsn_ie_len, elems.owe_dh,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002358 elems.owe_dh_len, link_addr);
Hai Shalom81f62d82019-07-22 12:10:00 -07002359 if (status != WLAN_STATUS_SUCCESS)
2360 ap_free_sta(hapd, sta);
2361
2362 return 0;
2363err:
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002364 hostapd_drv_update_dh_ie(hapd, link_addr ? link_addr : peer, status,
2365 NULL, 0);
Hai Shalom81f62d82019-07-22 12:10:00 -07002366 return 0;
2367}
2368#endif /* CONFIG_OWE */
2369
2370
Sunil Ravi7f769292024-07-23 22:21:32 +00002371#ifdef NEED_AP_MLME
2372static void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
2373 const u8 *data, size_t len, int ack,
2374 int link_id)
2375{
2376 struct sta_info *sta;
2377
2378 hapd = switch_link_hapd(hapd, link_id);
2379 hapd = hostapd_find_by_sta(hapd->iface, dst, false, &sta);
2380
2381 if (!sta) {
2382 wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
2383 MACSTR " that is not currently associated",
2384 MAC2STR(dst));
2385 return;
2386 }
2387
2388 ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
2389}
2390#endif /* NEED_AP_MLME */
2391
2392
2393#ifdef CONFIG_IEEE80211AX
2394static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
2395{
2396 struct hostapd_data *bss;
2397 size_t i;
2398
2399 for (i = 0; i < hapd->iface->num_bss; i++) {
2400 bss = hapd->iface->bss[i];
2401 if (bss->cca_color == 0)
2402 continue;
2403
2404 if (success)
2405 hapd->iface->conf->he_op.he_bss_color = bss->cca_color;
2406
2407 bss->cca_in_progress = 0;
2408 if (ieee802_11_set_beacon(bss)) {
2409 wpa_printf(MSG_ERROR, "Failed to remove BCCA element");
2410 bss->cca_in_progress = 1;
2411 } else {
2412 hostapd_cleanup_cca_params(bss);
2413 }
2414 }
2415}
2416#endif /* CONFIG_IEEE80211AX */
2417
2418
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002419void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
2420 union wpa_event_data *data)
2421{
2422 struct hostapd_data *hapd = ctx;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002423 struct sta_info *sta;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002424#ifndef CONFIG_NO_STDOUT_DEBUG
2425 int level = MSG_DEBUG;
2426
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002427 if (event == EVENT_RX_MGMT && data->rx_mgmt.frame &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002428 data->rx_mgmt.frame_len >= 24) {
2429 const struct ieee80211_hdr *hdr;
2430 u16 fc;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002431
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002432 hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
2433 fc = le_to_host16(hdr->frame_control);
2434 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
2435 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
2436 level = MSG_EXCESSIVE;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002437 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
2438 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ)
2439 level = MSG_EXCESSIVE;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002440 }
2441
2442 wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
2443 event_to_string(event), event);
2444#endif /* CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445
2446 switch (event) {
2447 case EVENT_MICHAEL_MIC_FAILURE:
2448 michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
2449 break;
2450 case EVENT_SCAN_RESULTS:
Sunil Ravi99c035e2024-07-12 01:42:03 +00002451#ifdef NEED_AP_MLME
2452 if (data)
2453 hapd = switch_link_scan(hapd,
2454 data->scan_info.scan_cookie);
2455#endif /* NEED_AP_MLME */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002456 if (hapd->iface->scan_cb)
2457 hapd->iface->scan_cb(hapd->iface);
Sunil Ravi99c035e2024-07-12 01:42:03 +00002458#ifdef CONFIG_IEEE80211BE
2459 if (!hapd->iface->scan_cb && hapd->conf->mld_ap) {
2460 /* Other links may be waiting for HT scan result */
2461 unsigned int i;
2462
2463 for (i = 0; i < hapd->iface->interfaces->count; i++) {
2464 struct hostapd_iface *h =
2465 hapd->iface->interfaces->iface[i];
2466 struct hostapd_data *h_hapd = h->bss[0];
2467
2468 if (hostapd_is_ml_partner(hapd, h_hapd) &&
2469 h_hapd->iface->scan_cb)
2470 h_hapd->iface->scan_cb(h_hapd->iface);
2471 }
2472 }
2473#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 case EVENT_WPS_BUTTON_PUSHED:
2476 hostapd_wps_button_pushed(hapd, NULL);
2477 break;
2478#ifdef NEED_AP_MLME
2479 case EVENT_TX_STATUS:
2480 switch (data->tx_status.type) {
2481 case WLAN_FC_TYPE_MGMT:
2482 hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
2483 data->tx_status.data_len,
2484 data->tx_status.stype,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002485 data->tx_status.ack,
2486 data->tx_status.link_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 break;
2488 case WLAN_FC_TYPE_DATA:
2489 hostapd_tx_status(hapd, data->tx_status.dst,
2490 data->tx_status.data,
2491 data->tx_status.data_len,
2492 data->tx_status.ack);
2493 break;
2494 }
2495 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002496 case EVENT_EAPOL_TX_STATUS:
2497 hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
2498 data->eapol_tx_status.data,
2499 data->eapol_tx_status.data_len,
Sunil Ravi7f769292024-07-23 22:21:32 +00002500 data->eapol_tx_status.ack,
2501 data->eapol_tx_status.link_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002502 break;
2503 case EVENT_DRIVER_CLIENT_POLL_OK:
2504 hostapd_client_poll_ok(hapd, data->client_poll.addr);
2505 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002506 case EVENT_RX_FROM_UNKNOWN:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002507 hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
2508 data->rx_from_unknown.addr,
2509 data->rx_from_unknown.wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511#endif /* NEED_AP_MLME */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002512 case EVENT_RX_MGMT:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002513 if (!data->rx_mgmt.frame)
2514 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002515#ifdef NEED_AP_MLME
Hai Shalom021b0b52019-04-10 11:17:58 -07002516 hostapd_mgmt_rx(hapd, &data->rx_mgmt);
2517#else /* NEED_AP_MLME */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002518 hostapd_action_rx(hapd, &data->rx_mgmt);
Hai Shalom021b0b52019-04-10 11:17:58 -07002519#endif /* NEED_AP_MLME */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002520 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 case EVENT_RX_PROBE_REQ:
2522 if (data->rx_probe_req.sa == NULL ||
2523 data->rx_probe_req.ie == NULL)
2524 break;
2525 hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002526 data->rx_probe_req.da,
2527 data->rx_probe_req.bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002528 data->rx_probe_req.ie,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002529 data->rx_probe_req.ie_len,
2530 data->rx_probe_req.ssi_signal);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 break;
2532 case EVENT_NEW_STA:
2533 hostapd_event_new_sta(hapd, data->new_sta.addr);
2534 break;
2535 case EVENT_EAPOL_RX:
2536 hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
2537 data->eapol_rx.data,
Sunil8cd6f4d2022-06-28 18:40:46 +00002538 data->eapol_rx.data_len,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002539 data->eapol_rx.encrypted,
2540 data->eapol_rx.link_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 break;
2542 case EVENT_ASSOC:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002543 if (!data)
2544 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002545#ifdef CONFIG_IEEE80211BE
2546 if (data->assoc_info.assoc_link_id != -1) {
2547 hapd = hostapd_mld_get_link_bss(
2548 hapd, data->assoc_info.assoc_link_id);
2549 if (!hapd) {
2550 wpa_printf(MSG_ERROR,
2551 "MLD: Failed to get link BSS for EVENT_ASSOC");
2552 return;
2553 }
2554 }
2555#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002556 hostapd_notif_assoc(hapd, data->assoc_info.addr,
2557 data->assoc_info.req_ies,
2558 data->assoc_info.req_ies_len,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002559 data->assoc_info.resp_ies,
2560 data->assoc_info.resp_ies_len,
2561 data->assoc_info.link_addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002562 data->assoc_info.reassoc);
2563 break;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002564 case EVENT_PORT_AUTHORIZED:
2565 /* Port authorized event for an associated STA */
2566 sta = ap_get_sta(hapd, data->port_authorized.sta_addr);
2567 if (sta)
2568 ap_sta_set_authorized(hapd, sta, 1);
2569 else
2570 wpa_printf(MSG_DEBUG,
2571 "No STA info matching port authorized event found");
2572 break;
Hai Shalom81f62d82019-07-22 12:10:00 -07002573#ifdef CONFIG_OWE
2574 case EVENT_UPDATE_DH:
2575 if (!data)
2576 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002577#ifdef CONFIG_IEEE80211BE
2578 if (data->update_dh.assoc_link_id != -1) {
2579 hapd = hostapd_mld_get_link_bss(
2580 hapd, data->update_dh.assoc_link_id);
2581 if (!hapd) {
2582 wpa_printf(MSG_ERROR,
2583 "MLD: Failed to get link BSS for EVENT_UPDATE_DH assoc_link_id=%d",
2584 data->update_dh.assoc_link_id);
2585 return;
2586 }
2587 }
2588#endif /* CONFIG_IEEE80211BE */
Hai Shalom81f62d82019-07-22 12:10:00 -07002589 hostapd_notif_update_dh_ie(hapd, data->update_dh.peer,
2590 data->update_dh.ie,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002591 data->update_dh.ie_len,
2592 data->update_dh.link_addr);
Hai Shalom81f62d82019-07-22 12:10:00 -07002593 break;
2594#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 case EVENT_DISASSOC:
2596 if (data)
2597 hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
2598 break;
2599 case EVENT_DEAUTH:
2600 if (data)
2601 hostapd_notif_disassoc(hapd, data->deauth_info.addr);
2602 break;
2603 case EVENT_STATION_LOW_ACK:
2604 if (!data)
2605 break;
2606 hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
2607 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 case EVENT_AUTH:
2609 hostapd_notif_auth(hapd, &data->auth);
2610 break;
Hai Shalom81f62d82019-07-22 12:10:00 -07002611 case EVENT_CH_SWITCH_STARTED:
Dmitry Shmidt04949592012-07-19 12:16:46 -07002612 case EVENT_CH_SWITCH:
2613 if (!data)
2614 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002615#ifdef CONFIG_IEEE80211BE
2616 if (data->ch_switch.link_id != -1) {
2617 hapd = hostapd_mld_get_link_bss(
2618 hapd, data->ch_switch.link_id);
2619 if (!hapd) {
2620 wpa_printf(MSG_ERROR,
2621 "MLD: Failed to get link (ID %d) BSS for EVENT_CH_SWITCH/EVENT_CH_SWITCH_STARTED",
2622 data->ch_switch.link_id);
2623 break;
2624 }
2625 }
2626#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002627 hostapd_event_ch_switch(hapd, data->ch_switch.freq,
2628 data->ch_switch.ht_enabled,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002629 data->ch_switch.ch_offset,
2630 data->ch_switch.ch_width,
2631 data->ch_switch.cf1,
Hai Shalom81f62d82019-07-22 12:10:00 -07002632 data->ch_switch.cf2,
Sunil Ravi036cec52023-03-29 11:35:17 -07002633 data->ch_switch.punct_bitmap,
Hai Shalom81f62d82019-07-22 12:10:00 -07002634 event == EVENT_CH_SWITCH);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002635 break;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002636 case EVENT_CONNECT_FAILED_REASON:
2637 if (!data)
2638 break;
2639 hostapd_event_connect_failed_reason(
2640 hapd, data->connect_failed_reason.addr,
2641 data->connect_failed_reason.code);
2642 break;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002643 case EVENT_SURVEY:
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08002644 hostapd_event_get_survey(hapd->iface, &data->survey_results);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002645 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002646#ifdef NEED_AP_MLME
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002647 case EVENT_INTERFACE_UNAVAILABLE:
2648 hostapd_event_iface_unavailable(hapd);
2649 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002650 case EVENT_DFS_RADAR_DETECTED:
2651 if (!data)
2652 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002653 hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002654 hostapd_event_dfs_radar_detected(hapd, &data->dfs_event);
2655 break;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002656 case EVENT_DFS_PRE_CAC_EXPIRED:
2657 if (!data)
2658 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002659 hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002660 hostapd_event_dfs_pre_cac_expired(hapd, &data->dfs_event);
2661 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002662 case EVENT_DFS_CAC_FINISHED:
2663 if (!data)
2664 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002665 hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002666 hostapd_event_dfs_cac_finished(hapd, &data->dfs_event);
2667 break;
2668 case EVENT_DFS_CAC_ABORTED:
2669 if (!data)
2670 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002671 hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002672 hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event);
2673 break;
2674 case EVENT_DFS_NOP_FINISHED:
2675 if (!data)
2676 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002677 hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002678 hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
2679 break;
2680 case EVENT_CHANNEL_LIST_CHANGED:
2681 /* channel list changed (regulatory?), update channel list */
2682 /* TODO: check this. hostapd_get_hw_features() initializes
2683 * too much stuff. */
2684 /* hostapd_get_hw_features(hapd->iface); */
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002685 hostapd_channel_list_updated(
2686 hapd->iface, data->channel_list_changed.initiator);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002687 break;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002688 case EVENT_DFS_CAC_STARTED:
2689 if (!data)
2690 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002691 hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002692 hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
2693 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002694#endif /* NEED_AP_MLME */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002695 case EVENT_INTERFACE_ENABLED:
2696 wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002697 if (hapd->disabled && hapd->started) {
2698 hapd->disabled = 0;
2699 /*
2700 * Try to re-enable interface if the driver stopped it
2701 * when the interface got disabled.
2702 */
Hai Shalomce48b4a2018-09-05 11:41:35 -07002703 if (hapd->wpa_auth)
2704 wpa_auth_reconfig_group_keys(hapd->wpa_auth);
2705 else
2706 hostapd_reconfig_encryption(hapd);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002707 hapd->reenable_beacon = 1;
2708 ieee802_11_set_beacon(hapd);
Hai Shalom74f70d42019-02-11 14:42:39 -08002709#ifdef NEED_AP_MLME
2710 } else if (hapd->disabled && hapd->iface->cac_started) {
2711 wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
2712 hostapd_handle_dfs(hapd->iface);
2713#endif /* NEED_AP_MLME */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002714 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002715 break;
2716 case EVENT_INTERFACE_DISABLED:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002717 hostapd_free_stas(hapd);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002718 wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002719 hapd->disabled = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002720 break;
2721#ifdef CONFIG_ACS
2722 case EVENT_ACS_CHANNEL_SELECTED:
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002723 hostapd_acs_channel_selected(hapd,
2724 &data->acs_selected_channels);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002725 break;
2726#endif /* CONFIG_ACS */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002727 case EVENT_STATION_OPMODE_CHANGED:
2728 hostapd_event_sta_opmode_changed(hapd, data->sta_opmode.addr,
2729 data->sta_opmode.smps_mode,
2730 data->sta_opmode.chan_width,
2731 data->sta_opmode.rx_nss);
2732 break;
2733 case EVENT_WDS_STA_INTERFACE_STATUS:
2734 hostapd_event_wds_sta_interface_status(
2735 hapd, data->wds_sta_interface.istatus,
2736 data->wds_sta_interface.ifname,
2737 data->wds_sta_interface.sta_addr);
2738 break;
Sunil Ravia04bd252022-05-02 22:54:18 -07002739#ifdef CONFIG_IEEE80211AX
2740 case EVENT_BSS_COLOR_COLLISION:
2741 /* The BSS color is shared amongst all BBSs on a specific phy.
2742 * Therefore we always start the color change on the primary
2743 * BSS. */
Sunil Ravi7f769292024-07-23 22:21:32 +00002744 hapd = switch_link_hapd(hapd,
2745 data->bss_color_collision.link_id);
Sunil Ravia04bd252022-05-02 22:54:18 -07002746 wpa_printf(MSG_DEBUG, "BSS color collision on %s",
2747 hapd->conf->iface);
2748 hostapd_switch_color(hapd->iface->bss[0],
2749 data->bss_color_collision.bitmap);
2750 break;
2751 case EVENT_CCA_STARTED_NOTIFY:
Sunil Ravi7f769292024-07-23 22:21:32 +00002752 hapd = switch_link_hapd(hapd,
2753 data->bss_color_collision.link_id);
2754 wpa_printf(MSG_DEBUG, "CCA started on %s",
Sunil Ravia04bd252022-05-02 22:54:18 -07002755 hapd->conf->iface);
2756 break;
2757 case EVENT_CCA_ABORTED_NOTIFY:
Sunil Ravi7f769292024-07-23 22:21:32 +00002758 hapd = switch_link_hapd(hapd,
2759 data->bss_color_collision.link_id);
2760 wpa_printf(MSG_DEBUG, "CCA aborted on %s",
Sunil Ravia04bd252022-05-02 22:54:18 -07002761 hapd->conf->iface);
Sunil Ravi7f769292024-07-23 22:21:32 +00002762 hostapd_event_color_change(hapd, false);
Sunil Ravia04bd252022-05-02 22:54:18 -07002763 break;
2764 case EVENT_CCA_NOTIFY:
Sunil Ravi7f769292024-07-23 22:21:32 +00002765 hapd = switch_link_hapd(hapd,
2766 data->bss_color_collision.link_id);
2767 wpa_printf(MSG_DEBUG, "CCA finished on %s",
Sunil Ravia04bd252022-05-02 22:54:18 -07002768 hapd->conf->iface);
Sunil Ravi7f769292024-07-23 22:21:32 +00002769 hostapd_event_color_change(hapd, true);
Sunil Ravia04bd252022-05-02 22:54:18 -07002770 break;
2771#endif /* CONFIG_IEEE80211AX */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 default:
2773 wpa_printf(MSG_DEBUG, "Unknown event %d", event);
2774 break;
2775 }
2776}
2777
Dmitry Shmidte4663042016-04-04 10:07:49 -07002778
2779void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
2780 union wpa_event_data *data)
2781{
2782 struct hapd_interfaces *interfaces = ctx;
2783 struct hostapd_data *hapd;
2784
2785 if (event != EVENT_INTERFACE_STATUS)
2786 return;
2787
2788 hapd = hostapd_get_iface(interfaces, data->interface_status.ifname);
2789 if (hapd && hapd->driver && hapd->driver->get_ifindex &&
2790 hapd->drv_priv) {
2791 unsigned int ifindex;
2792
2793 ifindex = hapd->driver->get_ifindex(hapd->drv_priv);
2794 if (ifindex != data->interface_status.ifindex) {
2795 wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
2796 "interface status ifindex %d mismatch (%d)",
2797 ifindex, data->interface_status.ifindex);
2798 return;
2799 }
2800 }
2801 if (hapd)
2802 wpa_supplicant_event(hapd, event, data);
2803}
2804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805#endif /* HOSTAPD */