drv_callbacks.c revision 337817
1205821Sedwin/*
213840Swosch * hostapd / Callback functions for driver wrappers
313840Swosch * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
413840Swosch *
513840Swosch * This software may be distributed under the terms of the BSD license.
613840Swosch * See README for more details.
713840Swosch */
813840Swosch
913840Swosch#include "utils/includes.h"
1013840Swosch
1113840Swosch#include "utils/common.h"
1213840Swosch#include "utils/eloop.h"
1313840Swosch#include "radius/radius.h"
1413840Swosch#include "drivers/driver.h"
1513840Swosch#include "common/ieee802_11_defs.h"
1613840Swosch#include "common/ieee802_11_common.h"
1713840Swosch#include "common/wpa_ctrl.h"
1813840Swosch#include "crypto/random.h"
1913840Swosch#include "p2p/p2p.h"
2013840Swosch#include "wps/wps.h"
2113840Swosch#include "fst/fst.h"
2213840Swosch#include "wnm_ap.h"
2313840Swosch#include "hostapd.h"
2413840Swosch#include "ieee802_11.h"
2513840Swosch#include "ieee802_11_auth.h"
2613840Swosch#include "sta_info.h"
2713840Swosch#include "accounting.h"
2813840Swosch#include "tkip_countermeasures.h"
2913840Swosch#include "ieee802_1x.h"
3013840Swosch#include "wpa_auth.h"
3115714Sache#include "wps_hostapd.h"
3213840Swosch#include "ap_drv_ops.h"
3313840Swosch#include "ap_config.h"
3487235Smarkm#include "hw_features.h"
3513840Swosch#include "dfs.h"
3687628Sdwmalone#include "beacon.h"
3713840Swosch#include "mbo_ap.h"
3887628Sdwmalone
3987235Smarkm
4087628Sdwmaloneint hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
4113840Swosch			const u8 *req_ies, size_t req_ies_len, int reassoc)
4287628Sdwmalone{
4387628Sdwmalone	struct sta_info *sta;
4487628Sdwmalone	int new_assoc, res;
4513840Swosch	struct ieee802_11_elems elems;
4687235Smarkm	const u8 *ie;
4787235Smarkm	size_t ielen;
4813840Swosch#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
4913840Swosch	u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
5013840Swosch	u8 *p = buf;
5174583Sache#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
5215714Sache	u16 reason = WLAN_REASON_UNSPECIFIED;
5387235Smarkm	u16 status = WLAN_STATUS_SUCCESS;
54285291Sbapt	const u8 *p2p_dev_addr = NULL;
55285291Sbapt
5687235Smarkm	if (addr == NULL) {
5787235Smarkm		/*
5813840Swosch		 * This could potentially happen with unexpected event from the
59285291Sbapt		 * driver wrapper. This was seen at least in one case where the
6087235Smarkm		 * driver ended up being set to station mode while hostapd was
6113840Swosch		 * running, so better make sure we stop processing such an
6213840Swosch		 * event here.
6313840Swosch		 */
6413840Swosch		wpa_printf(MSG_DEBUG,
65285291Sbapt			   "hostapd_notif_assoc: Skip event with no address");
66285291Sbapt		return -1;
67285291Sbapt	}
68285291Sbapt	random_add_randomness(addr, ETH_ALEN);
69285291Sbapt
70285291Sbapt	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
71181322Sedwin		       HOSTAPD_LEVEL_INFO, "associated");
72241737Sed
73241737Sed	ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
7413840Swosch	if (elems.wps_ie) {
75241737Sed		ie = elems.wps_ie - 2;
76181322Sedwin		ielen = elems.wps_ie_len + 2;
77205821Sedwin		wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
78205821Sedwin	} else if (elems.rsn_ie) {
7915720Sache		ie = elems.rsn_ie - 2;
80285291Sbapt		ielen = elems.rsn_ie_len + 2;
81285291Sbapt		wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
82285291Sbapt	} else if (elems.wpa_ie) {
83285291Sbapt		ie = elems.wpa_ie - 2;
84285291Sbapt		ielen = elems.wpa_ie_len + 2;
85285291Sbapt		wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
86285291Sbapt#ifdef CONFIG_HS20
87285291Sbapt	} else if (elems.osen) {
88285291Sbapt		ie = elems.osen - 2;
89285291Sbapt		ielen = elems.osen_len + 2;
90285291Sbapt		wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq");
91285291Sbapt#endif /* CONFIG_HS20 */
92285291Sbapt	} else {
93285291Sbapt		ie = NULL;
94285291Sbapt		ielen = 0;
95285291Sbapt		wpa_printf(MSG_DEBUG,
96285291Sbapt			   "STA did not include WPS/RSN/WPA IE in (Re)AssocReq");
97285291Sbapt	}
98285291Sbapt
99285291Sbapt	sta = ap_get_sta(hapd, addr);
100285291Sbapt	if (sta) {
101285291Sbapt		ap_sta_no_session_timeout(hapd, sta);
102285291Sbapt		accounting_sta_stop(hapd, sta);
103285291Sbapt
104285291Sbapt		/*
105285291Sbapt		 * Make sure that the previously registered inactivity timer
106285291Sbapt		 * will not remove the STA immediately.
107285291Sbapt		 */
108285291Sbapt		sta->timeout_next = STA_NULLFUNC;
109285291Sbapt	} else {
110285291Sbapt		sta = ap_sta_add(hapd, addr);
111285291Sbapt		if (sta == NULL) {
112285291Sbapt			hostapd_drv_sta_disassoc(hapd, addr,
113285291Sbapt						 WLAN_REASON_DISASSOC_AP_BUSY);
114285291Sbapt			return -1;
115285291Sbapt		}
116285291Sbapt	}
117285291Sbapt	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
118285291Sbapt
119285291Sbapt	/*
120285291Sbapt	 * ACL configurations to the drivers (implementing AP SME and ACL
121285291Sbapt	 * offload) without hostapd's knowledge, can result in a disconnection
122285291Sbapt	 * though the driver accepts the connection. Skip the hostapd check for
123285291Sbapt	 * ACL if the driver supports ACL offload to avoid potentially
124285291Sbapt	 * conflicting ACL rules.
125285291Sbapt	 */
126285291Sbapt	if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
127285291Sbapt	    hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
128285291Sbapt		wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
129285291Sbapt			   MAC2STR(addr));
130285291Sbapt		reason = WLAN_REASON_UNSPECIFIED;
131285291Sbapt		goto fail;
132285291Sbapt	}
133285291Sbapt
134285291Sbapt#ifdef CONFIG_P2P
135285291Sbapt	if (elems.p2p) {
136285291Sbapt		wpabuf_free(sta->p2p_ie);
137285291Sbapt		sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
138285291Sbapt							  P2P_IE_VENDOR_TYPE);
139285291Sbapt		if (sta->p2p_ie)
140285291Sbapt			p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
141285291Sbapt	}
142285291Sbapt#endif /* CONFIG_P2P */
143285291Sbapt
144285291Sbapt#ifdef CONFIG_IEEE80211N
145285291Sbapt#ifdef NEED_AP_MLME
146285291Sbapt	if (elems.ht_capabilities &&
147285291Sbapt	    (hapd->iface->conf->ht_capab &
148285291Sbapt	     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
149285291Sbapt		struct ieee80211_ht_capabilities *ht_cap =
150285291Sbapt			(struct ieee80211_ht_capabilities *)
151285291Sbapt			elems.ht_capabilities;
152285291Sbapt
153285291Sbapt		if (le_to_host16(ht_cap->ht_capabilities_info) &
154285291Sbapt		    HT_CAP_INFO_40MHZ_INTOLERANT)
155285291Sbapt			ht40_intolerant_add(hapd->iface, sta);
156285291Sbapt	}
157285291Sbapt#endif /* NEED_AP_MLME */
158285291Sbapt#endif /* CONFIG_IEEE80211N */
159285291Sbapt
160285291Sbapt#ifdef CONFIG_INTERWORKING
161285291Sbapt	if (elems.ext_capab && elems.ext_capab_len > 4) {
162285291Sbapt		if (elems.ext_capab[4] & 0x01)
163285291Sbapt			sta->qos_map_enabled = 1;
164285291Sbapt	}
165285291Sbapt#endif /* CONFIG_INTERWORKING */
166285291Sbapt
167285291Sbapt#ifdef CONFIG_HS20
168285291Sbapt	wpabuf_free(sta->hs20_ie);
169285291Sbapt	if (elems.hs20 && elems.hs20_len > 4) {
170285291Sbapt		sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
171285291Sbapt						 elems.hs20_len - 4);
172285291Sbapt	} else
173285291Sbapt		sta->hs20_ie = NULL;
174285291Sbapt#endif /* CONFIG_HS20 */
175285291Sbapt
176285291Sbapt#ifdef CONFIG_FST
177285291Sbapt	wpabuf_free(sta->mb_ies);
178285291Sbapt	if (hapd->iface->fst)
179285291Sbapt		sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
180285291Sbapt	else
181285291Sbapt		sta->mb_ies = NULL;
182285291Sbapt#endif /* CONFIG_FST */
183285291Sbapt
184285291Sbapt	mbo_ap_check_sta_assoc(hapd, sta, &elems);
185285291Sbapt
186285291Sbapt	ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
187285291Sbapt				    elems.supp_op_classes_len);
188285291Sbapt
189285291Sbapt	if (hapd->conf->wpa) {
190285291Sbapt		if (ie == NULL || ielen == 0) {
191285291Sbapt#ifdef CONFIG_WPS
192285291Sbapt			if (hapd->conf->wps_state) {
193285291Sbapt				wpa_printf(MSG_DEBUG,
194285291Sbapt					   "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use");
195285291Sbapt				sta->flags |= WLAN_STA_MAYBE_WPS;
196285291Sbapt				goto skip_wpa_check;
197285291Sbapt			}
198285291Sbapt#endif /* CONFIG_WPS */
199285291Sbapt
200285291Sbapt			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
201285291Sbapt			return -1;
202285291Sbapt		}
203285291Sbapt#ifdef CONFIG_WPS
204285291Sbapt		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
205285291Sbapt		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
206285291Sbapt			struct wpabuf *wps;
207285291Sbapt
208285291Sbapt			sta->flags |= WLAN_STA_WPS;
209285291Sbapt			wps = ieee802_11_vendor_ie_concat(ie, ielen,
210285291Sbapt							  WPS_IE_VENDOR_TYPE);
211285291Sbapt			if (wps) {
212285291Sbapt				if (wps_is_20(wps)) {
213285291Sbapt					wpa_printf(MSG_DEBUG,
214285291Sbapt						   "WPS: STA supports WPS 2.0");
215285291Sbapt					sta->flags |= WLAN_STA_WPS2;
216285291Sbapt				}
217285291Sbapt				wpabuf_free(wps);
218285291Sbapt			}
219285291Sbapt			goto skip_wpa_check;
220285291Sbapt		}
221205821Sedwin#endif /* CONFIG_WPS */
222205821Sedwin
223205821Sedwin		if (sta->wpa_sm == NULL)
224205821Sedwin			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
225205821Sedwin							sta->addr,
226205821Sedwin							p2p_dev_addr);
227205821Sedwin		if (sta->wpa_sm == NULL) {
228205821Sedwin			wpa_printf(MSG_ERROR,
229205821Sedwin				   "Failed to initialize WPA state machine");
230285291Sbapt			return -1;
231285291Sbapt		}
23213840Swosch		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
233285291Sbapt					  ie, ielen,
234285291Sbapt					  elems.mdie, elems.mdie_len);
235285291Sbapt		if (res != WPA_IE_OK) {
236285291Sbapt			wpa_printf(MSG_DEBUG,
237285291Sbapt				   "WPA/RSN information element rejected? (res %u)",
238285291Sbapt				   res);
239285291Sbapt			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
240285291Sbapt			if (res == WPA_INVALID_GROUP) {
241205821Sedwin				reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
242205821Sedwin				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
243205821Sedwin			} else if (res == WPA_INVALID_PAIRWISE) {
244285291Sbapt				reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
245285291Sbapt				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
246285291Sbapt			} else if (res == WPA_INVALID_AKMP) {
247285291Sbapt				reason = WLAN_REASON_AKMP_NOT_VALID;
248205821Sedwin				status = WLAN_STATUS_AKMP_NOT_VALID;
24913840Swosch			}
250205821Sedwin#ifdef CONFIG_IEEE80211W
251205821Sedwin			else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
252205821Sedwin				reason = WLAN_REASON_INVALID_IE;
253205821Sedwin				status = WLAN_STATUS_INVALID_IE;
254205821Sedwin			} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
255205821Sedwin				reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
256285291Sbapt				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
257285291Sbapt			}
258285291Sbapt#endif /* CONFIG_IEEE80211W */
259285291Sbapt			else {
260285291Sbapt				reason = WLAN_REASON_INVALID_IE;
261255715Sdb				status = WLAN_STATUS_INVALID_IE;
262285291Sbapt			}
263285291Sbapt			goto fail;
264285291Sbapt		}
265285291Sbapt#ifdef CONFIG_IEEE80211W
266285291Sbapt		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
267285291Sbapt		    sta->sa_query_count > 0)
268285291Sbapt			ap_check_sa_query_timeout(hapd, sta);
269285291Sbapt		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
270285291Sbapt		    (sta->auth_alg != WLAN_AUTH_FT)) {
271285291Sbapt			/*
272285291Sbapt			 * STA has already been associated with MFP and SA
273285291Sbapt			 * Query timeout has not been reached. Reject the
274285291Sbapt			 * association attempt temporarily and start SA Query,
275285291Sbapt			 * if one is not pending.
276285291Sbapt			 */
277285291Sbapt
278285291Sbapt			if (sta->sa_query_count == 0)
279285291Sbapt				ap_sta_start_sa_query(hapd, sta);
280285291Sbapt
281285291Sbapt			status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
28215714Sache
28315714Sache			p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
28415714Sache
28515714Sache			hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
28613840Swosch					  p - buf);
28713840Swosch			return 0;
288205821Sedwin		}
289205821Sedwin
29015714Sache		if (wpa_auth_uses_mfp(sta->wpa_sm))
291181322Sedwin			sta->flags |= WLAN_STA_MFP;
29274583Sache		else
29315714Sache			sta->flags &= ~WLAN_STA_MFP;
29415714Sache#endif /* CONFIG_IEEE80211W */
29515714Sache
296205821Sedwin#ifdef CONFIG_IEEE80211R
297205821Sedwin		if (sta->auth_alg == WLAN_AUTH_FT) {
298205821Sedwin			status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
299205821Sedwin							 req_ies_len);
300205821Sedwin			if (status != WLAN_STATUS_SUCCESS) {
301205821Sedwin				if (status == WLAN_STATUS_INVALID_PMKID)
302205821Sedwin					reason = WLAN_REASON_INVALID_IE;
303205821Sedwin				if (status == WLAN_STATUS_INVALID_MDIE)
304205821Sedwin					reason = WLAN_REASON_INVALID_IE;
305205821Sedwin				if (status == WLAN_STATUS_INVALID_FTIE)
306205821Sedwin					reason = WLAN_REASON_INVALID_IE;
30715720Sache				goto fail;
30815720Sache			}
30915723Sache		}
310181322Sedwin#endif /* CONFIG_IEEE80211R */
311205821Sedwin	} else if (hapd->conf->wps_state) {
312205821Sedwin#ifdef CONFIG_WPS
313181322Sedwin		struct wpabuf *wps;
314205821Sedwin
315205821Sedwin		if (req_ies)
316205821Sedwin			wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
317205821Sedwin							  WPS_IE_VENDOR_TYPE);
318170447Sgrog		else
319170447Sgrog			wps = NULL;
320205821Sedwin#ifdef CONFIG_WPS_STRICT
321207701Sache		if (wps && wps_validate_assoc_req(wps) < 0) {
322207701Sache			reason = WLAN_REASON_INVALID_IE;
323170447Sgrog			status = WLAN_STATUS_INVALID_IE;
324205821Sedwin			wpabuf_free(wps);
325205821Sedwin			goto fail;
326205821Sedwin		}
327170447Sgrog#endif /* CONFIG_WPS_STRICT */
328205821Sedwin		if (wps) {
329207703Sache			sta->flags |= WLAN_STA_WPS;
330205821Sedwin			if (wps_is_20(wps)) {
331205821Sedwin				wpa_printf(MSG_DEBUG,
332205821Sedwin					   "WPS: STA supports WPS 2.0");
333205821Sedwin				sta->flags |= WLAN_STA_WPS2;
334205821Sedwin			}
335205821Sedwin		} else
336205821Sedwin			sta->flags |= WLAN_STA_MAYBE_WPS;
337205821Sedwin		wpabuf_free(wps);
338205821Sedwin#endif /* CONFIG_WPS */
339205821Sedwin#ifdef CONFIG_HS20
340227370Sgrog	} else if (hapd->conf->osen) {
341227370Sgrog		if (elems.osen == NULL) {
342205821Sedwin			hostapd_logger(
343170447Sgrog				hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
344205821Sedwin				HOSTAPD_LEVEL_INFO,
345170447Sgrog				"No HS 2.0 OSEN element in association request");
346170447Sgrog			return WLAN_STATUS_INVALID_IE;
347205821Sedwin		}
348205821Sedwin
349205821Sedwin		wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
35013840Swosch		if (sta->wpa_sm == NULL)
351205821Sedwin			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
352205821Sedwin							sta->addr, NULL);
353170447Sgrog		if (sta->wpa_sm == NULL) {
354205821Sedwin			wpa_printf(MSG_WARNING,
355205821Sedwin				   "Failed to initialize WPA state machine");
356205821Sedwin			return WLAN_STATUS_UNSPECIFIED_FAILURE;
357205821Sedwin		}
358205821Sedwin		if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
359205821Sedwin				      elems.osen - 2, elems.osen_len + 2) < 0)
360205821Sedwin			return WLAN_STATUS_INVALID_IE;
361205821Sedwin#endif /* CONFIG_HS20 */
362205821Sedwin	}
363205821Sedwin
364205821Sedwin#ifdef CONFIG_MBO
365181322Sedwin	if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
36613840Swosch	    elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
36713840Swosch	    hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
368285291Sbapt		wpa_printf(MSG_INFO,
369285291Sbapt			   "MBO: Reject WPA2 association without PMF");
370285291Sbapt		return WLAN_STATUS_UNSPECIFIED_FAILURE;
371285291Sbapt	}
372285291Sbapt#endif /* CONFIG_MBO */
373285291Sbapt
374285291Sbapt#ifdef CONFIG_WPS
375285291Sbaptskip_wpa_check:
376285291Sbapt#endif /* CONFIG_WPS */
377285291Sbapt
378285291Sbapt#ifdef CONFIG_IEEE80211R
379285291Sbapt	p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
380285291Sbapt					sta->auth_alg, req_ies, req_ies_len);
381285291Sbapt
382285291Sbapt	hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
383285291Sbapt
384285291Sbapt	if (sta->auth_alg == WLAN_AUTH_FT)
385285291Sbapt		ap_sta_set_authorized(hapd, sta, 1);
386285291Sbapt#else /* CONFIG_IEEE80211R */
387285291Sbapt	/* Keep compiler silent about unused variables */
388285291Sbapt	if (status) {
389285291Sbapt	}
390285291Sbapt#endif /* CONFIG_IEEE80211R */
391285291Sbapt
392285291Sbapt	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
393285291Sbapt	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
394285291Sbapt	sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
395285291Sbapt
396255715Sdb	hostapd_set_sta_flags(hapd, sta);
397255715Sdb
39813840Swosch	if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
39913840Swosch		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
40013840Swosch	else
401255715Sdb		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
40213840Swosch
40313840Swosch	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
404255715Sdb
40513840Swosch	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
406255715Sdb
407255715Sdb#ifdef CONFIG_P2P
40813840Swosch	if (req_ies) {
409181322Sedwin		p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
410181322Sedwin				      req_ies, req_ies_len);
411181322Sedwin	}
412181322Sedwin#endif /* CONFIG_P2P */
413255715Sdb
414181322Sedwin	return 0;
41513840Swosch
416285291Sbaptfail:
41713840Swosch#ifdef CONFIG_IEEE80211R
41813840Swosch	hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
419255715Sdb#endif /* CONFIG_IEEE80211R */
420255715Sdb	hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
42113840Swosch	ap_free_sta(hapd, sta);
422255715Sdb	return -1;
423255715Sdb}
424255715Sdb
425255715Sdb
426255715Sdbvoid hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
42713840Swosch{
42813840Swosch	struct sta_info *sta;
42913840Swosch
43013840Swosch	if (addr == NULL) {
43113840Swosch		/*
432255715Sdb		 * This could potentially happen with unexpected event from the
43313840Swosch		 * driver wrapper. This was seen at least in one case where the
43413840Swosch		 * driver ended up reporting a station mode event while hostapd
43513840Swosch		 * was running, so better make sure we stop processing such an
43613840Swosch		 * event here.
43713840Swosch		 */
43813840Swosch		wpa_printf(MSG_DEBUG,
439169343Sdwmalone			   "hostapd_notif_disassoc: Skip event with no address");
44013840Swosch		return;
44122473Smpp	}
44213840Swosch
44313840Swosch	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
44413840Swosch		       HOSTAPD_LEVEL_INFO, "disassociated");
44513840Swosch
44613840Swosch	sta = ap_get_sta(hapd, addr);
44713840Swosch	if (sta == NULL) {
44813840Swosch		wpa_printf(MSG_DEBUG,
449200628Srse			   "Disassociation notification for unknown STA "
45013840Swosch			   MACSTR, MAC2STR(addr));
45113840Swosch		return;
45213840Swosch	}
45313840Swosch
45440302Sdes	ap_sta_set_authorized(hapd, sta, 0);
45513840Swosch	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
45613840Swosch	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
45713840Swosch	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
45813840Swosch	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
45913840Swosch	ap_free_sta(hapd, sta);
46013840Swosch}
46113840Swosch
46213840Swosch
46313840Swoschvoid hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
46413840Swosch{
46513840Swosch	struct sta_info *sta = ap_get_sta(hapd, addr);
46622473Smpp
46722473Smpp	if (!sta || !hapd->conf->disassoc_low_ack)
46826839Scharnier		return;
46922473Smpp
47022473Smpp	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
47122473Smpp		       HOSTAPD_LEVEL_INFO,
47226839Scharnier		       "disconnected due to excessive missing ACKs");
47322473Smpp	hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
47422473Smpp	if (sta)
47522473Smpp		ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
47626839Scharnier}
47722473Smpp
47822473Smpp
47913840Swoschvoid hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
48079452Sbrian			     int offset, int width, int cf1, int cf2)
48126839Scharnier{
48213840Swosch#ifdef NEED_AP_MLME
48313840Swosch	int channel, chwidth, is_dfs;
48413840Swosch	u8 seg0_idx = 0, seg1_idx = 0;
48513840Swosch
48613840Swosch	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
487205821Sedwin		       HOSTAPD_LEVEL_INFO,
488205821Sedwin		       "driver had channel switch: freq=%d, ht=%d, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
489205821Sedwin		       freq, ht, offset, width, channel_width_to_string(width),
490205821Sedwin		       cf1, cf2);
491222755Sjh
492205821Sedwin	hapd->iface->freq = freq;
493205821Sedwin
494205821Sedwin	channel = hostapd_hw_get_channel(hapd, freq);
49513840Swosch	if (!channel) {
49613840Swosch		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
49713840Swosch			       HOSTAPD_LEVEL_WARNING,
49813840Swosch			       "driver switched to bad channel!");
49913840Swosch		return;
50013840Swosch	}
50113840Swosch
502	switch (width) {
503	case CHAN_WIDTH_80:
504		chwidth = VHT_CHANWIDTH_80MHZ;
505		break;
506	case CHAN_WIDTH_80P80:
507		chwidth = VHT_CHANWIDTH_80P80MHZ;
508		break;
509	case CHAN_WIDTH_160:
510		chwidth = VHT_CHANWIDTH_160MHZ;
511		break;
512	case CHAN_WIDTH_20_NOHT:
513	case CHAN_WIDTH_20:
514	case CHAN_WIDTH_40:
515	default:
516		chwidth = VHT_CHANWIDTH_USE_HT;
517		break;
518	}
519
520	switch (hapd->iface->current_mode->mode) {
521	case HOSTAPD_MODE_IEEE80211A:
522		if (cf1 > 5000)
523			seg0_idx = (cf1 - 5000) / 5;
524		if (cf2 > 5000)
525			seg1_idx = (cf2 - 5000) / 5;
526		break;
527	default:
528		ieee80211_freq_to_chan(cf1, &seg0_idx);
529		ieee80211_freq_to_chan(cf2, &seg1_idx);
530		break;
531	}
532
533	hapd->iconf->channel = channel;
534	hapd->iconf->ieee80211n = ht;
535	if (!ht)
536		hapd->iconf->ieee80211ac = 0;
537	hapd->iconf->secondary_channel = offset;
538	hapd->iconf->vht_oper_chwidth = chwidth;
539	hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
540	hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
541
542	is_dfs = ieee80211_is_dfs(freq);
543
544	if (hapd->csa_in_progress &&
545	    freq == hapd->cs_freq_params.freq) {
546		hostapd_cleanup_cs_params(hapd);
547		ieee802_11_set_beacon(hapd);
548
549		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
550			"freq=%d dfs=%d", freq, is_dfs);
551	} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
552		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
553			"freq=%d dfs=%d", freq, is_dfs);
554	}
555#endif /* NEED_AP_MLME */
556}
557
558
559void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
560					 const u8 *addr, int reason_code)
561{
562	switch (reason_code) {
563	case MAX_CLIENT_REACHED:
564		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR,
565			MAC2STR(addr));
566		break;
567	case BLOCKED_CLIENT:
568		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR,
569			MAC2STR(addr));
570		break;
571	}
572}
573
574
575#ifdef CONFIG_ACS
576void hostapd_acs_channel_selected(struct hostapd_data *hapd,
577				  struct acs_selected_channels *acs_res)
578{
579	int ret, i;
580	int err = 0;
581
582	if (hapd->iconf->channel) {
583		wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
584			   hapd->iconf->channel);
585		return;
586	}
587
588	if (!hapd->iface->current_mode) {
589		for (i = 0; i < hapd->iface->num_hw_features; i++) {
590			struct hostapd_hw_modes *mode =
591				&hapd->iface->hw_features[i];
592
593			if (mode->mode == acs_res->hw_mode) {
594				hapd->iface->current_mode = mode;
595				break;
596			}
597		}
598		if (!hapd->iface->current_mode) {
599			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
600				       HOSTAPD_LEVEL_WARNING,
601				       "driver selected to bad hw_mode");
602			err = 1;
603			goto out;
604		}
605	}
606
607	hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
608
609	if (!acs_res->pri_channel) {
610		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
611			       HOSTAPD_LEVEL_WARNING,
612			       "driver switched to bad channel");
613		err = 1;
614		goto out;
615	}
616
617	hapd->iconf->channel = acs_res->pri_channel;
618	hapd->iconf->acs = 1;
619
620	if (acs_res->sec_channel == 0)
621		hapd->iconf->secondary_channel = 0;
622	else if (acs_res->sec_channel < acs_res->pri_channel)
623		hapd->iconf->secondary_channel = -1;
624	else if (acs_res->sec_channel > acs_res->pri_channel)
625		hapd->iconf->secondary_channel = 1;
626	else {
627		wpa_printf(MSG_ERROR, "Invalid secondary channel!");
628		err = 1;
629		goto out;
630	}
631
632	if (hapd->iface->conf->ieee80211ac) {
633		/* set defaults for backwards compatibility */
634		hapd->iconf->vht_oper_centr_freq_seg1_idx = 0;
635		hapd->iconf->vht_oper_centr_freq_seg0_idx = 0;
636		hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
637		if (acs_res->ch_width == 80) {
638			hapd->iconf->vht_oper_centr_freq_seg0_idx =
639				acs_res->vht_seg0_center_ch;
640			hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
641		} else if (acs_res->ch_width == 160) {
642			if (acs_res->vht_seg1_center_ch == 0) {
643				hapd->iconf->vht_oper_centr_freq_seg0_idx =
644					acs_res->vht_seg0_center_ch;
645				hapd->iconf->vht_oper_chwidth =
646					VHT_CHANWIDTH_160MHZ;
647			} else {
648				hapd->iconf->vht_oper_centr_freq_seg0_idx =
649					acs_res->vht_seg0_center_ch;
650				hapd->iconf->vht_oper_centr_freq_seg1_idx =
651					acs_res->vht_seg1_center_ch;
652				hapd->iconf->vht_oper_chwidth =
653					VHT_CHANWIDTH_80P80MHZ;
654			}
655		}
656	}
657
658out:
659	ret = hostapd_acs_completed(hapd->iface, err);
660	if (ret) {
661		wpa_printf(MSG_ERROR,
662			   "ACS: Possibly channel configuration is invalid");
663	}
664}
665#endif /* CONFIG_ACS */
666
667
668int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
669			 const u8 *bssid, const u8 *ie, size_t ie_len,
670			 int ssi_signal)
671{
672	size_t i;
673	int ret = 0;
674
675	if (sa == NULL || ie == NULL)
676		return -1;
677
678	random_add_randomness(sa, ETH_ALEN);
679	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
680		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
681					    sa, da, bssid, ie, ie_len,
682					    ssi_signal) > 0) {
683			ret = 1;
684			break;
685		}
686	}
687	return ret;
688}
689
690
691#ifdef HOSTAPD
692
693#ifdef CONFIG_IEEE80211R
694static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
695					  const u8 *bssid,
696					  u16 auth_transaction, u16 status,
697					  const u8 *ies, size_t ies_len)
698{
699	struct hostapd_data *hapd = ctx;
700	struct sta_info *sta;
701
702	sta = ap_get_sta(hapd, dst);
703	if (sta == NULL)
704		return;
705
706	hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
707		       HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
708	sta->flags |= WLAN_STA_AUTH;
709
710	hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len);
711}
712#endif /* CONFIG_IEEE80211R */
713
714
715static void hostapd_notif_auth(struct hostapd_data *hapd,
716			       struct auth_info *rx_auth)
717{
718	struct sta_info *sta;
719	u16 status = WLAN_STATUS_SUCCESS;
720	u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
721	size_t resp_ies_len = 0;
722
723	sta = ap_get_sta(hapd, rx_auth->peer);
724	if (!sta) {
725		sta = ap_sta_add(hapd, rx_auth->peer);
726		if (sta == NULL) {
727			status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
728			goto fail;
729		}
730	}
731	sta->flags &= ~WLAN_STA_PREAUTH;
732	ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
733#ifdef CONFIG_IEEE80211R
734	if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) {
735		sta->auth_alg = WLAN_AUTH_FT;
736		if (sta->wpa_sm == NULL)
737			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
738							sta->addr, NULL);
739		if (sta->wpa_sm == NULL) {
740			wpa_printf(MSG_DEBUG,
741				   "FT: Failed to initialize WPA state machine");
742			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
743			goto fail;
744		}
745		wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
746				    rx_auth->auth_transaction, rx_auth->ies,
747				    rx_auth->ies_len,
748				    hostapd_notify_auth_ft_finish, hapd);
749		return;
750	}
751#endif /* CONFIG_IEEE80211R */
752fail:
753	hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
754			 status, resp_ies, resp_ies_len);
755}
756
757
758static void hostapd_action_rx(struct hostapd_data *hapd,
759			      struct rx_mgmt *drv_mgmt)
760{
761	struct ieee80211_mgmt *mgmt;
762	struct sta_info *sta;
763	size_t plen __maybe_unused;
764	u16 fc;
765
766	if (drv_mgmt->frame_len < 24 + 1)
767		return;
768
769	plen = drv_mgmt->frame_len - 24 - 1;
770
771	mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
772	fc = le_to_host16(mgmt->frame_control);
773	if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
774		return; /* handled by the driver */
775
776	wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
777		   mgmt->u.action.category, (int) plen);
778
779	sta = ap_get_sta(hapd, mgmt->sa);
780	if (sta == NULL) {
781		wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
782		return;
783	}
784#ifdef CONFIG_IEEE80211R
785	if (mgmt->u.action.category == WLAN_ACTION_FT) {
786		const u8 *payload = drv_mgmt->frame + 24 + 1;
787
788		wpa_ft_action_rx(sta->wpa_sm, payload, plen);
789	}
790#endif /* CONFIG_IEEE80211R */
791#ifdef CONFIG_IEEE80211W
792	if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) {
793		ieee802_11_sa_query_action(
794			hapd, mgmt->sa,
795			mgmt->u.action.u.sa_query_resp.action,
796			mgmt->u.action.u.sa_query_resp.trans_id);
797	}
798#endif /* CONFIG_IEEE80211W */
799#ifdef CONFIG_WNM
800	if (mgmt->u.action.category == WLAN_ACTION_WNM) {
801		ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
802	}
803#endif /* CONFIG_WNM */
804#ifdef CONFIG_FST
805	if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) {
806		fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len);
807		return;
808	}
809#endif /* CONFIG_FST */
810
811}
812
813
814#ifdef NEED_AP_MLME
815
816#define HAPD_BROADCAST ((struct hostapd_data *) -1)
817
818static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
819					    const u8 *bssid)
820{
821	size_t i;
822
823	if (bssid == NULL)
824		return NULL;
825	if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
826	    bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
827		return HAPD_BROADCAST;
828
829	for (i = 0; i < iface->num_bss; i++) {
830		if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
831			return iface->bss[i];
832	}
833
834	return NULL;
835}
836
837
838static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
839					const u8 *bssid, const u8 *addr,
840					int wds)
841{
842	hapd = get_hapd_bssid(hapd->iface, bssid);
843	if (hapd == NULL || hapd == HAPD_BROADCAST)
844		return;
845
846	ieee802_11_rx_from_unknown(hapd, addr, wds);
847}
848
849
850static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
851{
852	struct hostapd_iface *iface = hapd->iface;
853	const struct ieee80211_hdr *hdr;
854	const u8 *bssid;
855	struct hostapd_frame_info fi;
856	int ret;
857
858#ifdef CONFIG_TESTING_OPTIONS
859	if (hapd->ext_mgmt_frame_handling) {
860		size_t hex_len = 2 * rx_mgmt->frame_len + 1;
861		char *hex = os_malloc(hex_len);
862
863		if (hex) {
864			wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame,
865					 rx_mgmt->frame_len);
866			wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex);
867			os_free(hex);
868		}
869		return 1;
870	}
871#endif /* CONFIG_TESTING_OPTIONS */
872
873	hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
874	bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
875	if (bssid == NULL)
876		return 0;
877
878	hapd = get_hapd_bssid(iface, bssid);
879	if (hapd == NULL) {
880		u16 fc = le_to_host16(hdr->frame_control);
881
882		/*
883		 * Drop frames to unknown BSSIDs except for Beacon frames which
884		 * could be used to update neighbor information.
885		 */
886		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
887		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
888			hapd = iface->bss[0];
889		else
890			return 0;
891	}
892
893	os_memset(&fi, 0, sizeof(fi));
894	fi.datarate = rx_mgmt->datarate;
895	fi.ssi_signal = rx_mgmt->ssi_signal;
896
897	if (hapd == HAPD_BROADCAST) {
898		size_t i;
899
900		ret = 0;
901		for (i = 0; i < iface->num_bss; i++) {
902			/* if bss is set, driver will call this function for
903			 * each bss individually. */
904			if (rx_mgmt->drv_priv &&
905			    (iface->bss[i]->drv_priv != rx_mgmt->drv_priv))
906				continue;
907
908			if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
909					    rx_mgmt->frame_len, &fi) > 0)
910				ret = 1;
911		}
912	} else
913		ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len,
914				      &fi);
915
916	random_add_randomness(&fi, sizeof(fi));
917
918	return ret;
919}
920
921
922static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
923			       size_t len, u16 stype, int ok)
924{
925	struct ieee80211_hdr *hdr;
926	struct hostapd_data *orig_hapd = hapd;
927
928	hdr = (struct ieee80211_hdr *) buf;
929	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
930	if (!hapd)
931		return;
932	if (hapd == HAPD_BROADCAST) {
933		if (stype != WLAN_FC_STYPE_ACTION || len <= 25 ||
934		    buf[24] != WLAN_ACTION_PUBLIC)
935			return;
936		hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2);
937		if (!hapd || hapd == HAPD_BROADCAST)
938			return;
939		/*
940		 * Allow processing of TX status for a Public Action frame that
941		 * used wildcard BBSID.
942		 */
943	}
944	ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
945}
946
947#endif /* NEED_AP_MLME */
948
949
950static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
951{
952	struct sta_info *sta = ap_get_sta(hapd, addr);
953
954	if (sta)
955		return 0;
956
957	wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
958		   " - adding a new STA", MAC2STR(addr));
959	sta = ap_sta_add(hapd, addr);
960	if (sta) {
961		hostapd_new_assoc_sta(hapd, sta, 0);
962	} else {
963		wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
964			   MAC2STR(addr));
965		return -1;
966	}
967
968	return 0;
969}
970
971
972static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
973				   const u8 *data, size_t data_len)
974{
975	struct hostapd_iface *iface = hapd->iface;
976	struct sta_info *sta;
977	size_t j;
978
979	for (j = 0; j < iface->num_bss; j++) {
980		sta = ap_get_sta(iface->bss[j], src);
981		if (sta && sta->flags & WLAN_STA_ASSOC) {
982			hapd = iface->bss[j];
983			break;
984		}
985	}
986
987	ieee802_1x_receive(hapd, src, data, data_len);
988}
989
990#endif /* HOSTAPD */
991
992
993static struct hostapd_channel_data * hostapd_get_mode_channel(
994	struct hostapd_iface *iface, unsigned int freq)
995{
996	int i;
997	struct hostapd_channel_data *chan;
998
999	for (i = 0; i < iface->current_mode->num_channels; i++) {
1000		chan = &iface->current_mode->channels[i];
1001		if ((unsigned int) chan->freq == freq)
1002			return chan;
1003	}
1004
1005	return NULL;
1006}
1007
1008
1009static void hostapd_update_nf(struct hostapd_iface *iface,
1010			      struct hostapd_channel_data *chan,
1011			      struct freq_survey *survey)
1012{
1013	if (!iface->chans_surveyed) {
1014		chan->min_nf = survey->nf;
1015		iface->lowest_nf = survey->nf;
1016	} else {
1017		if (dl_list_empty(&chan->survey_list))
1018			chan->min_nf = survey->nf;
1019		else if (survey->nf < chan->min_nf)
1020			chan->min_nf = survey->nf;
1021		if (survey->nf < iface->lowest_nf)
1022			iface->lowest_nf = survey->nf;
1023	}
1024}
1025
1026
1027static void hostapd_single_channel_get_survey(struct hostapd_iface *iface,
1028					      struct survey_results *survey_res)
1029{
1030	struct hostapd_channel_data *chan;
1031	struct freq_survey *survey;
1032	u64 divisor, dividend;
1033
1034	survey = dl_list_first(&survey_res->survey_list, struct freq_survey,
1035			       list);
1036	if (!survey || !survey->freq)
1037		return;
1038
1039	chan = hostapd_get_mode_channel(iface, survey->freq);
1040	if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED)
1041		return;
1042
1043	wpa_printf(MSG_DEBUG,
1044		   "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)",
1045		   survey->freq,
1046		   (unsigned long int) survey->channel_time,
1047		   (unsigned long int) survey->channel_time_busy);
1048
1049	if (survey->channel_time > iface->last_channel_time &&
1050	    survey->channel_time > survey->channel_time_busy) {
1051		dividend = survey->channel_time_busy -
1052			iface->last_channel_time_busy;
1053		divisor = survey->channel_time - iface->last_channel_time;
1054
1055		iface->channel_utilization = dividend * 255 / divisor;
1056		wpa_printf(MSG_DEBUG, "Channel Utilization: %d",
1057			   iface->channel_utilization);
1058	}
1059	iface->last_channel_time = survey->channel_time;
1060	iface->last_channel_time_busy = survey->channel_time_busy;
1061}
1062
1063
1064void hostapd_event_get_survey(struct hostapd_iface *iface,
1065			      struct survey_results *survey_results)
1066{
1067	struct freq_survey *survey, *tmp;
1068	struct hostapd_channel_data *chan;
1069
1070	if (dl_list_empty(&survey_results->survey_list)) {
1071		wpa_printf(MSG_DEBUG, "No survey data received");
1072		return;
1073	}
1074
1075	if (survey_results->freq_filter) {
1076		hostapd_single_channel_get_survey(iface, survey_results);
1077		return;
1078	}
1079
1080	dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
1081			      struct freq_survey, list) {
1082		chan = hostapd_get_mode_channel(iface, survey->freq);
1083		if (!chan)
1084			continue;
1085		if (chan->flag & HOSTAPD_CHAN_DISABLED)
1086			continue;
1087
1088		dl_list_del(&survey->list);
1089		dl_list_add_tail(&chan->survey_list, &survey->list);
1090
1091		hostapd_update_nf(iface, chan, survey);
1092
1093		iface->chans_surveyed++;
1094	}
1095}
1096
1097
1098#ifdef HOSTAPD
1099#ifdef NEED_AP_MLME
1100
1101static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
1102{
1103	wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped",
1104		   hapd->conf->iface);
1105
1106	if (hapd->csa_in_progress) {
1107		wpa_printf(MSG_INFO, "CSA failed (%s was stopped)",
1108			   hapd->conf->iface);
1109		hostapd_switch_channel_fallback(hapd->iface,
1110						&hapd->cs_freq_params);
1111	}
1112}
1113
1114
1115static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
1116					     struct dfs_event *radar)
1117{
1118	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
1119	hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled,
1120				   radar->chan_offset, radar->chan_width,
1121				   radar->cf1, radar->cf2);
1122}
1123
1124
1125static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd,
1126					   struct dfs_event *radar)
1127{
1128	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
1129	hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled,
1130				 radar->chan_offset, radar->chan_width,
1131				 radar->cf1, radar->cf2);
1132}
1133
1134
1135static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd,
1136					  struct dfs_event *radar)
1137{
1138	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
1139	hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled,
1140				 radar->chan_offset, radar->chan_width,
1141				 radar->cf1, radar->cf2);
1142}
1143
1144
1145static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
1146					   struct dfs_event *radar)
1147{
1148	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
1149	hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled,
1150				 radar->chan_offset, radar->chan_width,
1151				 radar->cf1, radar->cf2);
1152}
1153
1154
1155static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
1156					  struct dfs_event *radar)
1157{
1158	wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
1159	hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
1160			      radar->chan_offset, radar->chan_width,
1161			      radar->cf1, radar->cf2);
1162}
1163
1164#endif /* NEED_AP_MLME */
1165
1166
1167void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
1168			  union wpa_event_data *data)
1169{
1170	struct hostapd_data *hapd = ctx;
1171#ifndef CONFIG_NO_STDOUT_DEBUG
1172	int level = MSG_DEBUG;
1173
1174	if (event == EVENT_RX_MGMT && data->rx_mgmt.frame &&
1175	    data->rx_mgmt.frame_len >= 24) {
1176		const struct ieee80211_hdr *hdr;
1177		u16 fc;
1178
1179		hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
1180		fc = le_to_host16(hdr->frame_control);
1181		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
1182		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
1183			level = MSG_EXCESSIVE;
1184		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
1185		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ)
1186			level = MSG_EXCESSIVE;
1187	}
1188
1189	wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
1190		event_to_string(event), event);
1191#endif /* CONFIG_NO_STDOUT_DEBUG */
1192
1193	switch (event) {
1194	case EVENT_MICHAEL_MIC_FAILURE:
1195		michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
1196		break;
1197	case EVENT_SCAN_RESULTS:
1198		if (hapd->iface->scan_cb)
1199			hapd->iface->scan_cb(hapd->iface);
1200		break;
1201	case EVENT_WPS_BUTTON_PUSHED:
1202		hostapd_wps_button_pushed(hapd, NULL);
1203		break;
1204#ifdef NEED_AP_MLME
1205	case EVENT_TX_STATUS:
1206		switch (data->tx_status.type) {
1207		case WLAN_FC_TYPE_MGMT:
1208			hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
1209					   data->tx_status.data_len,
1210					   data->tx_status.stype,
1211					   data->tx_status.ack);
1212			break;
1213		case WLAN_FC_TYPE_DATA:
1214			hostapd_tx_status(hapd, data->tx_status.dst,
1215					  data->tx_status.data,
1216					  data->tx_status.data_len,
1217					  data->tx_status.ack);
1218			break;
1219		}
1220		break;
1221	case EVENT_EAPOL_TX_STATUS:
1222		hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
1223					data->eapol_tx_status.data,
1224					data->eapol_tx_status.data_len,
1225					data->eapol_tx_status.ack);
1226		break;
1227	case EVENT_DRIVER_CLIENT_POLL_OK:
1228		hostapd_client_poll_ok(hapd, data->client_poll.addr);
1229		break;
1230	case EVENT_RX_FROM_UNKNOWN:
1231		hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
1232					    data->rx_from_unknown.addr,
1233					    data->rx_from_unknown.wds);
1234		break;
1235#endif /* NEED_AP_MLME */
1236	case EVENT_RX_MGMT:
1237		if (!data->rx_mgmt.frame)
1238			break;
1239#ifdef NEED_AP_MLME
1240		if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0)
1241			break;
1242#endif /* NEED_AP_MLME */
1243		hostapd_action_rx(hapd, &data->rx_mgmt);
1244		break;
1245	case EVENT_RX_PROBE_REQ:
1246		if (data->rx_probe_req.sa == NULL ||
1247		    data->rx_probe_req.ie == NULL)
1248			break;
1249		hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
1250				     data->rx_probe_req.da,
1251				     data->rx_probe_req.bssid,
1252				     data->rx_probe_req.ie,
1253				     data->rx_probe_req.ie_len,
1254				     data->rx_probe_req.ssi_signal);
1255		break;
1256	case EVENT_NEW_STA:
1257		hostapd_event_new_sta(hapd, data->new_sta.addr);
1258		break;
1259	case EVENT_EAPOL_RX:
1260		hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
1261				       data->eapol_rx.data,
1262				       data->eapol_rx.data_len);
1263		break;
1264	case EVENT_ASSOC:
1265		if (!data)
1266			return;
1267		hostapd_notif_assoc(hapd, data->assoc_info.addr,
1268				    data->assoc_info.req_ies,
1269				    data->assoc_info.req_ies_len,
1270				    data->assoc_info.reassoc);
1271		break;
1272	case EVENT_DISASSOC:
1273		if (data)
1274			hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
1275		break;
1276	case EVENT_DEAUTH:
1277		if (data)
1278			hostapd_notif_disassoc(hapd, data->deauth_info.addr);
1279		break;
1280	case EVENT_STATION_LOW_ACK:
1281		if (!data)
1282			break;
1283		hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
1284		break;
1285	case EVENT_AUTH:
1286		hostapd_notif_auth(hapd, &data->auth);
1287		break;
1288	case EVENT_CH_SWITCH:
1289		if (!data)
1290			break;
1291		hostapd_event_ch_switch(hapd, data->ch_switch.freq,
1292					data->ch_switch.ht_enabled,
1293					data->ch_switch.ch_offset,
1294					data->ch_switch.ch_width,
1295					data->ch_switch.cf1,
1296					data->ch_switch.cf2);
1297		break;
1298	case EVENT_CONNECT_FAILED_REASON:
1299		if (!data)
1300			break;
1301		hostapd_event_connect_failed_reason(
1302			hapd, data->connect_failed_reason.addr,
1303			data->connect_failed_reason.code);
1304		break;
1305	case EVENT_SURVEY:
1306		hostapd_event_get_survey(hapd->iface, &data->survey_results);
1307		break;
1308#ifdef NEED_AP_MLME
1309	case EVENT_INTERFACE_UNAVAILABLE:
1310		hostapd_event_iface_unavailable(hapd);
1311		break;
1312	case EVENT_DFS_RADAR_DETECTED:
1313		if (!data)
1314			break;
1315		hostapd_event_dfs_radar_detected(hapd, &data->dfs_event);
1316		break;
1317	case EVENT_DFS_CAC_FINISHED:
1318		if (!data)
1319			break;
1320		hostapd_event_dfs_cac_finished(hapd, &data->dfs_event);
1321		break;
1322	case EVENT_DFS_CAC_ABORTED:
1323		if (!data)
1324			break;
1325		hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event);
1326		break;
1327	case EVENT_DFS_NOP_FINISHED:
1328		if (!data)
1329			break;
1330		hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
1331		break;
1332	case EVENT_CHANNEL_LIST_CHANGED:
1333		/* channel list changed (regulatory?), update channel list */
1334		/* TODO: check this. hostapd_get_hw_features() initializes
1335		 * too much stuff. */
1336		/* hostapd_get_hw_features(hapd->iface); */
1337		hostapd_channel_list_updated(
1338			hapd->iface, data->channel_list_changed.initiator);
1339		break;
1340	case EVENT_DFS_CAC_STARTED:
1341		if (!data)
1342			break;
1343		hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
1344		break;
1345#endif /* NEED_AP_MLME */
1346	case EVENT_INTERFACE_ENABLED:
1347		wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
1348		if (hapd->disabled && hapd->started) {
1349			hapd->disabled = 0;
1350			/*
1351			 * Try to re-enable interface if the driver stopped it
1352			 * when the interface got disabled.
1353			 */
1354			wpa_auth_reconfig_group_keys(hapd->wpa_auth);
1355			hapd->reenable_beacon = 1;
1356			ieee802_11_set_beacon(hapd);
1357		}
1358		break;
1359	case EVENT_INTERFACE_DISABLED:
1360		hostapd_free_stas(hapd);
1361		wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
1362		hapd->disabled = 1;
1363		break;
1364#ifdef CONFIG_ACS
1365	case EVENT_ACS_CHANNEL_SELECTED:
1366		hostapd_acs_channel_selected(hapd,
1367					     &data->acs_selected_channels);
1368		break;
1369#endif /* CONFIG_ACS */
1370	default:
1371		wpa_printf(MSG_DEBUG, "Unknown event %d", event);
1372		break;
1373	}
1374}
1375
1376
1377void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
1378				 union wpa_event_data *data)
1379{
1380	struct hapd_interfaces *interfaces = ctx;
1381	struct hostapd_data *hapd;
1382
1383	if (event != EVENT_INTERFACE_STATUS)
1384		return;
1385
1386	hapd = hostapd_get_iface(interfaces, data->interface_status.ifname);
1387	if (hapd && hapd->driver && hapd->driver->get_ifindex &&
1388	    hapd->drv_priv) {
1389		unsigned int ifindex;
1390
1391		ifindex = hapd->driver->get_ifindex(hapd->drv_priv);
1392		if (ifindex != data->interface_status.ifindex) {
1393			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1394				"interface status ifindex %d mismatch (%d)",
1395				ifindex, data->interface_status.ifindex);
1396			return;
1397		}
1398	}
1399	if (hapd)
1400		wpa_supplicant_event(hapd, event, data);
1401}
1402
1403#endif /* HOSTAPD */
1404