LCOV - code coverage report
Current view: top level - wpa_supplicant - sme.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 807 881 91.6 %
Date: 2016-10-02 Functions: 33 35 94.3 %

          Line data    Source code
       1             : /*
       2             :  * wpa_supplicant - SME
       3             :  * Copyright (c) 2009-2014, 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 "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "utils/eloop.h"
      13             : #include "common/ieee802_11_defs.h"
      14             : #include "common/ieee802_11_common.h"
      15             : #include "eapol_supp/eapol_supp_sm.h"
      16             : #include "common/wpa_common.h"
      17             : #include "common/sae.h"
      18             : #include "rsn_supp/wpa.h"
      19             : #include "rsn_supp/pmksa_cache.h"
      20             : #include "config.h"
      21             : #include "wpa_supplicant_i.h"
      22             : #include "driver_i.h"
      23             : #include "wpas_glue.h"
      24             : #include "wps_supplicant.h"
      25             : #include "p2p_supplicant.h"
      26             : #include "notify.h"
      27             : #include "bss.h"
      28             : #include "scan.h"
      29             : #include "sme.h"
      30             : #include "hs20_supplicant.h"
      31             : 
      32             : #define SME_AUTH_TIMEOUT 5
      33             : #define SME_ASSOC_TIMEOUT 5
      34             : 
      35             : static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
      36             : static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
      37             : static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
      38             : #ifdef CONFIG_IEEE80211W
      39             : static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
      40             : #endif /* CONFIG_IEEE80211W */
      41             : 
      42             : 
      43             : #ifdef CONFIG_SAE
      44             : 
      45         162 : static int index_within_array(const int *array, int idx)
      46             : {
      47             :         int i;
      48         175 :         for (i = 0; i < idx; i++) {
      49          13 :                 if (array[i] <= 0)
      50           0 :                         return 0;
      51             :         }
      52         162 :         return 1;
      53             : }
      54             : 
      55             : 
      56         162 : static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
      57             : {
      58         162 :         int *groups = wpa_s->conf->sae_groups;
      59         162 :         int default_groups[] = { 19, 20, 21, 25, 26, 0 };
      60             : 
      61         162 :         if (!groups || groups[0] <= 0)
      62          34 :                 groups = default_groups;
      63             : 
      64             :         /* Configuration may have changed, so validate current index */
      65         162 :         if (!index_within_array(groups, wpa_s->sme.sae_group_index))
      66           0 :                 return -1;
      67             : 
      68             :         for (;;) {
      69         166 :                 int group = groups[wpa_s->sme.sae_group_index];
      70         166 :                 if (group <= 0)
      71           4 :                         break;
      72         162 :                 if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
      73         158 :                         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
      74             :                                 wpa_s->sme.sae.group);
      75         158 :                        return 0;
      76             :                 }
      77           4 :                 wpa_s->sme.sae_group_index++;
      78           4 :         }
      79             : 
      80           4 :         return -1;
      81             : }
      82             : 
      83             : 
      84         162 : static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
      85             :                                                  struct wpa_ssid *ssid,
      86             :                                                  const u8 *bssid)
      87             : {
      88             :         struct wpabuf *buf;
      89             :         size_t len;
      90             : 
      91         162 :         if (ssid->passphrase == NULL) {
      92           4 :                 wpa_printf(MSG_DEBUG, "SAE: No password available");
      93           4 :                 return NULL;
      94             :         }
      95             : 
      96         158 :         if (sme_set_sae_group(wpa_s) < 0) {
      97           3 :                 wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
      98           3 :                 return NULL;
      99             :         }
     100             : 
     101         465 :         if (sae_prepare_commit(wpa_s->own_addr, bssid,
     102         155 :                                (u8 *) ssid->passphrase,
     103         155 :                                os_strlen(ssid->passphrase),
     104             :                                &wpa_s->sme.sae) < 0) {
     105          35 :                 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
     106          35 :                 return NULL;
     107             :         }
     108             : 
     109         120 :         len = wpa_s->sme.sae_token ? wpabuf_len(wpa_s->sme.sae_token) : 0;
     110         120 :         buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
     111         120 :         if (buf == NULL)
     112           1 :                 return NULL;
     113             : 
     114         119 :         wpabuf_put_le16(buf, 1); /* Transaction seq# */
     115         119 :         wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
     116         119 :         sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token);
     117             : 
     118         119 :         return buf;
     119             : }
     120             : 
     121             : 
     122          70 : static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s)
     123             : {
     124             :         struct wpabuf *buf;
     125             : 
     126          70 :         buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
     127          70 :         if (buf == NULL)
     128           1 :                 return NULL;
     129             : 
     130          69 :         wpabuf_put_le16(buf, 2); /* Transaction seq# */
     131          69 :         wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
     132          69 :         sae_write_confirm(&wpa_s->sme.sae, buf);
     133             : 
     134          69 :         return buf;
     135             : }
     136             : 
     137             : #endif /* CONFIG_SAE */
     138             : 
     139             : 
     140             : /**
     141             :  * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
     142             :  * @wpa_s: Pointer to wpa_supplicant data
     143             :  * @bss: Pointer to the bss which is the target of authentication attempt
     144             :  */
     145        4634 : static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
     146             :                                 struct wpa_bss *bss)
     147             : {
     148        4634 :         const u8 rrm_ie_len = 5;
     149             :         u8 *pos;
     150             :         const u8 *rrm_ie;
     151             : 
     152        4634 :         wpa_s->rrm.rrm_used = 0;
     153             : 
     154        4634 :         wpa_printf(MSG_DEBUG,
     155             :                    "RRM: Determining whether RRM can be used - device support: 0x%x",
     156             :                    wpa_s->drv_rrm_flags);
     157             : 
     158        4634 :         rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
     159        4634 :         if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
     160        4630 :                 wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
     161        4630 :                 return;
     162             :         }
     163             : 
     164           8 :         if (!((wpa_s->drv_rrm_flags &
     165             :                WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
     166           4 :               (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
     167           0 :             !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
     168           0 :                 wpa_printf(MSG_DEBUG,
     169             :                            "RRM: Insufficient RRM support in driver - do not use RRM");
     170           0 :                 return;
     171             :         }
     172             : 
     173           4 :         if (sizeof(wpa_s->sme.assoc_req_ie) <
     174           4 :             wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
     175           0 :                 wpa_printf(MSG_INFO,
     176             :                            "RRM: Unable to use RRM, no room for RRM IE");
     177           0 :                 return;
     178             :         }
     179             : 
     180           4 :         wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
     181           4 :         pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
     182           4 :         os_memset(pos, 0, 2 + rrm_ie_len);
     183           4 :         *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
     184           4 :         *pos++ = rrm_ie_len;
     185             : 
     186             :         /* Set supported capabilites flags */
     187           4 :         if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
     188           0 :                 *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
     189             : 
     190           4 :         if (wpa_s->lci)
     191           1 :                 pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
     192             : 
     193           4 :         wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
     194           4 :         wpa_s->rrm.rrm_used = 1;
     195             : }
     196             : 
     197             : 
     198        4639 : static void sme_send_authentication(struct wpa_supplicant *wpa_s,
     199             :                                     struct wpa_bss *bss, struct wpa_ssid *ssid,
     200             :                                     int start)
     201             : {
     202             :         struct wpa_driver_auth_params params;
     203             :         struct wpa_ssid *old_ssid;
     204             : #ifdef CONFIG_IEEE80211R
     205             :         const u8 *ie;
     206             : #endif /* CONFIG_IEEE80211R */
     207             : #ifdef CONFIG_IEEE80211R
     208        4639 :         const u8 *md = NULL;
     209             : #endif /* CONFIG_IEEE80211R */
     210             :         int i, bssid_changed;
     211        4639 :         struct wpabuf *resp = NULL;
     212             :         u8 ext_capab[18];
     213             :         int ext_capab_len;
     214             :         int skip_auth;
     215             : #ifdef CONFIG_MBO
     216             :         const u8 *mbo;
     217             : #endif /* CONFIG_MBO */
     218             : 
     219        4639 :         if (bss == NULL) {
     220           0 :                 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
     221             :                         "the network");
     222           0 :                 wpas_connect_work_done(wpa_s);
     223           0 :                 return;
     224             :         }
     225             : 
     226        4639 :         skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
     227             :                 wpa_s->reassoc_same_bss;
     228        4639 :         wpa_s->current_bss = bss;
     229             : 
     230        4639 :         os_memset(&params, 0, sizeof(params));
     231        4639 :         wpa_s->reassociate = 0;
     232             : 
     233        4639 :         params.freq = bss->freq;
     234        4639 :         params.bssid = bss->bssid;
     235        4639 :         params.ssid = bss->ssid;
     236        4639 :         params.ssid_len = bss->ssid_len;
     237        4639 :         params.p2p = ssid->p2p_group;
     238             : 
     239        8358 :         if (wpa_s->sme.ssid_len != params.ssid_len ||
     240        3719 :             os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
     241        1108 :                 wpa_s->sme.prev_bssid_set = 0;
     242             : 
     243        4639 :         wpa_s->sme.freq = params.freq;
     244        4639 :         os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
     245        4639 :         wpa_s->sme.ssid_len = params.ssid_len;
     246             : 
     247        4639 :         params.auth_alg = WPA_AUTH_ALG_OPEN;
     248             : #ifdef IEEE8021X_EAPOL
     249        4639 :         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
     250          21 :                 if (ssid->leap) {
     251           2 :                         if (ssid->non_leap == 0)
     252           1 :                                 params.auth_alg = WPA_AUTH_ALG_LEAP;
     253             :                         else
     254           1 :                                 params.auth_alg |= WPA_AUTH_ALG_LEAP;
     255             :                 }
     256             :         }
     257             : #endif /* IEEE8021X_EAPOL */
     258        4639 :         wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
     259             :                 params.auth_alg);
     260        4639 :         if (ssid->auth_alg) {
     261         366 :                 params.auth_alg = ssid->auth_alg;
     262         366 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
     263             :                         "0x%x", params.auth_alg);
     264             :         }
     265             : #ifdef CONFIG_SAE
     266        4639 :         wpa_s->sme.sae_pmksa_caching = 0;
     267        4639 :         if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
     268             :                 const u8 *rsn;
     269             :                 struct wpa_ie_data ied;
     270             : 
     271         236 :                 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
     272         236 :                 if (!rsn) {
     273           0 :                         wpa_dbg(wpa_s, MSG_DEBUG,
     274             :                                 "SAE enabled, but target BSS does not advertise RSN");
     275         472 :                 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
     276         236 :                            wpa_key_mgmt_sae(ied.key_mgmt)) {
     277         236 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
     278         236 :                         params.auth_alg = WPA_AUTH_ALG_SAE;
     279             :                 } else {
     280           0 :                         wpa_dbg(wpa_s, MSG_DEBUG,
     281             :                                 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
     282             :                 }
     283             :         }
     284             : #endif /* CONFIG_SAE */
     285             : 
     286       23195 :         for (i = 0; i < NUM_WEP_KEYS; i++) {
     287       18556 :                 if (ssid->wep_key_len[i])
     288          28 :                         params.wep_key[i] = ssid->wep_key[i];
     289       18556 :                 params.wep_key_len[i] = ssid->wep_key_len[i];
     290             :         }
     291        4639 :         params.wep_tx_keyidx = ssid->wep_tx_keyidx;
     292             : 
     293        4639 :         bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
     294        4639 :         os_memset(wpa_s->bssid, 0, ETH_ALEN);
     295        4639 :         os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
     296        4639 :         if (bssid_changed)
     297         325 :                 wpas_notify_bssid_changed(wpa_s);
     298             : 
     299        9173 :         if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
     300        8615 :              wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
     301        7647 :             wpa_key_mgmt_wpa(ssid->key_mgmt)) {
     302             :                 int try_opportunistic;
     303        7142 :                 try_opportunistic = (ssid->proactive_key_caching < 0 ?
     304        3553 :                                      wpa_s->conf->okc :
     305        7142 :                                      ssid->proactive_key_caching) &&
     306          18 :                         (ssid->proto & WPA_PROTO_RSN);
     307        3571 :                 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
     308        3571 :                                             wpa_s->current_ssid,
     309             :                                             try_opportunistic) == 0)
     310          89 :                         eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
     311        3571 :                 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
     312        7142 :                 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
     313        3571 :                                               wpa_s->sme.assoc_req_ie,
     314             :                                               &wpa_s->sme.assoc_req_ie_len)) {
     315           5 :                         wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
     316             :                                 "key management and encryption suites");
     317           5 :                         wpas_connect_work_done(wpa_s);
     318           5 :                         return;
     319             :                 }
     320        1089 :         } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
     321          21 :                    wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
     322             :                 /*
     323             :                  * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
     324             :                  * use non-WPA since the scan results did not indicate that the
     325             :                  * AP is using WPA or WPA2.
     326             :                  */
     327           1 :                 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
     328           1 :                 wpa_s->sme.assoc_req_ie_len = 0;
     329        1067 :         } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
     330           1 :                 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
     331           2 :                 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
     332           1 :                                               wpa_s->sme.assoc_req_ie,
     333             :                                               &wpa_s->sme.assoc_req_ie_len)) {
     334           0 :                         wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
     335             :                                 "key management and encryption suites (no "
     336             :                                 "scan results)");
     337           0 :                         wpas_connect_work_done(wpa_s);
     338           0 :                         return;
     339             :                 }
     340             : #ifdef CONFIG_WPS
     341        1066 :         } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
     342             :                 struct wpabuf *wps_ie;
     343         536 :                 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
     344         536 :                 if (wps_ie && wpabuf_len(wps_ie) <=
     345             :                     sizeof(wpa_s->sme.assoc_req_ie)) {
     346         535 :                         wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
     347         535 :                         os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
     348             :                                   wpa_s->sme.assoc_req_ie_len);
     349             :                 } else
     350           1 :                         wpa_s->sme.assoc_req_ie_len = 0;
     351         536 :                 wpabuf_free(wps_ie);
     352         536 :                 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
     353             : #endif /* CONFIG_WPS */
     354             :         } else {
     355         530 :                 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
     356         530 :                 wpa_s->sme.assoc_req_ie_len = 0;
     357             :         }
     358             : 
     359             : #ifdef CONFIG_IEEE80211R
     360        4634 :         ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
     361        4634 :         if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
     362         193 :                 md = ie + 2;
     363        4634 :         wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
     364        4634 :         if (md) {
     365             :                 /* Prepare for the next transition */
     366         193 :                 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
     367             :         }
     368             : 
     369        4634 :         if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) {
     370         185 :                 if (wpa_s->sme.assoc_req_ie_len + 5 <
     371             :                     sizeof(wpa_s->sme.assoc_req_ie)) {
     372             :                         struct rsn_mdie *mdie;
     373         185 :                         u8 *pos = wpa_s->sme.assoc_req_ie +
     374         185 :                                 wpa_s->sme.assoc_req_ie_len;
     375         185 :                         *pos++ = WLAN_EID_MOBILITY_DOMAIN;
     376         185 :                         *pos++ = sizeof(*mdie);
     377         185 :                         mdie = (struct rsn_mdie *) pos;
     378         185 :                         os_memcpy(mdie->mobility_domain, md,
     379             :                                   MOBILITY_DOMAIN_ID_LEN);
     380         185 :                         mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
     381         185 :                         wpa_s->sme.assoc_req_ie_len += 5;
     382             :                 }
     383             : 
     384         316 :                 if (wpa_s->sme.ft_used &&
     385         262 :                     os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
     386         131 :                     wpa_sm_has_ptk(wpa_s->wpa)) {
     387         131 :                         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
     388             :                                 "over-the-air");
     389         131 :                         params.auth_alg = WPA_AUTH_ALG_FT;
     390         131 :                         params.ie = wpa_s->sme.ft_ies;
     391         131 :                         params.ie_len = wpa_s->sme.ft_ies_len;
     392             :                 }
     393             :         }
     394             : #endif /* CONFIG_IEEE80211R */
     395             : 
     396             : #ifdef CONFIG_IEEE80211W
     397        4634 :         wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
     398        4634 :         if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
     399         469 :                 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
     400             :                 struct wpa_ie_data _ie;
     401         937 :                 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
     402         468 :                     _ie.capabilities &
     403             :                     (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
     404          71 :                         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
     405             :                                 "MFP: require MFP");
     406          71 :                         wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
     407             :                 }
     408             :         }
     409             : #endif /* CONFIG_IEEE80211W */
     410             : 
     411             : #ifdef CONFIG_P2P
     412        4634 :         if (wpa_s->global->p2p) {
     413             :                 u8 *pos;
     414             :                 size_t len;
     415             :                 int res;
     416        4634 :                 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
     417        4634 :                 len = sizeof(wpa_s->sme.assoc_req_ie) -
     418        4634 :                         wpa_s->sme.assoc_req_ie_len;
     419        4634 :                 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
     420             :                                             ssid->p2p_group);
     421        4634 :                 if (res >= 0)
     422        4628 :                         wpa_s->sme.assoc_req_ie_len += res;
     423             :         }
     424             : #endif /* CONFIG_P2P */
     425             : 
     426             : #ifdef CONFIG_FST
     427        4634 :         if (wpa_s->fst_ies) {
     428          10 :                 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
     429             : 
     430          10 :                 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
     431             :                     sizeof(wpa_s->sme.assoc_req_ie)) {
     432          10 :                         os_memcpy(wpa_s->sme.assoc_req_ie +
     433             :                                   wpa_s->sme.assoc_req_ie_len,
     434             :                                   wpabuf_head(wpa_s->fst_ies),
     435             :                                   fst_ies_len);
     436          10 :                         wpa_s->sme.assoc_req_ie_len += fst_ies_len;
     437             :                 }
     438             :         }
     439             : #endif /* CONFIG_FST */
     440             : 
     441        4634 :         sme_auth_handle_rrm(wpa_s, bss);
     442             : 
     443             : #ifdef CONFIG_MBO
     444        4634 :         mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
     445        4634 :         if (mbo) {
     446             :                 int len;
     447             : 
     448          40 :                 len = wpas_mbo_supp_op_class_ie(
     449             :                         wpa_s, bss->freq,
     450          20 :                         wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
     451             :                         sizeof(wpa_s->sme.assoc_req_ie) -
     452          20 :                         wpa_s->sme.assoc_req_ie_len);
     453          20 :                 if (len > 0)
     454          20 :                         wpa_s->sme.assoc_req_ie_len += len;
     455             :         }
     456             : #endif /* CONFIG_MBO */
     457             : 
     458        4634 :         if (params.p2p)
     459         528 :                 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
     460             :         else
     461        4106 :                 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
     462             : 
     463        4634 :         ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
     464             :                                              sizeof(ext_capab));
     465        4634 :         if (ext_capab_len > 0) {
     466        4634 :                 u8 *pos = wpa_s->sme.assoc_req_ie;
     467        4634 :                 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
     468        3517 :                         pos += 2 + pos[1];
     469        4634 :                 os_memmove(pos + ext_capab_len, pos,
     470             :                            wpa_s->sme.assoc_req_ie_len -
     471             :                            (pos - wpa_s->sme.assoc_req_ie));
     472        4634 :                 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
     473        4634 :                 os_memcpy(pos, ext_capab, ext_capab_len);
     474             :         }
     475             : 
     476             : #ifdef CONFIG_HS20
     477        4634 :         if (is_hs20_network(wpa_s, ssid, bss)) {
     478             :                 struct wpabuf *hs20;
     479             : 
     480         113 :                 hs20 = wpabuf_alloc(20);
     481         113 :                 if (hs20) {
     482         113 :                         int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
     483             :                         size_t len;
     484             : 
     485         113 :                         wpas_hs20_add_indication(hs20, pps_mo_id);
     486         113 :                         len = sizeof(wpa_s->sme.assoc_req_ie) -
     487         113 :                                 wpa_s->sme.assoc_req_ie_len;
     488         113 :                         if (wpabuf_len(hs20) <= len) {
     489         113 :                                 os_memcpy(wpa_s->sme.assoc_req_ie +
     490             :                                           wpa_s->sme.assoc_req_ie_len,
     491             :                                           wpabuf_head(hs20), wpabuf_len(hs20));
     492         113 :                                 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
     493             :                         }
     494         113 :                         wpabuf_free(hs20);
     495             :                 }
     496             :         }
     497             : #endif /* CONFIG_HS20 */
     498             : 
     499        4634 :         if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
     500          31 :                 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
     501             :                 size_t len;
     502             : 
     503          31 :                 len = sizeof(wpa_s->sme.assoc_req_ie) -
     504          31 :                         wpa_s->sme.assoc_req_ie_len;
     505          31 :                 if (wpabuf_len(buf) <= len) {
     506          31 :                         os_memcpy(wpa_s->sme.assoc_req_ie +
     507             :                                   wpa_s->sme.assoc_req_ie_len,
     508             :                                   wpabuf_head(buf), wpabuf_len(buf));
     509          31 :                         wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
     510             :                 }
     511             :         }
     512             : 
     513             : #ifdef CONFIG_MBO
     514        4634 :         if (mbo) {
     515             :                 int len;
     516             : 
     517          40 :                 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
     518          20 :                                   wpa_s->sme.assoc_req_ie_len,
     519             :                                   sizeof(wpa_s->sme.assoc_req_ie) -
     520          20 :                                   wpa_s->sme.assoc_req_ie_len);
     521          20 :                 if (len >= 0)
     522          20 :                         wpa_s->sme.assoc_req_ie_len += len;
     523             :         }
     524             : #endif /* CONFIG_MBO */
     525             : 
     526             : #ifdef CONFIG_SAE
     527        4868 :         if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
     528         234 :             pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0)
     529             :         {
     530           2 :                 wpa_dbg(wpa_s, MSG_DEBUG,
     531             :                         "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
     532           2 :                 params.auth_alg = WPA_AUTH_ALG_OPEN;
     533           2 :                 wpa_s->sme.sae_pmksa_caching = 1;
     534             :         }
     535             : 
     536        4634 :         if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
     537         232 :                 if (start)
     538         162 :                         resp = sme_auth_build_sae_commit(wpa_s, ssid,
     539         162 :                                                          bss->bssid);
     540             :                 else
     541          70 :                         resp = sme_auth_build_sae_confirm(wpa_s);
     542         232 :                 if (resp == NULL) {
     543          44 :                         wpas_connection_failed(wpa_s, bss->bssid);
     544          44 :                         return;
     545             :                 }
     546         188 :                 params.sae_data = wpabuf_head(resp);
     547         188 :                 params.sae_data_len = wpabuf_len(resp);
     548         188 :                 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
     549             :         }
     550             : #endif /* CONFIG_SAE */
     551             : 
     552        4590 :         wpa_supplicant_cancel_sched_scan(wpa_s);
     553        4590 :         wpa_supplicant_cancel_scan(wpa_s);
     554             : 
     555       32130 :         wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
     556       27540 :                 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
     557             :                 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
     558             : 
     559        4590 :         wpa_clear_keys(wpa_s, bss->bssid);
     560        4590 :         wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
     561        4590 :         old_ssid = wpa_s->current_ssid;
     562        4590 :         wpa_s->current_ssid = ssid;
     563        4590 :         wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
     564        4590 :         wpa_supplicant_initiate_eapol(wpa_s);
     565        4590 :         if (old_ssid != wpa_s->current_ssid)
     566        1210 :                 wpas_notify_network_changed(wpa_s);
     567             : 
     568             : #ifdef CONFIG_HS20
     569        4590 :         hs20_configure_frame_filters(wpa_s);
     570             : #endif /* CONFIG_HS20 */
     571             : 
     572             : #ifdef CONFIG_P2P
     573             :         /*
     574             :          * If multi-channel concurrency is not supported, check for any
     575             :          * frequency conflict. In case of any frequency conflict, remove the
     576             :          * least prioritized connection.
     577             :          */
     578        4590 :         if (wpa_s->num_multichan_concurrent < 2) {
     579             :                 int freq, num;
     580        4573 :                 num = get_shared_radio_freqs(wpa_s, &freq, 1);
     581        4573 :                 if (num > 0 && freq > 0 && freq != params.freq) {
     582           9 :                         wpa_printf(MSG_DEBUG,
     583             :                                    "Conflicting frequency found (%d != %d)",
     584             :                                    freq, params.freq);
     585           9 :                         if (wpas_p2p_handle_frequency_conflicts(wpa_s,
     586             :                                                                 params.freq,
     587             :                                                                 ssid) < 0) {
     588           0 :                                 wpas_connection_failed(wpa_s, bss->bssid);
     589           0 :                                 wpa_supplicant_mark_disassoc(wpa_s);
     590           0 :                                 wpabuf_free(resp);
     591           0 :                                 wpas_connect_work_done(wpa_s);
     592           0 :                                 return;
     593             :                         }
     594             :                 }
     595             :         }
     596             : #endif /* CONFIG_P2P */
     597             : 
     598        4590 :         if (skip_auth) {
     599           2 :                 wpa_msg(wpa_s, MSG_DEBUG,
     600             :                         "SME: Skip authentication step on reassoc-to-same-BSS");
     601           2 :                 wpabuf_free(resp);
     602           2 :                 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
     603           2 :                 return;
     604             :         }
     605             : 
     606             : 
     607        4588 :         wpa_s->sme.auth_alg = params.auth_alg;
     608        4588 :         if (wpa_drv_authenticate(wpa_s, &params) < 0) {
     609           1 :                 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
     610             :                         "driver failed");
     611           1 :                 wpas_connection_failed(wpa_s, bss->bssid);
     612           1 :                 wpa_supplicant_mark_disassoc(wpa_s);
     613           1 :                 wpabuf_free(resp);
     614           1 :                 wpas_connect_work_done(wpa_s);
     615           1 :                 return;
     616             :         }
     617             : 
     618        4587 :         eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
     619             :                                NULL);
     620             : 
     621             :         /*
     622             :          * Association will be started based on the authentication event from
     623             :          * the driver.
     624             :          */
     625             : 
     626        4587 :         wpabuf_free(resp);
     627             : }
     628             : 
     629             : 
     630        4568 : static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
     631             : {
     632        4568 :         struct wpa_connect_work *cwork = work->ctx;
     633        4568 :         struct wpa_supplicant *wpa_s = work->wpa_s;
     634             : 
     635        4568 :         if (deinit) {
     636           5 :                 if (work->started)
     637           1 :                         wpa_s->connect_work = NULL;
     638             : 
     639           5 :                 wpas_connect_work_free(cwork);
     640           5 :                 return;
     641             :         }
     642             : 
     643        4563 :         wpa_s->connect_work = work;
     644             : 
     645        9125 :         if (cwork->bss_removed ||
     646        9124 :             !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
     647        4562 :             wpas_network_disabled(wpa_s, cwork->ssid)) {
     648           2 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
     649           2 :                 wpas_connect_work_done(wpa_s);
     650           2 :                 return;
     651             :         }
     652             : 
     653        4561 :         sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
     654             : }
     655             : 
     656             : 
     657        4571 : void sme_authenticate(struct wpa_supplicant *wpa_s,
     658             :                       struct wpa_bss *bss, struct wpa_ssid *ssid)
     659             : {
     660             :         struct wpa_connect_work *cwork;
     661             : 
     662        4571 :         if (bss == NULL || ssid == NULL)
     663           2 :                 return;
     664        4569 :         if (wpa_s->connect_work) {
     665           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
     666           0 :                 return;
     667             :         }
     668             : 
     669        4569 :         if (radio_work_pending(wpa_s, "sme-connect")) {
     670             :                 /*
     671             :                  * The previous sme-connect work might no longer be valid due to
     672             :                  * the fact that the BSS list was updated. In addition, it makes
     673             :                  * sense to adhere to the 'newer' decision.
     674             :                  */
     675           3 :                 wpa_dbg(wpa_s, MSG_DEBUG,
     676             :                         "SME: Remove previous pending sme-connect");
     677           3 :                 radio_remove_works(wpa_s, "sme-connect", 0);
     678             :         }
     679             : 
     680        4569 :         wpas_abort_ongoing_scan(wpa_s);
     681             : 
     682        4569 :         cwork = os_zalloc(sizeof(*cwork));
     683        4569 :         if (cwork == NULL)
     684           1 :                 return;
     685        4568 :         cwork->bss = bss;
     686        4568 :         cwork->ssid = ssid;
     687        4568 :         cwork->sme = 1;
     688             : 
     689             : #ifdef CONFIG_SAE
     690        4568 :         wpa_s->sme.sae.state = SAE_NOTHING;
     691        4568 :         wpa_s->sme.sae.send_confirm = 0;
     692        4568 :         wpa_s->sme.sae_group_index = 0;
     693             : #endif /* CONFIG_SAE */
     694             : 
     695        4568 :         if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
     696             :                            sme_auth_start_cb, cwork) < 0)
     697           1 :                 wpas_connect_work_free(cwork);
     698             : }
     699             : 
     700             : 
     701             : #ifdef CONFIG_SAE
     702             : 
     703         185 : static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
     704             :                         u16 status_code, const u8 *data, size_t len)
     705             : {
     706             :         int *groups;
     707             : 
     708         185 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
     709             :                 "status code %u", auth_transaction, status_code);
     710             : 
     711         185 :         if (auth_transaction == 1 &&
     712           7 :             status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
     713          14 :             wpa_s->sme.sae.state == SAE_COMMITTED &&
     714          14 :             wpa_s->current_bss && wpa_s->current_ssid) {
     715           7 :                 int default_groups[] = { 19, 20, 21, 25, 26, 0 };
     716             :                 u16 group;
     717             : 
     718           7 :                 groups = wpa_s->conf->sae_groups;
     719           7 :                 if (!groups || groups[0] <= 0)
     720           6 :                         groups = default_groups;
     721             : 
     722           7 :                 if (len < sizeof(le16)) {
     723           1 :                         wpa_dbg(wpa_s, MSG_DEBUG,
     724             :                                 "SME: Too short SAE anti-clogging token request");
     725           1 :                         return -1;
     726             :                 }
     727           6 :                 group = WPA_GET_LE16(data);
     728           6 :                 wpa_dbg(wpa_s, MSG_DEBUG,
     729             :                         "SME: SAE anti-clogging token requested (group %u)",
     730             :                         group);
     731           6 :                 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
     732             :                     WLAN_STATUS_SUCCESS) {
     733           1 :                         wpa_dbg(wpa_s, MSG_ERROR,
     734             :                                 "SME: SAE group %u of anti-clogging request is invalid",
     735             :                                 group);
     736           1 :                         return -1;
     737             :                 }
     738           5 :                 wpabuf_free(wpa_s->sme.sae_token);
     739           5 :                 wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16),
     740             :                                                          len - sizeof(le16));
     741           5 :                 sme_send_authentication(wpa_s, wpa_s->current_bss,
     742             :                                         wpa_s->current_ssid, 1);
     743           5 :                 return 0;
     744             :         }
     745             : 
     746         178 :         if (auth_transaction == 1 &&
     747           4 :             status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
     748           8 :             wpa_s->sme.sae.state == SAE_COMMITTED &&
     749           8 :             wpa_s->current_bss && wpa_s->current_ssid) {
     750           4 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
     751           4 :                 wpa_s->sme.sae_group_index++;
     752           4 :                 if (sme_set_sae_group(wpa_s) < 0)
     753           1 :                         return -1; /* no other groups enabled */
     754           3 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
     755           3 :                 sme_send_authentication(wpa_s, wpa_s->current_bss,
     756             :                                         wpa_s->current_ssid, 1);
     757           3 :                 return 0;
     758             :         }
     759             : 
     760         174 :         if (status_code != WLAN_STATUS_SUCCESS)
     761           1 :                 return -1;
     762             : 
     763         173 :         if (auth_transaction == 1) {
     764             :                 u16 res;
     765             : 
     766         104 :                 groups = wpa_s->conf->sae_groups;
     767             : 
     768         104 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
     769         208 :                 if (wpa_s->current_bss == NULL ||
     770         104 :                     wpa_s->current_ssid == NULL)
     771           0 :                         return -1;
     772         104 :                 if (wpa_s->sme.sae.state != SAE_COMMITTED)
     773           0 :                         return -1;
     774         104 :                 if (groups && groups[0] <= 0)
     775          20 :                         groups = NULL;
     776         104 :                 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
     777             :                                        groups);
     778         104 :                 if (res == SAE_SILENTLY_DISCARD) {
     779           2 :                         wpa_printf(MSG_DEBUG,
     780             :                                    "SAE: Drop commit message due to reflection attack");
     781           2 :                         return 0;
     782             :                 }
     783         102 :                 if (res != WLAN_STATUS_SUCCESS)
     784          20 :                         return -1;
     785             : 
     786          82 :                 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
     787          12 :                         wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
     788             :                                    "commit");
     789          12 :                         return -1;
     790             :                 }
     791             : 
     792          70 :                 wpabuf_free(wpa_s->sme.sae_token);
     793          70 :                 wpa_s->sme.sae_token = NULL;
     794          70 :                 sme_send_authentication(wpa_s, wpa_s->current_bss,
     795             :                                         wpa_s->current_ssid, 0);
     796          70 :                 return 0;
     797          69 :         } else if (auth_transaction == 2) {
     798          69 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
     799          69 :                 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
     800           0 :                         return -1;
     801          69 :                 if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
     802           3 :                         return -1;
     803          66 :                 wpa_s->sme.sae.state = SAE_ACCEPTED;
     804          66 :                 sae_clear_temp_data(&wpa_s->sme.sae);
     805          66 :                 return 1;
     806             :         }
     807             : 
     808           0 :         return -1;
     809             : }
     810             : #endif /* CONFIG_SAE */
     811             : 
     812             : 
     813        4570 : void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
     814             : {
     815        4570 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
     816             : 
     817        4570 :         if (ssid == NULL) {
     818           5 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
     819             :                         "when network is not selected");
     820           5 :                 return;
     821             :         }
     822             : 
     823        4565 :         if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
     824           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
     825             :                         "when not in authenticating state");
     826           0 :                 return;
     827             :         }
     828             : 
     829        4565 :         if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) {
     830           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
     831             :                         "unexpected peer " MACSTR,
     832             :                         MAC2STR(data->auth.peer));
     833           0 :                 return;
     834             :         }
     835             : 
     836        4565 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
     837             :                 " auth_type=%d auth_transaction=%d status_code=%d",
     838             :                 MAC2STR(data->auth.peer), data->auth.auth_type,
     839             :                 data->auth.auth_transaction, data->auth.status_code);
     840        9130 :         wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
     841        4565 :                     data->auth.ies, data->auth.ies_len);
     842             : 
     843        4565 :         eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
     844             : 
     845             : #ifdef CONFIG_SAE
     846        4565 :         if (data->auth.auth_type == WLAN_AUTH_SAE) {
     847             :                 int res;
     848         370 :                 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
     849         185 :                                    data->auth.status_code, data->auth.ies,
     850             :                                    data->auth.ies_len);
     851         185 :                 if (res < 0) {
     852          39 :                         wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
     853          39 :                         wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
     854             : 
     855             :                 }
     856         185 :                 if (res != 1)
     857         119 :                         return;
     858             : 
     859          66 :                 wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for "
     860             :                            "4-way handshake");
     861          66 :                 wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
     862          66 :                                wpa_s->sme.sae.pmkid, wpa_s->pending_bssid);
     863             :         }
     864             : #endif /* CONFIG_SAE */
     865             : 
     866        4446 :         if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
     867          36 :                 char *ie_txt = NULL;
     868             : 
     869          36 :                 if (data->auth.ies && data->auth.ies_len) {
     870           3 :                         size_t buflen = 2 * data->auth.ies_len + 1;
     871           3 :                         ie_txt = os_malloc(buflen);
     872           3 :                         if (ie_txt) {
     873           3 :                                 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
     874             :                                                  data->auth.ies_len);
     875             :                         }
     876             :                 }
     877         324 :                 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
     878             :                         " auth_type=%u auth_transaction=%u status_code=%u ie=%s",
     879         252 :                         MAC2STR(data->auth.peer), data->auth.auth_type,
     880          72 :                         data->auth.auth_transaction, data->auth.status_code,
     881             :                         ie_txt);
     882          36 :                 os_free(ie_txt);
     883             : 
     884          36 :                 if (data->auth.status_code !=
     885           6 :                     WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
     886          12 :                     wpa_s->sme.auth_alg == data->auth.auth_type ||
     887           6 :                     wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
     888          33 :                         wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
     889          33 :                         wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
     890          33 :                         return;
     891             :                 }
     892             : 
     893           3 :                 wpas_connect_work_done(wpa_s);
     894             : 
     895           3 :                 switch (data->auth.auth_type) {
     896             :                 case WLAN_AUTH_OPEN:
     897           1 :                         wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
     898             : 
     899           1 :                         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
     900           1 :                         wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
     901             :                                                  wpa_s->current_ssid);
     902           1 :                         return;
     903             : 
     904             :                 case WLAN_AUTH_SHARED_KEY:
     905           1 :                         wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
     906             : 
     907           1 :                         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
     908           1 :                         wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
     909             :                                                  wpa_s->current_ssid);
     910           1 :                         return;
     911             : 
     912             :                 default:
     913           1 :                         return;
     914             :                 }
     915             :         }
     916             : 
     917             : #ifdef CONFIG_IEEE80211R
     918        4410 :         if (data->auth.auth_type == WLAN_AUTH_FT) {
     919         130 :                 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
     920             :                                             data->auth.ies_len, 0,
     921         130 :                                             data->auth.peer, NULL, 0) < 0) {
     922           8 :                         wpa_dbg(wpa_s, MSG_DEBUG,
     923             :                                 "SME: FT Authentication response processing failed");
     924          48 :                         wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
     925             :                                 MACSTR
     926             :                                 " reason=%d locally_generated=1",
     927          48 :                                 MAC2STR(wpa_s->pending_bssid),
     928             :                                 WLAN_REASON_DEAUTH_LEAVING);
     929           8 :                         wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
     930           8 :                         wpa_supplicant_mark_disassoc(wpa_s);
     931           8 :                         return;
     932             :                 }
     933             :         }
     934             : #endif /* CONFIG_IEEE80211R */
     935             : 
     936        4402 :         sme_associate(wpa_s, ssid->mode, data->auth.peer,
     937        4402 :                       data->auth.auth_type);
     938             : }
     939             : 
     940             : 
     941        4512 : void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
     942             :                    const u8 *bssid, u16 auth_type)
     943             : {
     944             :         struct wpa_driver_associate_params params;
     945             :         struct ieee802_11_elems elems;
     946             : #ifdef CONFIG_HT_OVERRIDES
     947             :         struct ieee80211_ht_capabilities htcaps;
     948             :         struct ieee80211_ht_capabilities htcaps_mask;
     949             : #endif /* CONFIG_HT_OVERRIDES */
     950             : #ifdef CONFIG_VHT_OVERRIDES
     951             :         struct ieee80211_vht_capabilities vhtcaps;
     952             :         struct ieee80211_vht_capabilities vhtcaps_mask;
     953             : #endif /* CONFIG_VHT_OVERRIDES */
     954             : 
     955        4512 :         os_memset(&params, 0, sizeof(params));
     956        4512 :         params.bssid = bssid;
     957        4512 :         params.ssid = wpa_s->sme.ssid;
     958        4512 :         params.ssid_len = wpa_s->sme.ssid_len;
     959        4512 :         params.freq.freq = wpa_s->sme.freq;
     960        9024 :         params.bg_scan_period = wpa_s->current_ssid ?
     961        4512 :                 wpa_s->current_ssid->bg_scan_period : -1;
     962        9024 :         params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
     963        4512 :                 wpa_s->sme.assoc_req_ie : NULL;
     964        4512 :         params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
     965        4512 :         params.pairwise_suite = wpa_s->pairwise_cipher;
     966        4512 :         params.group_suite = wpa_s->group_cipher;
     967        4512 :         params.key_mgmt_suite = wpa_s->key_mgmt;
     968        4512 :         params.wpa_proto = wpa_s->wpa_proto;
     969             : #ifdef CONFIG_HT_OVERRIDES
     970        4512 :         os_memset(&htcaps, 0, sizeof(htcaps));
     971        4512 :         os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
     972        4512 :         params.htcaps = (u8 *) &htcaps;
     973        4512 :         params.htcaps_mask = (u8 *) &htcaps_mask;
     974        4512 :         wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, &params);
     975             : #endif /* CONFIG_HT_OVERRIDES */
     976             : #ifdef CONFIG_VHT_OVERRIDES
     977        4512 :         os_memset(&vhtcaps, 0, sizeof(vhtcaps));
     978        4512 :         os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
     979        4512 :         params.vhtcaps = &vhtcaps;
     980        4512 :         params.vhtcaps_mask = &vhtcaps_mask;
     981        4512 :         wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
     982             : #endif /* CONFIG_VHT_OVERRIDES */
     983             : #ifdef CONFIG_IEEE80211R
     984        4512 :         if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
     985         230 :                 params.wpa_ie = wpa_s->sme.ft_ies;
     986         230 :                 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
     987             :         }
     988             : #endif /* CONFIG_IEEE80211R */
     989        4512 :         params.mode = mode;
     990        4512 :         params.mgmt_frame_protection = wpa_s->sme.mfp;
     991        4512 :         params.rrm_used = wpa_s->rrm.rrm_used;
     992        4512 :         if (wpa_s->sme.prev_bssid_set)
     993         331 :                 params.prev_bssid = wpa_s->sme.prev_bssid;
     994             : 
     995       40608 :         wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
     996       27072 :                 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
     997        9024 :                 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
     998             :                 params.freq.freq);
     999             : 
    1000        4512 :         wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
    1001             : 
    1002        9024 :         if (params.wpa_ie == NULL ||
    1003        4512 :             ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
    1004             :             < 0) {
    1005           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
    1006           0 :                 os_memset(&elems, 0, sizeof(elems));
    1007             :         }
    1008        4512 :         if (elems.rsn_ie) {
    1009        3428 :                 params.wpa_proto = WPA_PROTO_RSN;
    1010        3428 :                 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
    1011        3428 :                                         elems.rsn_ie_len + 2);
    1012        1084 :         } else if (elems.wpa_ie) {
    1013          47 :                 params.wpa_proto = WPA_PROTO_WPA;
    1014          47 :                 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
    1015          47 :                                         elems.wpa_ie_len + 2);
    1016        1037 :         } else if (elems.osen) {
    1017           1 :                 params.wpa_proto = WPA_PROTO_OSEN;
    1018           1 :                 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
    1019           1 :                                         elems.osen_len + 2);
    1020             :         } else
    1021        1036 :                 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
    1022        4512 :         if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)
    1023         521 :                 params.p2p = 1;
    1024             : 
    1025        4512 :         if (wpa_s->p2pdev->set_sta_uapsd)
    1026           0 :                 params.uapsd = wpa_s->p2pdev->sta_uapsd;
    1027             :         else
    1028        4512 :                 params.uapsd = -1;
    1029             : 
    1030        4512 :         if (wpa_drv_associate(wpa_s, &params) < 0) {
    1031           1 :                 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
    1032             :                         "driver failed");
    1033           1 :                 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
    1034           1 :                 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
    1035           1 :                 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
    1036        4513 :                 return;
    1037             :         }
    1038             : 
    1039        4511 :         eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
    1040             :                                NULL);
    1041             : }
    1042             : 
    1043             : 
    1044         968 : int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
    1045             :                       const u8 *ies, size_t ies_len)
    1046             : {
    1047         968 :         if (md == NULL || ies == NULL) {
    1048          51 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
    1049          51 :                 os_free(wpa_s->sme.ft_ies);
    1050          51 :                 wpa_s->sme.ft_ies = NULL;
    1051          51 :                 wpa_s->sme.ft_ies_len = 0;
    1052          51 :                 wpa_s->sme.ft_used = 0;
    1053          51 :                 return 0;
    1054             :         }
    1055             : 
    1056         917 :         os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
    1057         917 :         wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
    1058         917 :         os_free(wpa_s->sme.ft_ies);
    1059         917 :         wpa_s->sme.ft_ies = os_malloc(ies_len);
    1060         917 :         if (wpa_s->sme.ft_ies == NULL)
    1061           1 :                 return -1;
    1062         916 :         os_memcpy(wpa_s->sme.ft_ies, ies, ies_len);
    1063         916 :         wpa_s->sme.ft_ies_len = ies_len;
    1064         916 :         return 0;
    1065             : }
    1066             : 
    1067             : 
    1068          43 : static void sme_deauth(struct wpa_supplicant *wpa_s)
    1069             : {
    1070             :         int bssid_changed;
    1071             : 
    1072          43 :         bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
    1073             : 
    1074          43 :         if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
    1075             :                                    WLAN_REASON_DEAUTH_LEAVING) < 0) {
    1076          43 :                 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
    1077             :                         "failed");
    1078             :         }
    1079          43 :         wpa_s->sme.prev_bssid_set = 0;
    1080             : 
    1081          43 :         wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
    1082          43 :         wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
    1083          43 :         os_memset(wpa_s->bssid, 0, ETH_ALEN);
    1084          43 :         os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
    1085          43 :         if (bssid_changed)
    1086           0 :                 wpas_notify_bssid_changed(wpa_s);
    1087          43 : }
    1088             : 
    1089             : 
    1090          44 : void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
    1091             :                             union wpa_event_data *data)
    1092             : {
    1093          44 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
    1094             :                 "status code %d", MAC2STR(wpa_s->pending_bssid),
    1095             :                 data->assoc_reject.status_code);
    1096             : 
    1097          44 :         eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
    1098             : 
    1099             : #ifdef CONFIG_SAE
    1100          45 :         if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
    1101           1 :             wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
    1102           1 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    1103             :                         "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
    1104           1 :                 wpa_sm_aborted_cached(wpa_s->wpa);
    1105           1 :                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
    1106           1 :                 if (wpa_s->current_bss) {
    1107           1 :                         struct wpa_bss *bss = wpa_s->current_bss;
    1108           1 :                         struct wpa_ssid *ssid = wpa_s->current_ssid;
    1109             : 
    1110           1 :                         wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
    1111             :                                                WLAN_REASON_DEAUTH_LEAVING);
    1112           1 :                         wpas_connect_work_done(wpa_s);
    1113           1 :                         wpa_supplicant_mark_disassoc(wpa_s);
    1114           1 :                         wpa_supplicant_connect(wpa_s, bss, ssid);
    1115          45 :                         return;
    1116             :                 }
    1117             :         }
    1118             : #endif /* CONFIG_SAE */
    1119             : 
    1120             :         /*
    1121             :          * For now, unconditionally terminate the previous authentication. In
    1122             :          * theory, this should not be needed, but mac80211 gets quite confused
    1123             :          * if the authentication is left pending.. Some roaming cases might
    1124             :          * benefit from using the previous authentication, so this could be
    1125             :          * optimized in the future.
    1126             :          */
    1127          43 :         sme_deauth(wpa_s);
    1128             : }
    1129             : 
    1130             : 
    1131          17 : void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
    1132             :                               union wpa_event_data *data)
    1133             : {
    1134          17 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
    1135          17 :         wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
    1136          17 :         wpa_supplicant_mark_disassoc(wpa_s);
    1137          17 : }
    1138             : 
    1139             : 
    1140           1 : void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
    1141             :                                union wpa_event_data *data)
    1142             : {
    1143           1 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
    1144           1 :         wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
    1145           1 :         wpa_supplicant_mark_disassoc(wpa_s);
    1146           1 : }
    1147             : 
    1148             : 
    1149           9 : void sme_event_disassoc(struct wpa_supplicant *wpa_s,
    1150             :                         struct disassoc_info *info)
    1151             : {
    1152           9 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
    1153           9 :         if (wpa_s->sme.prev_bssid_set) {
    1154             :                 /*
    1155             :                  * cfg80211/mac80211 can get into somewhat confused state if
    1156             :                  * the AP only disassociates us and leaves us in authenticated
    1157             :                  * state. For now, force the state to be cleared to avoid
    1158             :                  * confusing errors if we try to associate with the AP again.
    1159             :                  */
    1160           9 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
    1161             :                         "driver state");
    1162           9 :                 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
    1163             :                                        WLAN_REASON_DEAUTH_LEAVING);
    1164             :         }
    1165           9 : }
    1166             : 
    1167             : 
    1168           0 : static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
    1169             : {
    1170           0 :         struct wpa_supplicant *wpa_s = eloop_ctx;
    1171           0 :         if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
    1172           0 :                 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
    1173           0 :                 sme_deauth(wpa_s);
    1174             :         }
    1175           0 : }
    1176             : 
    1177             : 
    1178           0 : static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
    1179             : {
    1180           0 :         struct wpa_supplicant *wpa_s = eloop_ctx;
    1181           0 :         if (wpa_s->wpa_state == WPA_ASSOCIATING) {
    1182           0 :                 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
    1183           0 :                 sme_deauth(wpa_s);
    1184             :         }
    1185           0 : }
    1186             : 
    1187             : 
    1188       35541 : void sme_state_changed(struct wpa_supplicant *wpa_s)
    1189             : {
    1190             :         /* Make sure timers are cleaned up appropriately. */
    1191       35541 :         if (wpa_s->wpa_state != WPA_ASSOCIATING)
    1192       30711 :                 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
    1193       35541 :         if (wpa_s->wpa_state != WPA_AUTHENTICATING)
    1194       31023 :                 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
    1195       35541 : }
    1196             : 
    1197             : 
    1198           7 : void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
    1199             :                                        const u8 *prev_pending_bssid)
    1200             : {
    1201             :         /*
    1202             :          * mac80211-workaround to force deauth on failed auth cmd,
    1203             :          * requires us to remain in authenticating state to allow the
    1204             :          * second authentication attempt to be continued properly.
    1205             :          */
    1206           7 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
    1207             :                 "to proceed after disconnection event");
    1208           7 :         wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
    1209           7 :         os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
    1210             : 
    1211             :         /*
    1212             :          * Re-arm authentication timer in case auth fails for whatever reason.
    1213             :          */
    1214           7 :         eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
    1215           7 :         eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
    1216             :                                NULL);
    1217           7 : }
    1218             : 
    1219             : 
    1220       11041 : void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
    1221             : {
    1222       11041 :         wpa_s->sme.prev_bssid_set = 0;
    1223             : #ifdef CONFIG_SAE
    1224       11041 :         wpabuf_free(wpa_s->sme.sae_token);
    1225       11041 :         wpa_s->sme.sae_token = NULL;
    1226       11041 :         sae_clear_data(&wpa_s->sme.sae);
    1227             : #endif /* CONFIG_SAE */
    1228             : #ifdef CONFIG_IEEE80211R
    1229       11041 :         if (wpa_s->sme.ft_ies)
    1230          51 :                 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
    1231             : #endif /* CONFIG_IEEE80211R */
    1232       11041 : }
    1233             : 
    1234             : 
    1235         733 : void sme_deinit(struct wpa_supplicant *wpa_s)
    1236             : {
    1237         733 :         os_free(wpa_s->sme.ft_ies);
    1238         733 :         wpa_s->sme.ft_ies = NULL;
    1239         733 :         wpa_s->sme.ft_ies_len = 0;
    1240             : #ifdef CONFIG_IEEE80211W
    1241         733 :         sme_stop_sa_query(wpa_s);
    1242             : #endif /* CONFIG_IEEE80211W */
    1243         733 :         sme_clear_on_disassoc(wpa_s);
    1244             : 
    1245         733 :         eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
    1246         733 :         eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
    1247         733 :         eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
    1248         733 : }
    1249             : 
    1250             : 
    1251           5 : static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
    1252             :                                    const u8 *chan_list, u8 num_channels,
    1253             :                                    u8 num_intol)
    1254             : {
    1255             :         struct ieee80211_2040_bss_coex_ie *bc_ie;
    1256             :         struct ieee80211_2040_intol_chan_report *ic_report;
    1257             :         struct wpabuf *buf;
    1258             : 
    1259          35 :         wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
    1260             :                    " (num_channels=%u num_intol=%u)",
    1261          30 :                    MAC2STR(wpa_s->bssid), num_channels, num_intol);
    1262           5 :         wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
    1263             :                     chan_list, num_channels);
    1264             : 
    1265           5 :         buf = wpabuf_alloc(2 + /* action.category + action_code */
    1266             :                            sizeof(struct ieee80211_2040_bss_coex_ie) +
    1267             :                            sizeof(struct ieee80211_2040_intol_chan_report) +
    1268             :                            num_channels);
    1269           5 :         if (buf == NULL)
    1270           5 :                 return;
    1271             : 
    1272           5 :         wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
    1273           5 :         wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
    1274             : 
    1275           5 :         bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
    1276           5 :         bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
    1277           5 :         bc_ie->length = 1;
    1278           5 :         if (num_intol)
    1279           2 :                 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
    1280             : 
    1281           5 :         if (num_channels > 0) {
    1282           4 :                 ic_report = wpabuf_put(buf, sizeof(*ic_report));
    1283           4 :                 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
    1284           4 :                 ic_report->length = num_channels + 1;
    1285           4 :                 ic_report->op_class = 0;
    1286           4 :                 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
    1287             :                           num_channels);
    1288             :         }
    1289             : 
    1290          10 :         if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
    1291           5 :                                 wpa_s->own_addr, wpa_s->bssid,
    1292           5 :                                 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
    1293           0 :                 wpa_msg(wpa_s, MSG_INFO,
    1294             :                         "SME: Failed to send 20/40 BSS Coexistence frame");
    1295             :         }
    1296             : 
    1297           5 :         wpabuf_free(buf);
    1298             : }
    1299             : 
    1300             : 
    1301        3068 : int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
    1302             : {
    1303             :         struct wpa_bss *bss;
    1304             :         const u8 *ie;
    1305             :         u16 ht_cap;
    1306             :         u8 chan_list[P2P_MAX_CHANNELS], channel;
    1307        3068 :         u8 num_channels = 0, num_intol = 0, i;
    1308             : 
    1309        3068 :         if (!wpa_s->sme.sched_obss_scan)
    1310        3063 :                 return 0;
    1311             : 
    1312           5 :         wpa_s->sme.sched_obss_scan = 0;
    1313           5 :         if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
    1314           0 :                 return 1;
    1315             : 
    1316             :         /*
    1317             :          * Check whether AP uses regulatory triplet or channel triplet in
    1318             :          * country info. Right now the operating class of the BSS channel
    1319             :          * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
    1320             :          * based on the assumption that operating class triplet is not used in
    1321             :          * beacon frame. If the First Channel Number/Operating Extension
    1322             :          * Identifier octet has a positive integer value of 201 or greater,
    1323             :          * then its operating class triplet.
    1324             :          *
    1325             :          * TODO: If Supported Operating Classes element is present in beacon
    1326             :          * frame, have to lookup operating class in Annex E and fill them in
    1327             :          * 2040 coex frame.
    1328             :          */
    1329           5 :         ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
    1330           5 :         if (ie && (ie[1] >= 6) && (ie[5] >= 201))
    1331           0 :                 return 1;
    1332             : 
    1333           5 :         os_memset(chan_list, 0, sizeof(chan_list));
    1334             : 
    1335          14 :         dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    1336             :                 /* Skip other band bss */
    1337             :                 enum hostapd_hw_mode mode;
    1338           9 :                 mode = ieee80211_freq_to_chan(bss->freq, &channel);
    1339           9 :                 if (mode != HOSTAPD_MODE_IEEE80211G &&
    1340             :                     mode != HOSTAPD_MODE_IEEE80211B)
    1341           0 :                         continue;
    1342             : 
    1343           9 :                 ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
    1344           9 :                 ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
    1345          63 :                 wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
    1346             :                            " freq=%u chan=%u ht_cap=0x%x",
    1347          54 :                            MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
    1348             : 
    1349           9 :                 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
    1350           4 :                         if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
    1351           2 :                                 num_intol++;
    1352             : 
    1353             :                         /* Check whether the channel is already considered */
    1354           4 :                         for (i = 0; i < num_channels; i++) {
    1355           0 :                                 if (channel == chan_list[i])
    1356           0 :                                         break;
    1357             :                         }
    1358           4 :                         if (i != num_channels)
    1359           0 :                                 continue;
    1360             : 
    1361           4 :                         chan_list[num_channels++] = channel;
    1362             :                 }
    1363             :         }
    1364             : 
    1365           5 :         sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
    1366           5 :         return 1;
    1367             : }
    1368             : 
    1369             : 
    1370           5 : static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
    1371             :                                      struct wpa_driver_scan_params *params)
    1372             : {
    1373             :         /* Include only affected channels */
    1374             :         struct hostapd_hw_modes *mode;
    1375             :         int count, i;
    1376             :         int start, end;
    1377             : 
    1378           5 :         mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
    1379             :                         HOSTAPD_MODE_IEEE80211G);
    1380           5 :         if (mode == NULL) {
    1381             :                 /* No channels supported in this band - use empty list */
    1382           0 :                 params->freqs = os_zalloc(sizeof(int));
    1383           0 :                 return;
    1384             :         }
    1385             : 
    1386           9 :         if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
    1387           4 :             wpa_s->current_bss) {
    1388             :                 const u8 *ie;
    1389             : 
    1390           4 :                 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
    1391           4 :                 if (ie && ie[1] >= 2) {
    1392             :                         u8 o;
    1393             : 
    1394           4 :                         o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
    1395           4 :                         if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
    1396           1 :                                 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
    1397           3 :                         else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
    1398           3 :                                 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
    1399             :                 }
    1400             :         }
    1401             : 
    1402           5 :         start = wpa_s->assoc_freq - 10;
    1403           5 :         end = wpa_s->assoc_freq + 10;
    1404           5 :         switch (wpa_s->sme.ht_sec_chan) {
    1405             :         case HT_SEC_CHAN_UNKNOWN:
    1406             :                 /* HT40+ possible on channels 1..9 */
    1407           0 :                 if (wpa_s->assoc_freq <= 2452)
    1408           0 :                         start -= 20;
    1409             :                 /* HT40- possible on channels 5-13 */
    1410           0 :                 if (wpa_s->assoc_freq >= 2432)
    1411           0 :                         end += 20;
    1412           0 :                 break;
    1413             :         case HT_SEC_CHAN_ABOVE:
    1414           1 :                 end += 20;
    1415           1 :                 break;
    1416             :         case HT_SEC_CHAN_BELOW:
    1417           4 :                 start -= 20;
    1418           4 :                 break;
    1419             :         }
    1420           5 :         wpa_printf(MSG_DEBUG,
    1421             :                    "OBSS: assoc_freq %d possible affected range %d-%d",
    1422             :                    wpa_s->assoc_freq, start, end);
    1423             : 
    1424           5 :         params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
    1425           5 :         if (params->freqs == NULL)
    1426           0 :                 return;
    1427          75 :         for (count = 0, i = 0; i < mode->num_channels; i++) {
    1428             :                 int freq;
    1429             : 
    1430          70 :                 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
    1431           0 :                         continue;
    1432          70 :                 freq = mode->channels[i].freq;
    1433          70 :                 if (freq - 10 >= end || freq + 10 <= start)
    1434          23 :                         continue; /* not affected */
    1435          47 :                 params->freqs[count++] = freq;
    1436             :         }
    1437             : }
    1438             : 
    1439             : 
    1440           5 : static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
    1441             : {
    1442           5 :         struct wpa_supplicant *wpa_s = eloop_ctx;
    1443             :         struct wpa_driver_scan_params params;
    1444             : 
    1445           5 :         if (!wpa_s->current_bss) {
    1446           0 :                 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
    1447           5 :                 return;
    1448             :         }
    1449             : 
    1450           5 :         os_memset(&params, 0, sizeof(params));
    1451           5 :         wpa_obss_scan_freqs_list(wpa_s, &params);
    1452           5 :         params.low_priority = 1;
    1453           5 :         wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
    1454             : 
    1455           5 :         if (wpa_supplicant_trigger_scan(wpa_s, &params))
    1456           0 :                 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
    1457             :         else
    1458           5 :                 wpa_s->sme.sched_obss_scan = 1;
    1459           5 :         os_free(params.freqs);
    1460             : 
    1461           5 :         eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
    1462             :                                sme_obss_scan_timeout, wpa_s, NULL);
    1463             : }
    1464             : 
    1465             : 
    1466       27130 : void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
    1467             : {
    1468             :         const u8 *ie;
    1469       27130 :         struct wpa_bss *bss = wpa_s->current_bss;
    1470       27130 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    1471       27130 :         struct hostapd_hw_modes *hw_mode = NULL;
    1472             :         int i;
    1473             : 
    1474       27130 :         eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
    1475       27130 :         wpa_s->sme.sched_obss_scan = 0;
    1476       27130 :         wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
    1477       27130 :         if (!enable)
    1478       23476 :                 return;
    1479             : 
    1480             :         /*
    1481             :          * Schedule OBSS scan if driver is using station SME in wpa_supplicant
    1482             :          * or it expects OBSS scan to be performed by wpa_supplicant.
    1483             :          */
    1484        3934 :         if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
    1485        3654 :               (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
    1486        3374 :             ssid == NULL || ssid->mode != IEEE80211_MODE_INFRA)
    1487         912 :                 return;
    1488             : 
    1489        2742 :         if (!wpa_s->hw.modes)
    1490           0 :                 return;
    1491             : 
    1492             :         /* only HT caps in 11g mode are relevant */
    1493        2742 :         for (i = 0; i < wpa_s->hw.num_modes; i++) {
    1494        2742 :                 hw_mode = &wpa_s->hw.modes[i];
    1495        2742 :                 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
    1496        2742 :                         break;
    1497             :         }
    1498             : 
    1499             :         /* Driver does not support HT40 for 11g or doesn't have 11g. */
    1500        5484 :         if (i == wpa_s->hw.num_modes || !hw_mode ||
    1501        2742 :             !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
    1502           0 :                 return;
    1503             : 
    1504        2742 :         if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
    1505          75 :                 return; /* Not associated on 2.4 GHz band */
    1506             : 
    1507             :         /* Check whether AP supports HT40 */
    1508        2667 :         ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
    1509        5301 :         if (!ie || ie[1] < 2 ||
    1510        2634 :             !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
    1511        2644 :                 return; /* AP does not support HT40 */
    1512             : 
    1513          23 :         ie = wpa_bss_get_ie(wpa_s->current_bss,
    1514             :                             WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
    1515          23 :         if (!ie || ie[1] < 14)
    1516          18 :                 return; /* AP does not request OBSS scans */
    1517             : 
    1518           5 :         wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
    1519           5 :         if (wpa_s->sme.obss_scan_int < 10) {
    1520           2 :                 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
    1521             :                            "replaced with the minimum 10 sec",
    1522           2 :                            wpa_s->sme.obss_scan_int);
    1523           2 :                 wpa_s->sme.obss_scan_int = 10;
    1524             :         }
    1525           5 :         wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
    1526           5 :                    wpa_s->sme.obss_scan_int);
    1527           5 :         eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
    1528             :                                sme_obss_scan_timeout, wpa_s, NULL);
    1529             : }
    1530             : 
    1531             : 
    1532             : #ifdef CONFIG_IEEE80211W
    1533             : 
    1534             : static const unsigned int sa_query_max_timeout = 1000;
    1535             : static const unsigned int sa_query_retry_timeout = 201;
    1536             : 
    1537           5 : static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
    1538             : {
    1539             :         u32 tu;
    1540             :         struct os_reltime now, passed;
    1541           5 :         os_get_reltime(&now);
    1542           5 :         os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
    1543           5 :         tu = (passed.sec * 1000000 + passed.usec) / 1024;
    1544           5 :         if (sa_query_max_timeout < tu) {
    1545           1 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
    1546           1 :                 sme_stop_sa_query(wpa_s);
    1547           1 :                 wpa_supplicant_deauthenticate(
    1548             :                         wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
    1549           1 :                 return 1;
    1550             :         }
    1551             : 
    1552           4 :         return 0;
    1553             : }
    1554             : 
    1555             : 
    1556           8 : static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
    1557             :                                   const u8 *trans_id)
    1558             : {
    1559             :         u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN];
    1560           8 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
    1561             :                 MACSTR, MAC2STR(wpa_s->bssid));
    1562           8 :         wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
    1563             :                     trans_id, WLAN_SA_QUERY_TR_ID_LEN);
    1564           8 :         req[0] = WLAN_ACTION_SA_QUERY;
    1565           8 :         req[1] = WLAN_SA_QUERY_REQUEST;
    1566           8 :         os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
    1567           8 :         if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
    1568           8 :                                 wpa_s->own_addr, wpa_s->bssid,
    1569             :                                 req, sizeof(req), 0) < 0)
    1570           0 :                 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
    1571             :                         "Request");
    1572           8 : }
    1573             : 
    1574             : 
    1575          11 : static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
    1576             : {
    1577          11 :         struct wpa_supplicant *wpa_s = eloop_ctx;
    1578             :         unsigned int timeout, sec, usec;
    1579             :         u8 *trans_id, *nbuf;
    1580             : 
    1581          16 :         if (wpa_s->sme.sa_query_count > 0 &&
    1582           5 :             sme_check_sa_query_timeout(wpa_s))
    1583           1 :                 return;
    1584             : 
    1585          10 :         nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
    1586          10 :                                 wpa_s->sme.sa_query_count + 1,
    1587             :                                 WLAN_SA_QUERY_TR_ID_LEN);
    1588          10 :         if (nbuf == NULL) {
    1589           1 :                 sme_stop_sa_query(wpa_s);
    1590           1 :                 return;
    1591             :         }
    1592           9 :         if (wpa_s->sme.sa_query_count == 0) {
    1593             :                 /* Starting a new SA Query procedure */
    1594           5 :                 os_get_reltime(&wpa_s->sme.sa_query_start);
    1595             :         }
    1596           9 :         trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
    1597           9 :         wpa_s->sme.sa_query_trans_id = nbuf;
    1598           9 :         wpa_s->sme.sa_query_count++;
    1599             : 
    1600           9 :         if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
    1601           1 :                 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
    1602           1 :                 sme_stop_sa_query(wpa_s);
    1603           1 :                 return;
    1604             :         }
    1605             : 
    1606           8 :         timeout = sa_query_retry_timeout;
    1607           8 :         sec = ((timeout / 1000) * 1024) / 1000;
    1608           8 :         usec = (timeout % 1000) * 1024;
    1609           8 :         eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
    1610             : 
    1611           8 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
    1612             :                 wpa_s->sme.sa_query_count);
    1613             : 
    1614           8 :         sme_send_sa_query_req(wpa_s, trans_id);
    1615             : }
    1616             : 
    1617             : 
    1618           6 : static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
    1619             : {
    1620           6 :         sme_sa_query_timer(wpa_s, NULL);
    1621           6 : }
    1622             : 
    1623             : 
    1624         739 : static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
    1625             : {
    1626         739 :         eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
    1627         739 :         os_free(wpa_s->sme.sa_query_trans_id);
    1628         739 :         wpa_s->sme.sa_query_trans_id = NULL;
    1629         739 :         wpa_s->sme.sa_query_count = 0;
    1630         739 : }
    1631             : 
    1632             : 
    1633          40 : void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
    1634             :                                  const u8 *da, u16 reason_code)
    1635             : {
    1636             :         struct wpa_ssid *ssid;
    1637             :         struct os_reltime now;
    1638             : 
    1639          40 :         if (wpa_s->wpa_state != WPA_COMPLETED)
    1640          34 :                 return;
    1641          40 :         ssid = wpa_s->current_ssid;
    1642          40 :         if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
    1643           0 :                 return;
    1644          40 :         if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
    1645           0 :                 return;
    1646          40 :         if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
    1647             :             reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
    1648           4 :                 return;
    1649          36 :         if (wpa_s->sme.sa_query_count > 0)
    1650           6 :                 return;
    1651             : 
    1652          30 :         os_get_reltime(&now);
    1653          55 :         if (wpa_s->sme.last_unprot_disconnect.sec &&
    1654          25 :             !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
    1655          24 :                 return; /* limit SA Query procedure frequency */
    1656           6 :         wpa_s->sme.last_unprot_disconnect = now;
    1657             : 
    1658           6 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
    1659             :                 "possible AP/STA state mismatch - trigger SA Query");
    1660           6 :         sme_start_sa_query(wpa_s);
    1661             : }
    1662             : 
    1663             : 
    1664           3 : void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
    1665             :                      const u8 *data, size_t len)
    1666             : {
    1667             :         int i;
    1668             : 
    1669           3 :         if (wpa_s->sme.sa_query_trans_id == NULL ||
    1670           3 :             len < 1 + WLAN_SA_QUERY_TR_ID_LEN ||
    1671           3 :             data[0] != WLAN_SA_QUERY_RESPONSE)
    1672           0 :                 return;
    1673           3 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
    1674             :                 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
    1675             : 
    1676           3 :         if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
    1677           0 :                 return;
    1678             : 
    1679           3 :         for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
    1680           3 :                 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
    1681             :                               i * WLAN_SA_QUERY_TR_ID_LEN,
    1682             :                               data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
    1683           3 :                         break;
    1684             :         }
    1685             : 
    1686           3 :         if (i >= wpa_s->sme.sa_query_count) {
    1687           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
    1688             :                         "transaction identifier found");
    1689           0 :                 return;
    1690             :         }
    1691             : 
    1692           3 :         wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
    1693             :                 "from " MACSTR, MAC2STR(sa));
    1694           3 :         sme_stop_sa_query(wpa_s);
    1695             : }
    1696             : 
    1697             : #endif /* CONFIG_IEEE80211W */

Generated by: LCOV version 1.10