LCOV - code coverage report
Current view: top level - src/ap - hostapd.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1388943092 Lines: 654 1133 57.7 %
Date: 2014-01-05 Functions: 44 57 77.2 %
Branches: 319 668 47.8 %

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

Generated by: LCOV version 1.9