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 1422976643 Lines: 219 608 36.0 %
Date: 2015-02-03 Functions: 15 26 57.7 %

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

Generated by: LCOV version 1.10