LCOV - code coverage report
Current view: top level - src/ap - hostapd.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 1371 1677 81.8 %
Date: 2016-10-02 Functions: 76 79 96.2 %

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

Generated by: LCOV version 1.10