LCOV - code coverage report
Current view: top level - src/ap - hostapd.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1388338050 Lines: 650 1135 57.3 %
Date: 2013-12-29 Functions: 44 57 77.2 %
Branches: 316 668 47.3 %

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

Generated by: LCOV version 1.9