LCOV - code coverage report
Current view: top level - src/ap - drv_callbacks.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 238 694 34.3 %
Date: 2016-10-02 Functions: 16 28 57.1 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / Callback functions for driver wrappers
       3             :  * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #include "utils/common.h"
      12             : #include "utils/eloop.h"
      13             : #include "radius/radius.h"
      14             : #include "drivers/driver.h"
      15             : #include "common/ieee802_11_defs.h"
      16             : #include "common/ieee802_11_common.h"
      17             : #include "common/wpa_ctrl.h"
      18             : #include "crypto/random.h"
      19             : #include "p2p/p2p.h"
      20             : #include "wps/wps.h"
      21             : #include "fst/fst.h"
      22             : #include "wnm_ap.h"
      23             : #include "hostapd.h"
      24             : #include "ieee802_11.h"
      25             : #include "ieee802_11_auth.h"
      26             : #include "sta_info.h"
      27             : #include "accounting.h"
      28             : #include "tkip_countermeasures.h"
      29             : #include "ieee802_1x.h"
      30             : #include "wpa_auth.h"
      31             : #include "wps_hostapd.h"
      32             : #include "ap_drv_ops.h"
      33             : #include "ap_config.h"
      34             : #include "hw_features.h"
      35             : #include "dfs.h"
      36             : #include "beacon.h"
      37             : #include "mbo_ap.h"
      38             : 
      39             : 
      40           0 : int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
      41             :                         const u8 *req_ies, size_t req_ies_len, int reassoc)
      42             : {
      43             :         struct sta_info *sta;
      44             :         int new_assoc, res;
      45             :         struct ieee802_11_elems elems;
      46             :         const u8 *ie;
      47             :         size_t ielen;
      48             : #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
      49             :         u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
      50           0 :         u8 *p = buf;
      51             : #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
      52           0 :         u16 reason = WLAN_REASON_UNSPECIFIED;
      53           0 :         u16 status = WLAN_STATUS_SUCCESS;
      54           0 :         const u8 *p2p_dev_addr = NULL;
      55             : 
      56           0 :         if (addr == NULL) {
      57             :                 /*
      58             :                  * This could potentially happen with unexpected event from the
      59             :                  * driver wrapper. This was seen at least in one case where the
      60             :                  * driver ended up being set to station mode while hostapd was
      61             :                  * running, so better make sure we stop processing such an
      62             :                  * event here.
      63             :                  */
      64           0 :                 wpa_printf(MSG_DEBUG,
      65             :                            "hostapd_notif_assoc: Skip event with no address");
      66           0 :                 return -1;
      67             :         }
      68             :         random_add_randomness(addr, ETH_ALEN);
      69             : 
      70           0 :         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
      71             :                        HOSTAPD_LEVEL_INFO, "associated");
      72             : 
      73           0 :         ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
      74           0 :         if (elems.wps_ie) {
      75           0 :                 ie = elems.wps_ie - 2;
      76           0 :                 ielen = elems.wps_ie_len + 2;
      77           0 :                 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
      78           0 :         } else if (elems.rsn_ie) {
      79           0 :                 ie = elems.rsn_ie - 2;
      80           0 :                 ielen = elems.rsn_ie_len + 2;
      81           0 :                 wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
      82           0 :         } else if (elems.wpa_ie) {
      83           0 :                 ie = elems.wpa_ie - 2;
      84           0 :                 ielen = elems.wpa_ie_len + 2;
      85           0 :                 wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
      86             : #ifdef CONFIG_HS20
      87           0 :         } else if (elems.osen) {
      88           0 :                 ie = elems.osen - 2;
      89           0 :                 ielen = elems.osen_len + 2;
      90           0 :                 wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq");
      91             : #endif /* CONFIG_HS20 */
      92             :         } else {
      93           0 :                 ie = NULL;
      94           0 :                 ielen = 0;
      95           0 :                 wpa_printf(MSG_DEBUG,
      96             :                            "STA did not include WPS/RSN/WPA IE in (Re)AssocReq");
      97             :         }
      98             : 
      99           0 :         sta = ap_get_sta(hapd, addr);
     100           0 :         if (sta) {
     101           0 :                 ap_sta_no_session_timeout(hapd, sta);
     102           0 :                 accounting_sta_stop(hapd, sta);
     103             : 
     104             :                 /*
     105             :                  * Make sure that the previously registered inactivity timer
     106             :                  * will not remove the STA immediately.
     107             :                  */
     108           0 :                 sta->timeout_next = STA_NULLFUNC;
     109             :         } else {
     110           0 :                 sta = ap_sta_add(hapd, addr);
     111           0 :                 if (sta == NULL) {
     112           0 :                         hostapd_drv_sta_disassoc(hapd, addr,
     113             :                                                  WLAN_REASON_DISASSOC_AP_BUSY);
     114           0 :                         return -1;
     115             :                 }
     116             :         }
     117           0 :         sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
     118             : 
     119             :         /*
     120             :          * ACL configurations to the drivers (implementing AP SME and ACL
     121             :          * offload) without hostapd's knowledge, can result in a disconnection
     122             :          * though the driver accepts the connection. Skip the hostapd check for
     123             :          * ACL if the driver supports ACL offload to avoid potentially
     124             :          * conflicting ACL rules.
     125             :          */
     126           0 :         if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
     127           0 :             hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
     128           0 :                 wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
     129           0 :                            MAC2STR(addr));
     130           0 :                 reason = WLAN_REASON_UNSPECIFIED;
     131           0 :                 goto fail;
     132             :         }
     133             : 
     134             : #ifdef CONFIG_P2P
     135           0 :         if (elems.p2p) {
     136           0 :                 wpabuf_free(sta->p2p_ie);
     137           0 :                 sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
     138             :                                                           P2P_IE_VENDOR_TYPE);
     139           0 :                 if (sta->p2p_ie)
     140           0 :                         p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
     141             :         }
     142             : #endif /* CONFIG_P2P */
     143             : 
     144             : #ifdef CONFIG_IEEE80211N
     145             : #ifdef NEED_AP_MLME
     146           0 :         if (elems.ht_capabilities &&
     147           0 :             (hapd->iface->conf->ht_capab &
     148             :              HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
     149           0 :                 struct ieee80211_ht_capabilities *ht_cap =
     150             :                         (struct ieee80211_ht_capabilities *)
     151             :                         elems.ht_capabilities;
     152             : 
     153           0 :                 if (le_to_host16(ht_cap->ht_capabilities_info) &
     154             :                     HT_CAP_INFO_40MHZ_INTOLERANT)
     155           0 :                         ht40_intolerant_add(hapd->iface, sta);
     156             :         }
     157             : #endif /* NEED_AP_MLME */
     158             : #endif /* CONFIG_IEEE80211N */
     159             : 
     160             : #ifdef CONFIG_INTERWORKING
     161           0 :         if (elems.ext_capab && elems.ext_capab_len > 4) {
     162           0 :                 if (elems.ext_capab[4] & 0x01)
     163           0 :                         sta->qos_map_enabled = 1;
     164             :         }
     165             : #endif /* CONFIG_INTERWORKING */
     166             : 
     167             : #ifdef CONFIG_HS20
     168           0 :         wpabuf_free(sta->hs20_ie);
     169           0 :         if (elems.hs20 && elems.hs20_len > 4) {
     170           0 :                 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
     171           0 :                                                  elems.hs20_len - 4);
     172             :         } else
     173           0 :                 sta->hs20_ie = NULL;
     174             : #endif /* CONFIG_HS20 */
     175             : 
     176             : #ifdef CONFIG_FST
     177           0 :         wpabuf_free(sta->mb_ies);
     178           0 :         if (hapd->iface->fst)
     179           0 :                 sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
     180             :         else
     181           0 :                 sta->mb_ies = NULL;
     182             : #endif /* CONFIG_FST */
     183             : 
     184           0 :         mbo_ap_check_sta_assoc(hapd, sta, &elems);
     185             : 
     186           0 :         ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
     187           0 :                                     elems.supp_op_classes_len);
     188             : 
     189           0 :         if (hapd->conf->wpa) {
     190           0 :                 if (ie == NULL || ielen == 0) {
     191             : #ifdef CONFIG_WPS
     192           0 :                         if (hapd->conf->wps_state) {
     193           0 :                                 wpa_printf(MSG_DEBUG,
     194             :                                            "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use");
     195           0 :                                 sta->flags |= WLAN_STA_MAYBE_WPS;
     196           0 :                                 goto skip_wpa_check;
     197             :                         }
     198             : #endif /* CONFIG_WPS */
     199             : 
     200           0 :                         wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
     201           0 :                         return -1;
     202             :                 }
     203             : #ifdef CONFIG_WPS
     204           0 :                 if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
     205           0 :                     os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
     206             :                         struct wpabuf *wps;
     207             : 
     208           0 :                         sta->flags |= WLAN_STA_WPS;
     209           0 :                         wps = ieee802_11_vendor_ie_concat(ie, ielen,
     210             :                                                           WPS_IE_VENDOR_TYPE);
     211           0 :                         if (wps) {
     212           0 :                                 if (wps_is_20(wps)) {
     213           0 :                                         wpa_printf(MSG_DEBUG,
     214             :                                                    "WPS: STA supports WPS 2.0");
     215           0 :                                         sta->flags |= WLAN_STA_WPS2;
     216             :                                 }
     217           0 :                                 wpabuf_free(wps);
     218             :                         }
     219           0 :                         goto skip_wpa_check;
     220             :                 }
     221             : #endif /* CONFIG_WPS */
     222             : 
     223           0 :                 if (sta->wpa_sm == NULL)
     224           0 :                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
     225           0 :                                                         sta->addr,
     226             :                                                         p2p_dev_addr);
     227           0 :                 if (sta->wpa_sm == NULL) {
     228           0 :                         wpa_printf(MSG_ERROR,
     229             :                                    "Failed to initialize WPA state machine");
     230           0 :                         return -1;
     231             :                 }
     232           0 :                 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
     233             :                                           ie, ielen,
     234           0 :                                           elems.mdie, elems.mdie_len);
     235           0 :                 if (res != WPA_IE_OK) {
     236           0 :                         wpa_printf(MSG_DEBUG,
     237             :                                    "WPA/RSN information element rejected? (res %u)",
     238             :                                    res);
     239           0 :                         wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
     240           0 :                         if (res == WPA_INVALID_GROUP) {
     241           0 :                                 reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
     242           0 :                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
     243           0 :                         } else if (res == WPA_INVALID_PAIRWISE) {
     244           0 :                                 reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
     245           0 :                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
     246           0 :                         } else if (res == WPA_INVALID_AKMP) {
     247           0 :                                 reason = WLAN_REASON_AKMP_NOT_VALID;
     248           0 :                                 status = WLAN_STATUS_AKMP_NOT_VALID;
     249             :                         }
     250             : #ifdef CONFIG_IEEE80211W
     251           0 :                         else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
     252           0 :                                 reason = WLAN_REASON_INVALID_IE;
     253           0 :                                 status = WLAN_STATUS_INVALID_IE;
     254           0 :                         } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
     255           0 :                                 reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
     256           0 :                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
     257             :                         }
     258             : #endif /* CONFIG_IEEE80211W */
     259             :                         else {
     260           0 :                                 reason = WLAN_REASON_INVALID_IE;
     261           0 :                                 status = WLAN_STATUS_INVALID_IE;
     262             :                         }
     263           0 :                         goto fail;
     264             :                 }
     265             : #ifdef CONFIG_IEEE80211W
     266           0 :                 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
     267           0 :                     sta->sa_query_count > 0)
     268           0 :                         ap_check_sa_query_timeout(hapd, sta);
     269           0 :                 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
     270           0 :                     (sta->auth_alg != WLAN_AUTH_FT)) {
     271             :                         /*
     272             :                          * STA has already been associated with MFP and SA
     273             :                          * Query timeout has not been reached. Reject the
     274             :                          * association attempt temporarily and start SA Query,
     275             :                          * if one is not pending.
     276             :                          */
     277             : 
     278           0 :                         if (sta->sa_query_count == 0)
     279           0 :                                 ap_sta_start_sa_query(hapd, sta);
     280             : 
     281           0 :                         status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
     282             : 
     283           0 :                         p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
     284             : 
     285           0 :                         hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
     286           0 :                                           p - buf);
     287           0 :                         return 0;
     288             :                 }
     289             : 
     290           0 :                 if (wpa_auth_uses_mfp(sta->wpa_sm))
     291           0 :                         sta->flags |= WLAN_STA_MFP;
     292             :                 else
     293           0 :                         sta->flags &= ~WLAN_STA_MFP;
     294             : #endif /* CONFIG_IEEE80211W */
     295             : 
     296             : #ifdef CONFIG_IEEE80211R
     297           0 :                 if (sta->auth_alg == WLAN_AUTH_FT) {
     298           0 :                         status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
     299             :                                                          req_ies_len);
     300           0 :                         if (status != WLAN_STATUS_SUCCESS) {
     301           0 :                                 if (status == WLAN_STATUS_INVALID_PMKID)
     302           0 :                                         reason = WLAN_REASON_INVALID_IE;
     303           0 :                                 if (status == WLAN_STATUS_INVALID_MDIE)
     304           0 :                                         reason = WLAN_REASON_INVALID_IE;
     305           0 :                                 if (status == WLAN_STATUS_INVALID_FTIE)
     306           0 :                                         reason = WLAN_REASON_INVALID_IE;
     307           0 :                                 goto fail;
     308             :                         }
     309             :                 }
     310             : #endif /* CONFIG_IEEE80211R */
     311           0 :         } else if (hapd->conf->wps_state) {
     312             : #ifdef CONFIG_WPS
     313             :                 struct wpabuf *wps;
     314             : 
     315           0 :                 if (req_ies)
     316           0 :                         wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
     317             :                                                           WPS_IE_VENDOR_TYPE);
     318             :                 else
     319           0 :                         wps = NULL;
     320             : #ifdef CONFIG_WPS_STRICT
     321             :                 if (wps && wps_validate_assoc_req(wps) < 0) {
     322             :                         reason = WLAN_REASON_INVALID_IE;
     323             :                         status = WLAN_STATUS_INVALID_IE;
     324             :                         wpabuf_free(wps);
     325             :                         goto fail;
     326             :                 }
     327             : #endif /* CONFIG_WPS_STRICT */
     328           0 :                 if (wps) {
     329           0 :                         sta->flags |= WLAN_STA_WPS;
     330           0 :                         if (wps_is_20(wps)) {
     331           0 :                                 wpa_printf(MSG_DEBUG,
     332             :                                            "WPS: STA supports WPS 2.0");
     333           0 :                                 sta->flags |= WLAN_STA_WPS2;
     334             :                         }
     335             :                 } else
     336           0 :                         sta->flags |= WLAN_STA_MAYBE_WPS;
     337           0 :                 wpabuf_free(wps);
     338             : #endif /* CONFIG_WPS */
     339             : #ifdef CONFIG_HS20
     340           0 :         } else if (hapd->conf->osen) {
     341           0 :                 if (elems.osen == NULL) {
     342           0 :                         hostapd_logger(
     343           0 :                                 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
     344             :                                 HOSTAPD_LEVEL_INFO,
     345             :                                 "No HS 2.0 OSEN element in association request");
     346           0 :                         return WLAN_STATUS_INVALID_IE;
     347             :                 }
     348             : 
     349           0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
     350           0 :                 if (sta->wpa_sm == NULL)
     351           0 :                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
     352           0 :                                                         sta->addr, NULL);
     353           0 :                 if (sta->wpa_sm == NULL) {
     354           0 :                         wpa_printf(MSG_WARNING,
     355             :                                    "Failed to initialize WPA state machine");
     356           0 :                         return WLAN_STATUS_UNSPECIFIED_FAILURE;
     357             :                 }
     358           0 :                 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
     359           0 :                                       elems.osen - 2, elems.osen_len + 2) < 0)
     360           0 :                         return WLAN_STATUS_INVALID_IE;
     361             : #endif /* CONFIG_HS20 */
     362             :         }
     363             : 
     364             : #ifdef CONFIG_MBO
     365           0 :         if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
     366           0 :             elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
     367           0 :             hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
     368           0 :                 wpa_printf(MSG_INFO,
     369             :                            "MBO: Reject WPA2 association without PMF");
     370           0 :                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
     371             :         }
     372             : #endif /* CONFIG_MBO */
     373             : 
     374             : #ifdef CONFIG_WPS
     375             : skip_wpa_check:
     376             : #endif /* CONFIG_WPS */
     377             : 
     378             : #ifdef CONFIG_IEEE80211R
     379           0 :         p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
     380           0 :                                         sta->auth_alg, req_ies, req_ies_len);
     381             : 
     382           0 :         hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
     383             : 
     384           0 :         if (sta->auth_alg == WLAN_AUTH_FT)
     385           0 :                 ap_sta_set_authorized(hapd, sta, 1);
     386             : #else /* CONFIG_IEEE80211R */
     387             :         /* Keep compiler silent about unused variables */
     388             :         if (status) {
     389             :         }
     390             : #endif /* CONFIG_IEEE80211R */
     391             : 
     392           0 :         new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
     393           0 :         sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
     394           0 :         sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
     395             : 
     396           0 :         hostapd_set_sta_flags(hapd, sta);
     397             : 
     398           0 :         if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
     399           0 :                 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
     400             :         else
     401           0 :                 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
     402             : 
     403           0 :         hostapd_new_assoc_sta(hapd, sta, !new_assoc);
     404             : 
     405           0 :         ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
     406             : 
     407             : #ifdef CONFIG_P2P
     408           0 :         if (req_ies) {
     409           0 :                 p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
     410             :                                       req_ies, req_ies_len);
     411             :         }
     412             : #endif /* CONFIG_P2P */
     413             : 
     414           0 :         return 0;
     415             : 
     416             : fail:
     417             : #ifdef CONFIG_IEEE80211R
     418           0 :         hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
     419             : #endif /* CONFIG_IEEE80211R */
     420           0 :         hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
     421           0 :         ap_free_sta(hapd, sta);
     422           0 :         return -1;
     423             : }
     424             : 
     425             : 
     426           0 : void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
     427             : {
     428             :         struct sta_info *sta;
     429             : 
     430           0 :         if (addr == NULL) {
     431             :                 /*
     432             :                  * This could potentially happen with unexpected event from the
     433             :                  * driver wrapper. This was seen at least in one case where the
     434             :                  * driver ended up reporting a station mode event while hostapd
     435             :                  * was running, so better make sure we stop processing such an
     436             :                  * event here.
     437             :                  */
     438           0 :                 wpa_printf(MSG_DEBUG,
     439             :                            "hostapd_notif_disassoc: Skip event with no address");
     440           0 :                 return;
     441             :         }
     442             : 
     443           0 :         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
     444             :                        HOSTAPD_LEVEL_INFO, "disassociated");
     445             : 
     446           0 :         sta = ap_get_sta(hapd, addr);
     447           0 :         if (sta == NULL) {
     448           0 :                 wpa_printf(MSG_DEBUG,
     449             :                            "Disassociation notification for unknown STA "
     450           0 :                            MACSTR, MAC2STR(addr));
     451           0 :                 return;
     452             :         }
     453             : 
     454           0 :         ap_sta_set_authorized(hapd, sta, 0);
     455           0 :         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
     456           0 :         wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
     457           0 :         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
     458           0 :         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
     459           0 :         ap_free_sta(hapd, sta);
     460             : }
     461             : 
     462             : 
     463           0 : void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
     464             : {
     465           0 :         struct sta_info *sta = ap_get_sta(hapd, addr);
     466             : 
     467           0 :         if (!sta || !hapd->conf->disassoc_low_ack)
     468           0 :                 return;
     469             : 
     470           0 :         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
     471             :                        HOSTAPD_LEVEL_INFO,
     472             :                        "disconnected due to excessive missing ACKs");
     473           0 :         hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
     474           0 :         if (sta)
     475           0 :                 ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
     476             : }
     477             : 
     478             : 
     479          23 : void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
     480             :                              int offset, int width, int cf1, int cf2)
     481             : {
     482             : #ifdef NEED_AP_MLME
     483             :         int channel, chwidth, is_dfs;
     484          23 :         u8 seg0_idx = 0, seg1_idx = 0;
     485             : 
     486          23 :         hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
     487             :                        HOSTAPD_LEVEL_INFO,
     488             :                        "driver had channel switch: freq=%d, ht=%d, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
     489             :                        freq, ht, offset, width, channel_width_to_string(width),
     490             :                        cf1, cf2);
     491             : 
     492          23 :         hapd->iface->freq = freq;
     493             : 
     494          23 :         channel = hostapd_hw_get_channel(hapd, freq);
     495          23 :         if (!channel) {
     496           0 :                 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
     497             :                                HOSTAPD_LEVEL_WARNING,
     498             :                                "driver switched to bad channel!");
     499          23 :                 return;
     500             :         }
     501             : 
     502          23 :         switch (width) {
     503             :         case CHAN_WIDTH_80:
     504           1 :                 chwidth = VHT_CHANWIDTH_80MHZ;
     505           1 :                 break;
     506             :         case CHAN_WIDTH_80P80:
     507           0 :                 chwidth = VHT_CHANWIDTH_80P80MHZ;
     508           0 :                 break;
     509             :         case CHAN_WIDTH_160:
     510           0 :                 chwidth = VHT_CHANWIDTH_160MHZ;
     511           0 :                 break;
     512             :         case CHAN_WIDTH_20_NOHT:
     513             :         case CHAN_WIDTH_20:
     514             :         case CHAN_WIDTH_40:
     515             :         default:
     516          22 :                 chwidth = VHT_CHANWIDTH_USE_HT;
     517          22 :                 break;
     518             :         }
     519             : 
     520          23 :         switch (hapd->iface->current_mode->mode) {
     521             :         case HOSTAPD_MODE_IEEE80211A:
     522          10 :                 if (cf1 > 5000)
     523          10 :                         seg0_idx = (cf1 - 5000) / 5;
     524          10 :                 if (cf2 > 5000)
     525           0 :                         seg1_idx = (cf2 - 5000) / 5;
     526          10 :                 break;
     527             :         default:
     528          13 :                 ieee80211_freq_to_chan(cf1, &seg0_idx);
     529          13 :                 ieee80211_freq_to_chan(cf2, &seg1_idx);
     530          13 :                 break;
     531             :         }
     532             : 
     533          23 :         hapd->iconf->channel = channel;
     534          23 :         hapd->iconf->ieee80211n = ht;
     535          23 :         if (!ht)
     536          13 :                 hapd->iconf->ieee80211ac = 0;
     537          23 :         hapd->iconf->secondary_channel = offset;
     538          23 :         hapd->iconf->vht_oper_chwidth = chwidth;
     539          23 :         hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
     540          23 :         hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
     541             : 
     542          23 :         is_dfs = ieee80211_is_dfs(freq);
     543             : 
     544          46 :         if (hapd->csa_in_progress &&
     545          23 :             freq == hapd->cs_freq_params.freq) {
     546          23 :                 hostapd_cleanup_cs_params(hapd);
     547          23 :                 ieee802_11_set_beacon(hapd);
     548             : 
     549          23 :                 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
     550             :                         "freq=%d dfs=%d", freq, is_dfs);
     551           0 :         } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
     552           0 :                 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
     553             :                         "freq=%d dfs=%d", freq, is_dfs);
     554             :         }
     555             : #endif /* NEED_AP_MLME */
     556             : }
     557             : 
     558             : 
     559           0 : void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
     560             :                                          const u8 *addr, int reason_code)
     561             : {
     562           0 :         switch (reason_code) {
     563             :         case MAX_CLIENT_REACHED:
     564           0 :                 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR,
     565           0 :                         MAC2STR(addr));
     566           0 :                 break;
     567             :         case BLOCKED_CLIENT:
     568           0 :                 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR,
     569           0 :                         MAC2STR(addr));
     570           0 :                 break;
     571             :         }
     572           0 : }
     573             : 
     574             : 
     575             : #ifdef CONFIG_ACS
     576           0 : void hostapd_acs_channel_selected(struct hostapd_data *hapd,
     577             :                                   struct acs_selected_channels *acs_res)
     578             : {
     579             :         int ret, i;
     580           0 :         int err = 0;
     581             : 
     582           0 :         if (hapd->iconf->channel) {
     583           0 :                 wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
     584           0 :                            hapd->iconf->channel);
     585           0 :                 return;
     586             :         }
     587             : 
     588           0 :         if (!hapd->iface->current_mode) {
     589           0 :                 for (i = 0; i < hapd->iface->num_hw_features; i++) {
     590           0 :                         struct hostapd_hw_modes *mode =
     591           0 :                                 &hapd->iface->hw_features[i];
     592             : 
     593           0 :                         if (mode->mode == acs_res->hw_mode) {
     594           0 :                                 hapd->iface->current_mode = mode;
     595           0 :                                 break;
     596             :                         }
     597             :                 }
     598           0 :                 if (!hapd->iface->current_mode) {
     599           0 :                         hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
     600             :                                        HOSTAPD_LEVEL_WARNING,
     601             :                                        "driver selected to bad hw_mode");
     602           0 :                         err = 1;
     603           0 :                         goto out;
     604             :                 }
     605             :         }
     606             : 
     607           0 :         hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
     608             : 
     609           0 :         if (!acs_res->pri_channel) {
     610           0 :                 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
     611             :                                HOSTAPD_LEVEL_WARNING,
     612             :                                "driver switched to bad channel");
     613           0 :                 err = 1;
     614           0 :                 goto out;
     615             :         }
     616             : 
     617           0 :         hapd->iconf->channel = acs_res->pri_channel;
     618           0 :         hapd->iconf->acs = 1;
     619             : 
     620           0 :         if (acs_res->sec_channel == 0)
     621           0 :                 hapd->iconf->secondary_channel = 0;
     622           0 :         else if (acs_res->sec_channel < acs_res->pri_channel)
     623           0 :                 hapd->iconf->secondary_channel = -1;
     624           0 :         else if (acs_res->sec_channel > acs_res->pri_channel)
     625           0 :                 hapd->iconf->secondary_channel = 1;
     626             :         else {
     627           0 :                 wpa_printf(MSG_ERROR, "Invalid secondary channel!");
     628           0 :                 err = 1;
     629           0 :                 goto out;
     630             :         }
     631             : 
     632           0 :         if (hapd->iface->conf->ieee80211ac) {
     633             :                 /* set defaults for backwards compatibility */
     634           0 :                 hapd->iconf->vht_oper_centr_freq_seg1_idx = 0;
     635           0 :                 hapd->iconf->vht_oper_centr_freq_seg0_idx = 0;
     636           0 :                 hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
     637           0 :                 if (acs_res->ch_width == 80) {
     638           0 :                         hapd->iconf->vht_oper_centr_freq_seg0_idx =
     639           0 :                                 acs_res->vht_seg0_center_ch;
     640           0 :                         hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
     641           0 :                 } else if (acs_res->ch_width == 160) {
     642           0 :                         if (acs_res->vht_seg1_center_ch == 0) {
     643           0 :                                 hapd->iconf->vht_oper_centr_freq_seg0_idx =
     644           0 :                                         acs_res->vht_seg0_center_ch;
     645           0 :                                 hapd->iconf->vht_oper_chwidth =
     646             :                                         VHT_CHANWIDTH_160MHZ;
     647             :                         } else {
     648           0 :                                 hapd->iconf->vht_oper_centr_freq_seg0_idx =
     649           0 :                                         acs_res->vht_seg0_center_ch;
     650           0 :                                 hapd->iconf->vht_oper_centr_freq_seg1_idx =
     651           0 :                                         acs_res->vht_seg1_center_ch;
     652           0 :                                 hapd->iconf->vht_oper_chwidth =
     653             :                                         VHT_CHANWIDTH_80P80MHZ;
     654             :                         }
     655             :                 }
     656             :         }
     657             : 
     658             : out:
     659           0 :         ret = hostapd_acs_completed(hapd->iface, err);
     660           0 :         if (ret) {
     661           0 :                 wpa_printf(MSG_ERROR,
     662             :                            "ACS: Possibly channel configuration is invalid");
     663             :         }
     664             : }
     665             : #endif /* CONFIG_ACS */
     666             : 
     667             : 
     668           0 : int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
     669             :                          const u8 *bssid, const u8 *ie, size_t ie_len,
     670             :                          int ssi_signal)
     671             : {
     672             :         size_t i;
     673           0 :         int ret = 0;
     674             : 
     675           0 :         if (sa == NULL || ie == NULL)
     676           0 :                 return -1;
     677             : 
     678             :         random_add_randomness(sa, ETH_ALEN);
     679           0 :         for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
     680           0 :                 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
     681             :                                             sa, da, bssid, ie, ie_len,
     682             :                                             ssi_signal) > 0) {
     683           0 :                         ret = 1;
     684           0 :                         break;
     685             :                 }
     686             :         }
     687           0 :         return ret;
     688             : }
     689             : 
     690             : 
     691             : #ifdef HOSTAPD
     692             : 
     693             : #ifdef CONFIG_IEEE80211R
     694           0 : static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
     695             :                                           const u8 *bssid,
     696             :                                           u16 auth_transaction, u16 status,
     697             :                                           const u8 *ies, size_t ies_len)
     698             : {
     699           0 :         struct hostapd_data *hapd = ctx;
     700             :         struct sta_info *sta;
     701             : 
     702           0 :         sta = ap_get_sta(hapd, dst);
     703           0 :         if (sta == NULL)
     704           0 :                 return;
     705             : 
     706           0 :         hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
     707             :                        HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
     708           0 :         sta->flags |= WLAN_STA_AUTH;
     709             : 
     710           0 :         hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len);
     711             : }
     712             : #endif /* CONFIG_IEEE80211R */
     713             : 
     714             : 
     715           0 : static void hostapd_notif_auth(struct hostapd_data *hapd,
     716             :                                struct auth_info *rx_auth)
     717             : {
     718             :         struct sta_info *sta;
     719           0 :         u16 status = WLAN_STATUS_SUCCESS;
     720             :         u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
     721           0 :         size_t resp_ies_len = 0;
     722             : 
     723           0 :         sta = ap_get_sta(hapd, rx_auth->peer);
     724           0 :         if (!sta) {
     725           0 :                 sta = ap_sta_add(hapd, rx_auth->peer);
     726           0 :                 if (sta == NULL) {
     727           0 :                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
     728           0 :                         goto fail;
     729             :                 }
     730             :         }
     731           0 :         sta->flags &= ~WLAN_STA_PREAUTH;
     732           0 :         ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
     733             : #ifdef CONFIG_IEEE80211R
     734           0 :         if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) {
     735           0 :                 sta->auth_alg = WLAN_AUTH_FT;
     736           0 :                 if (sta->wpa_sm == NULL)
     737           0 :                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
     738           0 :                                                         sta->addr, NULL);
     739           0 :                 if (sta->wpa_sm == NULL) {
     740           0 :                         wpa_printf(MSG_DEBUG,
     741             :                                    "FT: Failed to initialize WPA state machine");
     742           0 :                         status = WLAN_STATUS_UNSPECIFIED_FAILURE;
     743           0 :                         goto fail;
     744             :                 }
     745           0 :                 wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
     746           0 :                                     rx_auth->auth_transaction, rx_auth->ies,
     747             :                                     rx_auth->ies_len,
     748             :                                     hostapd_notify_auth_ft_finish, hapd);
     749           0 :                 return;
     750             :         }
     751             : #endif /* CONFIG_IEEE80211R */
     752             : fail:
     753           0 :         hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
     754             :                          status, resp_ies, resp_ies_len);
     755             : }
     756             : 
     757             : 
     758           0 : static void hostapd_action_rx(struct hostapd_data *hapd,
     759             :                               struct rx_mgmt *drv_mgmt)
     760             : {
     761             :         struct ieee80211_mgmt *mgmt;
     762             :         struct sta_info *sta;
     763             :         size_t plen __maybe_unused;
     764             :         u16 fc;
     765             : 
     766           0 :         if (drv_mgmt->frame_len < 24 + 1)
     767           0 :                 return;
     768             : 
     769           0 :         plen = drv_mgmt->frame_len - 24 - 1;
     770             : 
     771           0 :         mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
     772           0 :         fc = le_to_host16(mgmt->frame_control);
     773           0 :         if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
     774           0 :                 return; /* handled by the driver */
     775             : 
     776           0 :         wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
     777           0 :                    mgmt->u.action.category, (int) plen);
     778             : 
     779           0 :         sta = ap_get_sta(hapd, mgmt->sa);
     780           0 :         if (sta == NULL) {
     781           0 :                 wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
     782           0 :                 return;
     783             :         }
     784             : #ifdef CONFIG_IEEE80211R
     785           0 :         if (mgmt->u.action.category == WLAN_ACTION_FT) {
     786           0 :                 const u8 *payload = drv_mgmt->frame + 24 + 1;
     787             : 
     788           0 :                 wpa_ft_action_rx(sta->wpa_sm, payload, plen);
     789             :         }
     790             : #endif /* CONFIG_IEEE80211R */
     791             : #ifdef CONFIG_IEEE80211W
     792           0 :         if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) {
     793           0 :                 ieee802_11_sa_query_action(
     794           0 :                         hapd, mgmt->sa,
     795           0 :                         mgmt->u.action.u.sa_query_resp.action,
     796           0 :                         mgmt->u.action.u.sa_query_resp.trans_id);
     797             :         }
     798             : #endif /* CONFIG_IEEE80211W */
     799             : #ifdef CONFIG_WNM
     800           0 :         if (mgmt->u.action.category == WLAN_ACTION_WNM) {
     801           0 :                 ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
     802             :         }
     803             : #endif /* CONFIG_WNM */
     804             : #ifdef CONFIG_FST
     805           0 :         if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) {
     806           0 :                 fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len);
     807           0 :                 return;
     808             :         }
     809             : #endif /* CONFIG_FST */
     810             : 
     811             : }
     812             : 
     813             : 
     814             : #ifdef NEED_AP_MLME
     815             : 
     816             : #define HAPD_BROADCAST ((struct hostapd_data *) -1)
     817             : 
     818       39739 : static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
     819             :                                             const u8 *bssid)
     820             : {
     821             :         size_t i;
     822             : 
     823       39739 :         if (bssid == NULL)
     824           0 :                 return NULL;
     825       43920 :         if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
     826        8362 :             bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
     827        4181 :                 return HAPD_BROADCAST;
     828             : 
     829       46795 :         for (i = 0; i < iface->num_bss; i++) {
     830       35872 :                 if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
     831       24635 :                         return iface->bss[i];
     832             :         }
     833             : 
     834       10923 :         return NULL;
     835             : }
     836             : 
     837             : 
     838          10 : static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
     839             :                                         const u8 *bssid, const u8 *addr,
     840             :                                         int wds)
     841             : {
     842          10 :         hapd = get_hapd_bssid(hapd->iface, bssid);
     843          10 :         if (hapd == NULL || hapd == HAPD_BROADCAST)
     844          10 :                 return;
     845             : 
     846          10 :         ieee802_11_rx_from_unknown(hapd, addr, wds);
     847             : }
     848             : 
     849             : 
     850       29234 : static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
     851             : {
     852       29234 :         struct hostapd_iface *iface = hapd->iface;
     853             :         const struct ieee80211_hdr *hdr;
     854             :         const u8 *bssid;
     855             :         struct hostapd_frame_info fi;
     856             :         int ret;
     857             : 
     858             : #ifdef CONFIG_TESTING_OPTIONS
     859       29234 :         if (hapd->ext_mgmt_frame_handling) {
     860         367 :                 size_t hex_len = 2 * rx_mgmt->frame_len + 1;
     861         367 :                 char *hex = os_malloc(hex_len);
     862             : 
     863         367 :                 if (hex) {
     864         367 :                         wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame,
     865             :                                          rx_mgmt->frame_len);
     866         367 :                         wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex);
     867         367 :                         os_free(hex);
     868             :                 }
     869         367 :                 return 1;
     870             :         }
     871             : #endif /* CONFIG_TESTING_OPTIONS */
     872             : 
     873       28867 :         hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
     874       28867 :         bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
     875       28867 :         if (bssid == NULL)
     876           0 :                 return 0;
     877             : 
     878       28867 :         hapd = get_hapd_bssid(iface, bssid);
     879       28867 :         if (hapd == NULL) {
     880       10827 :                 u16 fc = le_to_host16(hdr->frame_control);
     881             : 
     882             :                 /*
     883             :                  * Drop frames to unknown BSSIDs except for Beacon frames which
     884             :                  * could be used to update neighbor information.
     885             :                  */
     886       21654 :                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
     887       10827 :                     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
     888       10827 :                         hapd = iface->bss[0];
     889             :                 else
     890           0 :                         return 0;
     891             :         }
     892             : 
     893       28867 :         os_memset(&fi, 0, sizeof(fi));
     894       28867 :         fi.datarate = rx_mgmt->datarate;
     895       28867 :         fi.ssi_signal = rx_mgmt->ssi_signal;
     896             : 
     897       28867 :         if (hapd == HAPD_BROADCAST) {
     898             :                 size_t i;
     899             : 
     900        4178 :                 ret = 0;
     901        8857 :                 for (i = 0; i < iface->num_bss; i++) {
     902             :                         /* if bss is set, driver will call this function for
     903             :                          * each bss individually. */
     904        9353 :                         if (rx_mgmt->drv_priv &&
     905        4674 :                             (iface->bss[i]->drv_priv != rx_mgmt->drv_priv))
     906         498 :                                 continue;
     907             : 
     908        4181 :                         if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
     909             :                                             rx_mgmt->frame_len, &fi) > 0)
     910        4181 :                                 ret = 1;
     911             :                 }
     912             :         } else
     913       24689 :                 ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len,
     914             :                                       &fi);
     915             : 
     916             :         random_add_randomness(&fi, sizeof(fi));
     917             : 
     918       28867 :         return ret;
     919             : }
     920             : 
     921             : 
     922       10860 : static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
     923             :                                size_t len, u16 stype, int ok)
     924             : {
     925             :         struct ieee80211_hdr *hdr;
     926       10860 :         struct hostapd_data *orig_hapd = hapd;
     927             : 
     928       10860 :         hdr = (struct ieee80211_hdr *) buf;
     929       10860 :         hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
     930       10860 :         if (!hapd)
     931          96 :                 return;
     932       10764 :         if (hapd == HAPD_BROADCAST) {
     933           5 :                 if (stype != WLAN_FC_STYPE_ACTION || len <= 25 ||
     934           2 :                     buf[24] != WLAN_ACTION_PUBLIC)
     935           1 :                         return;
     936           2 :                 hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2);
     937           2 :                 if (!hapd || hapd == HAPD_BROADCAST)
     938           0 :                         return;
     939             :                 /*
     940             :                  * Allow processing of TX status for a Public Action frame that
     941             :                  * used wildcard BBSID.
     942             :                  */
     943             :         }
     944       10763 :         ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
     945             : }
     946             : 
     947             : #endif /* NEED_AP_MLME */
     948             : 
     949             : 
     950           0 : static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
     951             : {
     952           0 :         struct sta_info *sta = ap_get_sta(hapd, addr);
     953             : 
     954           0 :         if (sta)
     955           0 :                 return 0;
     956             : 
     957           0 :         wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
     958           0 :                    " - adding a new STA", MAC2STR(addr));
     959           0 :         sta = ap_sta_add(hapd, addr);
     960           0 :         if (sta) {
     961           0 :                 hostapd_new_assoc_sta(hapd, sta, 0);
     962             :         } else {
     963           0 :                 wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
     964           0 :                            MAC2STR(addr));
     965           0 :                 return -1;
     966             :         }
     967             : 
     968           0 :         return 0;
     969             : }
     970             : 
     971             : 
     972       14103 : static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
     973             :                                    const u8 *data, size_t data_len)
     974             : {
     975       14103 :         struct hostapd_iface *iface = hapd->iface;
     976             :         struct sta_info *sta;
     977             :         size_t j;
     978             : 
     979       14170 :         for (j = 0; j < iface->num_bss; j++) {
     980       14133 :                 sta = ap_get_sta(iface->bss[j], src);
     981       14133 :                 if (sta && sta->flags & WLAN_STA_ASSOC) {
     982       14066 :                         hapd = iface->bss[j];
     983       14066 :                         break;
     984             :                 }
     985             :         }
     986             : 
     987       14103 :         ieee802_1x_receive(hapd, src, data, data_len);
     988       14103 : }
     989             : 
     990             : #endif /* HOSTAPD */
     991             : 
     992             : 
     993          56 : static struct hostapd_channel_data * hostapd_get_mode_channel(
     994             :         struct hostapd_iface *iface, unsigned int freq)
     995             : {
     996             :         int i;
     997             :         struct hostapd_channel_data *chan;
     998             : 
     999          56 :         for (i = 0; i < iface->current_mode->num_channels; i++) {
    1000          56 :                 chan = &iface->current_mode->channels[i];
    1001          56 :                 if ((unsigned int) chan->freq == freq)
    1002          56 :                         return chan;
    1003             :         }
    1004             : 
    1005           0 :         return NULL;
    1006             : }
    1007             : 
    1008             : 
    1009          50 : static void hostapd_update_nf(struct hostapd_iface *iface,
    1010             :                               struct hostapd_channel_data *chan,
    1011             :                               struct freq_survey *survey)
    1012             : {
    1013          50 :         if (!iface->chans_surveyed) {
    1014          10 :                 chan->min_nf = survey->nf;
    1015          10 :                 iface->lowest_nf = survey->nf;
    1016             :         } else {
    1017          40 :                 if (dl_list_empty(&chan->survey_list))
    1018           0 :                         chan->min_nf = survey->nf;
    1019          40 :                 else if (survey->nf < chan->min_nf)
    1020           0 :                         chan->min_nf = survey->nf;
    1021          40 :                 if (survey->nf < iface->lowest_nf)
    1022           0 :                         iface->lowest_nf = survey->nf;
    1023             :         }
    1024          50 : }
    1025             : 
    1026             : 
    1027           6 : static void hostapd_single_channel_get_survey(struct hostapd_iface *iface,
    1028             :                                               struct survey_results *survey_res)
    1029             : {
    1030             :         struct hostapd_channel_data *chan;
    1031             :         struct freq_survey *survey;
    1032             :         u64 divisor, dividend;
    1033             : 
    1034           6 :         survey = dl_list_first(&survey_res->survey_list, struct freq_survey,
    1035             :                                list);
    1036           6 :         if (!survey || !survey->freq)
    1037           0 :                 return;
    1038             : 
    1039           6 :         chan = hostapd_get_mode_channel(iface, survey->freq);
    1040           6 :         if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED)
    1041           0 :                 return;
    1042             : 
    1043           6 :         wpa_printf(MSG_DEBUG,
    1044             :                    "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)",
    1045             :                    survey->freq,
    1046             :                    (unsigned long int) survey->channel_time,
    1047             :                    (unsigned long int) survey->channel_time_busy);
    1048             : 
    1049           6 :         if (survey->channel_time > iface->last_channel_time &&
    1050           0 :             survey->channel_time > survey->channel_time_busy) {
    1051           0 :                 dividend = survey->channel_time_busy -
    1052           0 :                         iface->last_channel_time_busy;
    1053           0 :                 divisor = survey->channel_time - iface->last_channel_time;
    1054             : 
    1055           0 :                 iface->channel_utilization = dividend * 255 / divisor;
    1056           0 :                 wpa_printf(MSG_DEBUG, "Channel Utilization: %d",
    1057           0 :                            iface->channel_utilization);
    1058             :         }
    1059           6 :         iface->last_channel_time = survey->channel_time;
    1060           6 :         iface->last_channel_time_busy = survey->channel_time_busy;
    1061             : }
    1062             : 
    1063             : 
    1064          56 : void hostapd_event_get_survey(struct hostapd_iface *iface,
    1065             :                               struct survey_results *survey_results)
    1066             : {
    1067             :         struct freq_survey *survey, *tmp;
    1068             :         struct hostapd_channel_data *chan;
    1069             : 
    1070          56 :         if (dl_list_empty(&survey_results->survey_list)) {
    1071           0 :                 wpa_printf(MSG_DEBUG, "No survey data received");
    1072           0 :                 return;
    1073             :         }
    1074             : 
    1075          56 :         if (survey_results->freq_filter) {
    1076           6 :                 hostapd_single_channel_get_survey(iface, survey_results);
    1077           6 :                 return;
    1078             :         }
    1079             : 
    1080         100 :         dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
    1081             :                               struct freq_survey, list) {
    1082          50 :                 chan = hostapd_get_mode_channel(iface, survey->freq);
    1083          50 :                 if (!chan)
    1084           0 :                         continue;
    1085          50 :                 if (chan->flag & HOSTAPD_CHAN_DISABLED)
    1086           0 :                         continue;
    1087             : 
    1088          50 :                 dl_list_del(&survey->list);
    1089          50 :                 dl_list_add_tail(&chan->survey_list, &survey->list);
    1090             : 
    1091          50 :                 hostapd_update_nf(iface, chan, survey);
    1092             : 
    1093          50 :                 iface->chans_surveyed++;
    1094             :         }
    1095             : }
    1096             : 
    1097             : 
    1098             : #ifdef HOSTAPD
    1099             : #ifdef NEED_AP_MLME
    1100             : 
    1101           5 : static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
    1102             : {
    1103           5 :         wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped",
    1104           5 :                    hapd->conf->iface);
    1105             : 
    1106           5 :         if (hapd->csa_in_progress) {
    1107           0 :                 wpa_printf(MSG_INFO, "CSA failed (%s was stopped)",
    1108           0 :                            hapd->conf->iface);
    1109           0 :                 hostapd_switch_channel_fallback(hapd->iface,
    1110           0 :                                                 &hapd->cs_freq_params);
    1111             :         }
    1112           5 : }
    1113             : 
    1114             : 
    1115          11 : static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
    1116             :                                              struct dfs_event *radar)
    1117             : {
    1118          11 :         wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
    1119          22 :         hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled,
    1120          11 :                                    radar->chan_offset, radar->chan_width,
    1121             :                                    radar->cf1, radar->cf2);
    1122          11 : }
    1123             : 
    1124             : 
    1125           6 : static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd,
    1126             :                                            struct dfs_event *radar)
    1127             : {
    1128           6 :         wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
    1129          12 :         hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled,
    1130           6 :                                  radar->chan_offset, radar->chan_width,
    1131             :                                  radar->cf1, radar->cf2);
    1132           6 : }
    1133             : 
    1134             : 
    1135           6 : static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd,
    1136             :                                           struct dfs_event *radar)
    1137             : {
    1138           6 :         wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
    1139          12 :         hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled,
    1140           6 :                                  radar->chan_offset, radar->chan_width,
    1141             :                                  radar->cf1, radar->cf2);
    1142           6 : }
    1143             : 
    1144             : 
    1145           0 : static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
    1146             :                                            struct dfs_event *radar)
    1147             : {
    1148           0 :         wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
    1149           0 :         hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled,
    1150           0 :                                  radar->chan_offset, radar->chan_width,
    1151             :                                  radar->cf1, radar->cf2);
    1152           0 : }
    1153             : 
    1154             : 
    1155           0 : static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
    1156             :                                           struct dfs_event *radar)
    1157             : {
    1158           0 :         wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
    1159           0 :         hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
    1160           0 :                               radar->chan_offset, radar->chan_width,
    1161             :                               radar->cf1, radar->cf2);
    1162           0 : }
    1163             : 
    1164             : #endif /* NEED_AP_MLME */
    1165             : 
    1166             : 
    1167       75132 : void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
    1168             :                           union wpa_event_data *data)
    1169             : {
    1170       75132 :         struct hostapd_data *hapd = ctx;
    1171             : #ifndef CONFIG_NO_STDOUT_DEBUG
    1172       75132 :         int level = MSG_DEBUG;
    1173             : 
    1174      104366 :         if (event == EVENT_RX_MGMT && data->rx_mgmt.frame &&
    1175       29234 :             data->rx_mgmt.frame_len >= 24) {
    1176             :                 const struct ieee80211_hdr *hdr;
    1177             :                 u16 fc;
    1178             : 
    1179       29234 :                 hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
    1180       29234 :                 fc = le_to_host16(hdr->frame_control);
    1181       58468 :                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
    1182       29234 :                     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
    1183       10849 :                         level = MSG_EXCESSIVE;
    1184       58468 :                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
    1185       29234 :                     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ)
    1186        4434 :                         level = MSG_EXCESSIVE;
    1187             :         }
    1188             : 
    1189       75132 :         wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
    1190             :                 event_to_string(event), event);
    1191             : #endif /* CONFIG_NO_STDOUT_DEBUG */
    1192             : 
    1193       75132 :         switch (event) {
    1194             :         case EVENT_MICHAEL_MIC_FAILURE:
    1195           2 :                 michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
    1196           2 :                 break;
    1197             :         case EVENT_SCAN_RESULTS:
    1198         111 :                 if (hapd->iface->scan_cb)
    1199         111 :                         hapd->iface->scan_cb(hapd->iface);
    1200         111 :                 break;
    1201             :         case EVENT_WPS_BUTTON_PUSHED:
    1202           0 :                 hostapd_wps_button_pushed(hapd, NULL);
    1203           0 :                 break;
    1204             : #ifdef NEED_AP_MLME
    1205             :         case EVENT_TX_STATUS:
    1206       10862 :                 switch (data->tx_status.type) {
    1207             :                 case WLAN_FC_TYPE_MGMT:
    1208       21720 :                         hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
    1209             :                                            data->tx_status.data_len,
    1210       10860 :                                            data->tx_status.stype,
    1211             :                                            data->tx_status.ack);
    1212       10860 :                         break;
    1213             :                 case WLAN_FC_TYPE_DATA:
    1214           2 :                         hostapd_tx_status(hapd, data->tx_status.dst,
    1215             :                                           data->tx_status.data,
    1216             :                                           data->tx_status.data_len,
    1217             :                                           data->tx_status.ack);
    1218           2 :                         break;
    1219             :                 }
    1220       10862 :                 break;
    1221             :         case EVENT_EAPOL_TX_STATUS:
    1222       32804 :                 hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
    1223             :                                         data->eapol_tx_status.data,
    1224       16402 :                                         data->eapol_tx_status.data_len,
    1225             :                                         data->eapol_tx_status.ack);
    1226       16402 :                 break;
    1227             :         case EVENT_DRIVER_CLIENT_POLL_OK:
    1228           2 :                 hostapd_client_poll_ok(hapd, data->client_poll.addr);
    1229           2 :                 break;
    1230             :         case EVENT_RX_FROM_UNKNOWN:
    1231          10 :                 hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
    1232             :                                             data->rx_from_unknown.addr,
    1233             :                                             data->rx_from_unknown.wds);
    1234          10 :                 break;
    1235             : #endif /* NEED_AP_MLME */
    1236             :         case EVENT_RX_MGMT:
    1237       29234 :                 if (!data->rx_mgmt.frame)
    1238           0 :                         break;
    1239             : #ifdef NEED_AP_MLME
    1240       29234 :                 if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0)
    1241       29234 :                         break;
    1242             : #endif /* NEED_AP_MLME */
    1243           0 :                 hostapd_action_rx(hapd, &data->rx_mgmt);
    1244           0 :                 break;
    1245             :         case EVENT_RX_PROBE_REQ:
    1246           0 :                 if (data->rx_probe_req.sa == NULL ||
    1247           0 :                     data->rx_probe_req.ie == NULL)
    1248             :                         break;
    1249           0 :                 hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
    1250             :                                      data->rx_probe_req.da,
    1251             :                                      data->rx_probe_req.bssid,
    1252             :                                      data->rx_probe_req.ie,
    1253             :                                      data->rx_probe_req.ie_len,
    1254             :                                      data->rx_probe_req.ssi_signal);
    1255           0 :                 break;
    1256             :         case EVENT_NEW_STA:
    1257           0 :                 hostapd_event_new_sta(hapd, data->new_sta.addr);
    1258           0 :                 break;
    1259             :         case EVENT_EAPOL_RX:
    1260       14103 :                 hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
    1261             :                                        data->eapol_rx.data,
    1262             :                                        data->eapol_rx.data_len);
    1263       14103 :                 break;
    1264             :         case EVENT_ASSOC:
    1265           0 :                 if (!data)
    1266       75132 :                         return;
    1267           0 :                 hostapd_notif_assoc(hapd, data->assoc_info.addr,
    1268             :                                     data->assoc_info.req_ies,
    1269             :                                     data->assoc_info.req_ies_len,
    1270             :                                     data->assoc_info.reassoc);
    1271           0 :                 break;
    1272             :         case EVENT_DISASSOC:
    1273           0 :                 if (data)
    1274           0 :                         hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
    1275           0 :                 break;
    1276             :         case EVENT_DEAUTH:
    1277           0 :                 if (data)
    1278           0 :                         hostapd_notif_disassoc(hapd, data->deauth_info.addr);
    1279           0 :                 break;
    1280             :         case EVENT_STATION_LOW_ACK:
    1281           0 :                 if (!data)
    1282           0 :                         break;
    1283           0 :                 hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
    1284           0 :                 break;
    1285             :         case EVENT_AUTH:
    1286           0 :                 hostapd_notif_auth(hapd, &data->auth);
    1287           0 :                 break;
    1288             :         case EVENT_CH_SWITCH:
    1289          21 :                 if (!data)
    1290           0 :                         break;
    1291          42 :                 hostapd_event_ch_switch(hapd, data->ch_switch.freq,
    1292             :                                         data->ch_switch.ht_enabled,
    1293             :                                         data->ch_switch.ch_offset,
    1294          21 :                                         data->ch_switch.ch_width,
    1295             :                                         data->ch_switch.cf1,
    1296             :                                         data->ch_switch.cf2);
    1297          21 :                 break;
    1298             :         case EVENT_CONNECT_FAILED_REASON:
    1299           0 :                 if (!data)
    1300           0 :                         break;
    1301           0 :                 hostapd_event_connect_failed_reason(
    1302           0 :                         hapd, data->connect_failed_reason.addr,
    1303           0 :                         data->connect_failed_reason.code);
    1304           0 :                 break;
    1305             :         case EVENT_SURVEY:
    1306          51 :                 hostapd_event_get_survey(hapd->iface, &data->survey_results);
    1307          51 :                 break;
    1308             : #ifdef NEED_AP_MLME
    1309             :         case EVENT_INTERFACE_UNAVAILABLE:
    1310           5 :                 hostapd_event_iface_unavailable(hapd);
    1311           5 :                 break;
    1312             :         case EVENT_DFS_RADAR_DETECTED:
    1313          11 :                 if (!data)
    1314           0 :                         break;
    1315          11 :                 hostapd_event_dfs_radar_detected(hapd, &data->dfs_event);
    1316          11 :                 break;
    1317             :         case EVENT_DFS_CAC_FINISHED:
    1318           6 :                 if (!data)
    1319           0 :                         break;
    1320           6 :                 hostapd_event_dfs_cac_finished(hapd, &data->dfs_event);
    1321           6 :                 break;
    1322             :         case EVENT_DFS_CAC_ABORTED:
    1323           6 :                 if (!data)
    1324           0 :                         break;
    1325           6 :                 hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event);
    1326           6 :                 break;
    1327             :         case EVENT_DFS_NOP_FINISHED:
    1328           0 :                 if (!data)
    1329           0 :                         break;
    1330           0 :                 hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
    1331           0 :                 break;
    1332             :         case EVENT_CHANNEL_LIST_CHANGED:
    1333             :                 /* channel list changed (regulatory?), update channel list */
    1334             :                 /* TODO: check this. hostapd_get_hw_features() initializes
    1335             :                  * too much stuff. */
    1336             :                 /* hostapd_get_hw_features(hapd->iface); */
    1337        3200 :                 hostapd_channel_list_updated(
    1338        3200 :                         hapd->iface, data->channel_list_changed.initiator);
    1339        3200 :                 break;
    1340             :         case EVENT_DFS_CAC_STARTED:
    1341           0 :                 if (!data)
    1342           0 :                         break;
    1343           0 :                 hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
    1344           0 :                 break;
    1345             : #endif /* NEED_AP_MLME */
    1346             :         case EVENT_INTERFACE_ENABLED:
    1347           3 :                 wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
    1348           3 :                 if (hapd->disabled && hapd->started) {
    1349           3 :                         hapd->disabled = 0;
    1350             :                         /*
    1351             :                          * Try to re-enable interface if the driver stopped it
    1352             :                          * when the interface got disabled.
    1353             :                          */
    1354           3 :                         wpa_auth_reconfig_group_keys(hapd->wpa_auth);
    1355           3 :                         hapd->reenable_beacon = 1;
    1356           3 :                         ieee802_11_set_beacon(hapd);
    1357             :                 }
    1358           3 :                 break;
    1359             :         case EVENT_INTERFACE_DISABLED:
    1360           4 :                 hostapd_free_stas(hapd);
    1361           4 :                 wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
    1362           4 :                 hapd->disabled = 1;
    1363           4 :                 break;
    1364             : #ifdef CONFIG_ACS
    1365             :         case EVENT_ACS_CHANNEL_SELECTED:
    1366           0 :                 hostapd_acs_channel_selected(hapd,
    1367             :                                              &data->acs_selected_channels);
    1368           0 :                 break;
    1369             : #endif /* CONFIG_ACS */
    1370             :         default:
    1371        1099 :                 wpa_printf(MSG_DEBUG, "Unknown event %d", event);
    1372        1099 :                 break;
    1373             :         }
    1374             : }
    1375             : 
    1376             : 
    1377       40454 : void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
    1378             :                                  union wpa_event_data *data)
    1379             : {
    1380       40454 :         struct hapd_interfaces *interfaces = ctx;
    1381             :         struct hostapd_data *hapd;
    1382             : 
    1383       40454 :         if (event != EVENT_INTERFACE_STATUS)
    1384           0 :                 return;
    1385             : 
    1386       40454 :         hapd = hostapd_get_iface(interfaces, data->interface_status.ifname);
    1387       40730 :         if (hapd && hapd->driver && hapd->driver->get_ifindex &&
    1388         276 :             hapd->drv_priv) {
    1389             :                 unsigned int ifindex;
    1390             : 
    1391           0 :                 ifindex = hapd->driver->get_ifindex(hapd->drv_priv);
    1392           0 :                 if (ifindex != data->interface_status.ifindex) {
    1393           0 :                         wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
    1394             :                                 "interface status ifindex %d mismatch (%d)",
    1395             :                                 ifindex, data->interface_status.ifindex);
    1396           0 :                         return;
    1397             :                 }
    1398             :         }
    1399       40454 :         if (hapd)
    1400         278 :                 wpa_supplicant_event(hapd, event, data);
    1401             : }
    1402             : 
    1403             : #endif /* HOSTAPD */

Generated by: LCOV version 1.10