LCOV - code coverage report
Current view: top level - src/ap - ieee802_11.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1388338050 Lines: 716 1168 61.3 %
Date: 2013-12-29 Functions: 33 42 78.6 %
Branches: 417 810 51.5 %

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

Generated by: LCOV version 1.9