Make hostapd_for_each_interface() take context pointer as argument
[libeap.git] / hostapd / ieee802_11.c
index b92065e..8d4fe39 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * 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"
@@ -38,7 +37,6 @@
 #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)
@@ -103,153 +101,6 @@ u8 * hostapd_eid_ext_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)
 {
@@ -345,7 +196,8 @@ void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len)
  * @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;
 
@@ -366,7 +218,8 @@ void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason)
 
 
 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,
@@ -488,15 +341,15 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
 #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];
@@ -783,112 +636,12 @@ static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
 }
 
 
-#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) {
@@ -907,10 +660,12 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
        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;
@@ -1068,7 +823,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
 
 
 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;
@@ -1100,8 +855,10 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
        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) {
@@ -1127,11 +884,12 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 
 
 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;
 
@@ -1254,7 +1012,9 @@ static void handle_assoc(struct hostapd_data *hapd,
                        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,
@@ -1296,7 +1056,7 @@ static void handle_assoc(struct hostapd_data *hapd,
 
 
 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;
 
@@ -1345,7 +1105,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
 
 
 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;
 
@@ -1382,7 +1142,7 @@ static void handle_deauth(struct hostapd_data *hapd,
 
 
 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;
@@ -1433,10 +1193,11 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
 
 
 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 +
@@ -1498,7 +1259,7 @@ static int robust_action_frame(u8 category)
 
 
 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;
 
@@ -1558,6 +1319,8 @@ static void handle_action(struct hostapd_data *hapd,
                       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
@@ -1565,12 +1328,17 @@ static void handle_action(struct hostapd_data *hapd,
                 */
                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);
        }
 }
 
@@ -1581,7 +1349,6 @@ static void handle_action(struct hostapd_data *hapd,
  * 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
@@ -1589,11 +1356,16 @@ static void handle_action(struct hostapd_data *hapd,
  * 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);
@@ -1660,7 +1432,7 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype,
 
 
 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;
@@ -1700,40 +1472,15 @@ static void handle_auth_cb(struct hostapd_data *hapd,
 }
 
 
-#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,
@@ -1788,13 +1535,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
        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 */
@@ -1806,10 +1546,15 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
         */
        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,
@@ -1828,13 +1573,14 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
                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)
@@ -1863,10 +1609,11 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
  * @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:
@@ -1911,4 +1658,56 @@ int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
        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 */