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 1443382998 Lines: 225 658 34.2 %
Date: 2015-09-27 Functions: 15 27 55.6 %

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

Generated by: LCOV version 1.10