drv_callbacks.c revision 214501
1214501Srpaulo/*
2214501Srpaulo * hostapd / Callback functions for driver wrappers
3214501Srpaulo * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4214501Srpaulo *
5214501Srpaulo * This program is free software; you can redistribute it and/or modify
6214501Srpaulo * it under the terms of the GNU General Public License version 2 as
7214501Srpaulo * published by the Free Software Foundation.
8214501Srpaulo *
9214501Srpaulo * Alternatively, this software may be distributed under the terms of BSD
10214501Srpaulo * license.
11214501Srpaulo *
12214501Srpaulo * See README and COPYING for more details.
13214501Srpaulo */
14214501Srpaulo
15214501Srpaulo#include "utils/includes.h"
16214501Srpaulo
17214501Srpaulo#include "utils/common.h"
18214501Srpaulo#include "radius/radius.h"
19214501Srpaulo#include "drivers/driver.h"
20214501Srpaulo#include "common/ieee802_11_defs.h"
21214501Srpaulo#include "common/ieee802_11_common.h"
22214501Srpaulo#include "common/wpa_ctrl.h"
23214501Srpaulo#include "hostapd.h"
24214501Srpaulo#include "ieee802_11.h"
25214501Srpaulo#include "sta_info.h"
26214501Srpaulo#include "accounting.h"
27214501Srpaulo#include "tkip_countermeasures.h"
28214501Srpaulo#include "iapp.h"
29214501Srpaulo#include "ieee802_1x.h"
30214501Srpaulo#include "wpa_auth.h"
31214501Srpaulo#include "wmm.h"
32214501Srpaulo#include "wps_hostapd.h"
33214501Srpaulo#include "ap_config.h"
34214501Srpaulo
35214501Srpaulo
36214501Srpauloint hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
37214501Srpaulo			const u8 *ie, size_t ielen)
38214501Srpaulo{
39214501Srpaulo	struct sta_info *sta;
40214501Srpaulo	int new_assoc, res;
41214501Srpaulo	struct ieee802_11_elems elems;
42214501Srpaulo
43214501Srpaulo	if (addr == NULL) {
44214501Srpaulo		/*
45214501Srpaulo		 * This could potentially happen with unexpected event from the
46214501Srpaulo		 * driver wrapper. This was seen at least in one case where the
47214501Srpaulo		 * driver ended up being set to station mode while hostapd was
48214501Srpaulo		 * running, so better make sure we stop processing such an
49214501Srpaulo		 * event here.
50214501Srpaulo		 */
51214501Srpaulo		wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
52214501Srpaulo			   "no address");
53214501Srpaulo		return -1;
54214501Srpaulo	}
55214501Srpaulo
56214501Srpaulo	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
57214501Srpaulo		       HOSTAPD_LEVEL_INFO, "associated");
58214501Srpaulo
59214501Srpaulo	ieee802_11_parse_elems(ie, ielen, &elems, 0);
60214501Srpaulo	if (elems.wps_ie) {
61214501Srpaulo		ie = elems.wps_ie - 2;
62214501Srpaulo		ielen = elems.wps_ie_len + 2;
63214501Srpaulo		wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
64214501Srpaulo	} else if (elems.rsn_ie) {
65214501Srpaulo		ie = elems.rsn_ie - 2;
66214501Srpaulo		ielen = elems.rsn_ie_len + 2;
67214501Srpaulo		wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
68214501Srpaulo	} else if (elems.wpa_ie) {
69214501Srpaulo		ie = elems.wpa_ie - 2;
70214501Srpaulo		ielen = elems.wpa_ie_len + 2;
71214501Srpaulo		wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
72214501Srpaulo	} else {
73214501Srpaulo		ie = NULL;
74214501Srpaulo		ielen = 0;
75214501Srpaulo		wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
76214501Srpaulo			   "(Re)AssocReq");
77214501Srpaulo	}
78214501Srpaulo
79214501Srpaulo	sta = ap_get_sta(hapd, addr);
80214501Srpaulo	if (sta) {
81214501Srpaulo		accounting_sta_stop(hapd, sta);
82214501Srpaulo	} else {
83214501Srpaulo		sta = ap_sta_add(hapd, addr);
84214501Srpaulo		if (sta == NULL)
85214501Srpaulo			return -1;
86214501Srpaulo	}
87214501Srpaulo	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
88214501Srpaulo
89214501Srpaulo	if (hapd->conf->wpa) {
90214501Srpaulo		if (ie == NULL || ielen == 0) {
91214501Srpaulo			if (hapd->conf->wps_state) {
92214501Srpaulo				wpa_printf(MSG_DEBUG, "STA did not include "
93214501Srpaulo					   "WPA/RSN IE in (Re)Association "
94214501Srpaulo					   "Request - possible WPS use");
95214501Srpaulo				sta->flags |= WLAN_STA_MAYBE_WPS;
96214501Srpaulo				goto skip_wpa_check;
97214501Srpaulo			}
98214501Srpaulo
99214501Srpaulo			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
100214501Srpaulo			return -1;
101214501Srpaulo		}
102214501Srpaulo		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
103214501Srpaulo		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
104214501Srpaulo			sta->flags |= WLAN_STA_WPS;
105214501Srpaulo			goto skip_wpa_check;
106214501Srpaulo		}
107214501Srpaulo
108214501Srpaulo		if (sta->wpa_sm == NULL)
109214501Srpaulo			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
110214501Srpaulo							sta->addr);
111214501Srpaulo		if (sta->wpa_sm == NULL) {
112214501Srpaulo			wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
113214501Srpaulo				   "machine");
114214501Srpaulo			return -1;
115214501Srpaulo		}
116214501Srpaulo		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
117214501Srpaulo					  ie, ielen, NULL, 0);
118214501Srpaulo		if (res != WPA_IE_OK) {
119214501Srpaulo			int resp;
120214501Srpaulo			wpa_printf(MSG_DEBUG, "WPA/RSN information element "
121214501Srpaulo				   "rejected? (res %u)", res);
122214501Srpaulo			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
123214501Srpaulo			if (res == WPA_INVALID_GROUP)
124214501Srpaulo				resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
125214501Srpaulo			else if (res == WPA_INVALID_PAIRWISE)
126214501Srpaulo				resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
127214501Srpaulo			else if (res == WPA_INVALID_AKMP)
128214501Srpaulo				resp = WLAN_REASON_AKMP_NOT_VALID;
129214501Srpaulo#ifdef CONFIG_IEEE80211W
130214501Srpaulo			else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
131214501Srpaulo				resp = WLAN_REASON_INVALID_IE;
132214501Srpaulo			else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
133214501Srpaulo				resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
134214501Srpaulo#endif /* CONFIG_IEEE80211W */
135214501Srpaulo			else
136214501Srpaulo				resp = WLAN_REASON_INVALID_IE;
137214501Srpaulo			hapd->drv.sta_disassoc(hapd, sta->addr, resp);
138214501Srpaulo			ap_free_sta(hapd, sta);
139214501Srpaulo			return -1;
140214501Srpaulo		}
141214501Srpaulo	} else if (hapd->conf->wps_state) {
142214501Srpaulo		if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
143214501Srpaulo		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
144214501Srpaulo			sta->flags |= WLAN_STA_WPS;
145214501Srpaulo		} else
146214501Srpaulo			sta->flags |= WLAN_STA_MAYBE_WPS;
147214501Srpaulo	}
148214501Srpauloskip_wpa_check:
149214501Srpaulo
150214501Srpaulo	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
151214501Srpaulo	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
152214501Srpaulo	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
153214501Srpaulo
154214501Srpaulo	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
155214501Srpaulo
156214501Srpaulo	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
157214501Srpaulo
158214501Srpaulo	return 0;
159214501Srpaulo}
160214501Srpaulo
161214501Srpaulo
162214501Srpaulovoid hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
163214501Srpaulo{
164214501Srpaulo	struct sta_info *sta;
165214501Srpaulo
166214501Srpaulo	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
167214501Srpaulo		       HOSTAPD_LEVEL_INFO, "disassociated");
168214501Srpaulo
169214501Srpaulo	sta = ap_get_sta(hapd, addr);
170214501Srpaulo	if (sta == NULL) {
171214501Srpaulo		wpa_printf(MSG_DEBUG, "Disassociation notification for "
172214501Srpaulo			   "unknown STA " MACSTR, MAC2STR(addr));
173214501Srpaulo		return;
174214501Srpaulo	}
175214501Srpaulo
176214501Srpaulo	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
177214501Srpaulo	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
178214501Srpaulo		MAC2STR(sta->addr));
179214501Srpaulo	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
180214501Srpaulo	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
181214501Srpaulo	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
182214501Srpaulo	ap_free_sta(hapd, sta);
183214501Srpaulo}
184214501Srpaulo
185214501Srpaulo
186214501Srpaulo#ifdef HOSTAPD
187214501Srpaulo
188214501Srpaulo#ifdef NEED_AP_MLME
189214501Srpaulo
190214501Srpaulostatic const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
191214501Srpaulo{
192214501Srpaulo	u16 fc, type, stype;
193214501Srpaulo
194214501Srpaulo	/*
195214501Srpaulo	 * PS-Poll frames are 16 bytes. All other frames are
196214501Srpaulo	 * 24 bytes or longer.
197214501Srpaulo	 */
198214501Srpaulo	if (len < 16)
199214501Srpaulo		return NULL;
200214501Srpaulo
201214501Srpaulo	fc = le_to_host16(hdr->frame_control);
202214501Srpaulo	type = WLAN_FC_GET_TYPE(fc);
203214501Srpaulo	stype = WLAN_FC_GET_STYPE(fc);
204214501Srpaulo
205214501Srpaulo	switch (type) {
206214501Srpaulo	case WLAN_FC_TYPE_DATA:
207214501Srpaulo		if (len < 24)
208214501Srpaulo			return NULL;
209214501Srpaulo		switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
210214501Srpaulo		case WLAN_FC_FROMDS | WLAN_FC_TODS:
211214501Srpaulo		case WLAN_FC_TODS:
212214501Srpaulo			return hdr->addr1;
213214501Srpaulo		case WLAN_FC_FROMDS:
214214501Srpaulo			return hdr->addr2;
215214501Srpaulo		default:
216214501Srpaulo			return NULL;
217214501Srpaulo		}
218214501Srpaulo	case WLAN_FC_TYPE_CTRL:
219214501Srpaulo		if (stype != WLAN_FC_STYPE_PSPOLL)
220214501Srpaulo			return NULL;
221214501Srpaulo		return hdr->addr1;
222214501Srpaulo	case WLAN_FC_TYPE_MGMT:
223214501Srpaulo		return hdr->addr3;
224214501Srpaulo	default:
225214501Srpaulo		return NULL;
226214501Srpaulo	}
227214501Srpaulo}
228214501Srpaulo
229214501Srpaulo
230214501Srpaulo#define HAPD_BROADCAST ((struct hostapd_data *) -1)
231214501Srpaulo
232214501Srpaulostatic struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
233214501Srpaulo					    const u8 *bssid)
234214501Srpaulo{
235214501Srpaulo	size_t i;
236214501Srpaulo
237214501Srpaulo	if (bssid == NULL)
238214501Srpaulo		return NULL;
239214501Srpaulo	if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
240214501Srpaulo	    bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
241214501Srpaulo		return HAPD_BROADCAST;
242214501Srpaulo
243214501Srpaulo	for (i = 0; i < iface->num_bss; i++) {
244214501Srpaulo		if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
245214501Srpaulo			return iface->bss[i];
246214501Srpaulo	}
247214501Srpaulo
248214501Srpaulo	return NULL;
249214501Srpaulo}
250214501Srpaulo
251214501Srpaulo
252214501Srpaulostatic void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
253214501Srpaulo					const u8 *frame, size_t len)
254214501Srpaulo{
255214501Srpaulo	const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
256214501Srpaulo	u16 fc = le_to_host16(hdr->frame_control);
257214501Srpaulo	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
258214501Srpaulo	if (hapd == NULL || hapd == HAPD_BROADCAST)
259214501Srpaulo		return;
260214501Srpaulo
261214501Srpaulo	ieee802_11_rx_from_unknown(hapd, hdr->addr2,
262214501Srpaulo				   (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
263214501Srpaulo				   (WLAN_FC_TODS | WLAN_FC_FROMDS));
264214501Srpaulo}
265214501Srpaulo
266214501Srpaulo
267214501Srpaulostatic void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
268214501Srpaulo{
269214501Srpaulo	struct hostapd_iface *iface = hapd->iface;
270214501Srpaulo	const struct ieee80211_hdr *hdr;
271214501Srpaulo	const u8 *bssid;
272214501Srpaulo	struct hostapd_frame_info fi;
273214501Srpaulo
274214501Srpaulo	hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
275214501Srpaulo	bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
276214501Srpaulo	if (bssid == NULL)
277214501Srpaulo		return;
278214501Srpaulo
279214501Srpaulo	hapd = get_hapd_bssid(iface, bssid);
280214501Srpaulo	if (hapd == NULL) {
281214501Srpaulo		u16 fc;
282214501Srpaulo		fc = le_to_host16(hdr->frame_control);
283214501Srpaulo
284214501Srpaulo		/*
285214501Srpaulo		 * Drop frames to unknown BSSIDs except for Beacon frames which
286214501Srpaulo		 * could be used to update neighbor information.
287214501Srpaulo		 */
288214501Srpaulo		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
289214501Srpaulo		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
290214501Srpaulo			hapd = iface->bss[0];
291214501Srpaulo		else
292214501Srpaulo			return;
293214501Srpaulo	}
294214501Srpaulo
295214501Srpaulo	os_memset(&fi, 0, sizeof(fi));
296214501Srpaulo	fi.datarate = rx_mgmt->datarate;
297214501Srpaulo	fi.ssi_signal = rx_mgmt->ssi_signal;
298214501Srpaulo
299214501Srpaulo	if (hapd == HAPD_BROADCAST) {
300214501Srpaulo		size_t i;
301214501Srpaulo		for (i = 0; i < iface->num_bss; i++)
302214501Srpaulo			ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
303214501Srpaulo					rx_mgmt->frame_len, &fi);
304214501Srpaulo	} else
305214501Srpaulo		ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
306214501Srpaulo}
307214501Srpaulo
308214501Srpaulo
309214501Srpaulostatic void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
310214501Srpaulo			       size_t len, u16 stype, int ok)
311214501Srpaulo{
312214501Srpaulo	struct ieee80211_hdr *hdr;
313214501Srpaulo	hdr = (struct ieee80211_hdr *) buf;
314214501Srpaulo	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
315214501Srpaulo	if (hapd == NULL || hapd == HAPD_BROADCAST)
316214501Srpaulo		return;
317214501Srpaulo	ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
318214501Srpaulo}
319214501Srpaulo
320214501Srpaulo#endif /* NEED_AP_MLME */
321214501Srpaulo
322214501Srpaulo
323214501Srpaulostatic int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
324214501Srpaulo				const u8 *ie, size_t ie_len)
325214501Srpaulo{
326214501Srpaulo	size_t i;
327214501Srpaulo	int ret = 0;
328214501Srpaulo
329214501Srpaulo	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
330214501Srpaulo		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
331214501Srpaulo					    sa, ie, ie_len) > 0) {
332214501Srpaulo			ret = 1;
333214501Srpaulo			break;
334214501Srpaulo		}
335214501Srpaulo	}
336214501Srpaulo	return ret;
337214501Srpaulo}
338214501Srpaulo
339214501Srpaulo
340214501Srpaulostatic int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
341214501Srpaulo{
342214501Srpaulo	struct sta_info *sta = ap_get_sta(hapd, addr);
343214501Srpaulo	if (sta)
344214501Srpaulo		return 0;
345214501Srpaulo
346214501Srpaulo	wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
347214501Srpaulo		   " - adding a new STA", MAC2STR(addr));
348214501Srpaulo	sta = ap_sta_add(hapd, addr);
349214501Srpaulo	if (sta) {
350214501Srpaulo		hostapd_new_assoc_sta(hapd, sta, 0);
351214501Srpaulo	} else {
352214501Srpaulo		wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
353214501Srpaulo			   MAC2STR(addr));
354214501Srpaulo		return -1;
355214501Srpaulo	}
356214501Srpaulo
357214501Srpaulo	return 0;
358214501Srpaulo}
359214501Srpaulo
360214501Srpaulo
361214501Srpaulostatic void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
362214501Srpaulo				   const u8 *data, size_t data_len)
363214501Srpaulo{
364214501Srpaulo	struct hostapd_iface *iface = hapd->iface;
365214501Srpaulo	size_t j;
366214501Srpaulo
367214501Srpaulo	for (j = 0; j < iface->num_bss; j++) {
368214501Srpaulo		if (ap_get_sta(iface->bss[j], src)) {
369214501Srpaulo			hapd = iface->bss[j];
370214501Srpaulo			break;
371214501Srpaulo		}
372214501Srpaulo	}
373214501Srpaulo
374214501Srpaulo	ieee802_1x_receive(hapd, src, data, data_len);
375214501Srpaulo}
376214501Srpaulo
377214501Srpaulo
378214501Srpaulovoid wpa_supplicant_event(void *ctx, enum wpa_event_type event,
379214501Srpaulo			  union wpa_event_data *data)
380214501Srpaulo{
381214501Srpaulo	struct hostapd_data *hapd = ctx;
382214501Srpaulo
383214501Srpaulo	switch (event) {
384214501Srpaulo	case EVENT_MICHAEL_MIC_FAILURE:
385214501Srpaulo		michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
386214501Srpaulo		break;
387214501Srpaulo	case EVENT_SCAN_RESULTS:
388214501Srpaulo		if (hapd->iface->scan_cb)
389214501Srpaulo			hapd->iface->scan_cb(hapd->iface);
390214501Srpaulo		break;
391214501Srpaulo#ifdef CONFIG_IEEE80211R
392214501Srpaulo	case EVENT_FT_RRB_RX:
393214501Srpaulo		wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src,
394214501Srpaulo			      data->ft_rrb_rx.data, data->ft_rrb_rx.data_len);
395214501Srpaulo		break;
396214501Srpaulo#endif /* CONFIG_IEEE80211R */
397214501Srpaulo	case EVENT_WPS_BUTTON_PUSHED:
398214501Srpaulo		hostapd_wps_button_pushed(hapd);
399214501Srpaulo		break;
400214501Srpaulo#ifdef NEED_AP_MLME
401214501Srpaulo	case EVENT_TX_STATUS:
402214501Srpaulo		switch (data->tx_status.type) {
403214501Srpaulo		case WLAN_FC_TYPE_MGMT:
404214501Srpaulo			hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
405214501Srpaulo					   data->tx_status.data_len,
406214501Srpaulo					   data->tx_status.stype,
407214501Srpaulo					   data->tx_status.ack);
408214501Srpaulo			break;
409214501Srpaulo		case WLAN_FC_TYPE_DATA:
410214501Srpaulo			hostapd_tx_status(hapd, data->tx_status.dst,
411214501Srpaulo					  data->tx_status.data,
412214501Srpaulo					  data->tx_status.data_len,
413214501Srpaulo					  data->tx_status.ack);
414214501Srpaulo			break;
415214501Srpaulo		}
416214501Srpaulo		break;
417214501Srpaulo	case EVENT_RX_FROM_UNKNOWN:
418214501Srpaulo		hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
419214501Srpaulo					    data->rx_from_unknown.len);
420214501Srpaulo		break;
421214501Srpaulo	case EVENT_RX_MGMT:
422214501Srpaulo		hostapd_mgmt_rx(hapd, &data->rx_mgmt);
423214501Srpaulo		break;
424214501Srpaulo#endif /* NEED_AP_MLME */
425214501Srpaulo	case EVENT_RX_PROBE_REQ:
426214501Srpaulo		hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
427214501Srpaulo				     data->rx_probe_req.ie,
428214501Srpaulo				     data->rx_probe_req.ie_len);
429214501Srpaulo		break;
430214501Srpaulo	case EVENT_NEW_STA:
431214501Srpaulo		hostapd_event_new_sta(hapd, data->new_sta.addr);
432214501Srpaulo		break;
433214501Srpaulo	case EVENT_EAPOL_RX:
434214501Srpaulo		hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
435214501Srpaulo				       data->eapol_rx.data,
436214501Srpaulo				       data->eapol_rx.data_len);
437214501Srpaulo		break;
438214501Srpaulo	case EVENT_ASSOC:
439214501Srpaulo		hostapd_notif_assoc(hapd, data->assoc_info.addr,
440214501Srpaulo				    data->assoc_info.req_ies,
441214501Srpaulo				    data->assoc_info.req_ies_len);
442214501Srpaulo		break;
443214501Srpaulo	case EVENT_DISASSOC:
444214501Srpaulo		if (data)
445214501Srpaulo			hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
446214501Srpaulo		break;
447214501Srpaulo	case EVENT_DEAUTH:
448214501Srpaulo		if (data)
449214501Srpaulo			hostapd_notif_disassoc(hapd, data->deauth_info.addr);
450214501Srpaulo		break;
451214501Srpaulo	default:
452214501Srpaulo		wpa_printf(MSG_DEBUG, "Unknown event %d", event);
453214501Srpaulo		break;
454214501Srpaulo	}
455214501Srpaulo}
456214501Srpaulo
457214501Srpaulo#endif /* HOSTAPD */
458