drv_callbacks.c revision 7832adbbd72a1b784b7fb74a71a5d4085b0cb0d3
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * hostapd / Callback functions for driver wrappers 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This software may be distributed under the terms of the BSD license. 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * See README for more details. 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "utils/includes.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "utils/common.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "utils/eloop.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "radius/radius.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "drivers/driver.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "common/ieee802_11_defs.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "common/ieee802_11_common.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "common/wpa_ctrl.h" 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "crypto/random.h" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "p2p/p2p.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "wps/wps.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "wnm_ap.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "hostapd.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ieee802_11.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sta_info.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "accounting.h" 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "tkip_countermeasures.h" 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ieee802_1x.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "wpa_auth.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "wps_hostapd.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ap_drv_ops.h" 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ap_config.h" 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "hw_features.h" 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "dfs.h" 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "beacon.h" 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuint hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const u8 *req_ies, size_t req_ies_len, int reassoc) 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu struct sta_info *sta; 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int new_assoc, res; 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct ieee802_11_elems elems; 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const u8 *ie; 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t ielen; 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef CONFIG_IEEE80211R 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu u8 *p = buf; 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif /* CONFIG_IEEE80211R */ 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu u16 reason = WLAN_REASON_UNSPECIFIED; 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu u16 status = WLAN_STATUS_SUCCESS; 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const u8 *p2p_dev_addr = NULL; 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (addr == NULL) { 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /* 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * This could potentially happen with unexpected event from the 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * driver wrapper. This was seen at least in one case where the 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * driver ended up being set to station mode while hostapd was 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * running, so better make sure we stop processing such an 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * event here. 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with " 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "no address"); 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return -1; 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) random_add_randomness(addr, ETH_ALEN); 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HOSTAPD_LEVEL_INFO, "associated"); 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0); 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (elems.wps_ie) { 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ie = elems.wps_ie - 2; 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ielen = elems.wps_ie_len + 2; 747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq"); 757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else if (elems.rsn_ie) { 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ie = elems.rsn_ie - 2; 777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ielen = elems.rsn_ie_len + 2; 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (elems.wpa_ie) { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ie = elems.wpa_ie - 2; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ielen = elems.wpa_ie_len + 2; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq"); 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_HS20 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (elems.osen) { 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ie = elems.osen - 2; 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ielen = elems.osen_len + 2; 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq"); 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif /* CONFIG_HS20 */ 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ie = NULL; 917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ielen = 0; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in " 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "(Re)AssocReq"); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sta = ap_get_sta(hapd, addr); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sta) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ap_sta_no_session_timeout(hapd, sta); 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) accounting_sta_stop(hapd, sta); 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /* 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Make sure that the previously registered inactivity timer 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * will not remove the STA immediately. 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sta->timeout_next = STA_NULLFUNC; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sta = ap_sta_add(hapd, addr); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sta == NULL) { 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hostapd_drv_sta_disassoc(hapd, addr, 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WLAN_REASON_DISASSOC_AP_BUSY); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef CONFIG_P2P 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (elems.p2p) { 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) wpabuf_free(sta->p2p_ie); 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) P2P_IE_VENDOR_TYPE); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (sta->p2p_ie) 122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); 123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif /* CONFIG_P2P */ 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#ifdef CONFIG_IEEE80211N 127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#ifdef NEED_AP_MLME 128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (elems.ht_capabilities && 129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elems.ht_capabilities_len >= 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sizeof(struct ieee80211_ht_capabilities) && 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (hapd->iface->conf->ht_capab & 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct ieee80211_ht_capabilities *ht_cap = 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (struct ieee80211_ht_capabilities *) 135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elems.ht_capabilities; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (le_to_host16(ht_cap->ht_capabilities_info) & 138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) HT_CAP_INFO_40MHZ_INTOLERANT) 139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ht40_intolerant_add(hapd->iface, sta); 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* NEED_AP_MLME */ 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_IEEE80211N */ 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef CONFIG_INTERWORKING 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (elems.ext_capab && elems.ext_capab_len > 4) { 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (elems.ext_capab[4] & 0x01) 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sta->qos_map_enabled = 1; 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_INTERWORKING */ 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef CONFIG_HS20 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) wpabuf_free(sta->hs20_ie); 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (elems.hs20 && elems.hs20_len > 4) { 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4, 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) elems.hs20_len - 4); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sta->hs20_ie = NULL; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_HS20 */ 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (hapd->conf->wpa) { 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (ie == NULL || ielen == 0) { 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_WPS 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (hapd->conf->wps_state) { 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wpa_printf(MSG_DEBUG, "STA did not include " 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "WPA/RSN IE in (Re)Association " 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "Request - possible WPS use"); 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sta->flags |= WLAN_STA_MAYBE_WPS; 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) goto skip_wpa_check; 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif /* CONFIG_WPS */ 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return -1; 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_WPS 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) struct wpabuf *wps; 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sta->flags |= WLAN_STA_WPS; 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wps = ieee802_11_vendor_ie_concat(ie, ielen, 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WPS_IE_VENDOR_TYPE); 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (wps) { 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (wps_is_20(wps)) { 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wpa_printf(MSG_DEBUG, "WPS: STA " 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "supports WPS 2.0"); 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sta->flags |= WLAN_STA_WPS2; 1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu wpabuf_free(wps); 1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu goto skip_wpa_check; 1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif /* CONFIG_WPS */ 1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sta->wpa_sm == NULL) 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, 1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sta->addr, 1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu p2p_dev_addr); 1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sta->wpa_sm == NULL) { 1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu wpa_printf(MSG_ERROR, "Failed to initialize WPA state " 2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu "machine"); 2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return -1; 2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, 2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ie, ielen, 2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu elems.mdie, elems.mdie_len); 2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (res != WPA_IE_OK) { 2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu wpa_printf(MSG_DEBUG, "WPA/RSN information element " 2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu "rejected? (res %u)", res); 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); 2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (res == WPA_INVALID_GROUP) { 2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (res == WPA_INVALID_PAIRWISE) { 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (res == WPA_INVALID_AKMP) { 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reason = WLAN_REASON_AKMP_NOT_VALID; 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status = WLAN_STATUS_AKMP_NOT_VALID; 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_IEEE80211W 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) { 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reason = WLAN_REASON_INVALID_IE; 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status = WLAN_STATUS_INVALID_IE; 2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) { 2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; 226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif /* CONFIG_IEEE80211W */ 2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else { 2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reason = WLAN_REASON_INVALID_IE; 2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status = WLAN_STATUS_INVALID_IE; 2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) goto fail; 2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_IEEE80211W 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sta->sa_query_count > 0) 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ap_check_sa_query_timeout(hapd, sta); 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && 2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (sta->auth_alg != WLAN_AUTH_FT)) { 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * STA has already been associated with MFP and SA 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Query timeout has not been reached. Reject the 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * association attempt temporarily and start SA Query, 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * if one is not pending. 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sta->sa_query_count == 0) 2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ap_sta_start_sa_query(hapd, sta); 250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef CONFIG_IEEE80211R 252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; 2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) p = hostapd_eid_assoc_comeback_time(hapd, sta, p); 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) hostapd_sta_assoc(hapd, addr, reassoc, status, buf, 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) p - buf); 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return 0; 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (wpa_auth_uses_mfp(sta->wpa_sm)) 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sta->flags |= WLAN_STA_MFP; 264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else 265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sta->flags &= ~WLAN_STA_MFP; 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_IEEE80211W */ 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#ifdef CONFIG_IEEE80211R 269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (sta->auth_alg == WLAN_AUTH_FT) { 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies, 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch req_ies_len); 272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (status != WLAN_STATUS_SUCCESS) { 273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (status == WLAN_STATUS_INVALID_PMKID) 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reason = WLAN_REASON_INVALID_IE; 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (status == WLAN_STATUS_INVALID_MDIE) 276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) reason = WLAN_REASON_INVALID_IE; 277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (status == WLAN_STATUS_INVALID_FTIE) 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reason = WLAN_REASON_INVALID_IE; 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch goto fail; 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (hapd->conf->wps_state) { 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#ifdef CONFIG_WPS 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) struct wpabuf *wps; 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (req_ies) 2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) WPS_IE_VENDOR_TYPE); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wps = NULL; 2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_WPS_STRICT 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (wps && wps_validate_assoc_req(wps) < 0) { 2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reason = WLAN_REASON_INVALID_IE; 294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) status = WLAN_STATUS_INVALID_IE; 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) wpabuf_free(wps); 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) goto fail; 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_WPS_STRICT */ 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (wps) { 300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sta->flags |= WLAN_STA_WPS; 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (wps_is_20(wps)) { 3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) wpa_printf(MSG_DEBUG, "WPS: STA supports " 3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) "WPS 2.0"); 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sta->flags |= WLAN_STA_WPS2; 3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else 3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sta->flags |= WLAN_STA_MAYBE_WPS; 308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) wpabuf_free(wps); 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_WPS */ 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_HS20 311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else if (hapd->conf->osen) { 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (elems.osen == NULL) { 3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hostapd_logger( 314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HOSTAPD_LEVEL_INFO, 3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "No HS 2.0 OSEN element in association request"); 317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return WLAN_STATUS_INVALID_IE; 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association"); 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (sta->wpa_sm == NULL) 3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, 323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sta->addr, NULL); 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (sta->wpa_sm == NULL) { 3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wpa_printf(MSG_WARNING, "Failed to initialize WPA " 3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "state machine"); 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return WLAN_STATUS_UNSPECIFIED_FAILURE; 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm, 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) elems.osen - 2, elems.osen_len + 2) < 0) 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return WLAN_STATUS_INVALID_IE; 332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#endif /* CONFIG_HS20 */ 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_WPS 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)skip_wpa_check: 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_WPS */ 3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef CONFIG_IEEE80211R 339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sta->auth_alg, req_ies, req_ies_len); 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); 3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#else /* CONFIG_IEEE80211R */ 3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) /* Keep compiler silent about unused variables */ 3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (status) { 3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; 3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (reassoc && (sta->auth_alg == WLAN_AUTH_FT)) 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hostapd_new_assoc_sta(hapd, sta, !new_assoc); 359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); 361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef CONFIG_P2P 36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (req_ies) { 364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) p2p_group_notif_assoc(hapd->p2p_group, sta->addr, 3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) req_ies, req_ies_len); 3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif /* CONFIG_P2P */ 3681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return 0; 3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)fail: 3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_IEEE80211R 3738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hostapd_drv_sta_disassoc(hapd, sta->addr, reason); 3761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ap_free_sta(hapd, sta); 3771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return -1; 3781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch{ 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch struct sta_info *sta; 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (addr == NULL) { 386effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch /* 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * This could potentially happen with unexpected event from the 388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * driver wrapper. This was seen at least in one case where the 389effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * driver ended up reporting a station mode event while hostapd 390effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * was running, so better make sure we stop processing such an 391effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * event here. 392effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 393effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event " 394effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "with no address"); 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch HOSTAPD_LEVEL_INFO, "disassociated"); 4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sta = ap_get_sta(hapd, addr); 4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (sta == NULL) { 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_printf(MSG_DEBUG, "Disassociation notification for " 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "unknown STA " MACSTR, MAC2STR(addr)); 4056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 4066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ap_sta_set_authorized(hapd, sta, 0); 409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); 411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; 4127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ap_free_sta(hapd, sta); 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) 418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct sta_info *sta = ap_get_sta(hapd, addr); 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!sta || !hapd->conf->disassoc_low_ack) 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 425 HOSTAPD_LEVEL_INFO, "disconnected due to excessive " 426 "missing ACKs"); 427 hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK); 428 if (sta) 429 ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK); 430} 431 432 433void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, 434 int offset, int width, int cf1, int cf2) 435{ 436#ifdef NEED_AP_MLME 437 int channel, chwidth, seg0_idx = 0, seg1_idx = 0; 438 439 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 440 HOSTAPD_LEVEL_INFO, "driver had channel switch: " 441 "freq=%d, ht=%d, offset=%d, width=%d, cf1=%d, cf2=%d", 442 freq, ht, offset, width, cf1, cf2); 443 444 hapd->iface->freq = freq; 445 446 channel = hostapd_hw_get_channel(hapd, freq); 447 if (!channel) { 448 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 449 HOSTAPD_LEVEL_WARNING, "driver switched to " 450 "bad channel!"); 451 return; 452 } 453 454 switch (width) { 455 case CHAN_WIDTH_80: 456 chwidth = VHT_CHANWIDTH_80MHZ; 457 break; 458 case CHAN_WIDTH_80P80: 459 chwidth = VHT_CHANWIDTH_80P80MHZ; 460 break; 461 case CHAN_WIDTH_160: 462 chwidth = VHT_CHANWIDTH_160MHZ; 463 break; 464 case CHAN_WIDTH_20_NOHT: 465 case CHAN_WIDTH_20: 466 case CHAN_WIDTH_40: 467 default: 468 chwidth = VHT_CHANWIDTH_USE_HT; 469 break; 470 } 471 472 switch (hapd->iface->current_mode->mode) { 473 case HOSTAPD_MODE_IEEE80211A: 474 if (cf1 > 5000) 475 seg0_idx = (cf1 - 5000) / 5; 476 if (cf2 > 5000) 477 seg1_idx = (cf2 - 5000) / 5; 478 break; 479 default: 480 seg0_idx = hostapd_hw_get_channel(hapd, cf1); 481 seg1_idx = hostapd_hw_get_channel(hapd, cf2); 482 break; 483 } 484 485 hapd->iconf->channel = channel; 486 hapd->iconf->ieee80211n = ht; 487 hapd->iconf->secondary_channel = offset; 488 hapd->iconf->vht_oper_chwidth = chwidth; 489 hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx; 490 hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx; 491 492 if (hapd->iface->csa_in_progress && 493 freq == hapd->iface->cs_freq_params.freq) { 494 hostapd_cleanup_cs_params(hapd); 495 496 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d", 497 freq); 498 } 499#endif /* NEED_AP_MLME */ 500} 501 502 503void hostapd_event_connect_failed_reason(struct hostapd_data *hapd, 504 const u8 *addr, int reason_code) 505{ 506 switch (reason_code) { 507 case MAX_CLIENT_REACHED: 508 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR, 509 MAC2STR(addr)); 510 break; 511 case BLOCKED_CLIENT: 512 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR, 513 MAC2STR(addr)); 514 break; 515 } 516} 517 518 519int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, 520 const u8 *bssid, const u8 *ie, size_t ie_len, 521 int ssi_signal) 522{ 523 size_t i; 524 int ret = 0; 525 526 if (sa == NULL || ie == NULL) 527 return -1; 528 529 random_add_randomness(sa, ETH_ALEN); 530 for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) { 531 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, 532 sa, da, bssid, ie, ie_len, 533 ssi_signal) > 0) { 534 ret = 1; 535 break; 536 } 537 } 538 return ret; 539} 540 541 542#ifdef HOSTAPD 543 544#ifdef CONFIG_IEEE80211R 545static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst, 546 const u8 *bssid, 547 u16 auth_transaction, u16 status, 548 const u8 *ies, size_t ies_len) 549{ 550 struct hostapd_data *hapd = ctx; 551 struct sta_info *sta; 552 553 sta = ap_get_sta(hapd, dst); 554 if (sta == NULL) 555 return; 556 557 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, 558 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); 559 sta->flags |= WLAN_STA_AUTH; 560 561 hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len); 562} 563#endif /* CONFIG_IEEE80211R */ 564 565 566static void hostapd_notif_auth(struct hostapd_data *hapd, 567 struct auth_info *rx_auth) 568{ 569 struct sta_info *sta; 570 u16 status = WLAN_STATUS_SUCCESS; 571 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; 572 size_t resp_ies_len = 0; 573 574 sta = ap_get_sta(hapd, rx_auth->peer); 575 if (!sta) { 576 sta = ap_sta_add(hapd, rx_auth->peer); 577 if (sta == NULL) { 578 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 579 goto fail; 580 } 581 } 582 sta->flags &= ~WLAN_STA_PREAUTH; 583 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); 584#ifdef CONFIG_IEEE80211R 585 if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) { 586 sta->auth_alg = WLAN_AUTH_FT; 587 if (sta->wpa_sm == NULL) 588 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, 589 sta->addr, NULL); 590 if (sta->wpa_sm == NULL) { 591 wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA " 592 "state machine"); 593 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 594 goto fail; 595 } 596 wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid, 597 rx_auth->auth_transaction, rx_auth->ies, 598 rx_auth->ies_len, 599 hostapd_notify_auth_ft_finish, hapd); 600 return; 601 } 602#endif /* CONFIG_IEEE80211R */ 603fail: 604 hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1, 605 status, resp_ies, resp_ies_len); 606} 607 608 609static void hostapd_action_rx(struct hostapd_data *hapd, 610 struct rx_mgmt *drv_mgmt) 611{ 612 struct ieee80211_mgmt *mgmt; 613 struct sta_info *sta; 614 size_t plen __maybe_unused; 615 u16 fc; 616 617 if (drv_mgmt->frame_len < 24 + 1) 618 return; 619 620 plen = drv_mgmt->frame_len - 24 - 1; 621 622 mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; 623 fc = le_to_host16(mgmt->frame_control); 624 if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION) 625 return; /* handled by the driver */ 626 627 wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d", 628 mgmt->u.action.category, (int) plen); 629 630 sta = ap_get_sta(hapd, mgmt->sa); 631 if (sta == NULL) { 632 wpa_printf(MSG_DEBUG, "%s: station not found", __func__); 633 return; 634 } 635#ifdef CONFIG_IEEE80211R 636 if (mgmt->u.action.category == WLAN_ACTION_FT) { 637 const u8 *payload = drv_mgmt->frame + 24 + 1; 638 wpa_ft_action_rx(sta->wpa_sm, payload, plen); 639 } 640#endif /* CONFIG_IEEE80211R */ 641#ifdef CONFIG_IEEE80211W 642 if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) { 643 ieee802_11_sa_query_action( 644 hapd, mgmt->sa, 645 mgmt->u.action.u.sa_query_resp.action, 646 mgmt->u.action.u.sa_query_resp.trans_id); 647 } 648#endif /* CONFIG_IEEE80211W */ 649#ifdef CONFIG_WNM 650 if (mgmt->u.action.category == WLAN_ACTION_WNM) { 651 ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len); 652 } 653#endif /* CONFIG_WNM */ 654} 655 656 657#ifdef NEED_AP_MLME 658 659#define HAPD_BROADCAST ((struct hostapd_data *) -1) 660 661static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface, 662 const u8 *bssid) 663{ 664 size_t i; 665 666 if (bssid == NULL) 667 return NULL; 668 if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && 669 bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) 670 return HAPD_BROADCAST; 671 672 for (i = 0; i < iface->num_bss; i++) { 673 if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) 674 return iface->bss[i]; 675 } 676 677 return NULL; 678} 679 680 681static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, 682 const u8 *bssid, const u8 *addr, 683 int wds) 684{ 685 hapd = get_hapd_bssid(hapd->iface, bssid); 686 if (hapd == NULL || hapd == HAPD_BROADCAST) 687 return; 688 689 ieee802_11_rx_from_unknown(hapd, addr, wds); 690} 691 692 693static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) 694{ 695 struct hostapd_iface *iface = hapd->iface; 696 const struct ieee80211_hdr *hdr; 697 const u8 *bssid; 698 struct hostapd_frame_info fi; 699 int ret; 700 701#ifdef CONFIG_TESTING_OPTIONS 702 if (hapd->ext_mgmt_frame_handling) { 703 size_t hex_len = 2 * rx_mgmt->frame_len + 1; 704 char *hex = os_malloc(hex_len); 705 if (hex) { 706 wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame, 707 rx_mgmt->frame_len); 708 wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex); 709 os_free(hex); 710 } 711 return 1; 712 } 713#endif /* CONFIG_TESTING_OPTIONS */ 714 715 hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; 716 bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); 717 if (bssid == NULL) 718 return 0; 719 720 hapd = get_hapd_bssid(iface, bssid); 721 if (hapd == NULL) { 722 u16 fc; 723 fc = le_to_host16(hdr->frame_control); 724 725 /* 726 * Drop frames to unknown BSSIDs except for Beacon frames which 727 * could be used to update neighbor information. 728 */ 729 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 730 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) 731 hapd = iface->bss[0]; 732 else 733 return 0; 734 } 735 736 os_memset(&fi, 0, sizeof(fi)); 737 fi.datarate = rx_mgmt->datarate; 738 fi.ssi_signal = rx_mgmt->ssi_signal; 739 740 if (hapd == HAPD_BROADCAST) { 741 size_t i; 742 ret = 0; 743 for (i = 0; i < iface->num_bss; i++) { 744 /* if bss is set, driver will call this function for 745 * each bss individually. */ 746 if (rx_mgmt->drv_priv && 747 (iface->bss[i]->drv_priv != rx_mgmt->drv_priv)) 748 continue; 749 750 if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, 751 rx_mgmt->frame_len, &fi) > 0) 752 ret = 1; 753 } 754 } else 755 ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, 756 &fi); 757 758 random_add_randomness(&fi, sizeof(fi)); 759 760 return ret; 761} 762 763 764static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, 765 size_t len, u16 stype, int ok) 766{ 767 struct ieee80211_hdr *hdr; 768 hdr = (struct ieee80211_hdr *) buf; 769 hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); 770 if (hapd == NULL || hapd == HAPD_BROADCAST) 771 return; 772 ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); 773} 774 775#endif /* NEED_AP_MLME */ 776 777 778static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) 779{ 780 struct sta_info *sta = ap_get_sta(hapd, addr); 781 if (sta) 782 return 0; 783 784 wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR 785 " - adding a new STA", MAC2STR(addr)); 786 sta = ap_sta_add(hapd, addr); 787 if (sta) { 788 hostapd_new_assoc_sta(hapd, sta, 0); 789 } else { 790 wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, 791 MAC2STR(addr)); 792 return -1; 793 } 794 795 return 0; 796} 797 798 799static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, 800 const u8 *data, size_t data_len) 801{ 802 struct hostapd_iface *iface = hapd->iface; 803 struct sta_info *sta; 804 size_t j; 805 806 for (j = 0; j < iface->num_bss; j++) { 807 if ((sta = ap_get_sta(iface->bss[j], src))) { 808 if (sta->flags & WLAN_STA_ASSOC) { 809 hapd = iface->bss[j]; 810 break; 811 } 812 } 813 } 814 815 ieee802_1x_receive(hapd, src, data, data_len); 816} 817 818 819static struct hostapd_channel_data * hostapd_get_mode_channel( 820 struct hostapd_iface *iface, unsigned int freq) 821{ 822 int i; 823 struct hostapd_channel_data *chan; 824 825 for (i = 0; i < iface->current_mode->num_channels; i++) { 826 chan = &iface->current_mode->channels[i]; 827 if (!chan) 828 return NULL; 829 if ((unsigned int) chan->freq == freq) 830 return chan; 831 } 832 833 return NULL; 834} 835 836 837static void hostapd_update_nf(struct hostapd_iface *iface, 838 struct hostapd_channel_data *chan, 839 struct freq_survey *survey) 840{ 841 if (!iface->chans_surveyed) { 842 chan->min_nf = survey->nf; 843 iface->lowest_nf = survey->nf; 844 } else { 845 if (dl_list_empty(&chan->survey_list)) 846 chan->min_nf = survey->nf; 847 else if (survey->nf < chan->min_nf) 848 chan->min_nf = survey->nf; 849 if (survey->nf < iface->lowest_nf) 850 iface->lowest_nf = survey->nf; 851 } 852} 853 854 855static void hostapd_event_get_survey(struct hostapd_data *hapd, 856 struct survey_results *survey_results) 857{ 858 struct hostapd_iface *iface = hapd->iface; 859 struct freq_survey *survey, *tmp; 860 struct hostapd_channel_data *chan; 861 862 if (dl_list_empty(&survey_results->survey_list)) { 863 wpa_printf(MSG_DEBUG, "No survey data received"); 864 return; 865 } 866 867 dl_list_for_each_safe(survey, tmp, &survey_results->survey_list, 868 struct freq_survey, list) { 869 chan = hostapd_get_mode_channel(iface, survey->freq); 870 if (!chan) 871 continue; 872 if (chan->flag & HOSTAPD_CHAN_DISABLED) 873 continue; 874 875 dl_list_del(&survey->list); 876 dl_list_add_tail(&chan->survey_list, &survey->list); 877 878 hostapd_update_nf(iface, chan, survey); 879 880 iface->chans_surveyed++; 881 } 882} 883 884 885#ifdef NEED_AP_MLME 886 887static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd, 888 struct dfs_event *radar) 889{ 890 wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); 891 hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled, 892 radar->chan_offset, radar->chan_width, 893 radar->cf1, radar->cf2); 894} 895 896 897static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd, 898 struct dfs_event *radar) 899{ 900 wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); 901 hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled, 902 radar->chan_offset, radar->chan_width, 903 radar->cf1, radar->cf2); 904} 905 906 907static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd, 908 struct dfs_event *radar) 909{ 910 wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); 911 hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled, 912 radar->chan_offset, radar->chan_width, 913 radar->cf1, radar->cf2); 914} 915 916 917static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd, 918 struct dfs_event *radar) 919{ 920 wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); 921 hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled, 922 radar->chan_offset, radar->chan_width, 923 radar->cf1, radar->cf2); 924} 925 926#endif /* NEED_AP_MLME */ 927 928 929void wpa_supplicant_event(void *ctx, enum wpa_event_type event, 930 union wpa_event_data *data) 931{ 932 struct hostapd_data *hapd = ctx; 933#ifndef CONFIG_NO_STDOUT_DEBUG 934 int level = MSG_DEBUG; 935 936 if (event == EVENT_RX_MGMT && data->rx_mgmt.frame && 937 data->rx_mgmt.frame_len >= 24) { 938 const struct ieee80211_hdr *hdr; 939 u16 fc; 940 hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; 941 fc = le_to_host16(hdr->frame_control); 942 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 943 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) 944 level = MSG_EXCESSIVE; 945 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 946 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) 947 level = MSG_EXCESSIVE; 948 } 949 950 wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", 951 event_to_string(event), event); 952#endif /* CONFIG_NO_STDOUT_DEBUG */ 953 954 switch (event) { 955 case EVENT_MICHAEL_MIC_FAILURE: 956 michael_mic_failure(hapd, data->michael_mic_failure.src, 1); 957 break; 958 case EVENT_SCAN_RESULTS: 959 if (hapd->iface->scan_cb) 960 hapd->iface->scan_cb(hapd->iface); 961 break; 962#ifdef CONFIG_IEEE80211R 963 case EVENT_FT_RRB_RX: 964 wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src, 965 data->ft_rrb_rx.data, data->ft_rrb_rx.data_len); 966 break; 967#endif /* CONFIG_IEEE80211R */ 968 case EVENT_WPS_BUTTON_PUSHED: 969 hostapd_wps_button_pushed(hapd, NULL); 970 break; 971#ifdef NEED_AP_MLME 972 case EVENT_TX_STATUS: 973 switch (data->tx_status.type) { 974 case WLAN_FC_TYPE_MGMT: 975 hostapd_mgmt_tx_cb(hapd, data->tx_status.data, 976 data->tx_status.data_len, 977 data->tx_status.stype, 978 data->tx_status.ack); 979 break; 980 case WLAN_FC_TYPE_DATA: 981 hostapd_tx_status(hapd, data->tx_status.dst, 982 data->tx_status.data, 983 data->tx_status.data_len, 984 data->tx_status.ack); 985 break; 986 } 987 break; 988 case EVENT_EAPOL_TX_STATUS: 989 hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, 990 data->eapol_tx_status.data, 991 data->eapol_tx_status.data_len, 992 data->eapol_tx_status.ack); 993 break; 994 case EVENT_DRIVER_CLIENT_POLL_OK: 995 hostapd_client_poll_ok(hapd, data->client_poll.addr); 996 break; 997 case EVENT_RX_FROM_UNKNOWN: 998 hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, 999 data->rx_from_unknown.addr, 1000 data->rx_from_unknown.wds); 1001 break; 1002#endif /* NEED_AP_MLME */ 1003 case EVENT_RX_MGMT: 1004 if (!data->rx_mgmt.frame) 1005 break; 1006#ifdef NEED_AP_MLME 1007 if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0) 1008 break; 1009#endif /* NEED_AP_MLME */ 1010 hostapd_action_rx(hapd, &data->rx_mgmt); 1011 break; 1012 case EVENT_RX_PROBE_REQ: 1013 if (data->rx_probe_req.sa == NULL || 1014 data->rx_probe_req.ie == NULL) 1015 break; 1016 hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, 1017 data->rx_probe_req.da, 1018 data->rx_probe_req.bssid, 1019 data->rx_probe_req.ie, 1020 data->rx_probe_req.ie_len, 1021 data->rx_probe_req.ssi_signal); 1022 break; 1023 case EVENT_NEW_STA: 1024 hostapd_event_new_sta(hapd, data->new_sta.addr); 1025 break; 1026 case EVENT_EAPOL_RX: 1027 hostapd_event_eapol_rx(hapd, data->eapol_rx.src, 1028 data->eapol_rx.data, 1029 data->eapol_rx.data_len); 1030 break; 1031 case EVENT_ASSOC: 1032 hostapd_notif_assoc(hapd, data->assoc_info.addr, 1033 data->assoc_info.req_ies, 1034 data->assoc_info.req_ies_len, 1035 data->assoc_info.reassoc); 1036 break; 1037 case EVENT_DISASSOC: 1038 if (data) 1039 hostapd_notif_disassoc(hapd, data->disassoc_info.addr); 1040 break; 1041 case EVENT_DEAUTH: 1042 if (data) 1043 hostapd_notif_disassoc(hapd, data->deauth_info.addr); 1044 break; 1045 case EVENT_STATION_LOW_ACK: 1046 if (!data) 1047 break; 1048 hostapd_event_sta_low_ack(hapd, data->low_ack.addr); 1049 break; 1050 case EVENT_AUTH: 1051 hostapd_notif_auth(hapd, &data->auth); 1052 break; 1053 case EVENT_CH_SWITCH: 1054 if (!data) 1055 break; 1056 hostapd_event_ch_switch(hapd, data->ch_switch.freq, 1057 data->ch_switch.ht_enabled, 1058 data->ch_switch.ch_offset, 1059 data->ch_switch.ch_width, 1060 data->ch_switch.cf1, 1061 data->ch_switch.cf2); 1062 break; 1063 case EVENT_CONNECT_FAILED_REASON: 1064 if (!data) 1065 break; 1066 hostapd_event_connect_failed_reason( 1067 hapd, data->connect_failed_reason.addr, 1068 data->connect_failed_reason.code); 1069 break; 1070 case EVENT_SURVEY: 1071 hostapd_event_get_survey(hapd, &data->survey_results); 1072 break; 1073#ifdef NEED_AP_MLME 1074 case EVENT_DFS_RADAR_DETECTED: 1075 if (!data) 1076 break; 1077 hostapd_event_dfs_radar_detected(hapd, &data->dfs_event); 1078 break; 1079 case EVENT_DFS_CAC_FINISHED: 1080 if (!data) 1081 break; 1082 hostapd_event_dfs_cac_finished(hapd, &data->dfs_event); 1083 break; 1084 case EVENT_DFS_CAC_ABORTED: 1085 if (!data) 1086 break; 1087 hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event); 1088 break; 1089 case EVENT_DFS_NOP_FINISHED: 1090 if (!data) 1091 break; 1092 hostapd_event_dfs_nop_finished(hapd, &data->dfs_event); 1093 break; 1094 case EVENT_CHANNEL_LIST_CHANGED: 1095 /* channel list changed (regulatory?), update channel list */ 1096 /* TODO: check this. hostapd_get_hw_features() initializes 1097 * too much stuff. */ 1098 /* hostapd_get_hw_features(hapd->iface); */ 1099 hostapd_channel_list_updated( 1100 hapd->iface, data->channel_list_changed.initiator); 1101 break; 1102#endif /* NEED_AP_MLME */ 1103 default: 1104 wpa_printf(MSG_DEBUG, "Unknown event %d", event); 1105 break; 1106 } 1107} 1108 1109#endif /* HOSTAPD */ 1110