drv_callbacks.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /*
  2. * hostapd / Callback functions for driver wrappers
  3. * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "utils/includes.h"
  15. #include "utils/common.h"
  16. #include "radius/radius.h"
  17. #include "drivers/driver.h"
  18. #include "common/ieee802_11_defs.h"
  19. #include "common/ieee802_11_common.h"
  20. #include "common/wpa_ctrl.h"
  21. #include "crypto/random.h"
  22. #include "p2p/p2p.h"
  23. #include "wps/wps.h"
  24. #include "hostapd.h"
  25. #include "ieee802_11.h"
  26. #include "sta_info.h"
  27. #include "accounting.h"
  28. #include "tkip_countermeasures.h"
  29. #include "iapp.h"
  30. #include "ieee802_1x.h"
  31. #include "wpa_auth.h"
  32. #include "wmm.h"
  33. #include "wps_hostapd.h"
  34. #include "ap_drv_ops.h"
  35. #include "ap_config.h"
  36. int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
  37. const u8 *ie, size_t ielen, int reassoc)
  38. {
  39. struct sta_info *sta;
  40. int new_assoc, res;
  41. struct ieee802_11_elems elems;
  42. #ifdef CONFIG_P2P
  43. const u8 *all_ies = ie;
  44. size_t all_ies_len = ielen;
  45. #endif /* CONFIG_P2P */
  46. if (addr == NULL) {
  47. /*
  48. * This could potentially happen with unexpected event from the
  49. * driver wrapper. This was seen at least in one case where the
  50. * driver ended up being set to station mode while hostapd was
  51. * running, so better make sure we stop processing such an
  52. * event here.
  53. */
  54. wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
  55. "no address");
  56. return -1;
  57. }
  58. random_add_randomness(addr, ETH_ALEN);
  59. hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
  60. HOSTAPD_LEVEL_INFO, "associated");
  61. ieee802_11_parse_elems(ie, ielen, &elems, 0);
  62. if (elems.wps_ie) {
  63. ie = elems.wps_ie - 2;
  64. ielen = elems.wps_ie_len + 2;
  65. wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
  66. } else if (elems.rsn_ie) {
  67. ie = elems.rsn_ie - 2;
  68. ielen = elems.rsn_ie_len + 2;
  69. wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
  70. } else if (elems.wpa_ie) {
  71. ie = elems.wpa_ie - 2;
  72. ielen = elems.wpa_ie_len + 2;
  73. wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
  74. } else {
  75. ie = NULL;
  76. ielen = 0;
  77. wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
  78. "(Re)AssocReq");
  79. }
  80. sta = ap_get_sta(hapd, addr);
  81. if (sta) {
  82. accounting_sta_stop(hapd, sta);
  83. } else {
  84. sta = ap_sta_add(hapd, addr);
  85. if (sta == NULL)
  86. return -1;
  87. }
  88. sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
  89. #ifdef CONFIG_P2P
  90. if (elems.p2p) {
  91. wpabuf_free(sta->p2p_ie);
  92. sta->p2p_ie = ieee802_11_vendor_ie_concat(all_ies, all_ies_len,
  93. P2P_IE_VENDOR_TYPE);
  94. }
  95. #endif /* CONFIG_P2P */
  96. if (hapd->conf->wpa) {
  97. if (ie == NULL || ielen == 0) {
  98. #ifdef CONFIG_WPS
  99. if (hapd->conf->wps_state) {
  100. wpa_printf(MSG_DEBUG, "STA did not include "
  101. "WPA/RSN IE in (Re)Association "
  102. "Request - possible WPS use");
  103. sta->flags |= WLAN_STA_MAYBE_WPS;
  104. goto skip_wpa_check;
  105. }
  106. #endif /* CONFIG_WPS */
  107. wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
  108. return -1;
  109. }
  110. #ifdef CONFIG_WPS
  111. if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
  112. os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
  113. struct wpabuf *wps;
  114. sta->flags |= WLAN_STA_WPS;
  115. wps = ieee802_11_vendor_ie_concat(ie, ielen,
  116. WPS_IE_VENDOR_TYPE);
  117. if (wps) {
  118. if (wps_is_20(wps)) {
  119. wpa_printf(MSG_DEBUG, "WPS: STA "
  120. "supports WPS 2.0");
  121. sta->flags |= WLAN_STA_WPS2;
  122. }
  123. wpabuf_free(wps);
  124. }
  125. goto skip_wpa_check;
  126. }
  127. #endif /* CONFIG_WPS */
  128. if (sta->wpa_sm == NULL)
  129. sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
  130. sta->addr);
  131. if (sta->wpa_sm == NULL) {
  132. wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
  133. "machine");
  134. return -1;
  135. }
  136. res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
  137. ie, ielen, NULL, 0);
  138. if (res != WPA_IE_OK) {
  139. int resp;
  140. wpa_printf(MSG_DEBUG, "WPA/RSN information element "
  141. "rejected? (res %u)", res);
  142. wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
  143. if (res == WPA_INVALID_GROUP)
  144. resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
  145. else if (res == WPA_INVALID_PAIRWISE)
  146. resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
  147. else if (res == WPA_INVALID_AKMP)
  148. resp = WLAN_REASON_AKMP_NOT_VALID;
  149. #ifdef CONFIG_IEEE80211W
  150. else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
  151. resp = WLAN_REASON_INVALID_IE;
  152. else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
  153. resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
  154. #endif /* CONFIG_IEEE80211W */
  155. else
  156. resp = WLAN_REASON_INVALID_IE;
  157. hostapd_drv_sta_disassoc(hapd, sta->addr, resp);
  158. ap_free_sta(hapd, sta);
  159. return -1;
  160. }
  161. } else if (hapd->conf->wps_state) {
  162. #ifdef CONFIG_WPS
  163. struct wpabuf *wps;
  164. wps = ieee802_11_vendor_ie_concat(ie, ielen,
  165. WPS_IE_VENDOR_TYPE);
  166. #ifdef CONFIG_WPS_STRICT
  167. if (ie) {
  168. if (wps && wps_validate_assoc_req(wps) < 0) {
  169. hostapd_drv_sta_disassoc(
  170. hapd, sta->addr,
  171. WLAN_REASON_INVALID_IE);
  172. ap_free_sta(hapd, sta);
  173. wpabuf_free(wps);
  174. return -1;
  175. }
  176. wpabuf_free(wps);
  177. }
  178. #endif /* CONFIG_WPS_STRICT */
  179. if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
  180. os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
  181. sta->flags |= WLAN_STA_WPS;
  182. if (wps && wps_is_20(wps)) {
  183. wpa_printf(MSG_DEBUG, "WPS: STA supports "
  184. "WPS 2.0");
  185. sta->flags |= WLAN_STA_WPS2;
  186. }
  187. } else
  188. sta->flags |= WLAN_STA_MAYBE_WPS;
  189. wpabuf_free(wps);
  190. #endif /* CONFIG_WPS */
  191. }
  192. #ifdef CONFIG_WPS
  193. skip_wpa_check:
  194. #endif /* CONFIG_WPS */
  195. new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
  196. sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
  197. wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
  198. hostapd_new_assoc_sta(hapd, sta, !new_assoc);
  199. ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
  200. #ifdef CONFIG_P2P
  201. p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
  202. all_ies, all_ies_len);
  203. #endif /* CONFIG_P2P */
  204. return 0;
  205. }
  206. void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
  207. {
  208. struct sta_info *sta;
  209. if (addr == NULL) {
  210. /*
  211. * This could potentially happen with unexpected event from the
  212. * driver wrapper. This was seen at least in one case where the
  213. * driver ended up reporting a station mode event while hostapd
  214. * was running, so better make sure we stop processing such an
  215. * event here.
  216. */
  217. wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
  218. "with no address");
  219. return;
  220. }
  221. hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
  222. HOSTAPD_LEVEL_INFO, "disassociated");
  223. sta = ap_get_sta(hapd, addr);
  224. if (sta == NULL) {
  225. wpa_printf(MSG_DEBUG, "Disassociation notification for "
  226. "unknown STA " MACSTR, MAC2STR(addr));
  227. return;
  228. }
  229. sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
  230. wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
  231. MAC2STR(sta->addr));
  232. wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
  233. sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
  234. ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
  235. ap_free_sta(hapd, sta);
  236. }
  237. void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
  238. {
  239. struct sta_info *sta = ap_get_sta(hapd, addr);
  240. if (!sta || !hapd->conf->disassoc_low_ack)
  241. return;
  242. hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
  243. HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
  244. "missing ACKs");
  245. hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
  246. if (sta)
  247. ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
  248. }
  249. int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
  250. const u8 *bssid, const u8 *ie, size_t ie_len)
  251. {
  252. size_t i;
  253. int ret = 0;
  254. if (sa == NULL || ie == NULL)
  255. return -1;
  256. random_add_randomness(sa, ETH_ALEN);
  257. for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
  258. if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
  259. sa, da, bssid, ie, ie_len) > 0) {
  260. ret = 1;
  261. break;
  262. }
  263. }
  264. return ret;
  265. }
  266. #ifdef HOSTAPD
  267. #ifdef NEED_AP_MLME
  268. static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
  269. {
  270. u16 fc, type, stype;
  271. /*
  272. * PS-Poll frames are 16 bytes. All other frames are
  273. * 24 bytes or longer.
  274. */
  275. if (len < 16)
  276. return NULL;
  277. fc = le_to_host16(hdr->frame_control);
  278. type = WLAN_FC_GET_TYPE(fc);
  279. stype = WLAN_FC_GET_STYPE(fc);
  280. switch (type) {
  281. case WLAN_FC_TYPE_DATA:
  282. if (len < 24)
  283. return NULL;
  284. switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
  285. case WLAN_FC_FROMDS | WLAN_FC_TODS:
  286. case WLAN_FC_TODS:
  287. return hdr->addr1;
  288. case WLAN_FC_FROMDS:
  289. return hdr->addr2;
  290. default:
  291. return NULL;
  292. }
  293. case WLAN_FC_TYPE_CTRL:
  294. if (stype != WLAN_FC_STYPE_PSPOLL)
  295. return NULL;
  296. return hdr->addr1;
  297. case WLAN_FC_TYPE_MGMT:
  298. return hdr->addr3;
  299. default:
  300. return NULL;
  301. }
  302. }
  303. #define HAPD_BROADCAST ((struct hostapd_data *) -1)
  304. static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
  305. const u8 *bssid)
  306. {
  307. size_t i;
  308. if (bssid == NULL)
  309. return NULL;
  310. if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
  311. bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
  312. return HAPD_BROADCAST;
  313. for (i = 0; i < iface->num_bss; i++) {
  314. if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
  315. return iface->bss[i];
  316. }
  317. return NULL;
  318. }
  319. static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
  320. const u8 *frame, size_t len)
  321. {
  322. const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
  323. u16 fc = le_to_host16(hdr->frame_control);
  324. hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
  325. if (hapd == NULL || hapd == HAPD_BROADCAST)
  326. return;
  327. ieee802_11_rx_from_unknown(hapd, hdr->addr2,
  328. (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
  329. (WLAN_FC_TODS | WLAN_FC_FROMDS));
  330. }
  331. static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
  332. {
  333. struct hostapd_iface *iface = hapd->iface;
  334. const struct ieee80211_hdr *hdr;
  335. const u8 *bssid;
  336. struct hostapd_frame_info fi;
  337. hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
  338. bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
  339. if (bssid == NULL)
  340. return;
  341. hapd = get_hapd_bssid(iface, bssid);
  342. if (hapd == NULL) {
  343. u16 fc;
  344. fc = le_to_host16(hdr->frame_control);
  345. /*
  346. * Drop frames to unknown BSSIDs except for Beacon frames which
  347. * could be used to update neighbor information.
  348. */
  349. if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
  350. WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
  351. hapd = iface->bss[0];
  352. else
  353. return;
  354. }
  355. os_memset(&fi, 0, sizeof(fi));
  356. fi.datarate = rx_mgmt->datarate;
  357. fi.ssi_signal = rx_mgmt->ssi_signal;
  358. if (hapd == HAPD_BROADCAST) {
  359. size_t i;
  360. for (i = 0; i < iface->num_bss; i++)
  361. ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
  362. rx_mgmt->frame_len, &fi);
  363. } else
  364. ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
  365. random_add_randomness(&fi, sizeof(fi));
  366. }
  367. static void hostapd_rx_action(struct hostapd_data *hapd,
  368. struct rx_action *rx_action)
  369. {
  370. struct rx_mgmt rx_mgmt;
  371. u8 *buf;
  372. struct ieee80211_hdr *hdr;
  373. wpa_printf(MSG_DEBUG, "EVENT_RX_ACTION DA=" MACSTR " SA=" MACSTR
  374. " BSSID=" MACSTR " category=%u",
  375. MAC2STR(rx_action->da), MAC2STR(rx_action->sa),
  376. MAC2STR(rx_action->bssid), rx_action->category);
  377. wpa_hexdump(MSG_MSGDUMP, "Received action frame contents",
  378. rx_action->data, rx_action->len);
  379. buf = os_zalloc(24 + 1 + rx_action->len);
  380. if (buf == NULL)
  381. return;
  382. hdr = (struct ieee80211_hdr *) buf;
  383. hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
  384. WLAN_FC_STYPE_ACTION);
  385. if (rx_action->category == WLAN_ACTION_SA_QUERY) {
  386. /*
  387. * Assume frame was protected; it would have been dropped if
  388. * not.
  389. */
  390. hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
  391. }
  392. os_memcpy(hdr->addr1, rx_action->da, ETH_ALEN);
  393. os_memcpy(hdr->addr2, rx_action->sa, ETH_ALEN);
  394. os_memcpy(hdr->addr3, rx_action->bssid, ETH_ALEN);
  395. buf[24] = rx_action->category;
  396. os_memcpy(buf + 24 + 1, rx_action->data, rx_action->len);
  397. os_memset(&rx_mgmt, 0, sizeof(rx_mgmt));
  398. rx_mgmt.frame = buf;
  399. rx_mgmt.frame_len = 24 + 1 + rx_action->len;
  400. hostapd_mgmt_rx(hapd, &rx_mgmt);
  401. os_free(buf);
  402. }
  403. static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
  404. size_t len, u16 stype, int ok)
  405. {
  406. struct ieee80211_hdr *hdr;
  407. hdr = (struct ieee80211_hdr *) buf;
  408. hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
  409. if (hapd == NULL || hapd == HAPD_BROADCAST)
  410. return;
  411. ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
  412. }
  413. #endif /* NEED_AP_MLME */
  414. static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
  415. {
  416. struct sta_info *sta = ap_get_sta(hapd, addr);
  417. if (sta)
  418. return 0;
  419. wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
  420. " - adding a new STA", MAC2STR(addr));
  421. sta = ap_sta_add(hapd, addr);
  422. if (sta) {
  423. hostapd_new_assoc_sta(hapd, sta, 0);
  424. } else {
  425. wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
  426. MAC2STR(addr));
  427. return -1;
  428. }
  429. return 0;
  430. }
  431. static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
  432. const u8 *data, size_t data_len)
  433. {
  434. struct hostapd_iface *iface = hapd->iface;
  435. size_t j;
  436. for (j = 0; j < iface->num_bss; j++) {
  437. if (ap_get_sta(iface->bss[j], src)) {
  438. hapd = iface->bss[j];
  439. break;
  440. }
  441. }
  442. ieee802_1x_receive(hapd, src, data, data_len);
  443. }
  444. void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
  445. union wpa_event_data *data)
  446. {
  447. struct hostapd_data *hapd = ctx;
  448. switch (event) {
  449. case EVENT_MICHAEL_MIC_FAILURE:
  450. michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
  451. break;
  452. case EVENT_SCAN_RESULTS:
  453. if (hapd->iface->scan_cb)
  454. hapd->iface->scan_cb(hapd->iface);
  455. break;
  456. #ifdef CONFIG_IEEE80211R
  457. case EVENT_FT_RRB_RX:
  458. wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src,
  459. data->ft_rrb_rx.data, data->ft_rrb_rx.data_len);
  460. break;
  461. #endif /* CONFIG_IEEE80211R */
  462. case EVENT_WPS_BUTTON_PUSHED:
  463. hostapd_wps_button_pushed(hapd, NULL);
  464. break;
  465. #ifdef NEED_AP_MLME
  466. case EVENT_TX_STATUS:
  467. switch (data->tx_status.type) {
  468. case WLAN_FC_TYPE_MGMT:
  469. hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
  470. data->tx_status.data_len,
  471. data->tx_status.stype,
  472. data->tx_status.ack);
  473. break;
  474. case WLAN_FC_TYPE_DATA:
  475. hostapd_tx_status(hapd, data->tx_status.dst,
  476. data->tx_status.data,
  477. data->tx_status.data_len,
  478. data->tx_status.ack);
  479. break;
  480. }
  481. break;
  482. case EVENT_RX_FROM_UNKNOWN:
  483. hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
  484. data->rx_from_unknown.len);
  485. break;
  486. case EVENT_RX_MGMT:
  487. hostapd_mgmt_rx(hapd, &data->rx_mgmt);
  488. break;
  489. #endif /* NEED_AP_MLME */
  490. case EVENT_RX_PROBE_REQ:
  491. if (data->rx_probe_req.sa == NULL ||
  492. data->rx_probe_req.ie == NULL)
  493. break;
  494. hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
  495. data->rx_probe_req.da,
  496. data->rx_probe_req.bssid,
  497. data->rx_probe_req.ie,
  498. data->rx_probe_req.ie_len);
  499. break;
  500. case EVENT_NEW_STA:
  501. hostapd_event_new_sta(hapd, data->new_sta.addr);
  502. break;
  503. case EVENT_EAPOL_RX:
  504. hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
  505. data->eapol_rx.data,
  506. data->eapol_rx.data_len);
  507. break;
  508. case EVENT_ASSOC:
  509. hostapd_notif_assoc(hapd, data->assoc_info.addr,
  510. data->assoc_info.req_ies,
  511. data->assoc_info.req_ies_len,
  512. data->assoc_info.reassoc);
  513. break;
  514. case EVENT_DISASSOC:
  515. if (data)
  516. hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
  517. break;
  518. case EVENT_DEAUTH:
  519. if (data)
  520. hostapd_notif_disassoc(hapd, data->deauth_info.addr);
  521. break;
  522. case EVENT_STATION_LOW_ACK:
  523. if (!data)
  524. break;
  525. hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
  526. break;
  527. #ifdef NEED_AP_MLME
  528. case EVENT_RX_ACTION:
  529. if (data->rx_action.da == NULL || data->rx_action.sa == NULL ||
  530. data->rx_action.bssid == NULL)
  531. break;
  532. hostapd_rx_action(hapd, &data->rx_action);
  533. break;
  534. #endif /* NEED_AP_MLME */
  535. default:
  536. wpa_printf(MSG_DEBUG, "Unknown event %d", event);
  537. break;
  538. }
  539. }
  540. #endif /* HOSTAPD */