/*
* hostapd / IEEE 802.11 Management
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2007-2008, Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include "common.h"
#include "eloop.h"
+#include "crypto/crypto.h"
+#include "common/wpa_ctrl.h"
+#include "radius/radius.h"
+#include "radius/radius_client.h"
#include "hostapd.h"
#include "ieee802_11.h"
#include "beacon.h"
#include "hw_features.h"
-#include "radius/radius.h"
-#include "radius/radius_client.h"
#include "ieee802_11_auth.h"
-#include "sta_flags.h"
#include "sta_info.h"
-#include "crypto.h"
#include "ieee802_1x.h"
#include "wpa.h"
#include "wme.h"
#include "accounting.h"
#include "driver_i.h"
#include "mlme.h"
-#include "common/wpa_ctrl.h"
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
}
-u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
-{
-#ifdef CONFIG_IEEE80211N
- struct ieee80211_ht_capabilities *cap;
- u8 *pos = eid;
-
- if (!hapd->iconf->ieee80211n)
- return eid;
-
- *pos++ = WLAN_EID_HT_CAP;
- *pos++ = sizeof(*cap);
-
- cap = (struct ieee80211_ht_capabilities *) pos;
- os_memset(cap, 0, sizeof(*cap));
- cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab);
- cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params;
- os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set,
- 16);
-
- /* TODO: ht_extended_capabilities (now fully disabled) */
- /* TODO: tx_bf_capability_info (now fully disabled) */
- /* TODO: asel_capabilities (now fully disabled) */
-
- pos += sizeof(*cap);
-
- return pos;
-#else /* CONFIG_IEEE80211N */
- return eid;
-#endif /* CONFIG_IEEE80211N */
-}
-
-
-u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
-{
-#ifdef CONFIG_IEEE80211N
- struct ieee80211_ht_operation *oper;
- u8 *pos = eid;
-
- if (!hapd->iconf->ieee80211n)
- return eid;
-
- *pos++ = WLAN_EID_HT_OPERATION;
- *pos++ = sizeof(*oper);
-
- oper = (struct ieee80211_ht_operation *) pos;
- os_memset(oper, 0, sizeof(*oper));
-
- oper->control_chan = hapd->iconf->channel;
- oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
- if (hapd->iconf->secondary_channel == 1)
- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
- if (hapd->iconf->secondary_channel == -1)
- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
-
- pos += sizeof(*oper);
-
- return pos;
-#else /* CONFIG_IEEE80211N */
- return eid;
-#endif /* CONFIG_IEEE80211N */
-}
-
-
-#ifdef CONFIG_IEEE80211N
-
-/*
-op_mode
-Set to 0 (HT pure) under the followign conditions
- - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
- - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
-Set to 1 (HT non-member protection) if there may be non-HT STAs
- in both the primary and the secondary channel
-Set to 2 if only HT STAs are associated in BSS,
- however and at least one 20 MHz HT STA is associated
-Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
- (currently non-GF HT station is considered as non-HT STA also)
-*/
-int hostapd_ht_operation_update(struct hostapd_iface *iface)
-{
- u16 cur_op_mode, new_op_mode;
- int op_mode_changes = 0;
-
- if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
- return 0;
-
- wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X",
- __func__, iface->ht_op_mode);
-
- if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
- && iface->num_sta_ht_no_gf) {
- iface->ht_op_mode |=
- HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
- op_mode_changes++;
- } else if ((iface->ht_op_mode &
- HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
- iface->num_sta_ht_no_gf == 0) {
- iface->ht_op_mode &=
- ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
- op_mode_changes++;
- }
-
- if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
- (iface->num_sta_no_ht || iface->olbc_ht)) {
- iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
- op_mode_changes++;
- } else if ((iface->ht_op_mode &
- HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
- (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) {
- iface->ht_op_mode &=
- ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
- op_mode_changes++;
- }
-
- /* Note: currently we switch to the MIXED op mode if HT non-greenfield
- * station is associated. Probably it's a theoretical case, since
- * it looks like all known HT STAs support greenfield.
- */
- new_op_mode = 0;
- if (iface->num_sta_no_ht ||
- (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
- new_op_mode = OP_MODE_MIXED;
- else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
- && iface->num_sta_ht_20mhz)
- new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
- else if (iface->olbc_ht)
- new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
- else
- new_op_mode = OP_MODE_PURE;
-
- cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
- if (cur_op_mode != new_op_mode) {
- iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
- iface->ht_op_mode |= new_op_mode;
- op_mode_changes++;
- }
-
- wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d",
- __func__, iface->ht_op_mode, op_mode_changes);
-
- return op_mode_changes;
-}
-
-#endif /* CONFIG_IEEE80211N */
-
-
u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
int probe)
{
* @addr: Address of the destination STA
* @reason: Reason code for Deauthentication
*/
-void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason)
+void ieee802_11_send_deauth(struct hostapd_data *hapd, const u8 *addr,
+ u16 reason)
{
struct ieee80211_mgmt mgmt;
static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
- u16 auth_transaction, u8 *challenge, int iswep)
+ u16 auth_transaction, const u8 *challenge,
+ int iswep)
{
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
#endif /* CONFIG_IEEE80211R */
-static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
- size_t len)
+static void handle_auth(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt, size_t len)
{
u16 auth_alg, auth_transaction, status_code;
u16 resp = WLAN_STATUS_SUCCESS;
struct sta_info *sta = NULL;
int res;
u16 fc;
- u8 *challenge = NULL;
+ const u8 *challenge = NULL;
u32 session_timeout, acct_interim_interval;
int vlan_id = 0;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
}
-#ifdef CONFIG_IEEE80211N
-
-static u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
- size_t ht_capab_len)
-{
- if (!ht_capab ||
- ht_capab_len < sizeof(struct ieee80211_ht_capabilities)) {
- sta->flags &= ~WLAN_STA_HT;
- os_free(sta->ht_capabilities);
- sta->ht_capabilities = NULL;
- return WLAN_STATUS_SUCCESS;
- }
-
- if (sta->ht_capabilities == NULL) {
- sta->ht_capabilities =
- os_zalloc(sizeof(struct ieee80211_ht_capabilities));
- if (sta->ht_capabilities == NULL)
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
- }
-
- sta->flags |= WLAN_STA_HT;
- os_memcpy(sta->ht_capabilities, ht_capab,
- sizeof(struct ieee80211_ht_capabilities));
-
- return WLAN_STATUS_SUCCESS;
-}
-
-
-static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta)
-{
- u16 ht_capab;
-
- ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info);
- wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: "
- "0x%04x", MAC2STR(sta->addr), ht_capab);
- if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) {
- if (!sta->no_ht_gf_set) {
- sta->no_ht_gf_set = 1;
- hapd->iface->num_sta_ht_no_gf++;
- }
- wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num "
- "of non-gf stations %d",
- __func__, MAC2STR(sta->addr),
- hapd->iface->num_sta_ht_no_gf);
- }
- if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) {
- if (!sta->ht_20mhz_set) {
- sta->ht_20mhz_set = 1;
- hapd->iface->num_sta_ht_20mhz++;
- }
- wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of "
- "20MHz HT STAs %d",
- __func__, MAC2STR(sta->addr),
- hapd->iface->num_sta_ht_20mhz);
- }
-}
-
-
-static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta)
-{
- if (!sta->no_ht_set) {
- sta->no_ht_set = 1;
- hapd->iface->num_sta_no_ht++;
- }
- if (hapd->iconf->ieee80211n) {
- wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of "
- "non-HT stations %d",
- __func__, MAC2STR(sta->addr),
- hapd->iface->num_sta_no_ht);
- }
-}
-
-
-static void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta)
-{
- if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities)
- update_sta_ht(hapd, sta);
- else
- update_sta_no_ht(hapd, sta);
-
- if (hostapd_ht_operation_update(hapd->iface) > 0)
- ieee802_11_set_beacons(hapd->iface);
-}
-
-#else /* CONFIG_IEEE80211N */
-
-static u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
- size_t ht_capab_len)
-{
- return WLAN_STATUS_SUCCESS;
-}
-
-
-static void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta)
-{
-}
-
-#endif /* CONFIG_IEEE80211N */
-
-
static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
- u8 *ies, size_t ies_len, int reassoc)
+ const u8 *ies, size_t ies_len, int reassoc)
{
struct ieee802_11_elems elems;
u16 resp;
- u8 *wpa_ie;
+ const u8 *wpa_ie;
size_t wpa_ie_len;
if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
resp = copy_supp_rates(hapd, sta, &elems);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
+#ifdef CONFIG_IEEE80211N
resp = copy_sta_ht_capab(sta, elems.ht_capabilities,
elems.ht_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
+#endif /* CONFIG_IEEE80211N */
if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
wpa_ie = elems.rsn_ie;
static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
- u16 status_code, int reassoc, u8 *ies,
+ u16 status_code, int reassoc, const u8 *ies,
size_t ies_len)
{
int send_len;
if (sta->flags & WLAN_STA_WMM)
p = hostapd_eid_wmm(hapd, p);
+#ifdef CONFIG_IEEE80211N
p = hostapd_eid_ht_capabilities(hapd, p);
p = hostapd_eid_ht_operation(hapd, p);
+#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211R
if (status_code == WLAN_STATUS_SUCCESS) {
static void handle_assoc(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt, size_t len, int reassoc)
+ const struct ieee80211_mgmt *mgmt, size_t len,
+ int reassoc)
{
u16 capab_info, listen_interval;
u16 resp = WLAN_STATUS_SUCCESS;
- u8 *pos;
+ const u8 *pos;
int left, i;
struct sta_info *sta;
ieee802_11_set_beacons(hapd->iface);
}
+#ifdef CONFIG_IEEE80211N
update_ht_state(hapd, sta);
+#endif /* CONFIG_IEEE80211N */
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
static void handle_disassoc(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt, size_t len)
+ const struct ieee80211_mgmt *mgmt, size_t len)
{
struct sta_info *sta;
static void handle_deauth(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt, size_t len)
+ const struct ieee80211_mgmt *mgmt, size_t len)
{
struct sta_info *sta;
static void handle_beacon(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt, size_t len,
+ const struct ieee80211_mgmt *mgmt, size_t len,
struct hostapd_frame_info *fi)
{
struct ieee802_11_elems elems;
static void hostapd_sa_query_action(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt, size_t len)
+ const struct ieee80211_mgmt *mgmt,
+ size_t len)
{
struct sta_info *sta;
- u8 *end;
+ const u8 *end;
int i;
end = mgmt->u.action.u.sa_query_resp.trans_id +
static void handle_action(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt, size_t len)
+ const struct ieee80211_mgmt *mgmt, size_t len)
{
struct sta_info *sta;
mgmt->u.action.category);
if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
!(mgmt->sa[0] & 0x01)) {
+ struct ieee80211_mgmt *resp;
+
/*
* IEEE 802.11-REVma/D9.0 - 7.3.1.11
* Return the Action frame to the source without change
*/
wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
"frame back to sender");
- os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
- os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
- mgmt->u.action.category |= 0x80;
+ resp = os_malloc(len);
+ if (resp == NULL)
+ return;
+ os_memcpy(resp, mgmt, len);
+ os_memcpy(resp->da, resp->sa, ETH_ALEN);
+ os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+ resp->u.action.category |= 0x80;
- hostapd_send_mgmt_frame(hapd, mgmt, len);
+ hostapd_send_mgmt_frame(hapd, resp, len);
+ os_free(resp);
}
}
* sent to)
* @buf: management frame data (starting from IEEE 802.11 header)
* @len: length of frame data in octets
- * @stype: management frame subtype from frame control field
* @fi: meta data about received frame (signal level, etc.)
*
* Process all incoming IEEE 802.11 management frames. This will be called for
* addition, it can be called to re-inserted pending frames (e.g., when using
* external RADIUS server as an MAC ACL).
*/
-void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype,
+void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
struct hostapd_frame_info *fi)
{
- struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
+ struct ieee80211_mgmt *mgmt;
int broadcast;
+ u16 fc, stype;
+
+ mgmt = (struct ieee80211_mgmt *) buf;
+ fc = le_to_host16(mgmt->frame_control);
+ stype = WLAN_FC_GET_STYPE(fc);
if (stype == WLAN_FC_STYPE_BEACON) {
handle_beacon(hapd, mgmt, len, fi);
static void handle_auth_cb(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt,
+ const struct ieee80211_mgmt *mgmt,
size_t len, int ok)
{
u16 auth_alg, auth_transaction, status_code;
}
-#ifdef CONFIG_IEEE80211N
-static void
-hostapd_get_ht_capab(struct hostapd_data *hapd,
- struct ieee80211_ht_capabilities *ht_cap,
- struct ieee80211_ht_capabilities *neg_ht_cap)
-{
- u16 cap;
-
- if (ht_cap == NULL)
- return;
- os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
- cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
- cap &= hapd->iconf->ht_capab;
- cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
-
- /* FIXME: Rx STBC needs to be handled specially */
- cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK);
- neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
-}
-#endif /* CONFIG_IEEE80211N */
-
-
static void handle_assoc_cb(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt,
+ const struct ieee80211_mgmt *mgmt,
size_t len, int reassoc, int ok)
{
u16 status;
struct sta_info *sta;
int new_assoc = 1;
-#ifdef CONFIG_IEEE80211N
struct ieee80211_ht_capabilities ht_cap;
-#endif /* CONFIG_IEEE80211N */
- struct ieee80211_ht_capabilities *ht_cap_ptr = NULL;
- int set_flags, flags_and, flags_or;
+ int set_flags, total_flags, flags_and, flags_or;
if (!ok) {
hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
else
mlme_associate_indication(hapd, sta);
-#ifdef CONFIG_IEEE80211N
- if (sta->flags & WLAN_STA_HT) {
- ht_cap_ptr = &ht_cap;
- hostapd_get_ht_capab(hapd, sta->ht_capabilities, ht_cap_ptr);
- }
-#endif /* CONFIG_IEEE80211N */
-
#ifdef CONFIG_IEEE80211W
sta->sa_query_timed_out = 0;
#endif /* CONFIG_IEEE80211W */
*/
hostapd_sta_remove(hapd, sta->addr);
+#ifdef CONFIG_IEEE80211N
+ if (sta->flags & WLAN_STA_HT)
+ hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
+#endif /* CONFIG_IEEE80211N */
+
if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
sta->capability, sta->supported_rates,
- sta->supported_rates_len, 0, sta->listen_interval,
- ht_cap_ptr))
+ sta->supported_rates_len, sta->listen_interval,
+ sta->flags & WLAN_STA_HT ? &ht_cap : NULL))
{
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
ap_sta_bind_vlan(hapd, sta, 0);
}
- set_flags = WLAN_STA_SHORT_PREAMBLE | WLAN_STA_WMM | WLAN_STA_MFP;
+ total_flags = hostapd_sta_flags_to_drv(sta->flags);
+ set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
sta->flags & WLAN_STA_AUTHORIZED)
- set_flags |= WLAN_STA_AUTHORIZED;
- flags_or = sta->flags & set_flags;
- flags_and = sta->flags | ~set_flags;
- hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
+ set_flags |= WPA_STA_AUTHORIZED;
+ flags_or = total_flags & set_flags;
+ flags_and = total_flags | ~set_flags;
+ hostapd_sta_set_flags(hapd, sta->addr, total_flags,
flags_or, flags_and);
if (sta->auth_alg == WLAN_AUTH_FT)
* @stype: management frame subtype from frame control field
* @ok: Whether the frame was ACK'ed
*/
-void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
+void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
u16 stype, int ok)
{
- struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
+ const struct ieee80211_mgmt *mgmt;
+ mgmt = (const struct ieee80211_mgmt *) buf;
switch (stype) {
case WLAN_FC_STYPE_AUTH:
return 0;
}
+
+void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
+ const u8 *buf, size_t len, int ack)
+{
+ struct sta_info *sta;
+ struct hostapd_iface *iface = hapd->iface;
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL && iface->num_bss > 1) {
+ size_t j;
+ for (j = 0; j < iface->num_bss; j++) {
+ hapd = iface->bss[j];
+ sta = ap_get_sta(hapd, addr);
+ if (sta)
+ break;
+ }
+ }
+ if (sta == NULL)
+ return;
+ if (sta->flags & WLAN_STA_PENDING_POLL) {
+ wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
+ "activity poll", MAC2STR(sta->addr),
+ ack ? "ACKed" : "did not ACK");
+ if (ack)
+ sta->flags &= ~WLAN_STA_PENDING_POLL;
+ }
+
+ ieee802_1x_tx_status(hapd, sta, buf, len, ack);
+}
+
+
+void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src)
+{
+ struct sta_info *sta;
+
+ sta = ap_get_sta(hapd, src);
+ if (sta && (sta->flags & WLAN_STA_ASSOC))
+ return;
+
+ wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
+ MACSTR, MAC2STR(src));
+ if (sta && (sta->flags & WLAN_STA_AUTH))
+ hostapd_sta_disassoc(
+ hapd, src,
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ else
+ hostapd_sta_deauth(
+ hapd, src,
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+}
+
+
#endif /* CONFIG_NATIVE_WINDOWS */