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