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 1443382998 Lines: 756 865 87.4 %
Date: 2015-09-27 Functions: 34 36 94.4 %

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

Generated by: LCOV version 1.10