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 1393793999 Lines: 832 1167 71.3 %
Date: 2014-03-02 Functions: 53 57 93.0 %
Branches: 417 708 58.9 %

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

Generated by: LCOV version 1.9