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

Generated by: LCOV version 1.10