LCOV - code coverage report
Current view: top level - ap - ieee802_11.c (source / functions) Hit Total Coverage
Test: hostapd (AS) hwsim test run 1401872338 Lines: 23 1148 2.0 %
Date: 2014-06-04 Functions: 3 41 7.3 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / IEEE 802.11 Management
       3             :  * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #ifndef CONFIG_NATIVE_WINDOWS
      12             : 
      13             : #include "utils/common.h"
      14             : #include "utils/eloop.h"
      15             : #include "crypto/crypto.h"
      16             : #include "crypto/sha256.h"
      17             : #include "crypto/random.h"
      18             : #include "common/ieee802_11_defs.h"
      19             : #include "common/ieee802_11_common.h"
      20             : #include "common/wpa_ctrl.h"
      21             : #include "common/sae.h"
      22             : #include "radius/radius.h"
      23             : #include "radius/radius_client.h"
      24             : #include "p2p/p2p.h"
      25             : #include "wps/wps.h"
      26             : #include "hostapd.h"
      27             : #include "beacon.h"
      28             : #include "ieee802_11_auth.h"
      29             : #include "sta_info.h"
      30             : #include "ieee802_1x.h"
      31             : #include "wpa_auth.h"
      32             : #include "wmm.h"
      33             : #include "ap_list.h"
      34             : #include "accounting.h"
      35             : #include "ap_config.h"
      36             : #include "ap_mlme.h"
      37             : #include "p2p_hostapd.h"
      38             : #include "ap_drv_ops.h"
      39             : #include "wnm_ap.h"
      40             : #include "ieee802_11.h"
      41             : #include "dfs.h"
      42             : 
      43             : 
      44           2 : u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
      45             : {
      46           2 :         u8 *pos = eid;
      47             :         int i, num, count;
      48             : 
      49           2 :         if (hapd->iface->current_rates == NULL)
      50           2 :                 return eid;
      51             : 
      52           0 :         *pos++ = WLAN_EID_SUPP_RATES;
      53           0 :         num = hapd->iface->num_rates;
      54           0 :         if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
      55           0 :                 num++;
      56           0 :         if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
      57           0 :                 num++;
      58           0 :         if (num > 8) {
      59             :                 /* rest of the rates are encoded in Extended supported
      60             :                  * rates element */
      61           0 :                 num = 8;
      62             :         }
      63             : 
      64           0 :         *pos++ = num;
      65           0 :         for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
      66           0 :              i++) {
      67           0 :                 count++;
      68           0 :                 *pos = hapd->iface->current_rates[i].rate / 5;
      69           0 :                 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
      70           0 :                         *pos |= 0x80;
      71           0 :                 pos++;
      72             :         }
      73             : 
      74           0 :         if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
      75           0 :                 count++;
      76           0 :                 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
      77             :         }
      78             : 
      79           0 :         if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
      80           0 :                 count++;
      81           0 :                 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
      82             :         }
      83             : 
      84           0 :         return pos;
      85             : }
      86             : 
      87             : 
      88           2 : u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
      89             : {
      90           2 :         u8 *pos = eid;
      91             :         int i, num, count;
      92             : 
      93           2 :         if (hapd->iface->current_rates == NULL)
      94           2 :                 return eid;
      95             : 
      96           0 :         num = hapd->iface->num_rates;
      97           0 :         if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
      98           0 :                 num++;
      99           0 :         if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
     100           0 :                 num++;
     101           0 :         if (num <= 8)
     102           0 :                 return eid;
     103           0 :         num -= 8;
     104             : 
     105           0 :         *pos++ = WLAN_EID_EXT_SUPP_RATES;
     106           0 :         *pos++ = num;
     107           0 :         for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
     108           0 :              i++) {
     109           0 :                 count++;
     110           0 :                 if (count <= 8)
     111           0 :                         continue; /* already in SuppRates IE */
     112           0 :                 *pos = hapd->iface->current_rates[i].rate / 5;
     113           0 :                 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
     114           0 :                         *pos |= 0x80;
     115           0 :                 pos++;
     116             :         }
     117             : 
     118           0 :         if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
     119           0 :                 count++;
     120           0 :                 if (count > 8)
     121           0 :                         *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
     122             :         }
     123             : 
     124           0 :         if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
     125           0 :                 count++;
     126           0 :                 if (count > 8)
     127           0 :                         *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
     128             :         }
     129             : 
     130           0 :         return pos;
     131             : }
     132             : 
     133             : 
     134           2 : u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
     135             :                            int probe)
     136             : {
     137           2 :         int capab = WLAN_CAPABILITY_ESS;
     138             :         int privacy;
     139             :         int dfs;
     140             : 
     141             :         /* Check if any of configured channels require DFS */
     142           2 :         dfs = hostapd_is_dfs_required(hapd->iface);
     143           2 :         if (dfs < 0) {
     144           0 :                 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
     145             :                            dfs);
     146           0 :                 dfs = 0;
     147             :         }
     148             : 
     149           4 :         if (hapd->iface->num_sta_no_short_preamble == 0 &&
     150           2 :             hapd->iconf->preamble == SHORT_PREAMBLE)
     151           0 :                 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
     152             : 
     153           2 :         privacy = hapd->conf->ssid.wep.keys_set;
     154             : 
     155           2 :         if (hapd->conf->ieee802_1x &&
     156           0 :             (hapd->conf->default_wep_key_len ||
     157           0 :              hapd->conf->individual_wep_key_len))
     158           0 :                 privacy = 1;
     159             : 
     160           2 :         if (hapd->conf->wpa)
     161           0 :                 privacy = 1;
     162             : 
     163             : #ifdef CONFIG_HS20
     164           2 :         if (hapd->conf->osen)
     165           0 :                 privacy = 1;
     166             : #endif /* CONFIG_HS20 */
     167             : 
     168           2 :         if (sta) {
     169             :                 int policy, def_klen;
     170           0 :                 if (probe && sta->ssid_probe) {
     171           0 :                         policy = sta->ssid_probe->security_policy;
     172           0 :                         def_klen = sta->ssid_probe->wep.default_len;
     173             :                 } else {
     174           0 :                         policy = sta->ssid->security_policy;
     175           0 :                         def_klen = sta->ssid->wep.default_len;
     176             :                 }
     177           0 :                 privacy = policy != SECURITY_PLAINTEXT;
     178           0 :                 if (policy == SECURITY_IEEE_802_1X && def_klen == 0)
     179           0 :                         privacy = 0;
     180             :         }
     181             : 
     182           2 :         if (privacy)
     183           0 :                 capab |= WLAN_CAPABILITY_PRIVACY;
     184             : 
     185           2 :         if (hapd->iface->current_mode &&
     186           0 :             hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
     187           0 :             hapd->iface->num_sta_no_short_slot_time == 0)
     188           0 :                 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
     189             : 
     190             :         /*
     191             :          * Currently, Spectrum Management capability bit is set when directly
     192             :          * requested in configuration by spectrum_mgmt_required or when AP is
     193             :          * running on DFS channel.
     194             :          * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit
     195             :          */
     196           2 :         if (hapd->iface->current_mode &&
     197           0 :             hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
     198           0 :             (hapd->iconf->spectrum_mgmt_required || dfs))
     199           0 :                 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
     200             : 
     201           2 :         return capab;
     202             : }
     203             : 
     204             : 
     205           0 : static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
     206             :                            u16 auth_transaction, const u8 *challenge,
     207             :                            int iswep)
     208             : {
     209           0 :         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     210             :                        HOSTAPD_LEVEL_DEBUG,
     211             :                        "authentication (shared key, transaction %d)",
     212             :                        auth_transaction);
     213             : 
     214           0 :         if (auth_transaction == 1) {
     215           0 :                 if (!sta->challenge) {
     216             :                         /* Generate a pseudo-random challenge */
     217             :                         u8 key[8];
     218             :                         struct os_time now;
     219             :                         int r;
     220           0 :                         sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
     221           0 :                         if (sta->challenge == NULL)
     222           0 :                                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     223             : 
     224           0 :                         os_get_time(&now);
     225           0 :                         r = os_random();
     226           0 :                         os_memcpy(key, &now.sec, 4);
     227           0 :                         os_memcpy(key + 4, &r, 4);
     228           0 :                         rc4_skip(key, sizeof(key), 0,
     229             :                                  sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
     230             :                 }
     231           0 :                 return 0;
     232             :         }
     233             : 
     234           0 :         if (auth_transaction != 3)
     235           0 :                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     236             : 
     237             :         /* Transaction 3 */
     238           0 :         if (!iswep || !sta->challenge || !challenge ||
     239           0 :             os_memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) {
     240           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     241             :                                HOSTAPD_LEVEL_INFO,
     242             :                                "shared key authentication - invalid "
     243             :                                "challenge-response");
     244           0 :                 return WLAN_STATUS_CHALLENGE_FAIL;
     245             :         }
     246             : 
     247           0 :         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     248             :                        HOSTAPD_LEVEL_DEBUG,
     249             :                        "authentication OK (shared key)");
     250           0 :         sta->flags |= WLAN_STA_AUTH;
     251           0 :         wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
     252           0 :         os_free(sta->challenge);
     253           0 :         sta->challenge = NULL;
     254             : 
     255           0 :         return 0;
     256             : }
     257             : 
     258             : 
     259           0 : static void send_auth_reply(struct hostapd_data *hapd,
     260             :                             const u8 *dst, const u8 *bssid,
     261             :                             u16 auth_alg, u16 auth_transaction, u16 resp,
     262             :                             const u8 *ies, size_t ies_len)
     263             : {
     264             :         struct ieee80211_mgmt *reply;
     265             :         u8 *buf;
     266             :         size_t rlen;
     267             : 
     268           0 :         rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
     269           0 :         buf = os_zalloc(rlen);
     270           0 :         if (buf == NULL)
     271           0 :                 return;
     272             : 
     273           0 :         reply = (struct ieee80211_mgmt *) buf;
     274           0 :         reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
     275             :                                             WLAN_FC_STYPE_AUTH);
     276           0 :         os_memcpy(reply->da, dst, ETH_ALEN);
     277           0 :         os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
     278           0 :         os_memcpy(reply->bssid, bssid, ETH_ALEN);
     279             : 
     280           0 :         reply->u.auth.auth_alg = host_to_le16(auth_alg);
     281           0 :         reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
     282           0 :         reply->u.auth.status_code = host_to_le16(resp);
     283             : 
     284           0 :         if (ies && ies_len)
     285           0 :                 os_memcpy(reply->u.auth.variable, ies, ies_len);
     286             : 
     287           0 :         wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
     288             :                    " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
     289           0 :                    MAC2STR(dst), auth_alg, auth_transaction,
     290             :                    resp, (unsigned long) ies_len);
     291           0 :         if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
     292           0 :                 wpa_printf(MSG_INFO, "send_auth_reply: send");
     293             : 
     294           0 :         os_free(buf);
     295             : }
     296             : 
     297             : 
     298             : #ifdef CONFIG_IEEE80211R
     299           0 : static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
     300             :                                   u16 auth_transaction, u16 status,
     301             :                                   const u8 *ies, size_t ies_len)
     302             : {
     303           0 :         struct hostapd_data *hapd = ctx;
     304             :         struct sta_info *sta;
     305             : 
     306           0 :         send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, auth_transaction,
     307             :                         status, ies, ies_len);
     308             : 
     309           0 :         if (status != WLAN_STATUS_SUCCESS)
     310           0 :                 return;
     311             : 
     312           0 :         sta = ap_get_sta(hapd, dst);
     313           0 :         if (sta == NULL)
     314           0 :                 return;
     315             : 
     316           0 :         hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
     317             :                        HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
     318           0 :         sta->flags |= WLAN_STA_AUTH;
     319           0 :         mlme_authenticate_indication(hapd, sta);
     320             : }
     321             : #endif /* CONFIG_IEEE80211R */
     322             : 
     323             : 
     324             : #ifdef CONFIG_SAE
     325             : 
     326           0 : static struct wpabuf * auth_process_sae_commit(struct hostapd_data *hapd,
     327             :                                                struct sta_info *sta)
     328             : {
     329             :         struct wpabuf *buf;
     330             : 
     331           0 :         if (hapd->conf->ssid.wpa_passphrase == NULL) {
     332           0 :                 wpa_printf(MSG_DEBUG, "SAE: No password available");
     333           0 :                 return NULL;
     334             :         }
     335             : 
     336           0 :         if (sae_prepare_commit(hapd->own_addr, sta->addr,
     337           0 :                                (u8 *) hapd->conf->ssid.wpa_passphrase,
     338           0 :                                os_strlen(hapd->conf->ssid.wpa_passphrase),
     339             :                                sta->sae) < 0) {
     340           0 :                 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
     341           0 :                 return NULL;
     342             :         }
     343             : 
     344           0 :         if (sae_process_commit(sta->sae) < 0) {
     345           0 :                 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer commit");
     346           0 :                 return NULL;
     347             :         }
     348             : 
     349           0 :         buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
     350           0 :         if (buf == NULL)
     351           0 :                 return NULL;
     352           0 :         sae_write_commit(sta->sae, buf, NULL);
     353             : 
     354           0 :         return buf;
     355             : }
     356             : 
     357             : 
     358           0 : static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
     359             :                                               struct sta_info *sta)
     360             : {
     361             :         struct wpabuf *buf;
     362             : 
     363           0 :         buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
     364           0 :         if (buf == NULL)
     365           0 :                 return NULL;
     366             : 
     367           0 :         sae_write_confirm(sta->sae, buf);
     368             : 
     369           0 :         return buf;
     370             : }
     371             : 
     372             : 
     373           0 : static int use_sae_anti_clogging(struct hostapd_data *hapd)
     374             : {
     375             :         struct sta_info *sta;
     376           0 :         unsigned int open = 0;
     377             : 
     378           0 :         if (hapd->conf->sae_anti_clogging_threshold == 0)
     379           0 :                 return 1;
     380             : 
     381           0 :         for (sta = hapd->sta_list; sta; sta = sta->next) {
     382           0 :                 if (!sta->sae)
     383           0 :                         continue;
     384           0 :                 if (sta->sae->state != SAE_COMMITTED &&
     385           0 :                     sta->sae->state != SAE_CONFIRMED)
     386           0 :                         continue;
     387           0 :                 open++;
     388           0 :                 if (open >= hapd->conf->sae_anti_clogging_threshold)
     389           0 :                         return 1;
     390             :         }
     391             : 
     392           0 :         return 0;
     393             : }
     394             : 
     395             : 
     396           0 : static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
     397             :                            const u8 *token, size_t token_len)
     398             : {
     399             :         u8 mac[SHA256_MAC_LEN];
     400             : 
     401           0 :         if (token_len != SHA256_MAC_LEN)
     402           0 :                 return -1;
     403           0 :         if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
     404           0 :                         addr, ETH_ALEN, mac) < 0 ||
     405           0 :             os_memcmp(token, mac, SHA256_MAC_LEN) != 0)
     406           0 :                 return -1;
     407             : 
     408           0 :         return 0;
     409             : }
     410             : 
     411             : 
     412           0 : static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
     413             :                                             const u8 *addr)
     414             : {
     415             :         struct wpabuf *buf;
     416             :         u8 *token;
     417             :         struct os_reltime now;
     418             : 
     419           0 :         os_get_reltime(&now);
     420           0 :         if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
     421           0 :             os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) {
     422           0 :                 if (random_get_bytes(hapd->sae_token_key,
     423             :                                      sizeof(hapd->sae_token_key)) < 0)
     424           0 :                         return NULL;
     425           0 :                 wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
     426           0 :                             hapd->sae_token_key, sizeof(hapd->sae_token_key));
     427           0 :                 hapd->last_sae_token_key_update = now;
     428             :         }
     429             : 
     430           0 :         buf = wpabuf_alloc(SHA256_MAC_LEN);
     431           0 :         if (buf == NULL)
     432           0 :                 return NULL;
     433             : 
     434           0 :         token = wpabuf_put(buf, SHA256_MAC_LEN);
     435           0 :         hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
     436             :                     addr, ETH_ALEN, token);
     437             : 
     438           0 :         return buf;
     439             : }
     440             : 
     441             : 
     442           0 : static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
     443             :                             const struct ieee80211_mgmt *mgmt, size_t len,
     444             :                             u8 auth_transaction)
     445             : {
     446           0 :         u16 resp = WLAN_STATUS_SUCCESS;
     447           0 :         struct wpabuf *data = NULL;
     448             : 
     449           0 :         if (!sta->sae) {
     450           0 :                 if (auth_transaction != 1)
     451           0 :                         return;
     452           0 :                 sta->sae = os_zalloc(sizeof(*sta->sae));
     453           0 :                 if (sta->sae == NULL)
     454           0 :                         return;
     455           0 :                 sta->sae->state = SAE_NOTHING;
     456             :         }
     457             : 
     458           0 :         if (auth_transaction == 1) {
     459           0 :                 const u8 *token = NULL;
     460           0 :                 size_t token_len = 0;
     461           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     462             :                                HOSTAPD_LEVEL_DEBUG,
     463             :                                "start SAE authentication (RX commit)");
     464           0 :                 resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
     465           0 :                                         ((const u8 *) mgmt) + len -
     466             :                                         mgmt->u.auth.variable, &token,
     467           0 :                                         &token_len, hapd->conf->sae_groups);
     468           0 :                 if (token && check_sae_token(hapd, sta->addr, token, token_len)
     469             :                     < 0) {
     470           0 :                         wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
     471             :                                    "incorrect token from " MACSTR,
     472           0 :                                    MAC2STR(sta->addr));
     473           0 :                         return;
     474             :                 }
     475             : 
     476           0 :                 if (resp == WLAN_STATUS_SUCCESS) {
     477           0 :                         if (!token && use_sae_anti_clogging(hapd)) {
     478           0 :                                 wpa_printf(MSG_DEBUG, "SAE: Request anti-"
     479             :                                            "clogging token from " MACSTR,
     480           0 :                                            MAC2STR(sta->addr));
     481           0 :                                 data = auth_build_token_req(hapd, sta->addr);
     482           0 :                                 resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
     483             :                         } else {
     484           0 :                                 data = auth_process_sae_commit(hapd, sta);
     485           0 :                                 if (data == NULL)
     486           0 :                                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
     487             :                                 else
     488           0 :                                         sta->sae->state = SAE_COMMITTED;
     489             :                         }
     490             :                 }
     491           0 :         } else if (auth_transaction == 2) {
     492           0 :                 if (sta->sae->state != SAE_COMMITTED) {
     493           0 :                         hostapd_logger(hapd, sta->addr,
     494             :                                        HOSTAPD_MODULE_IEEE80211,
     495             :                                        HOSTAPD_LEVEL_DEBUG,
     496             :                                        "SAE confirm before commit");
     497           0 :                         resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
     498           0 :                         goto failed;
     499             :                 }
     500           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     501             :                                HOSTAPD_LEVEL_DEBUG,
     502             :                                "SAE authentication (RX confirm)");
     503           0 :                 if (sae_check_confirm(sta->sae, mgmt->u.auth.variable,
     504           0 :                                        ((u8 *) mgmt) + len -
     505             :                                        mgmt->u.auth.variable) < 0) {
     506           0 :                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
     507             :                 } else {
     508           0 :                         resp = WLAN_STATUS_SUCCESS;
     509           0 :                         sta->flags |= WLAN_STA_AUTH;
     510           0 :                         wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
     511           0 :                         sta->auth_alg = WLAN_AUTH_SAE;
     512           0 :                         mlme_authenticate_indication(hapd, sta);
     513             : 
     514           0 :                         data = auth_build_sae_confirm(hapd, sta);
     515           0 :                         if (data == NULL)
     516           0 :                                 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
     517             :                         else {
     518           0 :                                 sta->sae->state = SAE_ACCEPTED;
     519           0 :                                 sae_clear_temp_data(sta->sae);
     520             :                         }
     521             :                 }
     522             :         } else {
     523           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     524             :                                HOSTAPD_LEVEL_DEBUG,
     525             :                                "unexpected SAE authentication transaction %u",
     526             :                                auth_transaction);
     527           0 :                 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
     528             :         }
     529             : 
     530             : failed:
     531           0 :         sta->auth_alg = WLAN_AUTH_SAE;
     532             : 
     533           0 :         send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
     534             :                         auth_transaction, resp,
     535             :                         data ? wpabuf_head(data) : (u8 *) "",
     536             :                         data ? wpabuf_len(data) : 0);
     537           0 :         wpabuf_free(data);
     538             : }
     539             : #endif /* CONFIG_SAE */
     540             : 
     541             : 
     542           0 : static void handle_auth(struct hostapd_data *hapd,
     543             :                         const struct ieee80211_mgmt *mgmt, size_t len)
     544             : {
     545             :         u16 auth_alg, auth_transaction, status_code;
     546           0 :         u16 resp = WLAN_STATUS_SUCCESS;
     547           0 :         struct sta_info *sta = NULL;
     548             :         int res;
     549             :         u16 fc;
     550           0 :         const u8 *challenge = NULL;
     551             :         u32 session_timeout, acct_interim_interval;
     552           0 :         int vlan_id = 0;
     553           0 :         struct hostapd_sta_wpa_psk_short *psk = NULL;
     554             :         u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
     555           0 :         size_t resp_ies_len = 0;
     556           0 :         char *identity = NULL;
     557           0 :         char *radius_cui = NULL;
     558             : 
     559           0 :         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
     560           0 :                 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
     561             :                            (unsigned long) len);
     562           0 :                 return;
     563             :         }
     564             : 
     565             : #ifdef CONFIG_TESTING_OPTIONS
     566           0 :         if (hapd->iconf->ignore_auth_probability > 0.0 &&
     567           0 :             drand48() < hapd->iconf->ignore_auth_probability) {
     568           0 :                 wpa_printf(MSG_INFO,
     569             :                            "TESTING: ignoring auth frame from " MACSTR,
     570           0 :                            MAC2STR(mgmt->sa));
     571           0 :                 return;
     572             :         }
     573             : #endif /* CONFIG_TESTING_OPTIONS */
     574             : 
     575           0 :         auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
     576           0 :         auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
     577           0 :         status_code = le_to_host16(mgmt->u.auth.status_code);
     578           0 :         fc = le_to_host16(mgmt->frame_control);
     579             : 
     580           0 :         if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
     581           0 :             2 + WLAN_AUTH_CHALLENGE_LEN &&
     582           0 :             mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
     583           0 :             mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
     584           0 :                 challenge = &mgmt->u.auth.variable[2];
     585             : 
     586           0 :         wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
     587             :                    "auth_transaction=%d status_code=%d wep=%d%s",
     588           0 :                    MAC2STR(mgmt->sa), auth_alg, auth_transaction,
     589           0 :                    status_code, !!(fc & WLAN_FC_ISWEP),
     590             :                    challenge ? " challenge" : "");
     591             : 
     592           0 :         if (hapd->tkip_countermeasures) {
     593           0 :                 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
     594           0 :                 goto fail;
     595             :         }
     596             : 
     597           0 :         if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
     598           0 :                auth_alg == WLAN_AUTH_OPEN) ||
     599             : #ifdef CONFIG_IEEE80211R
     600           0 :               (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
     601           0 :                auth_alg == WLAN_AUTH_FT) ||
     602             : #endif /* CONFIG_IEEE80211R */
     603             : #ifdef CONFIG_SAE
     604           0 :               (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
     605             :                auth_alg == WLAN_AUTH_SAE) ||
     606             : #endif /* CONFIG_SAE */
     607           0 :               ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
     608             :                auth_alg == WLAN_AUTH_SHARED_KEY))) {
     609           0 :                 wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
     610             :                            auth_alg);
     611           0 :                 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
     612           0 :                 goto fail;
     613             :         }
     614             : 
     615           0 :         if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
     616           0 :               (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
     617           0 :                 wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
     618             :                            auth_transaction);
     619           0 :                 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
     620           0 :                 goto fail;
     621             :         }
     622             : 
     623           0 :         if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
     624           0 :                 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
     625           0 :                            MAC2STR(mgmt->sa));
     626           0 :                 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
     627           0 :                 goto fail;
     628             :         }
     629             : 
     630           0 :         res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
     631             :                                       &session_timeout,
     632             :                                       &acct_interim_interval, &vlan_id,
     633             :                                       &psk, &identity, &radius_cui);
     634             : 
     635           0 :         if (res == HOSTAPD_ACL_REJECT) {
     636           0 :                 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
     637           0 :                            MAC2STR(mgmt->sa));
     638           0 :                 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
     639           0 :                 goto fail;
     640             :         }
     641           0 :         if (res == HOSTAPD_ACL_PENDING) {
     642           0 :                 wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
     643             :                            " waiting for an external authentication",
     644           0 :                            MAC2STR(mgmt->sa));
     645             :                 /* Authentication code will re-send the authentication frame
     646             :                  * after it has received (and cached) information from the
     647             :                  * external source. */
     648           0 :                 return;
     649             :         }
     650             : 
     651           0 :         sta = ap_sta_add(hapd, mgmt->sa);
     652           0 :         if (!sta) {
     653           0 :                 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
     654           0 :                 goto fail;
     655             :         }
     656             : 
     657           0 :         if (vlan_id > 0) {
     658           0 :                 if (!hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
     659           0 :                         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
     660             :                                        HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
     661             :                                        "%d received from RADIUS server",
     662             :                                        vlan_id);
     663           0 :                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
     664           0 :                         goto fail;
     665             :                 }
     666           0 :                 sta->vlan_id = vlan_id;
     667           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
     668             :                                HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
     669             :         }
     670             : 
     671           0 :         hostapd_free_psk_list(sta->psk);
     672           0 :         if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
     673           0 :                 sta->psk = psk;
     674           0 :                 psk = NULL;
     675             :         } else {
     676           0 :                 sta->psk = NULL;
     677             :         }
     678             : 
     679           0 :         sta->identity = identity;
     680           0 :         identity = NULL;
     681           0 :         sta->radius_cui = radius_cui;
     682           0 :         radius_cui = NULL;
     683             : 
     684           0 :         sta->flags &= ~WLAN_STA_PREAUTH;
     685           0 :         ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
     686             : 
     687           0 :         if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
     688           0 :                 sta->acct_interim_interval = acct_interim_interval;
     689           0 :         if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
     690           0 :                 ap_sta_session_timeout(hapd, sta, session_timeout);
     691             :         else
     692           0 :                 ap_sta_no_session_timeout(hapd, sta);
     693             : 
     694           0 :         switch (auth_alg) {
     695             :         case WLAN_AUTH_OPEN:
     696           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     697             :                                HOSTAPD_LEVEL_DEBUG,
     698             :                                "authentication OK (open system)");
     699           0 :                 sta->flags |= WLAN_STA_AUTH;
     700           0 :                 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
     701           0 :                 sta->auth_alg = WLAN_AUTH_OPEN;
     702           0 :                 mlme_authenticate_indication(hapd, sta);
     703           0 :                 break;
     704             :         case WLAN_AUTH_SHARED_KEY:
     705           0 :                 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
     706             :                                        fc & WLAN_FC_ISWEP);
     707           0 :                 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
     708           0 :                 mlme_authenticate_indication(hapd, sta);
     709           0 :                 if (sta->challenge && auth_transaction == 1) {
     710           0 :                         resp_ies[0] = WLAN_EID_CHALLENGE;
     711           0 :                         resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
     712           0 :                         os_memcpy(resp_ies + 2, sta->challenge,
     713             :                                   WLAN_AUTH_CHALLENGE_LEN);
     714           0 :                         resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
     715             :                 }
     716           0 :                 break;
     717             : #ifdef CONFIG_IEEE80211R
     718             :         case WLAN_AUTH_FT:
     719           0 :                 sta->auth_alg = WLAN_AUTH_FT;
     720           0 :                 if (sta->wpa_sm == NULL)
     721           0 :                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
     722           0 :                                                         sta->addr, NULL);
     723           0 :                 if (sta->wpa_sm == NULL) {
     724           0 :                         wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
     725             :                                    "state machine");
     726           0 :                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
     727           0 :                         goto fail;
     728             :                 }
     729           0 :                 wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
     730           0 :                                     auth_transaction, mgmt->u.auth.variable,
     731             :                                     len - IEEE80211_HDRLEN -
     732             :                                     sizeof(mgmt->u.auth),
     733             :                                     handle_auth_ft_finish, hapd);
     734             :                 /* handle_auth_ft_finish() callback will complete auth. */
     735           0 :                 return;
     736             : #endif /* CONFIG_IEEE80211R */
     737             : #ifdef CONFIG_SAE
     738             :         case WLAN_AUTH_SAE:
     739           0 :                 handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
     740           0 :                 return;
     741             : #endif /* CONFIG_SAE */
     742             :         }
     743             : 
     744             :  fail:
     745           0 :         os_free(identity);
     746           0 :         os_free(radius_cui);
     747           0 :         hostapd_free_psk_list(psk);
     748             : 
     749           0 :         send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
     750             :                         auth_transaction + 1, resp, resp_ies, resp_ies_len);
     751             : }
     752             : 
     753             : 
     754           0 : static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
     755             : {
     756           0 :         int i, j = 32, aid;
     757             : 
     758             :         /* get a unique AID */
     759           0 :         if (sta->aid > 0) {
     760           0 :                 wpa_printf(MSG_DEBUG, "  old AID %d", sta->aid);
     761           0 :                 return 0;
     762             :         }
     763             : 
     764           0 :         for (i = 0; i < AID_WORDS; i++) {
     765           0 :                 if (hapd->sta_aid[i] == (u32) -1)
     766           0 :                         continue;
     767           0 :                 for (j = 0; j < 32; j++) {
     768           0 :                         if (!(hapd->sta_aid[i] & BIT(j)))
     769           0 :                                 break;
     770             :                 }
     771           0 :                 if (j < 32)
     772           0 :                         break;
     773             :         }
     774           0 :         if (j == 32)
     775           0 :                 return -1;
     776           0 :         aid = i * 32 + j + 1;
     777           0 :         if (aid > 2007)
     778           0 :                 return -1;
     779             : 
     780           0 :         sta->aid = aid;
     781           0 :         hapd->sta_aid[i] |= BIT(j);
     782           0 :         wpa_printf(MSG_DEBUG, "  new AID %d", sta->aid);
     783           0 :         return 0;
     784             : }
     785             : 
     786             : 
     787           0 : static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
     788             :                       const u8 *ssid_ie, size_t ssid_ie_len)
     789             : {
     790           0 :         if (ssid_ie == NULL)
     791           0 :                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     792             : 
     793           0 :         if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
     794           0 :             os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
     795           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     796             :                                HOSTAPD_LEVEL_INFO,
     797             :                                "Station tried to associate with unknown SSID "
     798             :                                "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
     799           0 :                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     800             :         }
     801             : 
     802           0 :         return WLAN_STATUS_SUCCESS;
     803             : }
     804             : 
     805             : 
     806           0 : static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
     807             :                      const u8 *wmm_ie, size_t wmm_ie_len)
     808             : {
     809           0 :         sta->flags &= ~WLAN_STA_WMM;
     810           0 :         sta->qosinfo = 0;
     811           0 :         if (wmm_ie && hapd->conf->wmm_enabled) {
     812             :                 struct wmm_information_element *wmm;
     813             : 
     814           0 :                 if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
     815           0 :                         hostapd_logger(hapd, sta->addr,
     816             :                                        HOSTAPD_MODULE_WPA,
     817             :                                        HOSTAPD_LEVEL_DEBUG,
     818             :                                        "invalid WMM element in association "
     819             :                                        "request");
     820           0 :                         return WLAN_STATUS_UNSPECIFIED_FAILURE;
     821             :                 }
     822             : 
     823           0 :                 sta->flags |= WLAN_STA_WMM;
     824           0 :                 wmm = (struct wmm_information_element *) wmm_ie;
     825           0 :                 sta->qosinfo = wmm->qos_info;
     826             :         }
     827           0 :         return WLAN_STATUS_SUCCESS;
     828             : }
     829             : 
     830             : 
     831           0 : static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
     832             :                            struct ieee802_11_elems *elems)
     833             : {
     834           0 :         if (!elems->supp_rates) {
     835           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     836             :                                HOSTAPD_LEVEL_DEBUG,
     837             :                                "No supported rates element in AssocReq");
     838           0 :                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     839             :         }
     840             : 
     841           0 :         if (elems->supp_rates_len + elems->ext_supp_rates_len >
     842             :             sizeof(sta->supported_rates)) {
     843           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     844             :                                HOSTAPD_LEVEL_DEBUG,
     845             :                                "Invalid supported rates element length %d+%d",
     846           0 :                                elems->supp_rates_len,
     847           0 :                                elems->ext_supp_rates_len);
     848           0 :                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     849             :         }
     850             : 
     851           0 :         sta->supported_rates_len = merge_byte_arrays(
     852           0 :                 sta->supported_rates, sizeof(sta->supported_rates),
     853           0 :                 elems->supp_rates, elems->supp_rates_len,
     854           0 :                 elems->ext_supp_rates, elems->ext_supp_rates_len);
     855             : 
     856           0 :         return WLAN_STATUS_SUCCESS;
     857             : }
     858             : 
     859             : 
     860           0 : static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
     861             :                            const u8 *ext_capab_ie, size_t ext_capab_ie_len)
     862             : {
     863             : #ifdef CONFIG_INTERWORKING
     864             :         /* check for QoS Map support */
     865           0 :         if (ext_capab_ie_len >= 5) {
     866           0 :                 if (ext_capab_ie[4] & 0x01)
     867           0 :                         sta->qos_map_enabled = 1;
     868             :         }
     869             : #endif /* CONFIG_INTERWORKING */
     870             : 
     871           0 :         return WLAN_STATUS_SUCCESS;
     872             : }
     873             : 
     874             : 
     875           0 : static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
     876             :                            const u8 *ies, size_t ies_len, int reassoc)
     877             : {
     878             :         struct ieee802_11_elems elems;
     879             :         u16 resp;
     880             :         const u8 *wpa_ie;
     881             :         size_t wpa_ie_len;
     882           0 :         const u8 *p2p_dev_addr = NULL;
     883             : 
     884           0 :         if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
     885           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     886             :                                HOSTAPD_LEVEL_INFO, "Station sent an invalid "
     887             :                                "association request");
     888           0 :                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     889             :         }
     890             : 
     891           0 :         resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
     892           0 :         if (resp != WLAN_STATUS_SUCCESS)
     893           0 :                 return resp;
     894           0 :         resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
     895           0 :         if (resp != WLAN_STATUS_SUCCESS)
     896           0 :                 return resp;
     897           0 :         resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
     898           0 :         if (resp != WLAN_STATUS_SUCCESS)
     899           0 :                 return resp;
     900           0 :         resp = copy_supp_rates(hapd, sta, &elems);
     901           0 :         if (resp != WLAN_STATUS_SUCCESS)
     902           0 :                 return resp;
     903             : #ifdef CONFIG_IEEE80211N
     904           0 :         resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities,
     905           0 :                                  elems.ht_capabilities_len);
     906           0 :         if (resp != WLAN_STATUS_SUCCESS)
     907           0 :                 return resp;
     908           0 :         if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
     909           0 :             !(sta->flags & WLAN_STA_HT)) {
     910           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     911             :                                HOSTAPD_LEVEL_INFO, "Station does not support "
     912             :                                "mandatory HT PHY - reject association");
     913           0 :                 return WLAN_STATUS_ASSOC_DENIED_NO_HT;
     914             :         }
     915             : #endif /* CONFIG_IEEE80211N */
     916             : 
     917             : #ifdef CONFIG_IEEE80211AC
     918           0 :         resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities,
     919           0 :                                   elems.vht_capabilities_len);
     920           0 :         if (resp != WLAN_STATUS_SUCCESS)
     921           0 :                 return resp;
     922             : 
     923           0 :         resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
     924           0 :         if (resp != WLAN_STATUS_SUCCESS)
     925           0 :                 return resp;
     926             : 
     927           0 :         if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
     928           0 :             !(sta->flags & WLAN_STA_VHT)) {
     929           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     930             :                                HOSTAPD_LEVEL_INFO, "Station does not support "
     931             :                                "mandatory VHT PHY - reject association");
     932           0 :                 return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
     933             :         }
     934             : #endif /* CONFIG_IEEE80211AC */
     935             : 
     936             : #ifdef CONFIG_P2P
     937             :         if (elems.p2p) {
     938             :                 wpabuf_free(sta->p2p_ie);
     939             :                 sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
     940             :                                                           P2P_IE_VENDOR_TYPE);
     941             :                 if (sta->p2p_ie)
     942             :                         p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
     943             :         } else {
     944             :                 wpabuf_free(sta->p2p_ie);
     945             :                 sta->p2p_ie = NULL;
     946             :         }
     947             : #endif /* CONFIG_P2P */
     948             : 
     949           0 :         if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
     950           0 :                 wpa_ie = elems.rsn_ie;
     951           0 :                 wpa_ie_len = elems.rsn_ie_len;
     952           0 :         } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
     953           0 :                    elems.wpa_ie) {
     954           0 :                 wpa_ie = elems.wpa_ie;
     955           0 :                 wpa_ie_len = elems.wpa_ie_len;
     956             :         } else {
     957           0 :                 wpa_ie = NULL;
     958           0 :                 wpa_ie_len = 0;
     959             :         }
     960             : 
     961             : #ifdef CONFIG_WPS
     962           0 :         sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
     963           0 :         if (hapd->conf->wps_state && elems.wps_ie) {
     964           0 :                 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
     965             :                            "Request - assume WPS is used");
     966           0 :                 sta->flags |= WLAN_STA_WPS;
     967           0 :                 wpabuf_free(sta->wps_ie);
     968           0 :                 sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
     969             :                                                           WPS_IE_VENDOR_TYPE);
     970           0 :                 if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
     971           0 :                         wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
     972           0 :                         sta->flags |= WLAN_STA_WPS2;
     973             :                 }
     974           0 :                 wpa_ie = NULL;
     975           0 :                 wpa_ie_len = 0;
     976           0 :                 if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
     977           0 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
     978             :                                    "(Re)Association Request - reject");
     979           0 :                         return WLAN_STATUS_INVALID_IE;
     980             :                 }
     981           0 :         } else if (hapd->conf->wps_state && wpa_ie == NULL) {
     982           0 :                 wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
     983             :                            "(Re)Association Request - possible WPS use");
     984           0 :                 sta->flags |= WLAN_STA_MAYBE_WPS;
     985             :         } else
     986             : #endif /* CONFIG_WPS */
     987           0 :         if (hapd->conf->wpa && wpa_ie == NULL) {
     988           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     989             :                                HOSTAPD_LEVEL_INFO,
     990             :                                "No WPA/RSN IE in association request");
     991           0 :                 return WLAN_STATUS_INVALID_IE;
     992             :         }
     993             : 
     994           0 :         if (hapd->conf->wpa && wpa_ie) {
     995             :                 int res;
     996           0 :                 wpa_ie -= 2;
     997           0 :                 wpa_ie_len += 2;
     998           0 :                 if (sta->wpa_sm == NULL)
     999           0 :                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
    1000           0 :                                                         sta->addr,
    1001             :                                                         p2p_dev_addr);
    1002           0 :                 if (sta->wpa_sm == NULL) {
    1003           0 :                         wpa_printf(MSG_WARNING, "Failed to initialize WPA "
    1004             :                                    "state machine");
    1005           0 :                         return WLAN_STATUS_UNSPECIFIED_FAILURE;
    1006             :                 }
    1007           0 :                 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
    1008             :                                           wpa_ie, wpa_ie_len,
    1009           0 :                                           elems.mdie, elems.mdie_len);
    1010           0 :                 if (res == WPA_INVALID_GROUP)
    1011           0 :                         resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
    1012           0 :                 else if (res == WPA_INVALID_PAIRWISE)
    1013           0 :                         resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
    1014           0 :                 else if (res == WPA_INVALID_AKMP)
    1015           0 :                         resp = WLAN_STATUS_AKMP_NOT_VALID;
    1016           0 :                 else if (res == WPA_ALLOC_FAIL)
    1017           0 :                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
    1018             : #ifdef CONFIG_IEEE80211W
    1019           0 :                 else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
    1020           0 :                         resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
    1021           0 :                 else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
    1022           0 :                         resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
    1023             : #endif /* CONFIG_IEEE80211W */
    1024           0 :                 else if (res == WPA_INVALID_MDIE)
    1025           0 :                         resp = WLAN_STATUS_INVALID_MDIE;
    1026           0 :                 else if (res != WPA_IE_OK)
    1027           0 :                         resp = WLAN_STATUS_INVALID_IE;
    1028           0 :                 if (resp != WLAN_STATUS_SUCCESS)
    1029           0 :                         return resp;
    1030             : #ifdef CONFIG_IEEE80211W
    1031           0 :                 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
    1032           0 :                     sta->sa_query_count > 0)
    1033           0 :                         ap_check_sa_query_timeout(hapd, sta);
    1034           0 :                 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
    1035           0 :                     (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
    1036             :                         /*
    1037             :                          * STA has already been associated with MFP and SA
    1038             :                          * Query timeout has not been reached. Reject the
    1039             :                          * association attempt temporarily and start SA Query,
    1040             :                          * if one is not pending.
    1041             :                          */
    1042             : 
    1043           0 :                         if (sta->sa_query_count == 0)
    1044           0 :                                 ap_sta_start_sa_query(hapd, sta);
    1045             : 
    1046           0 :                         return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
    1047             :                 }
    1048             : 
    1049           0 :                 if (wpa_auth_uses_mfp(sta->wpa_sm))
    1050           0 :                         sta->flags |= WLAN_STA_MFP;
    1051             :                 else
    1052           0 :                         sta->flags &= ~WLAN_STA_MFP;
    1053             : #endif /* CONFIG_IEEE80211W */
    1054             : 
    1055             : #ifdef CONFIG_IEEE80211R
    1056           0 :                 if (sta->auth_alg == WLAN_AUTH_FT) {
    1057           0 :                         if (!reassoc) {
    1058           0 :                                 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
    1059             :                                            "to use association (not "
    1060             :                                            "re-association) with FT auth_alg",
    1061           0 :                                            MAC2STR(sta->addr));
    1062           0 :                                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
    1063             :                         }
    1064             : 
    1065           0 :                         resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
    1066             :                                                        ies_len);
    1067           0 :                         if (resp != WLAN_STATUS_SUCCESS)
    1068           0 :                                 return resp;
    1069             :                 }
    1070             : #endif /* CONFIG_IEEE80211R */
    1071             : 
    1072             : #ifdef CONFIG_SAE
    1073           0 :                 if (wpa_auth_uses_sae(sta->wpa_sm) &&
    1074           0 :                     sta->auth_alg != WLAN_AUTH_SAE &&
    1075           0 :                     !(sta->auth_alg == WLAN_AUTH_FT &&
    1076           0 :                       wpa_auth_uses_ft_sae(sta->wpa_sm))) {
    1077           0 :                         wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
    1078             :                                    "SAE AKM after non-SAE auth_alg %u",
    1079           0 :                                    MAC2STR(sta->addr), sta->auth_alg);
    1080           0 :                         return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
    1081             :                 }
    1082             : #endif /* CONFIG_SAE */
    1083             : 
    1084             : #ifdef CONFIG_IEEE80211N
    1085           0 :                 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
    1086           0 :                     wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
    1087           0 :                         hostapd_logger(hapd, sta->addr,
    1088             :                                        HOSTAPD_MODULE_IEEE80211,
    1089             :                                        HOSTAPD_LEVEL_INFO,
    1090             :                                        "Station tried to use TKIP with HT "
    1091             :                                        "association");
    1092           0 :                         return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
    1093             :                 }
    1094             : #endif /* CONFIG_IEEE80211N */
    1095             : #ifdef CONFIG_HS20
    1096           0 :         } else if (hapd->conf->osen) {
    1097           0 :                 if (elems.osen == NULL) {
    1098           0 :                         hostapd_logger(
    1099           0 :                                 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    1100             :                                 HOSTAPD_LEVEL_INFO,
    1101             :                                 "No HS 2.0 OSEN element in association request");
    1102           0 :                         return WLAN_STATUS_INVALID_IE;
    1103             :                 }
    1104             : 
    1105           0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
    1106           0 :                 if (sta->wpa_sm == NULL)
    1107           0 :                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
    1108           0 :                                                         sta->addr, NULL);
    1109           0 :                 if (sta->wpa_sm == NULL) {
    1110           0 :                         wpa_printf(MSG_WARNING, "Failed to initialize WPA "
    1111             :                                    "state machine");
    1112           0 :                         return WLAN_STATUS_UNSPECIFIED_FAILURE;
    1113             :                 }
    1114           0 :                 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
    1115           0 :                                       elems.osen - 2, elems.osen_len + 2) < 0)
    1116           0 :                         return WLAN_STATUS_INVALID_IE;
    1117             : #endif /* CONFIG_HS20 */
    1118             :         } else
    1119           0 :                 wpa_auth_sta_no_wpa(sta->wpa_sm);
    1120             : 
    1121             : #ifdef CONFIG_P2P
    1122             :         p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
    1123             : #endif /* CONFIG_P2P */
    1124             : 
    1125             : #ifdef CONFIG_HS20
    1126           0 :         wpabuf_free(sta->hs20_ie);
    1127           0 :         if (elems.hs20 && elems.hs20_len > 4) {
    1128           0 :                 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
    1129           0 :                                                  elems.hs20_len - 4);
    1130             :         } else
    1131           0 :                 sta->hs20_ie = NULL;
    1132             : #endif /* CONFIG_HS20 */
    1133             : 
    1134           0 :         return WLAN_STATUS_SUCCESS;
    1135             : }
    1136             : 
    1137             : 
    1138           0 : static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
    1139             :                         u16 reason_code)
    1140             : {
    1141             :         int send_len;
    1142             :         struct ieee80211_mgmt reply;
    1143             : 
    1144           0 :         os_memset(&reply, 0, sizeof(reply));
    1145           0 :         reply.frame_control =
    1146             :                 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
    1147           0 :         os_memcpy(reply.da, addr, ETH_ALEN);
    1148           0 :         os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
    1149           0 :         os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
    1150             : 
    1151           0 :         send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
    1152           0 :         reply.u.deauth.reason_code = host_to_le16(reason_code);
    1153             : 
    1154           0 :         if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
    1155           0 :                 wpa_printf(MSG_INFO, "Failed to send deauth: %s",
    1156           0 :                            strerror(errno));
    1157           0 : }
    1158             : 
    1159             : 
    1160           0 : static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
    1161             :                             u16 status_code, int reassoc, const u8 *ies,
    1162             :                             size_t ies_len)
    1163             : {
    1164             :         int send_len;
    1165             :         u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
    1166             :         struct ieee80211_mgmt *reply;
    1167             :         u8 *p;
    1168             : 
    1169           0 :         os_memset(buf, 0, sizeof(buf));
    1170           0 :         reply = (struct ieee80211_mgmt *) buf;
    1171           0 :         reply->frame_control =
    1172           0 :                 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    1173             :                              (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
    1174             :                               WLAN_FC_STYPE_ASSOC_RESP));
    1175           0 :         os_memcpy(reply->da, sta->addr, ETH_ALEN);
    1176           0 :         os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
    1177           0 :         os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
    1178             : 
    1179           0 :         send_len = IEEE80211_HDRLEN;
    1180           0 :         send_len += sizeof(reply->u.assoc_resp);
    1181           0 :         reply->u.assoc_resp.capab_info =
    1182           0 :                 host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
    1183           0 :         reply->u.assoc_resp.status_code = host_to_le16(status_code);
    1184           0 :         reply->u.assoc_resp.aid = host_to_le16(sta->aid | BIT(14) | BIT(15));
    1185             :         /* Supported rates */
    1186           0 :         p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
    1187             :         /* Extended supported rates */
    1188           0 :         p = hostapd_eid_ext_supp_rates(hapd, p);
    1189             : 
    1190             : #ifdef CONFIG_IEEE80211R
    1191           0 :         if (status_code == WLAN_STATUS_SUCCESS) {
    1192             :                 /* IEEE 802.11r: Mobility Domain Information, Fast BSS
    1193             :                  * Transition Information, RSN, [RIC Response] */
    1194           0 :                 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
    1195           0 :                                                 buf + sizeof(buf) - p,
    1196           0 :                                                 sta->auth_alg, ies, ies_len);
    1197             :         }
    1198             : #endif /* CONFIG_IEEE80211R */
    1199             : 
    1200             : #ifdef CONFIG_IEEE80211W
    1201           0 :         if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
    1202           0 :                 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
    1203             : #endif /* CONFIG_IEEE80211W */
    1204             : 
    1205             : #ifdef CONFIG_IEEE80211N
    1206           0 :         p = hostapd_eid_ht_capabilities(hapd, p);
    1207           0 :         p = hostapd_eid_ht_operation(hapd, p);
    1208             : #endif /* CONFIG_IEEE80211N */
    1209             : 
    1210             : #ifdef CONFIG_IEEE80211AC
    1211           0 :         p = hostapd_eid_vht_capabilities(hapd, p);
    1212           0 :         p = hostapd_eid_vht_operation(hapd, p);
    1213             : #endif /* CONFIG_IEEE80211AC */
    1214             : 
    1215           0 :         p = hostapd_eid_ext_capab(hapd, p);
    1216           0 :         p = hostapd_eid_bss_max_idle_period(hapd, p);
    1217           0 :         if (sta->qos_map_enabled)
    1218           0 :                 p = hostapd_eid_qos_map_set(hapd, p);
    1219             : 
    1220           0 :         if (sta->flags & WLAN_STA_WMM)
    1221           0 :                 p = hostapd_eid_wmm(hapd, p);
    1222             : 
    1223             : #ifdef CONFIG_WPS
    1224           0 :         if ((sta->flags & WLAN_STA_WPS) ||
    1225           0 :             ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa)) {
    1226           0 :                 struct wpabuf *wps = wps_build_assoc_resp_ie();
    1227           0 :                 if (wps) {
    1228           0 :                         os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
    1229           0 :                         p += wpabuf_len(wps);
    1230           0 :                         wpabuf_free(wps);
    1231             :                 }
    1232             :         }
    1233             : #endif /* CONFIG_WPS */
    1234             : 
    1235             : #ifdef CONFIG_P2P
    1236             :         if (sta->p2p_ie) {
    1237             :                 struct wpabuf *p2p_resp_ie;
    1238             :                 enum p2p_status_code status;
    1239             :                 switch (status_code) {
    1240             :                 case WLAN_STATUS_SUCCESS:
    1241             :                         status = P2P_SC_SUCCESS;
    1242             :                         break;
    1243             :                 case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
    1244             :                         status = P2P_SC_FAIL_LIMIT_REACHED;
    1245             :                         break;
    1246             :                 default:
    1247             :                         status = P2P_SC_FAIL_INVALID_PARAMS;
    1248             :                         break;
    1249             :                 }
    1250             :                 p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
    1251             :                 if (p2p_resp_ie) {
    1252             :                         os_memcpy(p, wpabuf_head(p2p_resp_ie),
    1253             :                                   wpabuf_len(p2p_resp_ie));
    1254             :                         p += wpabuf_len(p2p_resp_ie);
    1255             :                         wpabuf_free(p2p_resp_ie);
    1256             :                 }
    1257             :         }
    1258             : #endif /* CONFIG_P2P */
    1259             : 
    1260             : #ifdef CONFIG_P2P_MANAGER
    1261           0 :         if (hapd->conf->p2p & P2P_MANAGE)
    1262           0 :                 p = hostapd_eid_p2p_manage(hapd, p);
    1263             : #endif /* CONFIG_P2P_MANAGER */
    1264             : 
    1265           0 :         send_len += p - reply->u.assoc_resp.variable;
    1266             : 
    1267           0 :         if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
    1268           0 :                 wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
    1269           0 :                            strerror(errno));
    1270           0 : }
    1271             : 
    1272             : 
    1273           0 : static void handle_assoc(struct hostapd_data *hapd,
    1274             :                          const struct ieee80211_mgmt *mgmt, size_t len,
    1275             :                          int reassoc)
    1276             : {
    1277             :         u16 capab_info, listen_interval;
    1278           0 :         u16 resp = WLAN_STATUS_SUCCESS;
    1279             :         const u8 *pos;
    1280             :         int left, i;
    1281             :         struct sta_info *sta;
    1282             : 
    1283           0 :         if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
    1284             :                                       sizeof(mgmt->u.assoc_req))) {
    1285           0 :                 wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)",
    1286             :                            reassoc, (unsigned long) len);
    1287           0 :                 return;
    1288             :         }
    1289             : 
    1290             : #ifdef CONFIG_TESTING_OPTIONS
    1291           0 :         if (reassoc) {
    1292           0 :                 if (hapd->iconf->ignore_reassoc_probability > 0.0 &&
    1293           0 :                     drand48() < hapd->iconf->ignore_reassoc_probability) {
    1294           0 :                         wpa_printf(MSG_INFO,
    1295             :                                    "TESTING: ignoring reassoc request from "
    1296           0 :                                    MACSTR, MAC2STR(mgmt->sa));
    1297           0 :                         return;
    1298             :                 }
    1299             :         } else {
    1300           0 :                 if (hapd->iconf->ignore_assoc_probability > 0.0 &&
    1301           0 :                     drand48() < hapd->iconf->ignore_assoc_probability) {
    1302           0 :                         wpa_printf(MSG_INFO,
    1303             :                                    "TESTING: ignoring assoc request from "
    1304           0 :                                    MACSTR, MAC2STR(mgmt->sa));
    1305           0 :                         return;
    1306             :                 }
    1307             :         }
    1308             : #endif /* CONFIG_TESTING_OPTIONS */
    1309             : 
    1310           0 :         if (reassoc) {
    1311           0 :                 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
    1312           0 :                 listen_interval = le_to_host16(
    1313             :                         mgmt->u.reassoc_req.listen_interval);
    1314           0 :                 wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
    1315             :                            " capab_info=0x%02x listen_interval=%d current_ap="
    1316             :                            MACSTR,
    1317           0 :                            MAC2STR(mgmt->sa), capab_info, listen_interval,
    1318           0 :                            MAC2STR(mgmt->u.reassoc_req.current_ap));
    1319           0 :                 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
    1320           0 :                 pos = mgmt->u.reassoc_req.variable;
    1321             :         } else {
    1322           0 :                 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
    1323           0 :                 listen_interval = le_to_host16(
    1324             :                         mgmt->u.assoc_req.listen_interval);
    1325           0 :                 wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
    1326             :                            " capab_info=0x%02x listen_interval=%d",
    1327           0 :                            MAC2STR(mgmt->sa), capab_info, listen_interval);
    1328           0 :                 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
    1329           0 :                 pos = mgmt->u.assoc_req.variable;
    1330             :         }
    1331             : 
    1332           0 :         sta = ap_get_sta(hapd, mgmt->sa);
    1333             : #ifdef CONFIG_IEEE80211R
    1334           0 :         if (sta && sta->auth_alg == WLAN_AUTH_FT &&
    1335           0 :             (sta->flags & WLAN_STA_AUTH) == 0) {
    1336           0 :                 wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
    1337             :                            "prior to authentication since it is using "
    1338           0 :                            "over-the-DS FT", MAC2STR(mgmt->sa));
    1339             :         } else
    1340             : #endif /* CONFIG_IEEE80211R */
    1341           0 :         if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
    1342           0 :                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1343             :                                HOSTAPD_LEVEL_INFO, "Station tried to "
    1344             :                                "associate before authentication "
    1345             :                                "(aid=%d flags=0x%x)",
    1346           0 :                                sta ? sta->aid : -1,
    1347             :                                sta ? sta->flags : 0);
    1348           0 :                 send_deauth(hapd, mgmt->sa,
    1349             :                             WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
    1350           0 :                 return;
    1351             :         }
    1352             : 
    1353           0 :         if (hapd->tkip_countermeasures) {
    1354           0 :                 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
    1355           0 :                 goto fail;
    1356             :         }
    1357             : 
    1358           0 :         if (listen_interval > hapd->conf->max_listen_interval) {
    1359           0 :                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1360             :                                HOSTAPD_LEVEL_DEBUG,
    1361             :                                "Too large Listen Interval (%d)",
    1362             :                                listen_interval);
    1363           0 :                 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
    1364           0 :                 goto fail;
    1365             :         }
    1366             : 
    1367             :         /* followed by SSID and Supported rates; and HT capabilities if 802.11n
    1368             :          * is used */
    1369           0 :         resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
    1370           0 :         if (resp != WLAN_STATUS_SUCCESS)
    1371           0 :                 goto fail;
    1372             : 
    1373           0 :         if (hostapd_get_aid(hapd, sta) < 0) {
    1374           0 :                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1375             :                                HOSTAPD_LEVEL_INFO, "No room for more AIDs");
    1376           0 :                 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
    1377           0 :                 goto fail;
    1378             :         }
    1379             : 
    1380           0 :         sta->capability = capab_info;
    1381           0 :         sta->listen_interval = listen_interval;
    1382             : 
    1383           0 :         if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
    1384           0 :                 sta->flags |= WLAN_STA_NONERP;
    1385           0 :         for (i = 0; i < sta->supported_rates_len; i++) {
    1386           0 :                 if ((sta->supported_rates[i] & 0x7f) > 22) {
    1387           0 :                         sta->flags &= ~WLAN_STA_NONERP;
    1388           0 :                         break;
    1389             :                 }
    1390             :         }
    1391           0 :         if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
    1392           0 :                 sta->nonerp_set = 1;
    1393           0 :                 hapd->iface->num_sta_non_erp++;
    1394           0 :                 if (hapd->iface->num_sta_non_erp == 1)
    1395           0 :                         ieee802_11_set_beacons(hapd->iface);
    1396             :         }
    1397             : 
    1398           0 :         if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
    1399           0 :             !sta->no_short_slot_time_set) {
    1400           0 :                 sta->no_short_slot_time_set = 1;
    1401           0 :                 hapd->iface->num_sta_no_short_slot_time++;
    1402           0 :                 if (hapd->iface->current_mode->mode ==
    1403           0 :                     HOSTAPD_MODE_IEEE80211G &&
    1404           0 :                     hapd->iface->num_sta_no_short_slot_time == 1)
    1405           0 :                         ieee802_11_set_beacons(hapd->iface);
    1406             :         }
    1407             : 
    1408           0 :         if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
    1409           0 :                 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
    1410             :         else
    1411           0 :                 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
    1412             : 
    1413           0 :         if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
    1414           0 :             !sta->no_short_preamble_set) {
    1415           0 :                 sta->no_short_preamble_set = 1;
    1416           0 :                 hapd->iface->num_sta_no_short_preamble++;
    1417           0 :                 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
    1418           0 :                     && hapd->iface->num_sta_no_short_preamble == 1)
    1419           0 :                         ieee802_11_set_beacons(hapd->iface);
    1420             :         }
    1421             : 
    1422             : #ifdef CONFIG_IEEE80211N
    1423           0 :         update_ht_state(hapd, sta);
    1424             : #endif /* CONFIG_IEEE80211N */
    1425             : 
    1426           0 :         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    1427             :                        HOSTAPD_LEVEL_DEBUG,
    1428           0 :                        "association OK (aid %d)", sta->aid);
    1429             :         /* Station will be marked associated, after it acknowledges AssocResp
    1430             :          */
    1431           0 :         sta->flags |= WLAN_STA_ASSOC_REQ_OK;
    1432             : 
    1433             : #ifdef CONFIG_IEEE80211W
    1434           0 :         if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
    1435           0 :                 wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
    1436             :                            "SA Query procedure", reassoc ? "re" : "");
    1437             :                 /* TODO: Send a protected Disassociate frame to the STA using
    1438             :                  * the old key and Reason Code "Previous Authentication no
    1439             :                  * longer valid". Make sure this is only sent protected since
    1440             :                  * unprotected frame would be received by the STA that is now
    1441             :                  * trying to associate.
    1442             :                  */
    1443             :         }
    1444             : #endif /* CONFIG_IEEE80211W */
    1445             : 
    1446             :         /* Make sure that the previously registered inactivity timer will not
    1447             :          * remove the STA immediately. */
    1448           0 :         sta->timeout_next = STA_NULLFUNC;
    1449             : 
    1450             :  fail:
    1451           0 :         send_assoc_resp(hapd, sta, resp, reassoc, pos, left);
    1452             : }
    1453             : 
    1454             : 
    1455           0 : static void handle_disassoc(struct hostapd_data *hapd,
    1456             :                             const struct ieee80211_mgmt *mgmt, size_t len)
    1457             : {
    1458             :         struct sta_info *sta;
    1459             : 
    1460           0 :         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
    1461           0 :                 wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)",
    1462             :                            (unsigned long) len);
    1463           0 :                 return;
    1464             :         }
    1465             : 
    1466           0 :         wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
    1467           0 :                    MAC2STR(mgmt->sa),
    1468           0 :                    le_to_host16(mgmt->u.disassoc.reason_code));
    1469             : 
    1470           0 :         sta = ap_get_sta(hapd, mgmt->sa);
    1471           0 :         if (sta == NULL) {
    1472           0 :                 wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated",
    1473           0 :                            MAC2STR(mgmt->sa));
    1474           0 :                 return;
    1475             :         }
    1476             : 
    1477           0 :         ap_sta_set_authorized(hapd, sta, 0);
    1478           0 :         sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
    1479           0 :         wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
    1480           0 :         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    1481             :                        HOSTAPD_LEVEL_INFO, "disassociated");
    1482           0 :         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
    1483           0 :         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
    1484             :         /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
    1485             :          * authenticated. */
    1486           0 :         accounting_sta_stop(hapd, sta);
    1487           0 :         ieee802_1x_free_station(sta);
    1488           0 :         hostapd_drv_sta_remove(hapd, sta->addr);
    1489             : 
    1490           0 :         if (sta->timeout_next == STA_NULLFUNC ||
    1491           0 :             sta->timeout_next == STA_DISASSOC) {
    1492           0 :                 sta->timeout_next = STA_DEAUTH;
    1493           0 :                 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
    1494           0 :                 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
    1495             :                                        hapd, sta);
    1496             :         }
    1497             : 
    1498           0 :         mlme_disassociate_indication(
    1499           0 :                 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
    1500             : }
    1501             : 
    1502             : 
    1503           0 : static void handle_deauth(struct hostapd_data *hapd,
    1504             :                           const struct ieee80211_mgmt *mgmt, size_t len)
    1505             : {
    1506             :         struct sta_info *sta;
    1507             : 
    1508           0 :         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
    1509           0 :                 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
    1510             :                         "payload (len=%lu)", (unsigned long) len);
    1511           0 :                 return;
    1512             :         }
    1513             : 
    1514           0 :         wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
    1515             :                 " reason_code=%d",
    1516           0 :                 MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
    1517             : 
    1518           0 :         sta = ap_get_sta(hapd, mgmt->sa);
    1519           0 :         if (sta == NULL) {
    1520           0 :                 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
    1521             :                         "to deauthenticate, but it is not authenticated",
    1522           0 :                         MAC2STR(mgmt->sa));
    1523           0 :                 return;
    1524             :         }
    1525             : 
    1526           0 :         ap_sta_set_authorized(hapd, sta, 0);
    1527           0 :         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
    1528             :                         WLAN_STA_ASSOC_REQ_OK);
    1529           0 :         wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
    1530           0 :         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    1531             :                        HOSTAPD_LEVEL_DEBUG, "deauthenticated");
    1532           0 :         mlme_deauthenticate_indication(
    1533           0 :                 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
    1534           0 :         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
    1535           0 :         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
    1536           0 :         ap_free_sta(hapd, sta);
    1537             : }
    1538             : 
    1539             : 
    1540           0 : static void handle_beacon(struct hostapd_data *hapd,
    1541             :                           const struct ieee80211_mgmt *mgmt, size_t len,
    1542             :                           struct hostapd_frame_info *fi)
    1543             : {
    1544             :         struct ieee802_11_elems elems;
    1545             : 
    1546           0 :         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
    1547           0 :                 wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)",
    1548             :                            (unsigned long) len);
    1549           0 :                 return;
    1550             :         }
    1551             : 
    1552           0 :         (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
    1553             :                                       len - (IEEE80211_HDRLEN +
    1554             :                                              sizeof(mgmt->u.beacon)), &elems,
    1555             :                                       0);
    1556             : 
    1557           0 :         ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
    1558             : }
    1559             : 
    1560             : 
    1561             : #ifdef CONFIG_IEEE80211W
    1562             : 
    1563           0 : static int hostapd_sa_query_action(struct hostapd_data *hapd,
    1564             :                                    const struct ieee80211_mgmt *mgmt,
    1565             :                                    size_t len)
    1566             : {
    1567             :         const u8 *end;
    1568             : 
    1569           0 :         end = mgmt->u.action.u.sa_query_resp.trans_id +
    1570             :                 WLAN_SA_QUERY_TR_ID_LEN;
    1571           0 :         if (((u8 *) mgmt) + len < end) {
    1572           0 :                 wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
    1573             :                            "frame (len=%lu)", (unsigned long) len);
    1574           0 :                 return 0;
    1575             :         }
    1576             : 
    1577           0 :         ieee802_11_sa_query_action(hapd, mgmt->sa,
    1578           0 :                                    mgmt->u.action.u.sa_query_resp.action,
    1579           0 :                                    mgmt->u.action.u.sa_query_resp.trans_id);
    1580           0 :         return 1;
    1581             : }
    1582             : 
    1583             : 
    1584           0 : static int robust_action_frame(u8 category)
    1585             : {
    1586           0 :         return category != WLAN_ACTION_PUBLIC &&
    1587             :                 category != WLAN_ACTION_HT;
    1588             : }
    1589             : #endif /* CONFIG_IEEE80211W */
    1590             : 
    1591             : 
    1592           0 : static int handle_action(struct hostapd_data *hapd,
    1593             :                          const struct ieee80211_mgmt *mgmt, size_t len)
    1594             : {
    1595             :         struct sta_info *sta;
    1596           0 :         sta = ap_get_sta(hapd, mgmt->sa);
    1597             : 
    1598           0 :         if (len < IEEE80211_HDRLEN + 1) {
    1599           0 :                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1600             :                                HOSTAPD_LEVEL_DEBUG,
    1601             :                                "handle_action - too short payload (len=%lu)",
    1602             :                                (unsigned long) len);
    1603           0 :                 return 0;
    1604             :         }
    1605             : 
    1606           0 :         if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
    1607           0 :             (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
    1608           0 :                 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
    1609             :                            "frame (category=%u) from unassociated STA " MACSTR,
    1610           0 :                            MAC2STR(mgmt->sa), mgmt->u.action.category);
    1611           0 :                 return 0;
    1612             :         }
    1613             : 
    1614             : #ifdef CONFIG_IEEE80211W
    1615           0 :         if (sta && (sta->flags & WLAN_STA_MFP) &&
    1616           0 :             !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
    1617           0 :             robust_action_frame(mgmt->u.action.category)) {
    1618           0 :                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1619             :                                HOSTAPD_LEVEL_DEBUG,
    1620             :                                "Dropped unprotected Robust Action frame from "
    1621             :                                "an MFP STA");
    1622           0 :                 return 0;
    1623             :         }
    1624             : #endif /* CONFIG_IEEE80211W */
    1625             : 
    1626           0 :         switch (mgmt->u.action.category) {
    1627             : #ifdef CONFIG_IEEE80211R
    1628             :         case WLAN_ACTION_FT:
    1629           0 :                 if (!sta ||
    1630           0 :                     wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
    1631             :                                      len - IEEE80211_HDRLEN))
    1632             :                         break;
    1633           0 :                 return 1;
    1634             : #endif /* CONFIG_IEEE80211R */
    1635             :         case WLAN_ACTION_WMM:
    1636           0 :                 hostapd_wmm_action(hapd, mgmt, len);
    1637           0 :                 return 1;
    1638             : #ifdef CONFIG_IEEE80211W
    1639             :         case WLAN_ACTION_SA_QUERY:
    1640           0 :                 return hostapd_sa_query_action(hapd, mgmt, len);
    1641             : #endif /* CONFIG_IEEE80211W */
    1642             : #ifdef CONFIG_WNM
    1643             :         case WLAN_ACTION_WNM:
    1644           0 :                 ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
    1645           0 :                 return 1;
    1646             : #endif /* CONFIG_WNM */
    1647             :         case WLAN_ACTION_PUBLIC:
    1648             :         case WLAN_ACTION_PROTECTED_DUAL:
    1649             : #ifdef CONFIG_IEEE80211N
    1650           0 :                 if (mgmt->u.action.u.public_action.action ==
    1651             :                     WLAN_PA_20_40_BSS_COEX) {
    1652           0 :                         wpa_printf(MSG_DEBUG,
    1653             :                                    "HT20/40 coex mgmt frame received from STA "
    1654           0 :                                    MACSTR, MAC2STR(mgmt->sa));
    1655           0 :                         hostapd_2040_coex_action(hapd, mgmt, len);
    1656             :                 }
    1657             : #endif /* CONFIG_IEEE80211N */
    1658           0 :                 if (hapd->public_action_cb) {
    1659           0 :                         hapd->public_action_cb(hapd->public_action_cb_ctx,
    1660             :                                                (u8 *) mgmt, len,
    1661           0 :                                                hapd->iface->freq);
    1662             :                 }
    1663           0 :                 if (hapd->public_action_cb2) {
    1664           0 :                         hapd->public_action_cb2(hapd->public_action_cb2_ctx,
    1665             :                                                 (u8 *) mgmt, len,
    1666           0 :                                                 hapd->iface->freq);
    1667             :                 }
    1668           0 :                 if (hapd->public_action_cb || hapd->public_action_cb2)
    1669           0 :                         return 1;
    1670           0 :                 break;
    1671             :         case WLAN_ACTION_VENDOR_SPECIFIC:
    1672           0 :                 if (hapd->vendor_action_cb) {
    1673           0 :                         if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
    1674             :                                                    (u8 *) mgmt, len,
    1675           0 :                                                    hapd->iface->freq) == 0)
    1676           0 :                                 return 1;
    1677             :                 }
    1678           0 :                 break;
    1679             :         }
    1680             : 
    1681           0 :         hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1682             :                        HOSTAPD_LEVEL_DEBUG,
    1683             :                        "handle_action - unknown action category %d or invalid "
    1684             :                        "frame",
    1685           0 :                        mgmt->u.action.category);
    1686           0 :         if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
    1687           0 :             !(mgmt->sa[0] & 0x01)) {
    1688             :                 struct ieee80211_mgmt *resp;
    1689             : 
    1690             :                 /*
    1691             :                  * IEEE 802.11-REVma/D9.0 - 7.3.1.11
    1692             :                  * Return the Action frame to the source without change
    1693             :                  * except that MSB of the Category set to 1.
    1694             :                  */
    1695           0 :                 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
    1696             :                            "frame back to sender");
    1697           0 :                 resp = os_malloc(len);
    1698           0 :                 if (resp == NULL)
    1699           0 :                         return 0;
    1700           0 :                 os_memcpy(resp, mgmt, len);
    1701           0 :                 os_memcpy(resp->da, resp->sa, ETH_ALEN);
    1702           0 :                 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
    1703           0 :                 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
    1704           0 :                 resp->u.action.category |= 0x80;
    1705             : 
    1706           0 :                 if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
    1707           0 :                         wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
    1708             :                                    "Action frame");
    1709             :                 }
    1710           0 :                 os_free(resp);
    1711             :         }
    1712             : 
    1713           0 :         return 1;
    1714             : }
    1715             : 
    1716             : 
    1717             : /**
    1718             :  * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
    1719             :  * @hapd: hostapd BSS data structure (the BSS to which the management frame was
    1720             :  * sent to)
    1721             :  * @buf: management frame data (starting from IEEE 802.11 header)
    1722             :  * @len: length of frame data in octets
    1723             :  * @fi: meta data about received frame (signal level, etc.)
    1724             :  *
    1725             :  * Process all incoming IEEE 802.11 management frames. This will be called for
    1726             :  * each frame received from the kernel driver through wlan#ap interface. In
    1727             :  * addition, it can be called to re-inserted pending frames (e.g., when using
    1728             :  * external RADIUS server as an MAC ACL).
    1729             :  */
    1730           0 : int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
    1731             :                     struct hostapd_frame_info *fi)
    1732             : {
    1733             :         struct ieee80211_mgmt *mgmt;
    1734             :         int broadcast;
    1735             :         u16 fc, stype;
    1736           0 :         int ret = 0;
    1737             : 
    1738           0 :         if (len < 24)
    1739           0 :                 return 0;
    1740             : 
    1741           0 :         mgmt = (struct ieee80211_mgmt *) buf;
    1742           0 :         fc = le_to_host16(mgmt->frame_control);
    1743           0 :         stype = WLAN_FC_GET_STYPE(fc);
    1744             : 
    1745           0 :         if (stype == WLAN_FC_STYPE_BEACON) {
    1746           0 :                 handle_beacon(hapd, mgmt, len, fi);
    1747           0 :                 return 1;
    1748             :         }
    1749             : 
    1750           0 :         broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
    1751           0 :                 mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
    1752           0 :                 mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
    1753             : 
    1754           0 :         if (!broadcast &&
    1755             : #ifdef CONFIG_P2P
    1756             :             /* Invitation responses can be sent with the peer MAC as BSSID */
    1757             :             !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
    1758             :               stype == WLAN_FC_STYPE_ACTION) &&
    1759             : #endif /* CONFIG_P2P */
    1760           0 :             os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
    1761           0 :                 wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
    1762           0 :                            MAC2STR(mgmt->bssid));
    1763           0 :                 return 0;
    1764             :         }
    1765             : 
    1766             : 
    1767           0 :         if (stype == WLAN_FC_STYPE_PROBE_REQ) {
    1768           0 :                 handle_probe_req(hapd, mgmt, len, fi->ssi_signal);
    1769           0 :                 return 1;
    1770             :         }
    1771             : 
    1772           0 :         if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
    1773           0 :                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1774             :                                HOSTAPD_LEVEL_DEBUG,
    1775             :                                "MGMT: DA=" MACSTR " not our address",
    1776           0 :                                MAC2STR(mgmt->da));
    1777           0 :                 return 0;
    1778             :         }
    1779             : 
    1780           0 :         switch (stype) {
    1781             :         case WLAN_FC_STYPE_AUTH:
    1782           0 :                 wpa_printf(MSG_DEBUG, "mgmt::auth");
    1783           0 :                 handle_auth(hapd, mgmt, len);
    1784           0 :                 ret = 1;
    1785           0 :                 break;
    1786             :         case WLAN_FC_STYPE_ASSOC_REQ:
    1787           0 :                 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
    1788           0 :                 handle_assoc(hapd, mgmt, len, 0);
    1789           0 :                 ret = 1;
    1790           0 :                 break;
    1791             :         case WLAN_FC_STYPE_REASSOC_REQ:
    1792           0 :                 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
    1793           0 :                 handle_assoc(hapd, mgmt, len, 1);
    1794           0 :                 ret = 1;
    1795           0 :                 break;
    1796             :         case WLAN_FC_STYPE_DISASSOC:
    1797           0 :                 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
    1798           0 :                 handle_disassoc(hapd, mgmt, len);
    1799           0 :                 ret = 1;
    1800           0 :                 break;
    1801             :         case WLAN_FC_STYPE_DEAUTH:
    1802           0 :                 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
    1803           0 :                 handle_deauth(hapd, mgmt, len);
    1804           0 :                 ret = 1;
    1805           0 :                 break;
    1806             :         case WLAN_FC_STYPE_ACTION:
    1807           0 :                 wpa_printf(MSG_DEBUG, "mgmt::action");
    1808           0 :                 ret = handle_action(hapd, mgmt, len);
    1809           0 :                 break;
    1810             :         default:
    1811           0 :                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
    1812             :                                HOSTAPD_LEVEL_DEBUG,
    1813             :                                "unknown mgmt frame subtype %d", stype);
    1814           0 :                 break;
    1815             :         }
    1816             : 
    1817           0 :         return ret;
    1818             : }
    1819             : 
    1820             : 
    1821           0 : static void handle_auth_cb(struct hostapd_data *hapd,
    1822             :                            const struct ieee80211_mgmt *mgmt,
    1823             :                            size_t len, int ok)
    1824             : {
    1825             :         u16 auth_alg, auth_transaction, status_code;
    1826             :         struct sta_info *sta;
    1827             : 
    1828           0 :         if (!ok) {
    1829           0 :                 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
    1830             :                                HOSTAPD_LEVEL_NOTICE,
    1831             :                                "did not acknowledge authentication response");
    1832           0 :                 return;
    1833             :         }
    1834             : 
    1835           0 :         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
    1836           0 :                 wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
    1837             :                            (unsigned long) len);
    1838           0 :                 return;
    1839             :         }
    1840             : 
    1841           0 :         auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
    1842           0 :         auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
    1843           0 :         status_code = le_to_host16(mgmt->u.auth.status_code);
    1844             : 
    1845           0 :         sta = ap_get_sta(hapd, mgmt->da);
    1846           0 :         if (!sta) {
    1847           0 :                 wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found",
    1848           0 :                            MAC2STR(mgmt->da));
    1849           0 :                 return;
    1850             :         }
    1851             : 
    1852           0 :         if (status_code == WLAN_STATUS_SUCCESS &&
    1853           0 :             ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
    1854           0 :              (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
    1855           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    1856             :                                HOSTAPD_LEVEL_INFO, "authenticated");
    1857           0 :                 sta->flags |= WLAN_STA_AUTH;
    1858             :         }
    1859             : }
    1860             : 
    1861             : 
    1862           0 : static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
    1863             :                                        struct sta_info *sta,
    1864             :                                        char *ifname_wds)
    1865             : {
    1866             :         int i;
    1867           0 :         struct hostapd_ssid *ssid = sta->ssid;
    1868             : 
    1869           0 :         if (hapd->conf->ieee802_1x || hapd->conf->wpa)
    1870           0 :                 return;
    1871             : 
    1872           0 :         for (i = 0; i < 4; i++) {
    1873           0 :                 if (ssid->wep.key[i] &&
    1874           0 :                     hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
    1875           0 :                                         i == ssid->wep.idx, NULL, 0,
    1876           0 :                                         ssid->wep.key[i], ssid->wep.len[i])) {
    1877           0 :                         wpa_printf(MSG_WARNING,
    1878             :                                    "Could not set WEP keys for WDS interface; %s",
    1879             :                                    ifname_wds);
    1880           0 :                         break;
    1881             :                 }
    1882             :         }
    1883             : }
    1884             : 
    1885             : 
    1886           0 : static void handle_assoc_cb(struct hostapd_data *hapd,
    1887             :                             const struct ieee80211_mgmt *mgmt,
    1888             :                             size_t len, int reassoc, int ok)
    1889             : {
    1890             :         u16 status;
    1891             :         struct sta_info *sta;
    1892           0 :         int new_assoc = 1;
    1893             :         struct ieee80211_ht_capabilities ht_cap;
    1894             :         struct ieee80211_vht_capabilities vht_cap;
    1895             : 
    1896           0 :         if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
    1897             :                                       sizeof(mgmt->u.assoc_resp))) {
    1898           0 :                 wpa_printf(MSG_INFO, "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
    1899             :                            reassoc, (unsigned long) len);
    1900           0 :                 return;
    1901             :         }
    1902             : 
    1903           0 :         sta = ap_get_sta(hapd, mgmt->da);
    1904           0 :         if (!sta) {
    1905           0 :                 wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found",
    1906           0 :                            MAC2STR(mgmt->da));
    1907           0 :                 return;
    1908             :         }
    1909             : 
    1910           0 :         if (!ok) {
    1911           0 :                 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
    1912             :                                HOSTAPD_LEVEL_DEBUG,
    1913             :                                "did not acknowledge association response");
    1914           0 :                 sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
    1915           0 :                 return;
    1916             :         }
    1917             : 
    1918           0 :         if (reassoc)
    1919           0 :                 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
    1920             :         else
    1921           0 :                 status = le_to_host16(mgmt->u.assoc_resp.status_code);
    1922             : 
    1923           0 :         if (status != WLAN_STATUS_SUCCESS)
    1924           0 :                 return;
    1925             : 
    1926             :         /* Stop previous accounting session, if one is started, and allocate
    1927             :          * new session id for the new session. */
    1928           0 :         accounting_sta_stop(hapd, sta);
    1929             : 
    1930           0 :         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    1931             :                        HOSTAPD_LEVEL_INFO,
    1932             :                        "associated (aid %d)",
    1933           0 :                        sta->aid);
    1934             : 
    1935           0 :         if (sta->flags & WLAN_STA_ASSOC)
    1936           0 :                 new_assoc = 0;
    1937           0 :         sta->flags |= WLAN_STA_ASSOC;
    1938           0 :         sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
    1939           0 :         if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) ||
    1940           0 :             sta->auth_alg == WLAN_AUTH_FT) {
    1941             :                 /*
    1942             :                  * Open, static WEP, or FT protocol; no separate authorization
    1943             :                  * step.
    1944             :                  */
    1945           0 :                 ap_sta_set_authorized(hapd, sta, 1);
    1946             :         }
    1947             : 
    1948           0 :         if (reassoc)
    1949           0 :                 mlme_reassociate_indication(hapd, sta);
    1950             :         else
    1951           0 :                 mlme_associate_indication(hapd, sta);
    1952             : 
    1953             : #ifdef CONFIG_IEEE80211W
    1954           0 :         sta->sa_query_timed_out = 0;
    1955             : #endif /* CONFIG_IEEE80211W */
    1956             : 
    1957             :         /*
    1958             :          * Remove the STA entry in order to make sure the STA PS state gets
    1959             :          * cleared and configuration gets updated in case of reassociation back
    1960             :          * to the same AP.
    1961             :          */
    1962           0 :         hostapd_drv_sta_remove(hapd, sta->addr);
    1963             : 
    1964             : #ifdef CONFIG_IEEE80211N
    1965           0 :         if (sta->flags & WLAN_STA_HT)
    1966           0 :                 hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
    1967             : #endif /* CONFIG_IEEE80211N */
    1968             : #ifdef CONFIG_IEEE80211AC
    1969           0 :         if (sta->flags & WLAN_STA_VHT)
    1970           0 :                 hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
    1971             : #endif /* CONFIG_IEEE80211AC */
    1972             : 
    1973           0 :         if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
    1974           0 :                             sta->supported_rates, sta->supported_rates_len,
    1975           0 :                             sta->listen_interval,
    1976           0 :                             sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
    1977           0 :                             sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
    1978           0 :                             sta->flags, sta->qosinfo, sta->vht_opmode)) {
    1979           0 :                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    1980             :                                HOSTAPD_LEVEL_NOTICE,
    1981             :                                "Could not add STA to kernel driver");
    1982             : 
    1983           0 :                 ap_sta_disconnect(hapd, sta, sta->addr,
    1984             :                                   WLAN_REASON_DISASSOC_AP_BUSY);
    1985             : 
    1986           0 :                 return;
    1987             :         }
    1988             : 
    1989           0 :         if (sta->flags & WLAN_STA_WDS) {
    1990             :                 int ret;
    1991             :                 char ifname_wds[IFNAMSIZ + 1];
    1992             : 
    1993           0 :                 ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
    1994           0 :                                           sta->aid, 1);
    1995           0 :                 if (!ret)
    1996           0 :                         hostapd_set_wds_encryption(hapd, sta, ifname_wds);
    1997             :         }
    1998             : 
    1999           0 :         if (sta->eapol_sm == NULL) {
    2000             :                 /*
    2001             :                  * This STA does not use RADIUS server for EAP authentication,
    2002             :                  * so bind it to the selected VLAN interface now, since the
    2003             :                  * interface selection is not going to change anymore.
    2004             :                  */
    2005           0 :                 if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
    2006           0 :                         return;
    2007           0 :         } else if (sta->vlan_id) {
    2008             :                 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
    2009           0 :                 if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
    2010           0 :                         return;
    2011             :         }
    2012             : 
    2013           0 :         hostapd_set_sta_flags(hapd, sta);
    2014             : 
    2015           0 :         if (sta->auth_alg == WLAN_AUTH_FT)
    2016           0 :                 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
    2017             :         else
    2018           0 :                 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
    2019           0 :         hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
    2020             : 
    2021           0 :         ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
    2022             : }
    2023             : 
    2024             : 
    2025           0 : static void handle_deauth_cb(struct hostapd_data *hapd,
    2026             :                              const struct ieee80211_mgmt *mgmt,
    2027             :                              size_t len, int ok)
    2028             : {
    2029             :         struct sta_info *sta;
    2030           0 :         if (mgmt->da[0] & 0x01)
    2031           0 :                 return;
    2032           0 :         sta = ap_get_sta(hapd, mgmt->da);
    2033           0 :         if (!sta) {
    2034           0 :                 wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
    2035           0 :                            " not found", MAC2STR(mgmt->da));
    2036           0 :                 return;
    2037             :         }
    2038           0 :         if (ok)
    2039           0 :                 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
    2040           0 :                            MAC2STR(sta->addr));
    2041             :         else
    2042           0 :                 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
    2043           0 :                            "deauth", MAC2STR(sta->addr));
    2044             : 
    2045           0 :         ap_sta_deauth_cb(hapd, sta);
    2046             : }
    2047             : 
    2048             : 
    2049           0 : static void handle_disassoc_cb(struct hostapd_data *hapd,
    2050             :                                const struct ieee80211_mgmt *mgmt,
    2051             :                                size_t len, int ok)
    2052             : {
    2053             :         struct sta_info *sta;
    2054           0 :         if (mgmt->da[0] & 0x01)
    2055           0 :                 return;
    2056           0 :         sta = ap_get_sta(hapd, mgmt->da);
    2057           0 :         if (!sta) {
    2058           0 :                 wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
    2059           0 :                            " not found", MAC2STR(mgmt->da));
    2060           0 :                 return;
    2061             :         }
    2062           0 :         if (ok)
    2063           0 :                 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
    2064           0 :                            MAC2STR(sta->addr));
    2065             :         else
    2066           0 :                 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
    2067           0 :                            "disassoc", MAC2STR(sta->addr));
    2068             : 
    2069           0 :         ap_sta_disassoc_cb(hapd, sta);
    2070             : }
    2071             : 
    2072             : 
    2073             : /**
    2074             :  * ieee802_11_mgmt_cb - Process management frame TX status callback
    2075             :  * @hapd: hostapd BSS data structure (the BSS from which the management frame
    2076             :  * was sent from)
    2077             :  * @buf: management frame data (starting from IEEE 802.11 header)
    2078             :  * @len: length of frame data in octets
    2079             :  * @stype: management frame subtype from frame control field
    2080             :  * @ok: Whether the frame was ACK'ed
    2081             :  */
    2082           0 : void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
    2083             :                         u16 stype, int ok)
    2084             : {
    2085             :         const struct ieee80211_mgmt *mgmt;
    2086           0 :         mgmt = (const struct ieee80211_mgmt *) buf;
    2087             : 
    2088             : #ifdef CONFIG_TESTING_OPTIONS
    2089           0 :         if (hapd->ext_mgmt_frame_handling) {
    2090           0 :                 wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-TX-STATUS stype=%u ok=%d",
    2091             :                         stype, ok);
    2092           0 :                 return;
    2093             :         }
    2094             : #endif /* CONFIG_TESTING_OPTIONS */
    2095             : 
    2096           0 :         switch (stype) {
    2097             :         case WLAN_FC_STYPE_AUTH:
    2098           0 :                 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
    2099           0 :                 handle_auth_cb(hapd, mgmt, len, ok);
    2100           0 :                 break;
    2101             :         case WLAN_FC_STYPE_ASSOC_RESP:
    2102           0 :                 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
    2103           0 :                 handle_assoc_cb(hapd, mgmt, len, 0, ok);
    2104           0 :                 break;
    2105             :         case WLAN_FC_STYPE_REASSOC_RESP:
    2106           0 :                 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
    2107           0 :                 handle_assoc_cb(hapd, mgmt, len, 1, ok);
    2108           0 :                 break;
    2109             :         case WLAN_FC_STYPE_PROBE_RESP:
    2110           0 :                 wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb");
    2111           0 :                 break;
    2112             :         case WLAN_FC_STYPE_DEAUTH:
    2113           0 :                 wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
    2114           0 :                 handle_deauth_cb(hapd, mgmt, len, ok);
    2115           0 :                 break;
    2116             :         case WLAN_FC_STYPE_DISASSOC:
    2117           0 :                 wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
    2118           0 :                 handle_disassoc_cb(hapd, mgmt, len, ok);
    2119           0 :                 break;
    2120             :         case WLAN_FC_STYPE_ACTION:
    2121           0 :                 wpa_printf(MSG_DEBUG, "mgmt::action cb");
    2122           0 :                 break;
    2123             :         default:
    2124           0 :                 wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
    2125           0 :                 break;
    2126             :         }
    2127             : }
    2128             : 
    2129             : 
    2130           0 : int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
    2131             : {
    2132             :         /* TODO */
    2133           0 :         return 0;
    2134             : }
    2135             : 
    2136             : 
    2137           0 : int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
    2138             :                            char *buf, size_t buflen)
    2139             : {
    2140             :         /* TODO */
    2141           0 :         return 0;
    2142             : }
    2143             : 
    2144             : 
    2145           0 : void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
    2146             :                        const u8 *buf, size_t len, int ack)
    2147             : {
    2148             :         struct sta_info *sta;
    2149           0 :         struct hostapd_iface *iface = hapd->iface;
    2150             : 
    2151           0 :         sta = ap_get_sta(hapd, addr);
    2152           0 :         if (sta == NULL && iface->num_bss > 1) {
    2153             :                 size_t j;
    2154           0 :                 for (j = 0; j < iface->num_bss; j++) {
    2155           0 :                         hapd = iface->bss[j];
    2156           0 :                         sta = ap_get_sta(hapd, addr);
    2157           0 :                         if (sta)
    2158           0 :                                 break;
    2159             :                 }
    2160             :         }
    2161           0 :         if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
    2162           0 :                 return;
    2163           0 :         if (sta->flags & WLAN_STA_PENDING_POLL) {
    2164           0 :                 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
    2165           0 :                            "activity poll", MAC2STR(sta->addr),
    2166             :                            ack ? "ACKed" : "did not ACK");
    2167           0 :                 if (ack)
    2168           0 :                         sta->flags &= ~WLAN_STA_PENDING_POLL;
    2169             :         }
    2170             : 
    2171           0 :         ieee802_1x_tx_status(hapd, sta, buf, len, ack);
    2172             : }
    2173             : 
    2174             : 
    2175           0 : void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
    2176             :                              const u8 *data, size_t len, int ack)
    2177             : {
    2178             :         struct sta_info *sta;
    2179           0 :         struct hostapd_iface *iface = hapd->iface;
    2180             : 
    2181           0 :         sta = ap_get_sta(hapd, dst);
    2182           0 :         if (sta == NULL && iface->num_bss > 1) {
    2183             :                 size_t j;
    2184           0 :                 for (j = 0; j < iface->num_bss; j++) {
    2185           0 :                         hapd = iface->bss[j];
    2186           0 :                         sta = ap_get_sta(hapd, dst);
    2187           0 :                         if (sta)
    2188           0 :                                 break;
    2189             :                 }
    2190             :         }
    2191           0 :         if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
    2192           0 :                 wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
    2193             :                            MACSTR " that is not currently associated",
    2194           0 :                            MAC2STR(dst));
    2195           0 :                 return;
    2196             :         }
    2197             : 
    2198           0 :         ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
    2199             : }
    2200             : 
    2201             : 
    2202           0 : void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
    2203             : {
    2204             :         struct sta_info *sta;
    2205           0 :         struct hostapd_iface *iface = hapd->iface;
    2206             : 
    2207           0 :         sta = ap_get_sta(hapd, addr);
    2208           0 :         if (sta == NULL && iface->num_bss > 1) {
    2209             :                 size_t j;
    2210           0 :                 for (j = 0; j < iface->num_bss; j++) {
    2211           0 :                         hapd = iface->bss[j];
    2212           0 :                         sta = ap_get_sta(hapd, addr);
    2213           0 :                         if (sta)
    2214           0 :                                 break;
    2215             :                 }
    2216             :         }
    2217           0 :         if (sta == NULL)
    2218           0 :                 return;
    2219           0 :         if (!(sta->flags & WLAN_STA_PENDING_POLL))
    2220           0 :                 return;
    2221             : 
    2222           0 :         wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
    2223           0 :                    "activity poll", MAC2STR(sta->addr));
    2224           0 :         sta->flags &= ~WLAN_STA_PENDING_POLL;
    2225             : }
    2226             : 
    2227             : 
    2228           0 : void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
    2229             :                                 int wds)
    2230             : {
    2231             :         struct sta_info *sta;
    2232             : 
    2233           0 :         sta = ap_get_sta(hapd, src);
    2234           0 :         if (sta && (sta->flags & WLAN_STA_ASSOC)) {
    2235           0 :                 if (!hapd->conf->wds_sta)
    2236           0 :                         return;
    2237             : 
    2238           0 :                 if (wds && !(sta->flags & WLAN_STA_WDS)) {
    2239             :                         int ret;
    2240             :                         char ifname_wds[IFNAMSIZ + 1];
    2241             : 
    2242           0 :                         wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
    2243             :                                    "STA " MACSTR " (aid %u)",
    2244           0 :                                    MAC2STR(sta->addr), sta->aid);
    2245           0 :                         sta->flags |= WLAN_STA_WDS;
    2246           0 :                         ret = hostapd_set_wds_sta(hapd, ifname_wds,
    2247           0 :                                                   sta->addr, sta->aid, 1);
    2248           0 :                         if (!ret)
    2249           0 :                                 hostapd_set_wds_encryption(hapd, sta,
    2250             :                                                            ifname_wds);
    2251             :                 }
    2252           0 :                 return;
    2253             :         }
    2254             : 
    2255           0 :         wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
    2256           0 :                    MACSTR, MAC2STR(src));
    2257           0 :         if (src[0] & 0x01) {
    2258             :                 /* Broadcast bit set in SA?! Ignore the frame silently. */
    2259           0 :                 return;
    2260             :         }
    2261             : 
    2262           0 :         if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
    2263           0 :                 wpa_printf(MSG_DEBUG, "Association Response to the STA has "
    2264             :                            "already been sent, but no TX status yet known - "
    2265             :                            "ignore Class 3 frame issue with " MACSTR,
    2266           0 :                            MAC2STR(src));
    2267           0 :                 return;
    2268             :         }
    2269             : 
    2270           0 :         if (sta && (sta->flags & WLAN_STA_AUTH))
    2271           0 :                 hostapd_drv_sta_disassoc(
    2272             :                         hapd, src,
    2273             :                         WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
    2274             :         else
    2275           0 :                 hostapd_drv_sta_deauth(
    2276             :                         hapd, src,
    2277             :                         WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
    2278             : }
    2279             : 
    2280             : 
    2281             : #endif /* CONFIG_NATIVE_WINDOWS */

Generated by: LCOV version 1.10