LCOV - code coverage report
Current view: top level - src/ap - hostapd.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 1144 1382 82.8 %
Date: 2015-02-03 Functions: 57 61 93.4 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / Initialization and configuration
       3             :  * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #include "utils/common.h"
      12             : #include "utils/eloop.h"
      13             : #include "common/ieee802_11_defs.h"
      14             : #include "common/wpa_ctrl.h"
      15             : #include "radius/radius_client.h"
      16             : #include "radius/radius_das.h"
      17             : #include "eap_server/tncs.h"
      18             : #include "eapol_auth/eapol_auth_sm.h"
      19             : #include "eapol_auth/eapol_auth_sm_i.h"
      20             : #include "hostapd.h"
      21             : #include "authsrv.h"
      22             : #include "sta_info.h"
      23             : #include "accounting.h"
      24             : #include "ap_list.h"
      25             : #include "beacon.h"
      26             : #include "iapp.h"
      27             : #include "ieee802_1x.h"
      28             : #include "ieee802_11_auth.h"
      29             : #include "vlan_init.h"
      30             : #include "wpa_auth.h"
      31             : #include "wps_hostapd.h"
      32             : #include "hw_features.h"
      33             : #include "wpa_auth_glue.h"
      34             : #include "ap_drv_ops.h"
      35             : #include "ap_config.h"
      36             : #include "p2p_hostapd.h"
      37             : #include "gas_serv.h"
      38             : #include "dfs.h"
      39             : #include "ieee802_11.h"
      40             : #include "bss_load.h"
      41             : #include "x_snoop.h"
      42             : #include "dhcp_snoop.h"
      43             : #include "ndisc_snoop.h"
      44             : 
      45             : 
      46             : static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
      47             : static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
      48             : static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
      49             : static int setup_interface2(struct hostapd_iface *iface);
      50             : static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
      51             : 
      52             : 
      53        2648 : int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
      54             :                                int (*cb)(struct hostapd_iface *iface,
      55             :                                          void *ctx), void *ctx)
      56             : {
      57             :         size_t i;
      58             :         int ret;
      59             : 
      60        5588 :         for (i = 0; i < interfaces->count; i++) {
      61        3197 :                 ret = cb(interfaces->iface[i], ctx);
      62        3197 :                 if (ret)
      63         257 :                         return ret;
      64             :         }
      65             : 
      66        2391 :         return 0;
      67             : }
      68             : 
      69             : 
      70          18 : static void hostapd_reload_bss(struct hostapd_data *hapd)
      71             : {
      72             :         struct hostapd_ssid *ssid;
      73             : 
      74             : #ifndef CONFIG_NO_RADIUS
      75          18 :         radius_client_reconfig(hapd->radius, hapd->conf->radius);
      76             : #endif /* CONFIG_NO_RADIUS */
      77             : 
      78          18 :         ssid = &hapd->conf->ssid;
      79          18 :         if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
      80           1 :             ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
      81             :                 /*
      82             :                  * Force PSK to be derived again since SSID or passphrase may
      83             :                  * have changed.
      84             :                  */
      85           1 :                 os_free(ssid->wpa_psk);
      86           1 :                 ssid->wpa_psk = NULL;
      87             :         }
      88          18 :         if (hostapd_setup_wpa_psk(hapd->conf)) {
      89           0 :                 wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
      90             :                            "after reloading configuration");
      91             :         }
      92             : 
      93          18 :         if (hapd->conf->ieee802_1x || hapd->conf->wpa)
      94          17 :                 hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
      95             :         else
      96           1 :                 hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
      97             : 
      98          18 :         if ((hapd->conf->wpa || hapd->conf->osen) && hapd->wpa_auth == NULL) {
      99          15 :                 hostapd_setup_wpa(hapd);
     100          30 :                 if (hapd->wpa_auth)
     101          15 :                         wpa_init_keys(hapd->wpa_auth);
     102           3 :         } else if (hapd->conf->wpa) {
     103             :                 const u8 *wpa_ie;
     104             :                 size_t wpa_ie_len;
     105           2 :                 hostapd_reconfig_wpa(hapd);
     106           2 :                 wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
     107           2 :                 if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len))
     108           0 :                         wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
     109             :                                    "the kernel driver.");
     110           1 :         } else if (hapd->wpa_auth) {
     111           1 :                 wpa_deinit(hapd->wpa_auth);
     112           1 :                 hapd->wpa_auth = NULL;
     113           1 :                 hostapd_set_privacy(hapd, 0);
     114           1 :                 hostapd_setup_encryption(hapd->conf->iface, hapd);
     115           1 :                 hostapd_set_generic_elem(hapd, (u8 *) "", 0);
     116             :         }
     117             : 
     118          18 :         ieee802_11_set_beacon(hapd);
     119          18 :         hostapd_update_wps(hapd);
     120             : 
     121          36 :         if (hapd->conf->ssid.ssid_set &&
     122          18 :             hostapd_set_ssid(hapd, hapd->conf->ssid.ssid,
     123          18 :                              hapd->conf->ssid.ssid_len)) {
     124           0 :                 wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
     125             :                 /* try to continue */
     126             :         }
     127          18 :         wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
     128          18 : }
     129             : 
     130             : 
     131          18 : static void hostapd_clear_old(struct hostapd_iface *iface)
     132             : {
     133             :         size_t j;
     134             : 
     135             :         /*
     136             :          * Deauthenticate all stations since the new configuration may not
     137             :          * allow them to use the BSS anymore.
     138             :          */
     139          36 :         for (j = 0; j < iface->num_bss; j++) {
     140          18 :                 hostapd_flush_old_stations(iface->bss[j],
     141             :                                            WLAN_REASON_PREV_AUTH_NOT_VALID);
     142          18 :                 hostapd_broadcast_wep_clear(iface->bss[j]);
     143             : 
     144             : #ifndef CONFIG_NO_RADIUS
     145             :                 /* TODO: update dynamic data based on changed configuration
     146             :                  * items (e.g., open/close sockets, etc.) */
     147          18 :                 radius_client_flush(iface->bss[j]->radius, 0);
     148             : #endif /* CONFIG_NO_RADIUS */
     149             :         }
     150          18 : }
     151             : 
     152             : 
     153          17 : int hostapd_reload_config(struct hostapd_iface *iface)
     154             : {
     155          17 :         struct hostapd_data *hapd = iface->bss[0];
     156             :         struct hostapd_config *newconf, *oldconf;
     157             :         size_t j;
     158             : 
     159          17 :         if (iface->config_fname == NULL) {
     160             :                 /* Only in-memory config in use - assume it has been updated */
     161          16 :                 hostapd_clear_old(iface);
     162          32 :                 for (j = 0; j < iface->num_bss; j++)
     163          16 :                         hostapd_reload_bss(iface->bss[j]);
     164          16 :                 return 0;
     165             :         }
     166             : 
     167           2 :         if (iface->interfaces == NULL ||
     168           1 :             iface->interfaces->config_read_cb == NULL)
     169           0 :                 return -1;
     170           1 :         newconf = iface->interfaces->config_read_cb(iface->config_fname);
     171           1 :         if (newconf == NULL)
     172           0 :                 return -1;
     173             : 
     174           1 :         hostapd_clear_old(iface);
     175             : 
     176           1 :         oldconf = hapd->iconf;
     177           1 :         iface->conf = newconf;
     178             : 
     179           2 :         for (j = 0; j < iface->num_bss; j++) {
     180           1 :                 hapd = iface->bss[j];
     181           1 :                 hapd->iconf = newconf;
     182           1 :                 hapd->iconf->channel = oldconf->channel;
     183           1 :                 hapd->iconf->secondary_channel = oldconf->secondary_channel;
     184           1 :                 hapd->iconf->ieee80211n = oldconf->ieee80211n;
     185           1 :                 hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
     186           1 :                 hapd->iconf->ht_capab = oldconf->ht_capab;
     187           1 :                 hapd->iconf->vht_capab = oldconf->vht_capab;
     188           1 :                 hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth;
     189           2 :                 hapd->iconf->vht_oper_centr_freq_seg0_idx =
     190           1 :                         oldconf->vht_oper_centr_freq_seg0_idx;
     191           2 :                 hapd->iconf->vht_oper_centr_freq_seg1_idx =
     192           1 :                         oldconf->vht_oper_centr_freq_seg1_idx;
     193           1 :                 hapd->conf = newconf->bss[j];
     194           1 :                 hostapd_reload_bss(hapd);
     195             :         }
     196             : 
     197           1 :         hostapd_config_free(oldconf);
     198             : 
     199             : 
     200           1 :         return 0;
     201             : }
     202             : 
     203             : 
     204        1353 : static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
     205             :                                               char *ifname)
     206             : {
     207             :         int i;
     208             : 
     209        6765 :         for (i = 0; i < NUM_WEP_KEYS; i++) {
     210        5412 :                 if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
     211             :                                         0, NULL, 0, NULL, 0)) {
     212          12 :                         wpa_printf(MSG_DEBUG, "Failed to clear default "
     213             :                                    "encryption keys (ifname=%s keyidx=%d)",
     214             :                                    ifname, i);
     215             :                 }
     216             :         }
     217             : #ifdef CONFIG_IEEE80211W
     218        1353 :         if (hapd->conf->ieee80211w) {
     219         456 :                 for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
     220         304 :                         if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
     221             :                                                 NULL, i, 0, NULL,
     222             :                                                 0, NULL, 0)) {
     223           0 :                                 wpa_printf(MSG_DEBUG, "Failed to clear "
     224             :                                            "default mgmt encryption keys "
     225             :                                            "(ifname=%s keyidx=%d)", ifname, i);
     226             :                         }
     227             :                 }
     228             :         }
     229             : #endif /* CONFIG_IEEE80211W */
     230        1353 : }
     231             : 
     232             : 
     233        1353 : static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
     234             : {
     235        1353 :         hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
     236        1353 :         return 0;
     237             : }
     238             : 
     239             : 
     240        1253 : static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
     241             : {
     242        1253 :         int errors = 0, idx;
     243        1253 :         struct hostapd_ssid *ssid = &hapd->conf->ssid;
     244             : 
     245        1253 :         idx = ssid->wep.idx;
     246        1255 :         if (ssid->wep.default_len &&
     247           4 :             hostapd_drv_set_key(hapd->conf->iface,
     248             :                                 hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
     249           2 :                                 1, NULL, 0, ssid->wep.key[idx],
     250             :                                 ssid->wep.len[idx])) {
     251           2 :                 wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
     252           2 :                 errors++;
     253             :         }
     254             : 
     255        1253 :         return errors;
     256             : }
     257             : 
     258             : 
     259        1421 : static void hostapd_free_hapd_data(struct hostapd_data *hapd)
     260             : {
     261        1421 :         os_free(hapd->probereq_cb);
     262        1421 :         hapd->probereq_cb = NULL;
     263             : 
     264             : #ifdef CONFIG_P2P
     265         265 :         wpabuf_free(hapd->p2p_beacon_ie);
     266         265 :         hapd->p2p_beacon_ie = NULL;
     267         265 :         wpabuf_free(hapd->p2p_probe_resp_ie);
     268         265 :         hapd->p2p_probe_resp_ie = NULL;
     269             : #endif /* CONFIG_P2P */
     270             : 
     271        1421 :         if (!hapd->started) {
     272         169 :                 wpa_printf(MSG_ERROR, "%s: Interface %s wasn't started",
     273         169 :                            __func__, hapd->conf->iface);
     274        1590 :                 return;
     275             :         }
     276        1252 :         hapd->started = 0;
     277             : 
     278        1252 :         wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
     279        1252 :         iapp_deinit(hapd->iapp);
     280        1252 :         hapd->iapp = NULL;
     281        1252 :         accounting_deinit(hapd);
     282        1252 :         hostapd_deinit_wpa(hapd);
     283        1252 :         vlan_deinit(hapd);
     284        1252 :         hostapd_acl_deinit(hapd);
     285             : #ifndef CONFIG_NO_RADIUS
     286         987 :         radius_client_deinit(hapd->radius);
     287         987 :         hapd->radius = NULL;
     288         987 :         radius_das_deinit(hapd->radius_das);
     289         987 :         hapd->radius_das = NULL;
     290             : #endif /* CONFIG_NO_RADIUS */
     291             : 
     292        1252 :         hostapd_deinit_wps(hapd);
     293             : 
     294        1252 :         authsrv_deinit(hapd);
     295             : 
     296        1252 :         if (hapd->interface_added) {
     297          41 :                 hapd->interface_added = 0;
     298          41 :                 if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
     299           0 :                         wpa_printf(MSG_WARNING,
     300             :                                    "Failed to remove BSS interface %s",
     301           0 :                                    hapd->conf->iface);
     302           0 :                         hapd->interface_added = 1;
     303             :                 } else {
     304             :                         /*
     305             :                          * Since this was a dynamically added interface, the
     306             :                          * driver wrapper may have removed its internal instance
     307             :                          * and hapd->drv_priv is not valid anymore.
     308             :                          */
     309          41 :                         hapd->drv_priv = NULL;
     310             :                 }
     311             :         }
     312             : 
     313        1252 :         wpabuf_free(hapd->time_adv);
     314             : 
     315             : #ifdef CONFIG_INTERWORKING
     316        1252 :         gas_serv_deinit(hapd);
     317             : #endif /* CONFIG_INTERWORKING */
     318             : 
     319        1252 :         bss_load_update_deinit(hapd);
     320        1252 :         ndisc_snoop_deinit(hapd);
     321        1252 :         dhcp_snoop_deinit(hapd);
     322        1252 :         x_snoop_deinit(hapd);
     323             : 
     324             : #ifdef CONFIG_SQLITE
     325         987 :         bin_clear_free(hapd->tmp_eap_user.identity,
     326             :                        hapd->tmp_eap_user.identity_len);
     327         987 :         bin_clear_free(hapd->tmp_eap_user.password,
     328             :                        hapd->tmp_eap_user.password_len);
     329             : #endif /* CONFIG_SQLITE */
     330             : 
     331             : #ifdef CONFIG_MESH
     332         265 :         wpabuf_free(hapd->mesh_pending_auth);
     333         265 :         hapd->mesh_pending_auth = NULL;
     334             : #endif /* CONFIG_MESH */
     335             : }
     336             : 
     337             : 
     338             : /**
     339             :  * hostapd_cleanup - Per-BSS cleanup (deinitialization)
     340             :  * @hapd: Pointer to BSS data
     341             :  *
     342             :  * This function is used to free all per-BSS data structures and resources.
     343             :  * Most of the modules that are initialized in hostapd_setup_bss() are
     344             :  * deinitialized here.
     345             :  */
     346        1341 : static void hostapd_cleanup(struct hostapd_data *hapd)
     347             : {
     348        1341 :         wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s))", __func__, hapd,
     349        1341 :                    hapd->conf->iface);
     350        2417 :         if (hapd->iface->interfaces &&
     351        1076 :             hapd->iface->interfaces->ctrl_iface_deinit)
     352        1076 :                 hapd->iface->interfaces->ctrl_iface_deinit(hapd);
     353        1341 :         hostapd_free_hapd_data(hapd);
     354        1341 : }
     355             : 
     356             : 
     357        1395 : static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
     358             : {
     359        1395 :         wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
     360        1395 :         hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
     361        1395 :         iface->hw_features = NULL;
     362        1395 :         os_free(iface->current_rates);
     363        1395 :         iface->current_rates = NULL;
     364        1395 :         os_free(iface->basic_rates);
     365        1395 :         iface->basic_rates = NULL;
     366        1395 :         ap_list_deinit(iface);
     367        1395 : }
     368             : 
     369             : 
     370             : /**
     371             :  * hostapd_cleanup_iface - Complete per-interface cleanup
     372             :  * @iface: Pointer to interface data
     373             :  *
     374             :  * This function is called after per-BSS data structures are deinitialized
     375             :  * with hostapd_cleanup().
     376             :  */
     377        1326 : static void hostapd_cleanup_iface(struct hostapd_iface *iface)
     378             : {
     379        1326 :         wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
     380        1326 :         eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
     381             : 
     382        1326 :         hostapd_cleanup_iface_partial(iface);
     383        1326 :         hostapd_config_free(iface->conf);
     384        1326 :         iface->conf = NULL;
     385             : 
     386        1326 :         os_free(iface->config_fname);
     387        1326 :         os_free(iface->bss);
     388        1326 :         wpa_printf(MSG_DEBUG, "%s: free iface=%p", __func__, iface);
     389        1326 :         os_free(iface);
     390        1326 : }
     391             : 
     392             : 
     393        1416 : static void hostapd_clear_wep(struct hostapd_data *hapd)
     394             : {
     395        1416 :         if (hapd->drv_priv && !hapd->iface->driver_ap_teardown) {
     396          83 :                 hostapd_set_privacy(hapd, 0);
     397          83 :                 hostapd_broadcast_wep_clear(hapd);
     398             :         }
     399        1416 : }
     400             : 
     401             : 
     402        1253 : static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
     403             : {
     404             :         int i;
     405             : 
     406        1253 :         hostapd_broadcast_wep_set(hapd);
     407             : 
     408        1253 :         if (hapd->conf->ssid.wep.default_len) {
     409           2 :                 hostapd_set_privacy(hapd, 1);
     410           2 :                 return 0;
     411             :         }
     412             : 
     413             :         /*
     414             :          * When IEEE 802.1X is not enabled, the driver may need to know how to
     415             :          * set authentication algorithms for static WEP.
     416             :          */
     417        1251 :         hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs);
     418             : 
     419        6255 :         for (i = 0; i < 4; i++) {
     420        5021 :                 if (hapd->conf->ssid.wep.key[i] &&
     421          34 :                     hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
     422          17 :                                         i == hapd->conf->ssid.wep.idx, NULL, 0,
     423          17 :                                         hapd->conf->ssid.wep.key[i],
     424          17 :                                         hapd->conf->ssid.wep.len[i])) {
     425           0 :                         wpa_printf(MSG_WARNING, "Could not set WEP "
     426             :                                    "encryption.");
     427           0 :                         return -1;
     428             :                 }
     429        5021 :                 if (hapd->conf->ssid.wep.key[i] &&
     430          17 :                     i == hapd->conf->ssid.wep.idx)
     431          15 :                         hostapd_set_privacy(hapd, 1);
     432             :         }
     433             : 
     434        1251 :         return 0;
     435             : }
     436             : 
     437             : 
     438        2450 : static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
     439             : {
     440        2450 :         int ret = 0;
     441             :         u8 addr[ETH_ALEN];
     442             : 
     443        2450 :         if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
     444         173 :                 return 0;
     445             : 
     446        2277 :         if (!hapd->iface->driver_ap_teardown) {
     447        1097 :                 wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
     448             :                         "Flushing old station entries");
     449             : 
     450        1097 :                 if (hostapd_flush(hapd)) {
     451          26 :                         wpa_msg(hapd->msg_ctx, MSG_WARNING,
     452             :                                 "Could not connect to kernel driver");
     453          26 :                         ret = -1;
     454             :                 }
     455             :         }
     456        2277 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations");
     457        2277 :         os_memset(addr, 0xff, ETH_ALEN);
     458        2277 :         hostapd_drv_sta_deauth(hapd, addr, reason);
     459        2277 :         hostapd_free_stas(hapd);
     460             : 
     461        2277 :         return ret;
     462             : }
     463             : 
     464             : 
     465        1416 : static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
     466             : {
     467        1416 :         hostapd_free_stas(hapd);
     468        1416 :         hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
     469        1416 :         hostapd_clear_wep(hapd);
     470        1416 : }
     471             : 
     472             : 
     473             : /**
     474             :  * hostapd_validate_bssid_configuration - Validate BSSID configuration
     475             :  * @iface: Pointer to interface data
     476             :  * Returns: 0 on success, -1 on failure
     477             :  *
     478             :  * This function is used to validate that the configured BSSIDs are valid.
     479             :  */
     480        1224 : static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
     481             : {
     482        1224 :         u8 mask[ETH_ALEN] = { 0 };
     483        1224 :         struct hostapd_data *hapd = iface->bss[0];
     484        1224 :         unsigned int i = iface->conf->num_bss, bits = 0, j;
     485        1224 :         int auto_addr = 0;
     486             : 
     487        1224 :         if (hostapd_drv_none(hapd))
     488          10 :                 return 0;
     489             : 
     490             :         /* Generate BSSID mask that is large enough to cover the BSSIDs. */
     491             : 
     492             :         /* Determine the bits necessary to cover the number of BSSIDs. */
     493        1225 :         for (i--; i; i >>= 1)
     494          11 :                 bits++;
     495             : 
     496             :         /* Determine the bits necessary to any configured BSSIDs,
     497             :            if they are higher than the number of BSSIDs. */
     498        2439 :         for (j = 0; j < iface->conf->num_bss; j++) {
     499        1225 :                 if (hostapd_mac_comp_empty(iface->conf->bss[j]->bssid) == 0) {
     500        1171 :                         if (j)
     501           4 :                                 auto_addr++;
     502        1171 :                         continue;
     503             :                 }
     504             : 
     505         378 :                 for (i = 0; i < ETH_ALEN; i++) {
     506         648 :                         mask[i] |=
     507         324 :                                 iface->conf->bss[j]->bssid[i] ^
     508         324 :                                 hapd->own_addr[i];
     509             :                 }
     510             :         }
     511             : 
     512        1214 :         if (!auto_addr)
     513        1210 :                 goto skip_mask_ext;
     514             : 
     515           4 :         for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
     516             :                 ;
     517           4 :         j = 0;
     518           4 :         if (i < ETH_ALEN) {
     519           0 :                 j = (5 - i) * 8;
     520             : 
     521           0 :                 while (mask[i] != 0) {
     522           0 :                         mask[i] >>= 1;
     523           0 :                         j++;
     524             :                 }
     525             :         }
     526             : 
     527           4 :         if (bits < j)
     528           0 :                 bits = j;
     529             : 
     530           4 :         if (bits > 40) {
     531           0 :                 wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
     532             :                            bits);
     533           0 :                 return -1;
     534             :         }
     535             : 
     536           4 :         os_memset(mask, 0xff, ETH_ALEN);
     537           4 :         j = bits / 8;
     538           4 :         for (i = 5; i > 5 - j; i--)
     539           0 :                 mask[i] = 0;
     540           4 :         j = bits % 8;
     541          12 :         while (j--)
     542           4 :                 mask[i] <<= 1;
     543             : 
     544             : skip_mask_ext:
     545        8498 :         wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
     546        8498 :                    (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
     547             : 
     548        1214 :         if (!auto_addr)
     549        1210 :                 return 0;
     550             : 
     551          28 :         for (i = 0; i < ETH_ALEN; i++) {
     552          24 :                 if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
     553           0 :                         wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
     554             :                                    " for start address " MACSTR ".",
     555           0 :                                    MAC2STR(mask), MAC2STR(hapd->own_addr));
     556           0 :                         wpa_printf(MSG_ERROR, "Start address must be the "
     557             :                                    "first address in the block (i.e., addr "
     558             :                                    "AND mask == addr).");
     559           0 :                         return -1;
     560             :                 }
     561             :         }
     562             : 
     563           4 :         return 0;
     564             : }
     565             : 
     566             : 
     567           0 : static int mac_in_conf(struct hostapd_config *conf, const void *a)
     568             : {
     569             :         size_t i;
     570             : 
     571           0 :         for (i = 0; i < conf->num_bss; i++) {
     572           0 :                 if (hostapd_mac_comp(conf->bss[i]->bssid, a) == 0) {
     573           0 :                         return 1;
     574             :                 }
     575             :         }
     576             : 
     577           0 :         return 0;
     578             : }
     579             : 
     580             : 
     581             : #ifndef CONFIG_NO_RADIUS
     582             : 
     583          22 : static int hostapd_das_nas_mismatch(struct hostapd_data *hapd,
     584             :                                     struct radius_das_attrs *attr)
     585             : {
     586          33 :         if (attr->nas_identifier &&
     587          22 :             (!hapd->conf->nas_identifier ||
     588          11 :              os_strlen(hapd->conf->nas_identifier) !=
     589          21 :              attr->nas_identifier_len ||
     590          10 :              os_memcmp(hapd->conf->nas_identifier, attr->nas_identifier,
     591             :                        attr->nas_identifier_len) != 0)) {
     592           1 :                 wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-Identifier mismatch");
     593           1 :                 return 1;
     594             :         }
     595             : 
     596          30 :         if (attr->nas_ip_addr &&
     597          18 :             (hapd->conf->own_ip_addr.af != AF_INET ||
     598           9 :              os_memcmp(&hapd->conf->own_ip_addr.u.v4, attr->nas_ip_addr, 4) !=
     599             :              0)) {
     600           1 :                 wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IP-Address mismatch");
     601           1 :                 return 1;
     602             :         }
     603             : 
     604             : #ifdef CONFIG_IPV6
     605          20 :         if (attr->nas_ipv6_addr &&
     606           0 :             (hapd->conf->own_ip_addr.af != AF_INET6 ||
     607           0 :              os_memcmp(&hapd->conf->own_ip_addr.u.v6, attr->nas_ipv6_addr, 16)
     608             :              != 0)) {
     609           0 :                 wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IPv6-Address mismatch");
     610           0 :                 return 1;
     611             :         }
     612             : #endif /* CONFIG_IPV6 */
     613             : 
     614          20 :         return 0;
     615             : }
     616             : 
     617             : 
     618          20 : static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
     619             :                                               struct radius_das_attrs *attr,
     620             :                                               int *multi)
     621             : {
     622             :         struct sta_info *selected, *sta;
     623             :         char buf[128];
     624          20 :         int num_attr = 0;
     625             :         int count;
     626             : 
     627          20 :         *multi = 0;
     628             : 
     629          43 :         for (sta = hapd->sta_list; sta; sta = sta->next)
     630          23 :                 sta->radius_das_match = 1;
     631             : 
     632          20 :         if (attr->sta_addr) {
     633           6 :                 num_attr++;
     634           6 :                 sta = ap_get_sta(hapd, attr->sta_addr);
     635           6 :                 if (!sta) {
     636           3 :                         wpa_printf(MSG_DEBUG,
     637             :                                    "RADIUS DAS: No Calling-Station-Id match");
     638           3 :                         return NULL;
     639             :                 }
     640             : 
     641           3 :                 selected = sta;
     642           8 :                 for (sta = hapd->sta_list; sta; sta = sta->next) {
     643           5 :                         if (sta != selected)
     644           2 :                                 sta->radius_das_match = 0;
     645             :                 }
     646           3 :                 wpa_printf(MSG_DEBUG, "RADIUS DAS: Calling-Station-Id match");
     647             :         }
     648             : 
     649          17 :         if (attr->acct_session_id) {
     650           3 :                 num_attr++;
     651           3 :                 if (attr->acct_session_id_len != 17) {
     652           1 :                         wpa_printf(MSG_DEBUG,
     653             :                                    "RADIUS DAS: Acct-Session-Id cannot match");
     654           1 :                         return NULL;
     655             :                 }
     656           2 :                 count = 0;
     657             : 
     658           4 :                 for (sta = hapd->sta_list; sta; sta = sta->next) {
     659           2 :                         if (!sta->radius_das_match)
     660           0 :                                 continue;
     661           2 :                         os_snprintf(buf, sizeof(buf), "%08X-%08X",
     662             :                                     sta->acct_session_id_hi,
     663             :                                     sta->acct_session_id_lo);
     664           2 :                         if (os_memcmp(attr->acct_session_id, buf, 17) != 0)
     665           1 :                                 sta->radius_das_match = 0;
     666             :                         else
     667           1 :                                 count++;
     668             :                 }
     669             : 
     670           2 :                 if (count == 0) {
     671           1 :                         wpa_printf(MSG_DEBUG,
     672             :                                    "RADIUS DAS: No matches remaining after Acct-Session-Id check");
     673           1 :                         return NULL;
     674             :                 }
     675           1 :                 wpa_printf(MSG_DEBUG, "RADIUS DAS: Acct-Session-Id match");
     676             :         }
     677             : 
     678          15 :         if (attr->acct_multi_session_id) {
     679           4 :                 num_attr++;
     680           4 :                 if (attr->acct_multi_session_id_len != 17) {
     681           1 :                         wpa_printf(MSG_DEBUG,
     682             :                                    "RADIUS DAS: Acct-Multi-Session-Id cannot match");
     683           1 :                         return NULL;
     684             :                 }
     685           3 :                 count = 0;
     686             : 
     687           7 :                 for (sta = hapd->sta_list; sta; sta = sta->next) {
     688           4 :                         if (!sta->radius_das_match)
     689           0 :                                 continue;
     690           8 :                         if (!sta->eapol_sm ||
     691           4 :                             !sta->eapol_sm->acct_multi_session_id_hi) {
     692           0 :                                 sta->radius_das_match = 0;
     693           0 :                                 continue;
     694             :                         }
     695           8 :                         os_snprintf(buf, sizeof(buf), "%08X+%08X",
     696           4 :                                     sta->eapol_sm->acct_multi_session_id_hi,
     697           4 :                                     sta->eapol_sm->acct_multi_session_id_lo);
     698           4 :                         if (os_memcmp(attr->acct_multi_session_id, buf, 17) !=
     699             :                             0)
     700           3 :                                 sta->radius_das_match = 0;
     701             :                         else
     702           1 :                                 count++;
     703             :                 }
     704             : 
     705           3 :                 if (count == 0) {
     706           2 :                         wpa_printf(MSG_DEBUG,
     707             :                                    "RADIUS DAS: No matches remaining after Acct-Multi-Session-Id check");
     708           2 :                         return NULL;
     709             :                 }
     710           1 :                 wpa_printf(MSG_DEBUG,
     711             :                            "RADIUS DAS: Acct-Multi-Session-Id match");
     712             :         }
     713             : 
     714          12 :         if (attr->cui) {
     715           3 :                 num_attr++;
     716           3 :                 count = 0;
     717             : 
     718           6 :                 for (sta = hapd->sta_list; sta; sta = sta->next) {
     719             :                         struct wpabuf *cui;
     720             : 
     721           3 :                         if (!sta->radius_das_match)
     722           0 :                                 continue;
     723           3 :                         cui = ieee802_1x_get_radius_cui(sta->eapol_sm);
     724           4 :                         if (!cui || wpabuf_len(cui) != attr->cui_len ||
     725           1 :                             os_memcmp(wpabuf_head(cui), attr->cui,
     726             :                                       attr->cui_len) != 0)
     727           2 :                                 sta->radius_das_match = 0;
     728             :                         else
     729           1 :                                 count++;
     730             :                 }
     731             : 
     732           3 :                 if (count == 0) {
     733           2 :                         wpa_printf(MSG_DEBUG,
     734             :                                    "RADIUS DAS: No matches remaining after Chargeable-User-Identity check");
     735           2 :                         return NULL;
     736             :                 }
     737           1 :                 wpa_printf(MSG_DEBUG,
     738             :                            "RADIUS DAS: Chargeable-User-Identity match");
     739             :         }
     740             : 
     741          10 :         if (attr->user_name) {
     742           5 :                 num_attr++;
     743           5 :                 count = 0;
     744             : 
     745          14 :                 for (sta = hapd->sta_list; sta; sta = sta->next) {
     746             :                         u8 *identity;
     747             :                         size_t identity_len;
     748             : 
     749           9 :                         if (!sta->radius_das_match)
     750           2 :                                 continue;
     751           7 :                         identity = ieee802_1x_get_identity(sta->eapol_sm,
     752             :                                                            &identity_len);
     753          14 :                         if (!identity ||
     754          11 :                             identity_len != attr->user_name_len ||
     755           4 :                             os_memcmp(identity, attr->user_name, identity_len)
     756             :                             != 0)
     757           3 :                                 sta->radius_das_match = 0;
     758             :                         else
     759           4 :                                 count++;
     760             :                 }
     761             : 
     762           5 :                 if (count == 0) {
     763           2 :                         wpa_printf(MSG_DEBUG,
     764             :                                    "RADIUS DAS: No matches remaining after User-Name check");
     765           2 :                         return NULL;
     766             :                 }
     767           3 :                 wpa_printf(MSG_DEBUG,
     768             :                            "RADIUS DAS: User-Name match");
     769             :         }
     770             : 
     771           8 :         if (num_attr == 0) {
     772             :                 /*
     773             :                  * In theory, we could match all current associations, but it
     774             :                  * seems safer to just reject requests that do not include any
     775             :                  * session identification attributes.
     776             :                  */
     777           1 :                 wpa_printf(MSG_DEBUG,
     778             :                            "RADIUS DAS: No session identification attributes included");
     779           1 :                 return NULL;
     780             :         }
     781             : 
     782           7 :         selected = NULL;
     783          18 :         for (sta = hapd->sta_list; sta; sta = sta->next) {
     784          12 :                 if (sta->radius_das_match) {
     785           8 :                         if (selected) {
     786           1 :                                 *multi = 1;
     787           1 :                                 return NULL;
     788             :                         }
     789           7 :                         selected = sta;
     790             :                 }
     791             :         }
     792             : 
     793           6 :         return selected;
     794             : }
     795             : 
     796             : 
     797          13 : static int hostapd_das_disconnect_pmksa(struct hostapd_data *hapd,
     798             :                                         struct radius_das_attrs *attr)
     799             : {
     800          13 :         if (!hapd->wpa_auth)
     801           0 :                 return -1;
     802          13 :         return wpa_auth_radius_das_disconnect_pmksa(hapd->wpa_auth, attr);
     803             : }
     804             : 
     805             : 
     806             : static enum radius_das_res
     807          22 : hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
     808             : {
     809          22 :         struct hostapd_data *hapd = ctx;
     810             :         struct sta_info *sta;
     811             :         int multi;
     812             : 
     813          22 :         if (hostapd_das_nas_mismatch(hapd, attr))
     814           2 :                 return RADIUS_DAS_NAS_MISMATCH;
     815             : 
     816          20 :         sta = hostapd_das_find_sta(hapd, attr, &multi);
     817          20 :         if (sta == NULL) {
     818          14 :                 if (multi) {
     819           1 :                         wpa_printf(MSG_DEBUG,
     820             :                                    "RADIUS DAS: Multiple sessions match - not supported");
     821           1 :                         return RADIUS_DAS_MULTI_SESSION_MATCH;
     822             :                 }
     823          13 :                 if (hostapd_das_disconnect_pmksa(hapd, attr) == 0) {
     824           4 :                         wpa_printf(MSG_DEBUG,
     825             :                                    "RADIUS DAS: PMKSA cache entry matched");
     826           4 :                         return RADIUS_DAS_SUCCESS;
     827             :                 }
     828           9 :                 wpa_printf(MSG_DEBUG, "RADIUS DAS: No matching session found");
     829           9 :                 return RADIUS_DAS_SESSION_NOT_FOUND;
     830             :         }
     831             : 
     832          36 :         wpa_printf(MSG_DEBUG, "RADIUS DAS: Found a matching session " MACSTR
     833          36 :                    " - disconnecting", MAC2STR(sta->addr));
     834           6 :         wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
     835             : 
     836           6 :         hostapd_drv_sta_deauth(hapd, sta->addr,
     837             :                                WLAN_REASON_PREV_AUTH_NOT_VALID);
     838           6 :         ap_sta_deauthenticate(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID);
     839             : 
     840           6 :         return RADIUS_DAS_SUCCESS;
     841             : }
     842             : 
     843             : #endif /* CONFIG_NO_RADIUS */
     844             : 
     845             : 
     846             : /**
     847             :  * hostapd_setup_bss - Per-BSS setup (initialization)
     848             :  * @hapd: Pointer to BSS data
     849             :  * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
     850             :  *      but interface may exist
     851             :  *
     852             :  * This function is used to initialize all per-BSS data structures and
     853             :  * resources. This gets called in a loop for each BSS when an interface is
     854             :  * initialized. Most of the modules that are initialized here will be
     855             :  * deinitialized in hostapd_cleanup().
     856             :  */
     857        1252 : static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
     858             : {
     859        1252 :         struct hostapd_bss_config *conf = hapd->conf;
     860             :         u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
     861             :         int ssid_len, set_ssid;
     862             :         char force_ifname[IFNAMSIZ];
     863             :         u8 if_addr[ETH_ALEN];
     864        1252 :         int flush_old_stations = 1;
     865             : 
     866        1252 :         wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
     867        1252 :                    __func__, hapd, conf->iface, first);
     868             : 
     869             : #ifdef EAP_SERVER_TNC
     870         987 :         if (conf->tnc && tncs_global_init() < 0) {
     871           0 :                 wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
     872           0 :                 return -1;
     873             :         }
     874             : #endif /* EAP_SERVER_TNC */
     875             : 
     876        1252 :         if (hapd->started) {
     877           0 :                 wpa_printf(MSG_ERROR, "%s: Interface %s was already started",
     878           0 :                            __func__, conf->iface);
     879           0 :                 return -1;
     880             :         }
     881        1252 :         hapd->started = 1;
     882             : 
     883        1252 :         if (!first || first == -1) {
     884          41 :                 if (hostapd_mac_comp_empty(conf->bssid) == 0) {
     885             :                         /* Allocate the next available BSSID. */
     886             :                         do {
     887           0 :                                 inc_byte_array(hapd->own_addr, ETH_ALEN);
     888           0 :                         } while (mac_in_conf(hapd->iconf, hapd->own_addr));
     889             :                 } else {
     890             :                         /* Allocate the configured BSSID. */
     891          41 :                         os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN);
     892             : 
     893          41 :                         if (hostapd_mac_comp(hapd->own_addr,
     894          41 :                                              hapd->iface->bss[0]->own_addr) ==
     895             :                             0) {
     896           0 :                                 wpa_printf(MSG_ERROR, "BSS '%s' may not have "
     897             :                                            "BSSID set to the MAC address of "
     898           0 :                                            "the radio", conf->iface);
     899           0 :                                 return -1;
     900             :                         }
     901             :                 }
     902             : 
     903          41 :                 hapd->interface_added = 1;
     904         123 :                 if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
     905          41 :                                    conf->iface, hapd->own_addr, hapd,
     906             :                                    &hapd->drv_priv, force_ifname, if_addr,
     907          41 :                                    conf->bridge[0] ? conf->bridge : NULL,
     908             :                                    first == -1)) {
     909           0 :                         wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
     910           0 :                                    MACSTR ")", MAC2STR(hapd->own_addr));
     911           0 :                         hapd->interface_added = 0;
     912           0 :                         return -1;
     913             :                 }
     914             :         }
     915             : 
     916        1252 :         if (conf->wmm_enabled < 0)
     917        1007 :                 conf->wmm_enabled = hapd->iconf->ieee80211n;
     918             : 
     919             : #ifdef CONFIG_MESH
     920         265 :         if (hapd->iface->mconf == NULL)
     921         236 :                 flush_old_stations = 0;
     922             : #endif /* CONFIG_MESH */
     923             : 
     924        1252 :         if (flush_old_stations)
     925        1016 :                 hostapd_flush_old_stations(hapd,
     926             :                                            WLAN_REASON_PREV_AUTH_NOT_VALID);
     927        1252 :         hostapd_set_privacy(hapd, 0);
     928             : 
     929        1252 :         hostapd_broadcast_wep_clear(hapd);
     930        1252 :         if (hostapd_setup_encryption(conf->iface, hapd))
     931           0 :                 return -1;
     932             : 
     933             :         /*
     934             :          * Fetch the SSID from the system and use it or,
     935             :          * if one was specified in the config file, verify they
     936             :          * match.
     937             :          */
     938        1252 :         ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
     939        1252 :         if (ssid_len < 0) {
     940           0 :                 wpa_printf(MSG_ERROR, "Could not read SSID from system");
     941           0 :                 return -1;
     942             :         }
     943        1252 :         if (conf->ssid.ssid_set) {
     944             :                 /*
     945             :                  * If SSID is specified in the config file and it differs
     946             :                  * from what is being used then force installation of the
     947             :                  * new SSID.
     948             :                  */
     949        1213 :                 set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
     950           0 :                             os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
     951             :         } else {
     952             :                 /*
     953             :                  * No SSID in the config file; just use the one we got
     954             :                  * from the system.
     955             :                  */
     956          39 :                 set_ssid = 0;
     957          39 :                 conf->ssid.ssid_len = ssid_len;
     958          39 :                 os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
     959             :         }
     960             : 
     961        1252 :         if (!hostapd_drv_none(hapd)) {
     962       11178 :                 wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
     963             :                            " and ssid \"%s\"",
     964        8694 :                            conf->iface, MAC2STR(hapd->own_addr),
     965        1242 :                            wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
     966             :         }
     967             : 
     968        1252 :         if (hostapd_setup_wpa_psk(conf)) {
     969           4 :                 wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
     970           4 :                 return -1;
     971             :         }
     972             : 
     973             :         /* Set SSID for the kernel driver (to be used in beacon and probe
     974             :          * response frames) */
     975        1248 :         if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid,
     976             :                                          conf->ssid.ssid_len)) {
     977           0 :                 wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
     978           0 :                 return -1;
     979             :         }
     980             : 
     981        1248 :         if (wpa_debug_level <= MSG_MSGDUMP)
     982        1248 :                 conf->radius->msg_dumps = 1;
     983             : #ifndef CONFIG_NO_RADIUS
     984         983 :         hapd->radius = radius_client_init(hapd, conf->radius);
     985         983 :         if (hapd->radius == NULL) {
     986           0 :                 wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
     987           0 :                 return -1;
     988             :         }
     989             : 
     990         983 :         if (conf->radius_das_port) {
     991             :                 struct radius_das_conf das_conf;
     992           2 :                 os_memset(&das_conf, 0, sizeof(das_conf));
     993           2 :                 das_conf.port = conf->radius_das_port;
     994           2 :                 das_conf.shared_secret = conf->radius_das_shared_secret;
     995           2 :                 das_conf.shared_secret_len =
     996           2 :                         conf->radius_das_shared_secret_len;
     997           2 :                 das_conf.client_addr = &conf->radius_das_client_addr;
     998           2 :                 das_conf.time_window = conf->radius_das_time_window;
     999           2 :                 das_conf.require_event_timestamp =
    1000           2 :                         conf->radius_das_require_event_timestamp;
    1001           2 :                 das_conf.ctx = hapd;
    1002           2 :                 das_conf.disconnect = hostapd_das_disconnect;
    1003           2 :                 hapd->radius_das = radius_das_init(&das_conf);
    1004           2 :                 if (hapd->radius_das == NULL) {
    1005           0 :                         wpa_printf(MSG_ERROR, "RADIUS DAS initialization "
    1006             :                                    "failed.");
    1007           0 :                         return -1;
    1008             :                 }
    1009             :         }
    1010             : #endif /* CONFIG_NO_RADIUS */
    1011             : 
    1012        1248 :         if (hostapd_acl_init(hapd)) {
    1013           0 :                 wpa_printf(MSG_ERROR, "ACL initialization failed.");
    1014           0 :                 return -1;
    1015             :         }
    1016        1248 :         if (hostapd_init_wps(hapd, conf))
    1017           0 :                 return -1;
    1018             : 
    1019        1248 :         if (authsrv_init(hapd) < 0)
    1020           0 :                 return -1;
    1021             : 
    1022        1248 :         if (ieee802_1x_init(hapd)) {
    1023           0 :                 wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
    1024           0 :                 return -1;
    1025             :         }
    1026             : 
    1027        1248 :         if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd))
    1028           0 :                 return -1;
    1029             : 
    1030        1248 :         if (accounting_init(hapd)) {
    1031           1 :                 wpa_printf(MSG_ERROR, "Accounting initialization failed.");
    1032           1 :                 return -1;
    1033             :         }
    1034             : 
    1035        1247 :         if (conf->ieee802_11f &&
    1036           0 :             (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) {
    1037           0 :                 wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
    1038             :                            "failed.");
    1039           0 :                 return -1;
    1040             :         }
    1041             : 
    1042             : #ifdef CONFIG_INTERWORKING
    1043        1247 :         if (gas_serv_init(hapd)) {
    1044           0 :                 wpa_printf(MSG_ERROR, "GAS server initialization failed");
    1045           0 :                 return -1;
    1046             :         }
    1047             : 
    1048        1248 :         if (conf->qos_map_set_len &&
    1049           1 :             hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
    1050           1 :                                     conf->qos_map_set_len)) {
    1051           0 :                 wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
    1052           0 :                 return -1;
    1053             :         }
    1054             : #endif /* CONFIG_INTERWORKING */
    1055             : 
    1056        1247 :         if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
    1057           0 :                 wpa_printf(MSG_ERROR, "BSS Load initialization failed");
    1058           0 :                 return -1;
    1059             :         }
    1060             : 
    1061        1247 :         if (conf->proxy_arp) {
    1062           7 :                 if (x_snoop_init(hapd)) {
    1063           2 :                         wpa_printf(MSG_ERROR,
    1064             :                                    "Generic snooping infrastructure initialization failed");
    1065           2 :                         return -1;
    1066             :                 }
    1067             : 
    1068           5 :                 if (dhcp_snoop_init(hapd)) {
    1069           0 :                         wpa_printf(MSG_ERROR,
    1070             :                                    "DHCP snooping initialization failed");
    1071           0 :                         return -1;
    1072             :                 }
    1073             : 
    1074           5 :                 if (ndisc_snoop_init(hapd)) {
    1075           0 :                         wpa_printf(MSG_ERROR,
    1076             :                                    "Neighbor Discovery snooping initialization failed");
    1077           0 :                         return -1;
    1078             :                 }
    1079             :         }
    1080             : 
    1081        1245 :         if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
    1082           0 :                 wpa_printf(MSG_ERROR, "VLAN initialization failed.");
    1083           0 :                 return -1;
    1084             :         }
    1085             : 
    1086        1245 :         if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
    1087           3 :                 return -1;
    1088             : 
    1089        1242 :         if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
    1090           0 :                 return -1;
    1091             : 
    1092        1242 :         if (hapd->driver && hapd->driver->set_operstate)
    1093        1232 :                 hapd->driver->set_operstate(hapd->drv_priv, 1);
    1094             : 
    1095        1242 :         return 0;
    1096             : }
    1097             : 
    1098             : 
    1099        1202 : static void hostapd_tx_queue_params(struct hostapd_iface *iface)
    1100             : {
    1101        1202 :         struct hostapd_data *hapd = iface->bss[0];
    1102             :         int i;
    1103             :         struct hostapd_tx_queue_params *p;
    1104             : 
    1105             : #ifdef CONFIG_MESH
    1106         265 :         if (iface->mconf == NULL)
    1107         501 :                 return;
    1108             : #endif /* CONFIG_MESH */
    1109             : 
    1110        4830 :         for (i = 0; i < NUM_TX_QUEUES; i++) {
    1111        3864 :                 p = &iface->conf->tx_queue[i];
    1112             : 
    1113        3864 :                 if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
    1114             :                                                 p->cwmax, p->burst)) {
    1115         116 :                         wpa_printf(MSG_DEBUG, "Failed to set TX queue "
    1116             :                                    "parameters for queue %d.", i);
    1117             :                         /* Continue anyway */
    1118             :                 }
    1119             :         }
    1120         937 : }
    1121             : 
    1122             : 
    1123           0 : static int hostapd_set_acl_list(struct hostapd_data *hapd,
    1124             :                                 struct mac_acl_entry *mac_acl,
    1125             :                                 int n_entries, u8 accept_acl)
    1126             : {
    1127             :         struct hostapd_acl_params *acl_params;
    1128             :         int i, err;
    1129             : 
    1130           0 :         acl_params = os_zalloc(sizeof(*acl_params) +
    1131           0 :                                (n_entries * sizeof(acl_params->mac_acl[0])));
    1132           0 :         if (!acl_params)
    1133           0 :                 return -ENOMEM;
    1134             : 
    1135           0 :         for (i = 0; i < n_entries; i++)
    1136           0 :                 os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr,
    1137             :                           ETH_ALEN);
    1138             : 
    1139           0 :         acl_params->acl_policy = accept_acl;
    1140           0 :         acl_params->num_mac_acl = n_entries;
    1141             : 
    1142           0 :         err = hostapd_drv_set_acl(hapd, acl_params);
    1143             : 
    1144           0 :         os_free(acl_params);
    1145             : 
    1146           0 :         return err;
    1147             : }
    1148             : 
    1149             : 
    1150        1202 : static void hostapd_set_acl(struct hostapd_data *hapd)
    1151             : {
    1152        1202 :         struct hostapd_config *conf = hapd->iconf;
    1153             :         int err;
    1154             :         u8 accept_acl;
    1155             : 
    1156        1202 :         if (hapd->iface->drv_max_acl_mac_addrs == 0)
    1157        1202 :                 return;
    1158             : 
    1159           0 :         if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) {
    1160           0 :                 accept_acl = 1;
    1161           0 :                 err = hostapd_set_acl_list(hapd, conf->bss[0]->accept_mac,
    1162           0 :                                            conf->bss[0]->num_accept_mac,
    1163             :                                            accept_acl);
    1164           0 :                 if (err) {
    1165           0 :                         wpa_printf(MSG_DEBUG, "Failed to set accept acl");
    1166           0 :                         return;
    1167             :                 }
    1168           0 :         } else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) {
    1169           0 :                 accept_acl = 0;
    1170           0 :                 err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac,
    1171           0 :                                            conf->bss[0]->num_deny_mac,
    1172             :                                            accept_acl);
    1173           0 :                 if (err) {
    1174           0 :                         wpa_printf(MSG_DEBUG, "Failed to set deny acl");
    1175           0 :                         return;
    1176             :                 }
    1177             :         }
    1178             : }
    1179             : 
    1180             : 
    1181          36 : static int start_ctrl_iface_bss(struct hostapd_data *hapd)
    1182             : {
    1183          72 :         if (!hapd->iface->interfaces ||
    1184          36 :             !hapd->iface->interfaces->ctrl_iface_init)
    1185           0 :                 return 0;
    1186             : 
    1187          36 :         if (hapd->iface->interfaces->ctrl_iface_init(hapd)) {
    1188           0 :                 wpa_printf(MSG_ERROR,
    1189             :                            "Failed to setup control interface for %s",
    1190           0 :                            hapd->conf->iface);
    1191           0 :                 return -1;
    1192             :         }
    1193             : 
    1194          36 :         return 0;
    1195             : }
    1196             : 
    1197             : 
    1198        2235 : static int start_ctrl_iface(struct hostapd_iface *iface)
    1199             : {
    1200             :         size_t i;
    1201             : 
    1202        2235 :         if (!iface->interfaces || !iface->interfaces->ctrl_iface_init)
    1203         265 :                 return 0;
    1204             : 
    1205        3950 :         for (i = 0; i < iface->num_bss; i++) {
    1206        1983 :                 struct hostapd_data *hapd = iface->bss[i];
    1207        1983 :                 if (iface->interfaces->ctrl_iface_init(hapd)) {
    1208           3 :                         wpa_printf(MSG_ERROR,
    1209             :                                    "Failed to setup control interface for %s",
    1210           3 :                                    hapd->conf->iface);
    1211           3 :                         return -1;
    1212             :                 }
    1213             :         }
    1214             : 
    1215        1967 :         return 0;
    1216             : }
    1217             : 
    1218             : 
    1219           0 : static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx)
    1220             : {
    1221           0 :         struct hostapd_iface *iface = eloop_ctx;
    1222             : 
    1223           0 :         if (!iface->wait_channel_update) {
    1224           0 :                 wpa_printf(MSG_INFO, "Channel list update timeout, but interface was not waiting for it");
    1225           0 :                 return;
    1226             :         }
    1227             : 
    1228             :         /*
    1229             :          * It is possible that the existing channel list is acceptable, so try
    1230             :          * to proceed.
    1231             :          */
    1232           0 :         wpa_printf(MSG_DEBUG, "Channel list update timeout - try to continue anyway");
    1233           0 :         setup_interface2(iface);
    1234             : }
    1235             : 
    1236             : 
    1237        1403 : void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator)
    1238             : {
    1239        1403 :         if (!iface->wait_channel_update || initiator != REGDOM_SET_BY_USER)
    1240        2771 :                 return;
    1241             : 
    1242          35 :         wpa_printf(MSG_DEBUG, "Channel list updated - continue setup");
    1243          35 :         eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
    1244          35 :         setup_interface2(iface);
    1245             : }
    1246             : 
    1247             : 
    1248        1224 : static int setup_interface(struct hostapd_iface *iface)
    1249             : {
    1250        1224 :         struct hostapd_data *hapd = iface->bss[0];
    1251             :         size_t i;
    1252             : 
    1253             :         /*
    1254             :          * It is possible that setup_interface() is called after the interface
    1255             :          * was disabled etc., in which case driver_ap_teardown is possibly set
    1256             :          * to 1. Clear it here so any other key/station deletion, which is not
    1257             :          * part of a teardown flow, would also call the relevant driver
    1258             :          * callbacks.
    1259             :          */
    1260        1224 :         iface->driver_ap_teardown = 0;
    1261             : 
    1262        1224 :         if (!iface->phy[0]) {
    1263        1199 :                 const char *phy = hostapd_drv_get_radio_name(hapd);
    1264        1199 :                 if (phy) {
    1265        1189 :                         wpa_printf(MSG_DEBUG, "phy: %s", phy);
    1266        1189 :                         os_strlcpy(iface->phy, phy, sizeof(iface->phy));
    1267             :                 }
    1268             :         }
    1269             : 
    1270             :         /*
    1271             :          * Make sure that all BSSes get configured with a pointer to the same
    1272             :          * driver interface.
    1273             :          */
    1274        1231 :         for (i = 1; i < iface->num_bss; i++) {
    1275           7 :                 iface->bss[i]->driver = hapd->driver;
    1276           7 :                 iface->bss[i]->drv_priv = hapd->drv_priv;
    1277             :         }
    1278             : 
    1279        1224 :         if (hostapd_validate_bssid_configuration(iface))
    1280           0 :                 return -1;
    1281             : 
    1282             :         /*
    1283             :          * Initialize control interfaces early to allow external monitoring of
    1284             :          * channel setup operations that may take considerable amount of time
    1285             :          * especially for DFS cases.
    1286             :          */
    1287        1224 :         if (start_ctrl_iface(iface))
    1288           0 :                 return -1;
    1289             : 
    1290        1224 :         if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
    1291             :                 char country[4], previous_country[4];
    1292             : 
    1293          40 :                 hostapd_set_state(iface, HAPD_IFACE_COUNTRY_UPDATE);
    1294          40 :                 if (hostapd_get_country(hapd, previous_country) < 0)
    1295           0 :                         previous_country[0] = '\0';
    1296             : 
    1297          40 :                 os_memcpy(country, hapd->iconf->country, 3);
    1298          40 :                 country[3] = '\0';
    1299          40 :                 if (hostapd_set_country(hapd, country) < 0) {
    1300           0 :                         wpa_printf(MSG_ERROR, "Failed to set country code");
    1301          35 :                         return -1;
    1302             :                 }
    1303             : 
    1304          40 :                 wpa_printf(MSG_DEBUG, "Previous country code %s, new country code %s",
    1305             :                            previous_country, country);
    1306             : 
    1307          40 :                 if (os_strncmp(previous_country, country, 2) != 0) {
    1308          35 :                         wpa_printf(MSG_DEBUG, "Continue interface setup after channel list update");
    1309          35 :                         iface->wait_channel_update = 1;
    1310          35 :                         eloop_register_timeout(5, 0,
    1311             :                                                channel_list_update_timeout,
    1312             :                                                iface, NULL);
    1313          35 :                         return 0;
    1314             :                 }
    1315             :         }
    1316             : 
    1317        1189 :         return setup_interface2(iface);
    1318             : }
    1319             : 
    1320             : 
    1321        1224 : static int setup_interface2(struct hostapd_iface *iface)
    1322             : {
    1323        1224 :         iface->wait_channel_update = 0;
    1324             : 
    1325        1224 :         if (hostapd_get_hw_features(iface)) {
    1326             :                 /* Not all drivers support this yet, so continue without hw
    1327             :                  * feature data. */
    1328             :         } else {
    1329        1214 :                 int ret = hostapd_select_hw_mode(iface);
    1330        1214 :                 if (ret < 0) {
    1331           2 :                         wpa_printf(MSG_ERROR, "Could not select hw_mode and "
    1332             :                                    "channel. (%d)", ret);
    1333           2 :                         goto fail;
    1334             :                 }
    1335        1212 :                 if (ret == 1) {
    1336           9 :                         wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
    1337           9 :                         return 0;
    1338             :                 }
    1339        1203 :                 ret = hostapd_check_ht_capab(iface);
    1340        1203 :                 if (ret < 0)
    1341           2 :                         goto fail;
    1342        1201 :                 if (ret == 1) {
    1343          42 :                         wpa_printf(MSG_DEBUG, "Interface initialization will "
    1344             :                                    "be completed in a callback");
    1345          42 :                         return 0;
    1346             :                 }
    1347             : 
    1348        1159 :                 if (iface->conf->ieee80211h)
    1349           5 :                         wpa_printf(MSG_DEBUG, "DFS support is enabled");
    1350             :         }
    1351        1169 :         return hostapd_setup_interface_complete(iface, 0);
    1352             : 
    1353             : fail:
    1354           4 :         hostapd_set_state(iface, HAPD_IFACE_DISABLED);
    1355           4 :         wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
    1356           4 :         if (iface->interfaces && iface->interfaces->terminate_on_error)
    1357           0 :                 eloop_terminate();
    1358           4 :         return -1;
    1359             : }
    1360             : 
    1361             : 
    1362             : /**
    1363             :  * hostapd_setup_interface_complete - Complete interface setup
    1364             :  *
    1365             :  * This function is called when previous steps in the interface setup has been
    1366             :  * completed. This can also start operations, e.g., DFS, that will require
    1367             :  * additional processing before interface is ready to be enabled. Such
    1368             :  * operations will call this function from eloop callbacks when finished.
    1369             :  */
    1370        1226 : int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
    1371             : {
    1372        1226 :         struct hostapd_data *hapd = iface->bss[0];
    1373             :         size_t j;
    1374             :         u8 *prev_addr;
    1375        1226 :         int delay_apply_cfg = 0;
    1376             : 
    1377        1226 :         if (err)
    1378           3 :                 goto fail;
    1379             : 
    1380        1223 :         wpa_printf(MSG_DEBUG, "Completing interface initialization");
    1381        1223 :         if (iface->conf->channel) {
    1382             : #ifdef NEED_AP_MLME
    1383             :                 int res;
    1384             : #endif /* NEED_AP_MLME */
    1385             : 
    1386        1213 :                 iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel);
    1387        3639 :                 wpa_printf(MSG_DEBUG, "Mode: %s  Channel: %d  "
    1388             :                            "Frequency: %d MHz",
    1389        1213 :                            hostapd_hw_mode_txt(iface->conf->hw_mode),
    1390        1213 :                            iface->conf->channel, iface->freq);
    1391             : 
    1392             : #ifdef NEED_AP_MLME
    1393             :                 /* Handle DFS only if it is not offloaded to the driver */
    1394        1213 :                 if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
    1395             :                         /* Check DFS */
    1396        1213 :                         res = hostapd_handle_dfs(iface);
    1397        1213 :                         if (res <= 0) {
    1398          12 :                                 if (res < 0)
    1399           1 :                                         goto fail;
    1400          11 :                                 return res;
    1401             :                         }
    1402             :                 }
    1403             : #endif /* NEED_AP_MLME */
    1404             : 
    1405             : #ifdef CONFIG_MESH
    1406         265 :                 if (iface->mconf != NULL) {
    1407          29 :                         wpa_printf(MSG_DEBUG,
    1408             :                                    "%s: Mesh configuration will be applied while joining the mesh network",
    1409          29 :                                    iface->bss[0]->conf->iface);
    1410          29 :                         delay_apply_cfg = 1;
    1411             :                 }
    1412             : #endif /* CONFIG_MESH */
    1413             : 
    1414        2373 :                 if (!delay_apply_cfg &&
    1415        8204 :                     hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
    1416        1172 :                                      hapd->iconf->channel,
    1417        1172 :                                      hapd->iconf->ieee80211n,
    1418        1172 :                                      hapd->iconf->ieee80211ac,
    1419        1172 :                                      hapd->iconf->secondary_channel,
    1420        1172 :                                      hapd->iconf->vht_oper_chwidth,
    1421        1172 :                                      hapd->iconf->vht_oper_centr_freq_seg0_idx,
    1422        1172 :                                      hapd->iconf->vht_oper_centr_freq_seg1_idx)) {
    1423           0 :                         wpa_printf(MSG_ERROR, "Could not set channel for "
    1424             :                                    "kernel driver");
    1425           0 :                         goto fail;
    1426             :                 }
    1427             :         }
    1428             : 
    1429        1211 :         if (iface->current_mode) {
    1430        1201 :                 if (hostapd_prepare_rates(iface, iface->current_mode)) {
    1431           0 :                         wpa_printf(MSG_ERROR, "Failed to prepare rates "
    1432             :                                    "table.");
    1433           0 :                         hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
    1434             :                                        HOSTAPD_LEVEL_WARNING,
    1435             :                                        "Failed to prepare rates table.");
    1436           0 :                         goto fail;
    1437             :                 }
    1438             :         }
    1439             : 
    1440        1212 :         if (hapd->iconf->rts_threshold > -1 &&
    1441           1 :             hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
    1442           0 :                 wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
    1443             :                            "kernel driver");
    1444           0 :                 goto fail;
    1445             :         }
    1446             : 
    1447        1214 :         if (hapd->iconf->fragm_threshold > -1 &&
    1448           3 :             hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
    1449           0 :                 wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
    1450             :                            "for kernel driver");
    1451           0 :                 goto fail;
    1452             :         }
    1453             : 
    1454        1211 :         prev_addr = hapd->own_addr;
    1455             : 
    1456        2421 :         for (j = 0; j < iface->num_bss; j++) {
    1457        1219 :                 hapd = iface->bss[j];
    1458        1219 :                 if (j)
    1459           8 :                         os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
    1460        1219 :                 if (hostapd_setup_bss(hapd, j == 0)) {
    1461             :                         do {
    1462           9 :                                 hapd = iface->bss[j];
    1463           9 :                                 hostapd_bss_deinit_no_free(hapd);
    1464           9 :                                 hostapd_free_hapd_data(hapd);
    1465           9 :                         } while (j-- > 0);
    1466           9 :                         goto fail;
    1467             :                 }
    1468        1210 :                 if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
    1469        1157 :                         prev_addr = hapd->own_addr;
    1470             :         }
    1471        1202 :         hapd = iface->bss[0];
    1472             : 
    1473        1202 :         hostapd_tx_queue_params(iface);
    1474             : 
    1475        1202 :         ap_list_init(iface);
    1476             : 
    1477        1202 :         hostapd_set_acl(hapd);
    1478             : 
    1479        1202 :         if (hostapd_driver_commit(hapd) < 0) {
    1480           0 :                 wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
    1481             :                            "configuration", __func__);
    1482           0 :                 goto fail;
    1483             :         }
    1484             : 
    1485             :         /*
    1486             :          * WPS UPnP module can be initialized only when the "upnp_iface" is up.
    1487             :          * If "interface" and "upnp_iface" are the same (e.g., non-bridge
    1488             :          * mode), the interface is up only after driver_commit, so initialize
    1489             :          * WPS after driver_commit.
    1490             :          */
    1491        2412 :         for (j = 0; j < iface->num_bss; j++) {
    1492        1210 :                 if (hostapd_init_wps_complete(iface->bss[j]))
    1493           0 :                         goto fail;
    1494             :         }
    1495             : 
    1496        1202 :         hostapd_set_state(iface, HAPD_IFACE_ENABLED);
    1497        1202 :         wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
    1498        1202 :         if (hapd->setup_complete_cb)
    1499         236 :                 hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
    1500             : 
    1501        1202 :         wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
    1502        1202 :                    iface->bss[0]->conf->iface);
    1503        1202 :         if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
    1504          10 :                 iface->interfaces->terminate_on_error--;
    1505             : 
    1506        1202 :         return 0;
    1507             : 
    1508             : fail:
    1509          13 :         wpa_printf(MSG_ERROR, "Interface initialization failed");
    1510          13 :         hostapd_set_state(iface, HAPD_IFACE_DISABLED);
    1511          13 :         wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
    1512          13 :         if (iface->interfaces && iface->interfaces->terminate_on_error)
    1513           0 :                 eloop_terminate();
    1514          13 :         return -1;
    1515             : }
    1516             : 
    1517             : 
    1518             : /**
    1519             :  * hostapd_setup_interface - Setup of an interface
    1520             :  * @iface: Pointer to interface data.
    1521             :  * Returns: 0 on success, -1 on failure
    1522             :  *
    1523             :  * Initializes the driver interface, validates the configuration,
    1524             :  * and sets driver parameters based on the configuration.
    1525             :  * Flushes old stations, sets the channel, encryption,
    1526             :  * beacons, and WDS links based on the configuration.
    1527             :  *
    1528             :  * If interface setup requires more time, e.g., to perform HT co-ex scans, ACS,
    1529             :  * or DFS operations, this function returns 0 before such operations have been
    1530             :  * completed. The pending operations are registered into eloop and will be
    1531             :  * completed from eloop callbacks. Those callbacks end up calling
    1532             :  * hostapd_setup_interface_complete() once setup has been completed.
    1533             :  */
    1534        1224 : int hostapd_setup_interface(struct hostapd_iface *iface)
    1535             : {
    1536             :         int ret;
    1537             : 
    1538        1224 :         ret = setup_interface(iface);
    1539        1224 :         if (ret) {
    1540          12 :                 wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
    1541          12 :                            iface->bss[0]->conf->iface);
    1542          12 :                 return -1;
    1543             :         }
    1544             : 
    1545        1212 :         return 0;
    1546             : }
    1547             : 
    1548             : 
    1549             : /**
    1550             :  * hostapd_alloc_bss_data - Allocate and initialize per-BSS data
    1551             :  * @hapd_iface: Pointer to interface data
    1552             :  * @conf: Pointer to per-interface configuration
    1553             :  * @bss: Pointer to per-BSS configuration for this BSS
    1554             :  * Returns: Pointer to allocated BSS data
    1555             :  *
    1556             :  * This function is used to allocate per-BSS data structure. This data will be
    1557             :  * freed after hostapd_cleanup() is called for it during interface
    1558             :  * deinitialization.
    1559             :  */
    1560             : struct hostapd_data *
    1561        1316 : hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
    1562             :                        struct hostapd_config *conf,
    1563             :                        struct hostapd_bss_config *bss)
    1564             : {
    1565             :         struct hostapd_data *hapd;
    1566             : 
    1567        1316 :         hapd = os_zalloc(sizeof(*hapd));
    1568        1316 :         if (hapd == NULL)
    1569           4 :                 return NULL;
    1570             : 
    1571        1312 :         hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
    1572        1312 :         hapd->iconf = conf;
    1573        1312 :         hapd->conf = bss;
    1574        1312 :         hapd->iface = hapd_iface;
    1575        1312 :         hapd->driver = hapd->iconf->driver;
    1576        1312 :         hapd->ctrl_sock = -1;
    1577             : 
    1578        1312 :         return hapd;
    1579             : }
    1580             : 
    1581             : 
    1582        1336 : static void hostapd_bss_deinit(struct hostapd_data *hapd)
    1583             : {
    1584        1336 :         wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__,
    1585        1336 :                    hapd->conf->iface);
    1586        1336 :         hostapd_bss_deinit_no_free(hapd);
    1587        1336 :         hostapd_cleanup(hapd);
    1588        1336 : }
    1589             : 
    1590             : 
    1591        1295 : void hostapd_interface_deinit(struct hostapd_iface *iface)
    1592             : {
    1593             :         int j;
    1594             : 
    1595        1295 :         wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
    1596        1295 :         if (iface == NULL)
    1597        1295 :                 return;
    1598             : 
    1599             : #ifdef CONFIG_IEEE80211N
    1600             : #ifdef NEED_AP_MLME
    1601        1295 :         hostapd_stop_setup_timers(iface);
    1602        1295 :         eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
    1603             : #endif /* NEED_AP_MLME */
    1604             : #endif /* CONFIG_IEEE80211N */
    1605        1295 :         eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
    1606        1295 :         iface->wait_channel_update = 0;
    1607             : 
    1608        2595 :         for (j = iface->num_bss - 1; j >= 0; j--)
    1609        1300 :                 hostapd_bss_deinit(iface->bss[j]);
    1610             : }
    1611             : 
    1612             : 
    1613        1295 : void hostapd_interface_free(struct hostapd_iface *iface)
    1614             : {
    1615             :         size_t j;
    1616        1295 :         wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
    1617        2595 :         for (j = 0; j < iface->num_bss; j++) {
    1618        1300 :                 wpa_printf(MSG_DEBUG, "%s: free hapd %p",
    1619        1300 :                            __func__, iface->bss[j]);
    1620        1300 :                 os_free(iface->bss[j]);
    1621             :         }
    1622        1295 :         hostapd_cleanup_iface(iface);
    1623        1295 : }
    1624             : 
    1625             : 
    1626             : /**
    1627             :  * hostapd_init - Allocate and initialize per-interface data
    1628             :  * @config_file: Path to the configuration file
    1629             :  * Returns: Pointer to the allocated interface data or %NULL on failure
    1630             :  *
    1631             :  * This function is used to allocate main data structures for per-interface
    1632             :  * data. The allocated data buffer will be freed by calling
    1633             :  * hostapd_cleanup_iface().
    1634             :  */
    1635          26 : struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
    1636             :                                     const char *config_file)
    1637             : {
    1638          26 :         struct hostapd_iface *hapd_iface = NULL;
    1639          26 :         struct hostapd_config *conf = NULL;
    1640             :         struct hostapd_data *hapd;
    1641             :         size_t i;
    1642             : 
    1643          26 :         hapd_iface = os_zalloc(sizeof(*hapd_iface));
    1644          26 :         if (hapd_iface == NULL)
    1645           2 :                 goto fail;
    1646             : 
    1647          24 :         hapd_iface->config_fname = os_strdup(config_file);
    1648          24 :         if (hapd_iface->config_fname == NULL)
    1649           1 :                 goto fail;
    1650             : 
    1651          23 :         conf = interfaces->config_read_cb(hapd_iface->config_fname);
    1652          23 :         if (conf == NULL)
    1653           0 :                 goto fail;
    1654          23 :         hapd_iface->conf = conf;
    1655             : 
    1656          23 :         hapd_iface->num_bss = conf->num_bss;
    1657          23 :         hapd_iface->bss = os_calloc(conf->num_bss,
    1658             :                                     sizeof(struct hostapd_data *));
    1659          23 :         if (hapd_iface->bss == NULL)
    1660           0 :                 goto fail;
    1661             : 
    1662          46 :         for (i = 0; i < conf->num_bss; i++) {
    1663          46 :                 hapd = hapd_iface->bss[i] =
    1664          23 :                         hostapd_alloc_bss_data(hapd_iface, conf,
    1665          23 :                                                conf->bss[i]);
    1666          23 :                 if (hapd == NULL)
    1667           0 :                         goto fail;
    1668          23 :                 hapd->msg_ctx = hapd;
    1669             :         }
    1670             : 
    1671          23 :         return hapd_iface;
    1672             : 
    1673             : fail:
    1674           3 :         wpa_printf(MSG_ERROR, "Failed to set up interface with %s",
    1675             :                    config_file);
    1676           3 :         if (conf)
    1677           0 :                 hostapd_config_free(conf);
    1678           3 :         if (hapd_iface) {
    1679           1 :                 os_free(hapd_iface->config_fname);
    1680           1 :                 os_free(hapd_iface->bss);
    1681           1 :                 wpa_printf(MSG_DEBUG, "%s: free iface %p",
    1682             :                            __func__, hapd_iface);
    1683           1 :                 os_free(hapd_iface);
    1684             :         }
    1685           3 :         return NULL;
    1686             : }
    1687             : 
    1688             : 
    1689          37 : static int ifname_in_use(struct hapd_interfaces *interfaces, const char *ifname)
    1690             : {
    1691             :         size_t i, j;
    1692             : 
    1693          75 :         for (i = 0; i < interfaces->count; i++) {
    1694          39 :                 struct hostapd_iface *iface = interfaces->iface[i];
    1695         206 :                 for (j = 0; j < iface->num_bss; j++) {
    1696         168 :                         struct hostapd_data *hapd = iface->bss[j];
    1697         168 :                         if (os_strcmp(ifname, hapd->conf->iface) == 0)
    1698           1 :                                 return 1;
    1699             :                 }
    1700             :         }
    1701             : 
    1702          36 :         return 0;
    1703             : }
    1704             : 
    1705             : 
    1706             : /**
    1707             :  * hostapd_interface_init_bss - Read configuration file and init BSS data
    1708             :  *
    1709             :  * This function is used to parse configuration file for a BSS. This BSS is
    1710             :  * added to an existing interface sharing the same radio (if any) or a new
    1711             :  * interface is created if this is the first interface on a radio. This
    1712             :  * allocate memory for the BSS. No actual driver operations are started.
    1713             :  *
    1714             :  * This is similar to hostapd_interface_init(), but for a case where the
    1715             :  * configuration is used to add a single BSS instead of all BSSes for a radio.
    1716             :  */
    1717             : struct hostapd_iface *
    1718          54 : hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
    1719             :                            const char *config_fname, int debug)
    1720             : {
    1721          54 :         struct hostapd_iface *new_iface = NULL, *iface = NULL;
    1722             :         struct hostapd_data *hapd;
    1723             :         int k;
    1724             :         size_t i, bss_idx;
    1725             : 
    1726          54 :         if (!phy || !*phy)
    1727           0 :                 return NULL;
    1728             : 
    1729          62 :         for (i = 0; i < interfaces->count; i++) {
    1730          46 :                 if (os_strcmp(interfaces->iface[i]->phy, phy) == 0) {
    1731          38 :                         iface = interfaces->iface[i];
    1732          38 :                         break;
    1733             :                 }
    1734             :         }
    1735             : 
    1736          54 :         wpa_printf(MSG_INFO, "Configuration file: %s (phy %s)%s",
    1737             :                    config_fname, phy, iface ? "" : " --> new PHY");
    1738          54 :         if (iface) {
    1739             :                 struct hostapd_config *conf;
    1740             :                 struct hostapd_bss_config **tmp_conf;
    1741             :                 struct hostapd_data **tmp_bss;
    1742             :                 struct hostapd_bss_config *bss;
    1743             :                 const char *ifname;
    1744             : 
    1745             :                 /* Add new BSS to existing iface */
    1746          38 :                 conf = interfaces->config_read_cb(config_fname);
    1747          38 :                 if (conf == NULL)
    1748           1 :                         return NULL;
    1749          37 :                 if (conf->num_bss > 1) {
    1750           0 :                         wpa_printf(MSG_ERROR, "Multiple BSSes specified in BSS-config");
    1751           0 :                         hostapd_config_free(conf);
    1752           0 :                         return NULL;
    1753             :                 }
    1754             : 
    1755          37 :                 ifname = conf->bss[0]->iface;
    1756          37 :                 if (ifname[0] != '\0' && ifname_in_use(interfaces, ifname)) {
    1757           1 :                         wpa_printf(MSG_ERROR,
    1758             :                                    "Interface name %s already in use", ifname);
    1759           1 :                         hostapd_config_free(conf);
    1760           1 :                         return NULL;
    1761             :                 }
    1762             : 
    1763          72 :                 tmp_conf = os_realloc_array(
    1764          72 :                         iface->conf->bss, iface->conf->num_bss + 1,
    1765             :                         sizeof(struct hostapd_bss_config *));
    1766          36 :                 tmp_bss = os_realloc_array(iface->bss, iface->num_bss + 1,
    1767             :                                            sizeof(struct hostapd_data *));
    1768          36 :                 if (tmp_bss)
    1769          36 :                         iface->bss = tmp_bss;
    1770          36 :                 if (tmp_conf) {
    1771          36 :                         iface->conf->bss = tmp_conf;
    1772          36 :                         iface->conf->last_bss = tmp_conf[0];
    1773             :                 }
    1774          36 :                 if (tmp_bss == NULL || tmp_conf == NULL) {
    1775           0 :                         hostapd_config_free(conf);
    1776           0 :                         return NULL;
    1777             :                 }
    1778          36 :                 bss = iface->conf->bss[iface->conf->num_bss] = conf->bss[0];
    1779          36 :                 iface->conf->num_bss++;
    1780             : 
    1781          36 :                 hapd = hostapd_alloc_bss_data(iface, iface->conf, bss);
    1782          36 :                 if (hapd == NULL) {
    1783           0 :                         iface->conf->num_bss--;
    1784           0 :                         hostapd_config_free(conf);
    1785           0 :                         return NULL;
    1786             :                 }
    1787          36 :                 iface->conf->last_bss = bss;
    1788          36 :                 iface->bss[iface->num_bss] = hapd;
    1789          36 :                 hapd->msg_ctx = hapd;
    1790             : 
    1791          36 :                 bss_idx = iface->num_bss++;
    1792          36 :                 conf->num_bss--;
    1793          36 :                 conf->bss[0] = NULL;
    1794          36 :                 hostapd_config_free(conf);
    1795             :         } else {
    1796             :                 /* Add a new iface with the first BSS */
    1797          16 :                 new_iface = iface = hostapd_init(interfaces, config_fname);
    1798          16 :                 if (!iface)
    1799           3 :                         return NULL;
    1800          13 :                 os_strlcpy(iface->phy, phy, sizeof(iface->phy));
    1801          13 :                 iface->interfaces = interfaces;
    1802          13 :                 bss_idx = 0;
    1803             :         }
    1804             : 
    1805          49 :         for (k = 0; k < debug; k++) {
    1806           0 :                 if (iface->bss[bss_idx]->conf->logger_stdout_level > 0)
    1807           0 :                         iface->bss[bss_idx]->conf->logger_stdout_level--;
    1808             :         }
    1809             : 
    1810          49 :         if (iface->conf->bss[bss_idx]->iface[0] == '\0' &&
    1811           0 :             !hostapd_drv_none(iface->bss[bss_idx])) {
    1812           0 :                 wpa_printf(MSG_ERROR, "Interface name not specified in %s",
    1813             :                            config_fname);
    1814           0 :                 if (new_iface)
    1815           0 :                         hostapd_interface_deinit_free(new_iface);
    1816           0 :                 return NULL;
    1817             :         }
    1818             : 
    1819          49 :         return iface;
    1820             : }
    1821             : 
    1822             : 
    1823        1030 : void hostapd_interface_deinit_free(struct hostapd_iface *iface)
    1824             : {
    1825             :         const struct wpa_driver_ops *driver;
    1826             :         void *drv_priv;
    1827             : 
    1828        1030 :         wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
    1829        1030 :         if (iface == NULL)
    1830        1030 :                 return;
    1831        2060 :         wpa_printf(MSG_DEBUG, "%s: num_bss=%u conf->num_bss=%u",
    1832        1030 :                    __func__, (unsigned int) iface->num_bss,
    1833        1030 :                    (unsigned int) iface->conf->num_bss);
    1834        1030 :         driver = iface->bss[0]->driver;
    1835        1030 :         drv_priv = iface->bss[0]->drv_priv;
    1836        1030 :         hostapd_interface_deinit(iface);
    1837        1030 :         wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
    1838             :                    __func__, driver, drv_priv);
    1839        1030 :         if (driver && driver->hapd_deinit && drv_priv) {
    1840         878 :                 driver->hapd_deinit(drv_priv);
    1841         878 :                 iface->bss[0]->drv_priv = NULL;
    1842             :         }
    1843        1030 :         hostapd_interface_free(iface);
    1844             : }
    1845             : 
    1846             : 
    1847          81 : static void hostapd_deinit_driver(const struct wpa_driver_ops *driver,
    1848             :                                   void *drv_priv,
    1849             :                                   struct hostapd_iface *hapd_iface)
    1850             : {
    1851             :         size_t j;
    1852             : 
    1853          81 :         wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
    1854             :                    __func__, driver, drv_priv);
    1855          81 :         if (driver && driver->hapd_deinit && drv_priv) {
    1856          81 :                 driver->hapd_deinit(drv_priv);
    1857         164 :                 for (j = 0; j < hapd_iface->num_bss; j++) {
    1858          83 :                         wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p",
    1859             :                                    __func__, (int) j,
    1860          83 :                                    hapd_iface->bss[j]->drv_priv);
    1861          83 :                         if (hapd_iface->bss[j]->drv_priv == drv_priv)
    1862          81 :                                 hapd_iface->bss[j]->drv_priv = NULL;
    1863             :                 }
    1864             :         }
    1865          81 : }
    1866             : 
    1867             : 
    1868         961 : int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
    1869             : {
    1870             :         size_t j;
    1871             : 
    1872         961 :         if (hapd_iface->bss[0]->drv_priv != NULL) {
    1873           0 :                 wpa_printf(MSG_ERROR, "Interface %s already enabled",
    1874           0 :                            hapd_iface->conf->bss[0]->iface);
    1875           0 :                 return -1;
    1876             :         }
    1877             : 
    1878         961 :         wpa_printf(MSG_DEBUG, "Enable interface %s",
    1879         961 :                    hapd_iface->conf->bss[0]->iface);
    1880             : 
    1881        1929 :         for (j = 0; j < hapd_iface->num_bss; j++)
    1882         968 :                 hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
    1883         961 :         if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
    1884           8 :                 wpa_printf(MSG_INFO, "Invalid configuration - cannot enable");
    1885           8 :                 return -1;
    1886             :         }
    1887             : 
    1888        1906 :         if (hapd_iface->interfaces == NULL ||
    1889        1906 :             hapd_iface->interfaces->driver_init == NULL ||
    1890         953 :             hapd_iface->interfaces->driver_init(hapd_iface))
    1891          17 :                 return -1;
    1892             : 
    1893         936 :         if (hostapd_setup_interface(hapd_iface)) {
    1894          11 :                 hostapd_deinit_driver(hapd_iface->bss[0]->driver,
    1895          11 :                                       hapd_iface->bss[0]->drv_priv,
    1896             :                                       hapd_iface);
    1897          11 :                 return -1;
    1898             :         }
    1899             : 
    1900         925 :         return 0;
    1901             : }
    1902             : 
    1903             : 
    1904           1 : int hostapd_reload_iface(struct hostapd_iface *hapd_iface)
    1905             : {
    1906             :         size_t j;
    1907             : 
    1908           1 :         wpa_printf(MSG_DEBUG, "Reload interface %s",
    1909           1 :                    hapd_iface->conf->bss[0]->iface);
    1910           2 :         for (j = 0; j < hapd_iface->num_bss; j++)
    1911           1 :                 hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
    1912           1 :         if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
    1913           0 :                 wpa_printf(MSG_ERROR, "Updated configuration is invalid");
    1914           0 :                 return -1;
    1915             :         }
    1916           1 :         hostapd_clear_old(hapd_iface);
    1917           2 :         for (j = 0; j < hapd_iface->num_bss; j++)
    1918           1 :                 hostapd_reload_bss(hapd_iface->bss[j]);
    1919             : 
    1920           1 :         return 0;
    1921             : }
    1922             : 
    1923             : 
    1924          78 : int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
    1925             : {
    1926             :         size_t j;
    1927             :         const struct wpa_driver_ops *driver;
    1928             :         void *drv_priv;
    1929             : 
    1930          78 :         if (hapd_iface == NULL)
    1931           0 :                 return -1;
    1932             : 
    1933          78 :         if (hapd_iface->bss[0]->drv_priv == NULL) {
    1934           9 :                 wpa_printf(MSG_INFO, "Interface %s already disabled",
    1935           9 :                            hapd_iface->conf->bss[0]->iface);
    1936           9 :                 return -1;
    1937             :         }
    1938             : 
    1939          69 :         wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
    1940          69 :         driver = hapd_iface->bss[0]->driver;
    1941          69 :         drv_priv = hapd_iface->bss[0]->drv_priv;
    1942             : 
    1943          69 :         hapd_iface->driver_ap_teardown =
    1944          69 :                 !!(hapd_iface->drv_flags &
    1945             :                    WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
    1946             : 
    1947             :         /* same as hostapd_interface_deinit without deinitializing ctrl-iface */
    1948         140 :         for (j = 0; j < hapd_iface->num_bss; j++) {
    1949          71 :                 struct hostapd_data *hapd = hapd_iface->bss[j];
    1950          71 :                 hostapd_bss_deinit_no_free(hapd);
    1951          71 :                 hostapd_free_hapd_data(hapd);
    1952             :         }
    1953             : 
    1954          69 :         hostapd_deinit_driver(driver, drv_priv, hapd_iface);
    1955             : 
    1956             :         /* From hostapd_cleanup_iface: These were initialized in
    1957             :          * hostapd_setup_interface and hostapd_setup_interface_complete
    1958             :          */
    1959          69 :         hostapd_cleanup_iface_partial(hapd_iface);
    1960             : 
    1961          69 :         wpa_printf(MSG_DEBUG, "Interface %s disabled",
    1962          69 :                    hapd_iface->bss[0]->conf->iface);
    1963          69 :         hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED);
    1964          69 :         return 0;
    1965             : }
    1966             : 
    1967             : 
    1968             : static struct hostapd_iface *
    1969        1046 : hostapd_iface_alloc(struct hapd_interfaces *interfaces)
    1970             : {
    1971             :         struct hostapd_iface **iface, *hapd_iface;
    1972             : 
    1973        1046 :         iface = os_realloc_array(interfaces->iface, interfaces->count + 1,
    1974             :                                  sizeof(struct hostapd_iface *));
    1975        1046 :         if (iface == NULL)
    1976           4 :                 return NULL;
    1977        1042 :         interfaces->iface = iface;
    1978        2084 :         hapd_iface = interfaces->iface[interfaces->count] =
    1979        1042 :                 os_zalloc(sizeof(*hapd_iface));
    1980        1042 :         if (hapd_iface == NULL) {
    1981           4 :                 wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
    1982             :                            "the interface", __func__);
    1983           4 :                 return NULL;
    1984             :         }
    1985        1038 :         interfaces->count++;
    1986        1038 :         hapd_iface->interfaces = interfaces;
    1987             : 
    1988        1038 :         return hapd_iface;
    1989             : }
    1990             : 
    1991             : 
    1992             : static struct hostapd_config *
    1993        1035 : hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
    1994             :                      const char *ctrl_iface)
    1995             : {
    1996             :         struct hostapd_bss_config *bss;
    1997             :         struct hostapd_config *conf;
    1998             : 
    1999             :         /* Allocates memory for bss and conf */
    2000        1035 :         conf = hostapd_config_defaults();
    2001        1035 :         if (conf == NULL) {
    2002          17 :                  wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
    2003             :                                 "configuration", __func__);
    2004          17 :                 return NULL;
    2005             :         }
    2006             : 
    2007        1018 :         conf->driver = wpa_drivers[0];
    2008        1018 :         if (conf->driver == NULL) {
    2009           0 :                 wpa_printf(MSG_ERROR, "No driver wrappers registered!");
    2010           0 :                 hostapd_config_free(conf);
    2011           0 :                 return NULL;
    2012             :         }
    2013             : 
    2014        1018 :         bss = conf->last_bss = conf->bss[0];
    2015             : 
    2016        1018 :         os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
    2017        1018 :         bss->ctrl_interface = os_strdup(ctrl_iface);
    2018        1018 :         if (bss->ctrl_interface == NULL) {
    2019           3 :                 hostapd_config_free(conf);
    2020           3 :                 return NULL;
    2021             :         }
    2022             : 
    2023             :         /* Reading configuration file skipped, will be done in SET!
    2024             :          * From reading the configuration till the end has to be done in
    2025             :          * SET
    2026             :          */
    2027        1015 :         return conf;
    2028             : }
    2029             : 
    2030             : 
    2031        1018 : static int hostapd_data_alloc(struct hostapd_iface *hapd_iface,
    2032             :                               struct hostapd_config *conf)
    2033             : {
    2034             :         size_t i;
    2035             :         struct hostapd_data *hapd;
    2036             : 
    2037        1018 :         hapd_iface->bss = os_calloc(conf->num_bss,
    2038             :                                     sizeof(struct hostapd_data *));
    2039        1018 :         if (hapd_iface->bss == NULL)
    2040           3 :                 return -1;
    2041             : 
    2042        2032 :         for (i = 0; i < conf->num_bss; i++) {
    2043        2042 :                 hapd = hapd_iface->bss[i] =
    2044        1021 :                         hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]);
    2045        1021 :                 if (hapd == NULL) {
    2046           8 :                         while (i > 0) {
    2047           0 :                                 i--;
    2048           0 :                                 os_free(hapd_iface->bss[i]);
    2049           0 :                                 hapd_iface->bss[i] = NULL;
    2050             :                         }
    2051           4 :                         os_free(hapd_iface->bss);
    2052           4 :                         hapd_iface->bss = NULL;
    2053           4 :                         return -1;
    2054             :                 }
    2055        1017 :                 hapd->msg_ctx = hapd;
    2056             :         }
    2057             : 
    2058        1011 :         hapd_iface->conf = conf;
    2059        1011 :         hapd_iface->num_bss = conf->num_bss;
    2060             : 
    2061        1011 :         return 0;
    2062             : }
    2063             : 
    2064             : 
    2065        1100 : int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
    2066             : {
    2067        1100 :         struct hostapd_config *conf = NULL;
    2068        1100 :         struct hostapd_iface *hapd_iface = NULL, *new_iface = NULL;
    2069             :         struct hostapd_data *hapd;
    2070             :         char *ptr;
    2071             :         size_t i, j;
    2072        1100 :         const char *conf_file = NULL, *phy_name = NULL;
    2073             : 
    2074        1100 :         if (os_strncmp(buf, "bss_config=", 11) == 0) {
    2075             :                 char *pos;
    2076          54 :                 phy_name = buf + 11;
    2077          54 :                 pos = os_strchr(phy_name, ':');
    2078          54 :                 if (!pos)
    2079           0 :                         return -1;
    2080          54 :                 *pos++ = '\0';
    2081          54 :                 conf_file = pos;
    2082          54 :                 if (!os_strlen(conf_file))
    2083           0 :                         return -1;
    2084             : 
    2085          54 :                 hapd_iface = hostapd_interface_init_bss(interfaces, phy_name,
    2086             :                                                         conf_file, 0);
    2087          54 :                 if (!hapd_iface)
    2088           5 :                         return -1;
    2089          53 :                 for (j = 0; j < interfaces->count; j++) {
    2090          40 :                         if (interfaces->iface[j] == hapd_iface)
    2091          36 :                                 break;
    2092             :                 }
    2093          49 :                 if (j == interfaces->count) {
    2094             :                         struct hostapd_iface **tmp;
    2095          13 :                         tmp = os_realloc_array(interfaces->iface,
    2096          13 :                                                interfaces->count + 1,
    2097             :                                                sizeof(struct hostapd_iface *));
    2098          13 :                         if (!tmp) {
    2099           0 :                                 hostapd_interface_deinit_free(hapd_iface);
    2100           0 :                                 return -1;
    2101             :                         }
    2102          13 :                         interfaces->iface = tmp;
    2103          13 :                         interfaces->iface[interfaces->count++] = hapd_iface;
    2104          13 :                         new_iface = hapd_iface;
    2105             :                 }
    2106             : 
    2107          49 :                 if (new_iface) {
    2108          13 :                         if (interfaces->driver_init(hapd_iface))
    2109           0 :                                 goto fail;
    2110             : 
    2111          13 :                         if (hostapd_setup_interface(hapd_iface)) {
    2112           2 :                                 hostapd_deinit_driver(
    2113           1 :                                         hapd_iface->bss[0]->driver,
    2114           1 :                                         hapd_iface->bss[0]->drv_priv,
    2115             :                                         hapd_iface);
    2116           1 :                                 goto fail;
    2117             :                         }
    2118             :                 } else {
    2119             :                         /* Assign new BSS with bss[0]'s driver info */
    2120          36 :                         hapd = hapd_iface->bss[hapd_iface->num_bss - 1];
    2121          36 :                         hapd->driver = hapd_iface->bss[0]->driver;
    2122          36 :                         hapd->drv_priv = hapd_iface->bss[0]->drv_priv;
    2123          36 :                         os_memcpy(hapd->own_addr, hapd_iface->bss[0]->own_addr,
    2124             :                                   ETH_ALEN);
    2125             : 
    2126          72 :                         if (start_ctrl_iface_bss(hapd) < 0 ||
    2127          69 :                             (hapd_iface->state == HAPD_IFACE_ENABLED &&
    2128          33 :                              hostapd_setup_bss(hapd, -1))) {
    2129           1 :                                 hostapd_cleanup(hapd);
    2130           1 :                                 hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
    2131           1 :                                 hapd_iface->conf->num_bss--;
    2132           1 :                                 hapd_iface->num_bss--;
    2133           1 :                                 wpa_printf(MSG_DEBUG, "%s: free hapd %p %s",
    2134           1 :                                            __func__, hapd, hapd->conf->iface);
    2135           1 :                                 hostapd_config_free_bss(hapd->conf);
    2136           1 :                                 hapd->conf = NULL;
    2137           1 :                                 os_free(hapd);
    2138           1 :                                 return -1;
    2139             :                         }
    2140             :                 }
    2141          47 :                 return 0;
    2142             :         }
    2143             : 
    2144        1046 :         ptr = os_strchr(buf, ' ');
    2145        1046 :         if (ptr == NULL)
    2146           0 :                 return -1;
    2147        1046 :         *ptr++ = '\0';
    2148             : 
    2149        1046 :         if (os_strncmp(ptr, "config=", 7) == 0)
    2150           3 :                 conf_file = ptr + 7;
    2151             : 
    2152        1321 :         for (i = 0; i < interfaces->count; i++) {
    2153         275 :                 if (!os_strcmp(interfaces->iface[i]->conf->bss[0]->iface,
    2154             :                                buf)) {
    2155           0 :                         wpa_printf(MSG_INFO, "Cannot add interface - it "
    2156             :                                    "already exists");
    2157           0 :                         return -1;
    2158             :                 }
    2159             :         }
    2160             : 
    2161        1046 :         hapd_iface = hostapd_iface_alloc(interfaces);
    2162        1046 :         if (hapd_iface == NULL) {
    2163           8 :                 wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
    2164             :                            "for interface", __func__);
    2165           8 :                 goto fail;
    2166             :         }
    2167        1038 :         new_iface = hapd_iface;
    2168             : 
    2169        1038 :         if (conf_file && interfaces->config_read_cb) {
    2170           3 :                 conf = interfaces->config_read_cb(conf_file);
    2171           6 :                 if (conf && conf->bss)
    2172           3 :                         os_strlcpy(conf->bss[0]->iface, buf,
    2173             :                                    sizeof(conf->bss[0]->iface));
    2174             :         } else
    2175        1035 :                 conf = hostapd_config_alloc(interfaces, buf, ptr);
    2176        1038 :         if (conf == NULL || conf->bss == NULL) {
    2177          20 :                 wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
    2178             :                            "for configuration", __func__);
    2179          20 :                 goto fail;
    2180             :         }
    2181             : 
    2182        1018 :         if (hostapd_data_alloc(hapd_iface, conf) < 0) {
    2183           7 :                 wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
    2184             :                            "for hostapd", __func__);
    2185           7 :                 goto fail;
    2186             :         }
    2187        1011 :         conf = NULL;
    2188             : 
    2189        1011 :         if (start_ctrl_iface(hapd_iface) < 0)
    2190           3 :                 goto fail;
    2191             : 
    2192        1008 :         wpa_printf(MSG_INFO, "Add interface '%s'",
    2193        1008 :                    hapd_iface->conf->bss[0]->iface);
    2194             : 
    2195        1008 :         return 0;
    2196             : 
    2197             : fail:
    2198          39 :         if (conf)
    2199           7 :                 hostapd_config_free(conf);
    2200          39 :         if (hapd_iface) {
    2201          31 :                 if (hapd_iface->bss) {
    2202           8 :                         for (i = 0; i < hapd_iface->num_bss; i++) {
    2203           4 :                                 hapd = hapd_iface->bss[i];
    2204           4 :                                 if (!hapd)
    2205           0 :                                         continue;
    2206           8 :                                 if (hapd_iface->interfaces &&
    2207           4 :                                     hapd_iface->interfaces->ctrl_iface_deinit)
    2208           4 :                                         hapd_iface->interfaces->
    2209           4 :                                                 ctrl_iface_deinit(hapd);
    2210           4 :                                 wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
    2211           4 :                                            __func__, hapd_iface->bss[i],
    2212           4 :                                            hapd->conf->iface);
    2213           4 :                                 hostapd_cleanup(hapd);
    2214           4 :                                 os_free(hapd);
    2215           4 :                                 hapd_iface->bss[i] = NULL;
    2216             :                         }
    2217           4 :                         os_free(hapd_iface->bss);
    2218           4 :                         hapd_iface->bss = NULL;
    2219             :                 }
    2220          31 :                 if (new_iface) {
    2221          31 :                         interfaces->count--;
    2222          31 :                         interfaces->iface[interfaces->count] = NULL;
    2223             :                 }
    2224          31 :                 hostapd_cleanup_iface(hapd_iface);
    2225             :         }
    2226          39 :         return -1;
    2227             : }
    2228             : 
    2229             : 
    2230          38 : static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx)
    2231             : {
    2232             :         size_t i;
    2233             : 
    2234          38 :         wpa_printf(MSG_INFO, "Remove BSS '%s'", iface->conf->bss[idx]->iface);
    2235             : 
    2236             :         /* Remove hostapd_data only if it has already been initialized */
    2237          38 :         if (idx < iface->num_bss) {
    2238          36 :                 struct hostapd_data *hapd = iface->bss[idx];
    2239             : 
    2240          36 :                 hostapd_bss_deinit(hapd);
    2241          36 :                 wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
    2242          36 :                            __func__, hapd, hapd->conf->iface);
    2243          36 :                 hostapd_config_free_bss(hapd->conf);
    2244          36 :                 hapd->conf = NULL;
    2245          36 :                 os_free(hapd);
    2246             : 
    2247          36 :                 iface->num_bss--;
    2248             : 
    2249         159 :                 for (i = idx; i < iface->num_bss; i++)
    2250         123 :                         iface->bss[i] = iface->bss[i + 1];
    2251             :         } else {
    2252           2 :                 hostapd_config_free_bss(iface->conf->bss[idx]);
    2253           2 :                 iface->conf->bss[idx] = NULL;
    2254             :         }
    2255             : 
    2256          38 :         iface->conf->num_bss--;
    2257         161 :         for (i = idx; i < iface->conf->num_bss; i++)
    2258         123 :                 iface->conf->bss[i] = iface->conf->bss[i + 1];
    2259             : 
    2260          38 :         return 0;
    2261             : }
    2262             : 
    2263             : 
    2264        5405 : int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
    2265             : {
    2266             :         struct hostapd_iface *hapd_iface;
    2267        5405 :         size_t i, j, k = 0;
    2268             : 
    2269        7388 :         for (i = 0; i < interfaces->count; i++) {
    2270        3041 :                 hapd_iface = interfaces->iface[i];
    2271        3041 :                 if (hapd_iface == NULL)
    2272           0 :                         return -1;
    2273        3041 :                 if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
    2274        1020 :                         wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
    2275        1020 :                         hapd_iface->driver_ap_teardown =
    2276        1020 :                                 !!(hapd_iface->drv_flags &
    2277             :                                    WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
    2278             : 
    2279        1020 :                         hostapd_interface_deinit_free(hapd_iface);
    2280        1020 :                         k = i;
    2281        2126 :                         while (k < (interfaces->count - 1)) {
    2282         172 :                                 interfaces->iface[k] =
    2283          86 :                                         interfaces->iface[k + 1];
    2284          86 :                                 k++;
    2285             :                         }
    2286        1020 :                         interfaces->count--;
    2287        1020 :                         return 0;
    2288             :                 }
    2289             : 
    2290        4051 :                 for (j = 0; j < hapd_iface->conf->num_bss; j++) {
    2291        2068 :                         if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf)) {
    2292          38 :                                 hapd_iface->driver_ap_teardown =
    2293          38 :                                         !(hapd_iface->drv_flags &
    2294             :                                           WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
    2295          38 :                                 return hostapd_remove_bss(hapd_iface, j);
    2296             :                         }
    2297             :                 }
    2298             :         }
    2299        4347 :         return -1;
    2300             : }
    2301             : 
    2302             : 
    2303             : /**
    2304             :  * hostapd_new_assoc_sta - Notify that a new station associated with the AP
    2305             :  * @hapd: Pointer to BSS data
    2306             :  * @sta: Pointer to the associated STA data
    2307             :  * @reassoc: 1 to indicate this was a re-association; 0 = first association
    2308             :  *
    2309             :  * This function will be called whenever a station associates with the AP. It
    2310             :  * can be called from ieee802_11.c for drivers that export MLME to hostapd and
    2311             :  * from drv_callbacks.c based on driver events for drivers that take care of
    2312             :  * management frames (IEEE 802.11 authentication and association) internally.
    2313             :  */
    2314        2462 : void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
    2315             :                            int reassoc)
    2316             : {
    2317        2462 :         if (hapd->tkip_countermeasures) {
    2318           0 :                 hostapd_drv_sta_deauth(hapd, sta->addr,
    2319             :                                        WLAN_REASON_MICHAEL_MIC_FAILURE);
    2320        2462 :                 return;
    2321             :         }
    2322             : 
    2323        2462 :         hostapd_prune_associations(hapd, sta->addr);
    2324             : 
    2325             :         /* IEEE 802.11F (IAPP) */
    2326        2462 :         if (hapd->conf->ieee802_11f)
    2327           0 :                 iapp_new_station(hapd->iapp, sta);
    2328             : 
    2329             : #ifdef CONFIG_P2P
    2330         390 :         if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
    2331          29 :                 sta->no_p2p_set = 1;
    2332          29 :                 hapd->num_sta_no_p2p++;
    2333          29 :                 if (hapd->num_sta_no_p2p == 1)
    2334          25 :                         hostapd_p2p_non_p2p_sta_connected(hapd);
    2335             :         }
    2336             : #endif /* CONFIG_P2P */
    2337             : 
    2338             :         /* Start accounting here, if IEEE 802.1X and WPA are not used.
    2339             :          * IEEE 802.1X/WPA code will start accounting after the station has
    2340             :          * been authorized. */
    2341        2462 :         if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) {
    2342         333 :                 ap_sta_set_authorized(hapd, sta, 1);
    2343         333 :                 os_get_reltime(&sta->connected_time);
    2344         333 :                 accounting_sta_start(hapd, sta);
    2345             :         }
    2346             : 
    2347             :         /* Start IEEE 802.1X authentication process for new stations */
    2348        2462 :         ieee802_1x_new_station(hapd, sta);
    2349        2462 :         if (reassoc) {
    2350          12 :                 if (sta->auth_alg != WLAN_AUTH_FT &&
    2351           6 :                     !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
    2352           6 :                         wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
    2353             :         } else
    2354        2456 :                 wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
    2355             : 
    2356        2462 :         if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
    2357       17234 :                 wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
    2358             :                            "for " MACSTR " (%d seconds - ap_max_inactivity)",
    2359       14772 :                            __func__, MAC2STR(sta->addr),
    2360        2462 :                            hapd->conf->ap_max_inactivity);
    2361        2462 :                 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
    2362        2462 :                 eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
    2363             :                                        ap_handle_timer, hapd, sta);
    2364             :         }
    2365             : }
    2366             : 
    2367             : 
    2368        3154 : const char * hostapd_state_text(enum hostapd_iface_state s)
    2369             : {
    2370        3154 :         switch (s) {
    2371             :         case HAPD_IFACE_UNINITIALIZED:
    2372        1212 :                 return "UNINITIALIZED";
    2373             :         case HAPD_IFACE_DISABLED:
    2374         102 :                 return "DISABLED";
    2375             :         case HAPD_IFACE_COUNTRY_UPDATE:
    2376          80 :                 return "COUNTRY_UPDATE";
    2377             :         case HAPD_IFACE_ACS:
    2378          22 :                 return "ACS";
    2379             :         case HAPD_IFACE_HT_SCAN:
    2380          90 :                 return "HT_SCAN";
    2381             :         case HAPD_IFACE_DFS:
    2382          34 :                 return "DFS";
    2383             :         case HAPD_IFACE_ENABLED:
    2384        1614 :                 return "ENABLED";
    2385             :         }
    2386             : 
    2387           0 :         return "UNKNOWN";
    2388             : }
    2389             : 
    2390             : 
    2391        1392 : void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s)
    2392             : {
    2393        2784 :         wpa_printf(MSG_INFO, "%s: interface state %s->%s",
    2394        1392 :                    iface->conf->bss[0]->iface, hostapd_state_text(iface->state),
    2395             :                    hostapd_state_text(s));
    2396        1392 :         iface->state = s;
    2397        1392 : }
    2398             : 
    2399             : 
    2400             : #ifdef NEED_AP_MLME
    2401             : 
    2402          46 : static void free_beacon_data(struct beacon_data *beacon)
    2403             : {
    2404          46 :         os_free(beacon->head);
    2405          46 :         beacon->head = NULL;
    2406          46 :         os_free(beacon->tail);
    2407          46 :         beacon->tail = NULL;
    2408          46 :         os_free(beacon->probe_resp);
    2409          46 :         beacon->probe_resp = NULL;
    2410          46 :         os_free(beacon->beacon_ies);
    2411          46 :         beacon->beacon_ies = NULL;
    2412          46 :         os_free(beacon->proberesp_ies);
    2413          46 :         beacon->proberesp_ies = NULL;
    2414          46 :         os_free(beacon->assocresp_ies);
    2415          46 :         beacon->assocresp_ies = NULL;
    2416          46 : }
    2417             : 
    2418             : 
    2419          46 : static int hostapd_build_beacon_data(struct hostapd_data *hapd,
    2420             :                                      struct beacon_data *beacon)
    2421             : {
    2422             :         struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra;
    2423             :         struct wpa_driver_ap_params params;
    2424             :         int ret;
    2425             : 
    2426          46 :         os_memset(beacon, 0, sizeof(*beacon));
    2427          46 :         ret = ieee802_11_build_ap_params(hapd, &params);
    2428          46 :         if (ret < 0)
    2429           0 :                 return ret;
    2430             : 
    2431          46 :         ret = hostapd_build_ap_extra_ies(hapd, &beacon_extra,
    2432             :                                          &proberesp_extra,
    2433             :                                          &assocresp_extra);
    2434          46 :         if (ret)
    2435           0 :                 goto free_ap_params;
    2436             : 
    2437          46 :         ret = -1;
    2438          46 :         beacon->head = os_malloc(params.head_len);
    2439          46 :         if (!beacon->head)
    2440           0 :                 goto free_ap_extra_ies;
    2441             : 
    2442          46 :         os_memcpy(beacon->head, params.head, params.head_len);
    2443          46 :         beacon->head_len = params.head_len;
    2444             : 
    2445          46 :         beacon->tail = os_malloc(params.tail_len);
    2446          46 :         if (!beacon->tail)
    2447           0 :                 goto free_beacon;
    2448             : 
    2449          46 :         os_memcpy(beacon->tail, params.tail, params.tail_len);
    2450          46 :         beacon->tail_len = params.tail_len;
    2451             : 
    2452          46 :         if (params.proberesp != NULL) {
    2453           0 :                 beacon->probe_resp = os_malloc(params.proberesp_len);
    2454           0 :                 if (!beacon->probe_resp)
    2455           0 :                         goto free_beacon;
    2456             : 
    2457           0 :                 os_memcpy(beacon->probe_resp, params.proberesp,
    2458             :                           params.proberesp_len);
    2459           0 :                 beacon->probe_resp_len = params.proberesp_len;
    2460             :         }
    2461             : 
    2462             :         /* copy the extra ies */
    2463          46 :         if (beacon_extra) {
    2464          46 :                 beacon->beacon_ies = os_malloc(wpabuf_len(beacon_extra));
    2465          46 :                 if (!beacon->beacon_ies)
    2466           0 :                         goto free_beacon;
    2467             : 
    2468          46 :                 os_memcpy(beacon->beacon_ies,
    2469             :                           beacon_extra->buf, wpabuf_len(beacon_extra));
    2470          46 :                 beacon->beacon_ies_len = wpabuf_len(beacon_extra);
    2471             :         }
    2472             : 
    2473          46 :         if (proberesp_extra) {
    2474          46 :                 beacon->proberesp_ies =
    2475          46 :                         os_malloc(wpabuf_len(proberesp_extra));
    2476          46 :                 if (!beacon->proberesp_ies)
    2477           0 :                         goto free_beacon;
    2478             : 
    2479          46 :                 os_memcpy(beacon->proberesp_ies, proberesp_extra->buf,
    2480             :                           wpabuf_len(proberesp_extra));
    2481          46 :                 beacon->proberesp_ies_len = wpabuf_len(proberesp_extra);
    2482             :         }
    2483             : 
    2484          46 :         if (assocresp_extra) {
    2485          46 :                 beacon->assocresp_ies =
    2486          46 :                         os_malloc(wpabuf_len(assocresp_extra));
    2487          46 :                 if (!beacon->assocresp_ies)
    2488           0 :                         goto free_beacon;
    2489             : 
    2490          46 :                 os_memcpy(beacon->assocresp_ies, assocresp_extra->buf,
    2491             :                           wpabuf_len(assocresp_extra));
    2492          46 :                 beacon->assocresp_ies_len = wpabuf_len(assocresp_extra);
    2493             :         }
    2494             : 
    2495          46 :         ret = 0;
    2496             : free_beacon:
    2497             :         /* if the function fails, the caller should not free beacon data */
    2498          46 :         if (ret)
    2499           0 :                 free_beacon_data(beacon);
    2500             : 
    2501             : free_ap_extra_ies:
    2502          46 :         hostapd_free_ap_extra_ies(hapd, beacon_extra, proberesp_extra,
    2503             :                                   assocresp_extra);
    2504             : free_ap_params:
    2505          46 :         ieee802_11_free_ap_params(&params);
    2506          46 :         return ret;
    2507             : }
    2508             : 
    2509             : 
    2510             : /*
    2511             :  * TODO: This flow currently supports only changing frequency within the
    2512             :  * same hw_mode. Any other changes to MAC parameters or provided settings (even
    2513             :  * width) are not supported.
    2514             :  */
    2515          46 : static int hostapd_change_config_freq(struct hostapd_data *hapd,
    2516             :                                       struct hostapd_config *conf,
    2517             :                                       struct hostapd_freq_params *params,
    2518             :                                       struct hostapd_freq_params *old_params)
    2519             : {
    2520             :         int channel;
    2521             : 
    2522          46 :         if (!params->channel) {
    2523             :                 /* check if the new channel is supported by hw */
    2524          21 :                 params->channel = hostapd_hw_get_channel(hapd, params->freq);
    2525             :         }
    2526             : 
    2527          46 :         channel = params->channel;
    2528          46 :         if (!channel)
    2529           0 :                 return -1;
    2530             : 
    2531             :         /* if a pointer to old_params is provided we save previous state */
    2532          46 :         if (old_params) {
    2533          23 :                 old_params->channel = conf->channel;
    2534          23 :                 old_params->ht_enabled = conf->ieee80211n;
    2535          23 :                 old_params->sec_channel_offset = conf->secondary_channel;
    2536             :         }
    2537             : 
    2538          46 :         conf->channel = channel;
    2539          46 :         conf->ieee80211n = params->ht_enabled;
    2540          46 :         conf->secondary_channel = params->sec_channel_offset;
    2541             : 
    2542             :         /* TODO: maybe call here hostapd_config_check here? */
    2543             : 
    2544          46 :         return 0;
    2545             : }
    2546             : 
    2547             : 
    2548          23 : static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
    2549             :                                      struct csa_settings *settings)
    2550             : {
    2551          23 :         struct hostapd_iface *iface = hapd->iface;
    2552             :         struct hostapd_freq_params old_freq;
    2553             :         int ret;
    2554             : 
    2555          23 :         os_memset(&old_freq, 0, sizeof(old_freq));
    2556          23 :         if (!iface || !iface->freq || hapd->csa_in_progress)
    2557           0 :                 return -1;
    2558             : 
    2559          23 :         ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
    2560             :                                          &settings->freq_params,
    2561             :                                          &old_freq);
    2562          23 :         if (ret)
    2563           0 :                 return ret;
    2564             : 
    2565          23 :         ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
    2566             : 
    2567             :         /* change back the configuration */
    2568          23 :         hostapd_change_config_freq(iface->bss[0], iface->conf,
    2569             :                                    &old_freq, NULL);
    2570             : 
    2571          23 :         if (ret)
    2572           0 :                 return ret;
    2573             : 
    2574             :         /* set channel switch parameters for csa ie */
    2575          23 :         hapd->cs_freq_params = settings->freq_params;
    2576          23 :         hapd->cs_count = settings->cs_count;
    2577          23 :         hapd->cs_block_tx = settings->block_tx;
    2578             : 
    2579          23 :         ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa);
    2580          23 :         if (ret) {
    2581           0 :                 free_beacon_data(&settings->beacon_after);
    2582           0 :                 return ret;
    2583             :         }
    2584             : 
    2585          23 :         settings->counter_offset_beacon = hapd->cs_c_off_beacon;
    2586          23 :         settings->counter_offset_presp = hapd->cs_c_off_proberesp;
    2587             : 
    2588          23 :         return 0;
    2589             : }
    2590             : 
    2591             : 
    2592          23 : void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
    2593             : {
    2594          23 :         os_memset(&hapd->cs_freq_params, 0, sizeof(hapd->cs_freq_params));
    2595          23 :         hapd->cs_count = 0;
    2596          23 :         hapd->cs_block_tx = 0;
    2597          23 :         hapd->cs_c_off_beacon = 0;
    2598          23 :         hapd->cs_c_off_proberesp = 0;
    2599          23 :         hapd->csa_in_progress = 0;
    2600          23 : }
    2601             : 
    2602             : 
    2603          23 : int hostapd_switch_channel(struct hostapd_data *hapd,
    2604             :                            struct csa_settings *settings)
    2605             : {
    2606             :         int ret;
    2607             : 
    2608          23 :         if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) {
    2609           0 :                 wpa_printf(MSG_INFO, "CSA is not supported");
    2610           0 :                 return -1;
    2611             :         }
    2612             : 
    2613          23 :         ret = hostapd_fill_csa_settings(hapd, settings);
    2614          23 :         if (ret)
    2615           0 :                 return ret;
    2616             : 
    2617          23 :         ret = hostapd_drv_switch_channel(hapd, settings);
    2618          23 :         free_beacon_data(&settings->beacon_csa);
    2619          23 :         free_beacon_data(&settings->beacon_after);
    2620             : 
    2621          23 :         if (ret) {
    2622             :                 /* if we failed, clean cs parameters */
    2623           2 :                 hostapd_cleanup_cs_params(hapd);
    2624           2 :                 return ret;
    2625             :         }
    2626             : 
    2627          21 :         hapd->csa_in_progress = 1;
    2628          21 :         return 0;
    2629             : }
    2630             : 
    2631             : 
    2632             : void
    2633           0 : hostapd_switch_channel_fallback(struct hostapd_iface *iface,
    2634             :                                 const struct hostapd_freq_params *freq_params)
    2635             : {
    2636           0 :         int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT;
    2637             :         unsigned int i;
    2638             : 
    2639           0 :         wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes");
    2640             : 
    2641           0 :         if (freq_params->center_freq1)
    2642           0 :                 vht_seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5;
    2643           0 :         if (freq_params->center_freq2)
    2644           0 :                 vht_seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5;
    2645             : 
    2646           0 :         switch (freq_params->bandwidth) {
    2647             :         case 0:
    2648             :         case 20:
    2649             :         case 40:
    2650           0 :                 vht_bw = VHT_CHANWIDTH_USE_HT;
    2651           0 :                 break;
    2652             :         case 80:
    2653           0 :                 if (freq_params->center_freq2)
    2654           0 :                         vht_bw = VHT_CHANWIDTH_80P80MHZ;
    2655             :                 else
    2656           0 :                         vht_bw = VHT_CHANWIDTH_80MHZ;
    2657           0 :                 break;
    2658             :         case 160:
    2659           0 :                 vht_bw = VHT_CHANWIDTH_160MHZ;
    2660           0 :                 break;
    2661             :         default:
    2662           0 :                 wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
    2663             :                            freq_params->bandwidth);
    2664           0 :                 break;
    2665             :         }
    2666             : 
    2667           0 :         iface->freq = freq_params->freq;
    2668           0 :         iface->conf->channel = freq_params->channel;
    2669           0 :         iface->conf->secondary_channel = freq_params->sec_channel_offset;
    2670           0 :         iface->conf->vht_oper_centr_freq_seg0_idx = vht_seg0_idx;
    2671           0 :         iface->conf->vht_oper_centr_freq_seg1_idx = vht_seg1_idx;
    2672           0 :         iface->conf->vht_oper_chwidth = vht_bw;
    2673           0 :         iface->conf->ieee80211n = freq_params->ht_enabled;
    2674           0 :         iface->conf->ieee80211ac = freq_params->vht_enabled;
    2675             : 
    2676             :         /*
    2677             :          * cs_params must not be cleared earlier because the freq_params
    2678             :          * argument may actually point to one of these.
    2679             :          */
    2680           0 :         for (i = 0; i < iface->num_bss; i++)
    2681           0 :                 hostapd_cleanup_cs_params(iface->bss[i]);
    2682             : 
    2683           0 :         hostapd_disable_iface(iface);
    2684           0 :         hostapd_enable_iface(iface);
    2685           0 : }
    2686             : 
    2687             : #endif /* NEED_AP_MLME */

Generated by: LCOV version 1.10