#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
+#include "common/hw_features_common.h"
#include "radius/radius_client.h"
#include "radius/radius_das.h"
#include "eap_server/tncs.h"
#include "x_snoop.h"
#include "dhcp_snoop.h"
#include "ndisc_snoop.h"
+#include "neighbor_db.h"
+#include "rrm.h"
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
- char *ifname)
+ const char *ifname)
{
int i;
+ if (!ifname)
+ return;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
0, NULL, 0, NULL, 0)) {
wpabuf_free(hapd->mesh_pending_auth);
hapd->mesh_pending_auth = NULL;
#endif /* CONFIG_MESH */
+
+ hostapd_clean_rrm(hapd);
}
list))) {
dl_list_del(&info->list);
iface->num_sta_seen--;
- os_free(info);
+ sta_track_del(info);
}
}
if (hostapd_drv_none(hapd))
return 0;
+ if (iface->conf->use_driver_iface_addr)
+ return 0;
+
/* Generate BSSID mask that is large enough to cover the BSSIDs. */
/* Determine the bits necessary to cover the number of BSSIDs. */
/* Determine the bits necessary to any configured BSSIDs,
if they are higher than the number of BSSIDs. */
for (j = 0; j < iface->conf->num_bss; j++) {
- if (hostapd_mac_comp_empty(iface->conf->bss[j]->bssid) == 0) {
+ if (is_zero_ether_addr(iface->conf->bss[j]->bssid)) {
if (j)
auto_addr++;
continue;
if (attr->acct_session_id) {
num_attr++;
- if (attr->acct_session_id_len != 17) {
+ if (attr->acct_session_id_len != 16) {
wpa_printf(MSG_DEBUG,
"RADIUS DAS: Acct-Session-Id cannot match");
return NULL;
for (sta = hapd->sta_list; sta; sta = sta->next) {
if (!sta->radius_das_match)
continue;
- os_snprintf(buf, sizeof(buf), "%08X-%08X",
- sta->acct_session_id_hi,
- sta->acct_session_id_lo);
- if (os_memcmp(attr->acct_session_id, buf, 17) != 0)
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long) sta->acct_session_id);
+ if (os_memcmp(attr->acct_session_id, buf, 16) != 0)
sta->radius_das_match = 0;
else
count++;
if (attr->acct_multi_session_id) {
num_attr++;
- if (attr->acct_multi_session_id_len != 17) {
+ if (attr->acct_multi_session_id_len != 16) {
wpa_printf(MSG_DEBUG,
"RADIUS DAS: Acct-Multi-Session-Id cannot match");
return NULL;
if (!sta->radius_das_match)
continue;
if (!sta->eapol_sm ||
- !sta->eapol_sm->acct_multi_session_id_hi) {
+ !sta->eapol_sm->acct_multi_session_id) {
sta->radius_das_match = 0;
continue;
}
- os_snprintf(buf, sizeof(buf), "%08X+%08X",
- sta->eapol_sm->acct_multi_session_id_hi,
- sta->eapol_sm->acct_multi_session_id_lo);
- if (os_memcmp(attr->acct_multi_session_id, buf, 17) !=
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long)
+ sta->eapol_sm->acct_multi_session_id);
+ if (os_memcmp(attr->acct_multi_session_id, buf, 16) !=
0)
sta->radius_das_match = 0;
else
hapd->started = 1;
if (!first || first == -1) {
- if (hostapd_mac_comp_empty(conf->bssid) == 0) {
- /* Allocate the next available BSSID. */
- do {
- inc_byte_array(hapd->own_addr, ETH_ALEN);
- } while (mac_in_conf(hapd->iconf, hapd->own_addr));
- } else {
+ u8 *addr = hapd->own_addr;
+
+ if (!is_zero_ether_addr(conf->bssid)) {
/* Allocate the configured BSSID. */
os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN);
"the radio", conf->iface);
return -1;
}
+ } else if (hapd->iconf->use_driver_iface_addr) {
+ addr = NULL;
+ } else {
+ /* Allocate the next available BSSID. */
+ do {
+ inc_byte_array(hapd->own_addr, ETH_ALEN);
+ } while (mac_in_conf(hapd->iconf, hapd->own_addr));
}
hapd->interface_added = 1;
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
- conf->iface, hapd->own_addr, hapd,
+ conf->iface, addr, hapd,
&hapd->drv_priv, force_ifname, if_addr,
conf->bridge[0] ? conf->bridge : NULL,
first == -1)) {
hapd->interface_added = 0;
return -1;
}
+
+ if (!addr)
+ os_memcpy(hapd->own_addr, if_addr, ETH_ALEN);
}
if (conf->wmm_enabled < 0)
conf->wmm_enabled = hapd->iconf->ieee80211n;
+#ifdef CONFIG_IEEE80211R
+ if (is_zero_ether_addr(conf->r1_key_holder))
+ os_memcpy(conf->r1_key_holder, hapd->own_addr, ETH_ALEN);
+#endif /* CONFIG_IEEE80211R */
+
#ifdef CONFIG_MESH
if (hapd->iface->mconf == NULL)
flush_old_stations = 0;
das_conf.time_window = conf->radius_das_time_window;
das_conf.require_event_timestamp =
conf->radius_das_require_event_timestamp;
+ das_conf.require_message_authenticator =
+ conf->radius_das_require_message_authenticator;
das_conf.ctx = hapd;
das_conf.disconnect = hostapd_das_disconnect;
hapd->radius_das = radius_das_init(&das_conf);
#endif /* CONFIG_FST */
-/**
- * hostapd_setup_interface_complete - Complete interface setup
- *
- * This function is called when previous steps in the interface setup has been
- * completed. This can also start operations, e.g., DFS, that will require
- * additional processing before interface is ready to be enabled. Such
- * operations will call this function from eloop callbacks when finished.
- */
-int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
+#ifdef NEED_AP_MLME
+static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
+ int ht, int vht)
+{
+ if (!ht && !vht)
+ return NR_CHAN_WIDTH_20;
+ if (!hapd->iconf->secondary_channel)
+ return NR_CHAN_WIDTH_20;
+ if (!vht || hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_USE_HT)
+ return NR_CHAN_WIDTH_40;
+ if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
+ return NR_CHAN_WIDTH_80;
+ if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_160MHZ)
+ return NR_CHAN_WIDTH_160;
+ if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ)
+ return NR_CHAN_WIDTH_80P80;
+ return NR_CHAN_WIDTH_20;
+}
+#endif /* NEED_AP_MLME */
+
+
+static void hostapd_set_own_neighbor_report(struct hostapd_data *hapd)
+{
+#ifdef NEED_AP_MLME
+ u16 capab = hostapd_own_capab_info(hapd);
+ int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
+ int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
+ struct wpa_ssid_value ssid;
+ u8 channel, op_class;
+ int center_freq1 = 0, center_freq2 = 0;
+ enum nr_chan_width width;
+ u32 bssid_info;
+ struct wpabuf *nr;
+
+ if (!(hapd->conf->radio_measurements[0] &
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT))
+ return;
+
+ bssid_info = 3; /* AP is reachable */
+ bssid_info |= NEI_REP_BSSID_INFO_SECURITY; /* "same as the AP" */
+ bssid_info |= NEI_REP_BSSID_INFO_KEY_SCOPE; /* "same as the AP" */
+
+ if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT)
+ bssid_info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
+
+ bssid_info |= NEI_REP_BSSID_INFO_RM; /* RRM is supported */
+
+ if (hapd->conf->wmm_enabled) {
+ bssid_info |= NEI_REP_BSSID_INFO_QOS;
+
+ if (hapd->conf->wmm_uapsd &&
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
+ bssid_info |= NEI_REP_BSSID_INFO_APSD;
+ }
+
+ if (ht) {
+ bssid_info |= NEI_REP_BSSID_INFO_HT |
+ NEI_REP_BSSID_INFO_DELAYED_BA;
+
+ /* VHT bit added in IEEE P802.11-REVmc/D4.3 */
+ if (vht)
+ bssid_info |= NEI_REP_BSSID_INFO_VHT;
+ }
+
+ /* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
+
+ ieee80211_freq_to_channel_ext(hapd->iface->freq,
+ hapd->iconf->secondary_channel,
+ hapd->iconf->vht_oper_chwidth,
+ &op_class, &channel);
+ width = hostapd_get_nr_chan_width(hapd, ht, vht);
+ if (vht) {
+ center_freq1 = ieee80211_chan_to_freq(
+ NULL, op_class,
+ hapd->iconf->vht_oper_centr_freq_seg0_idx);
+ if (width == NR_CHAN_WIDTH_80P80)
+ center_freq2 = ieee80211_chan_to_freq(
+ NULL, op_class,
+ hapd->iconf->vht_oper_centr_freq_seg1_idx);
+ } else if (ht) {
+ center_freq1 = hapd->iface->freq +
+ 10 * hapd->iconf->secondary_channel;
+ }
+
+ ssid.ssid_len = hapd->conf->ssid.ssid_len;
+ os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
+
+ /*
+ * Neighbor Report element size = BSSID + BSSID info + op_class + chan +
+ * phy type + wide bandwidth channel subelement.
+ */
+ nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5);
+ if (!nr)
+ return;
+
+ wpabuf_put_data(nr, hapd->own_addr, ETH_ALEN);
+ wpabuf_put_le32(nr, bssid_info);
+ wpabuf_put_u8(nr, op_class);
+ wpabuf_put_u8(nr, channel);
+ wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht));
+
+ /*
+ * Wide Bandwidth Channel subelement may be needed to allow the
+ * receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0
+ * Figure 9-301.
+ */
+ wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN);
+ wpabuf_put_u8(nr, 3);
+ wpabuf_put_u8(nr, width);
+ wpabuf_put_u8(nr, center_freq1);
+ wpabuf_put_u8(nr, center_freq2);
+
+ hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
+ hapd->iconf->civic);
+
+ wpabuf_free(nr);
+#endif /* NEED_AP_MLME */
+}
+
+
+static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ int err)
{
struct hostapd_data *hapd = iface->bss[0];
size_t j;
} while (j-- > 0);
goto fail;
}
- if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
+ if (is_zero_ether_addr(hapd->conf->bssid))
prev_addr = hapd->own_addr;
}
hapd = iface->bss[0];
hostapd_tx_queue_params(iface);
ap_list_init(iface);
- dl_list_init(&iface->sta_seen);
hostapd_set_acl(hapd);
if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
iface->interfaces->terminate_on_error--;
+ for (j = 0; j < iface->num_bss; j++)
+ hostapd_set_own_neighbor_report(iface->bss[j]);
+
return 0;
fail:
/**
+ * hostapd_setup_interface_complete - Complete interface setup
+ *
+ * This function is called when previous steps in the interface setup has been
+ * completed. This can also start operations, e.g., DFS, that will require
+ * additional processing before interface is ready to be enabled. Such
+ * operations will call this function from eloop callbacks when finished.
+ */
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
+{
+ struct hapd_interfaces *interfaces = iface->interfaces;
+ struct hostapd_data *hapd = iface->bss[0];
+ unsigned int i;
+ int not_ready_in_sync_ifaces = 0;
+
+ if (!iface->need_to_start_in_sync)
+ return hostapd_setup_interface_complete_sync(iface, err);
+
+ if (err) {
+ wpa_printf(MSG_ERROR, "Interface initialization failed");
+ hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+ iface->need_to_start_in_sync = 0;
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+ if (interfaces && interfaces->terminate_on_error)
+ eloop_terminate();
+ return -1;
+ }
+
+ if (iface->ready_to_start_in_sync) {
+ /* Already in ready and waiting. should never happpen */
+ return 0;
+ }
+
+ for (i = 0; i < interfaces->count; i++) {
+ if (interfaces->iface[i]->need_to_start_in_sync &&
+ !interfaces->iface[i]->ready_to_start_in_sync)
+ not_ready_in_sync_ifaces++;
+ }
+
+ /*
+ * Check if this is the last interface, if yes then start all the other
+ * waiting interfaces. If not, add this interface to the waiting list.
+ */
+ if (not_ready_in_sync_ifaces > 1 && iface->state == HAPD_IFACE_DFS) {
+ /*
+ * If this interface went through CAC, do not synchronize, just
+ * start immediately.
+ */
+ iface->need_to_start_in_sync = 0;
+ wpa_printf(MSG_INFO,
+ "%s: Finished CAC - bypass sync and start interface",
+ iface->bss[0]->conf->iface);
+ return hostapd_setup_interface_complete_sync(iface, err);
+ }
+
+ if (not_ready_in_sync_ifaces > 1) {
+ /* need to wait as there are other interfaces still coming up */
+ iface->ready_to_start_in_sync = 1;
+ wpa_printf(MSG_INFO,
+ "%s: Interface waiting to sync with other interfaces",
+ iface->bss[0]->conf->iface);
+ return 0;
+ }
+
+ wpa_printf(MSG_INFO,
+ "%s: Last interface to sync - starting all interfaces",
+ iface->bss[0]->conf->iface);
+ iface->need_to_start_in_sync = 0;
+ hostapd_setup_interface_complete_sync(iface, err);
+ for (i = 0; i < interfaces->count; i++) {
+ if (interfaces->iface[i]->need_to_start_in_sync &&
+ interfaces->iface[i]->ready_to_start_in_sync) {
+ hostapd_setup_interface_complete_sync(
+ interfaces->iface[i], 0);
+ /* Only once the interfaces are sync started */
+ interfaces->iface[i]->need_to_start_in_sync = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
* hostapd_setup_interface - Setup of an interface
* @iface: Pointer to interface data.
* Returns: 0 on success, -1 on failure
hapd->iface = hapd_iface;
hapd->driver = hapd->iconf->driver;
hapd->ctrl_sock = -1;
+ dl_list_init(&hapd->ctrl_dst);
+ dl_list_init(&hapd->nr_db);
return hapd;
}
static void hostapd_bss_deinit(struct hostapd_data *hapd)
{
+ if (!hapd)
+ return;
wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__,
hapd->conf->iface);
hostapd_bss_deinit_no_free(hapd);
}
#endif /* CONFIG_FST */
- for (j = iface->num_bss - 1; j >= 0; j--)
+ for (j = iface->num_bss - 1; j >= 0; j--) {
+ if (!iface->bss)
+ break;
hostapd_bss_deinit(iface->bss[j]);
+ }
}
size_t j;
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
for (j = 0; j < iface->num_bss; j++) {
+ if (!iface->bss)
+ break;
wpa_printf(MSG_DEBUG, "%s: free hapd %p",
__func__, iface->bss[j]);
os_free(iface->bss[j]);
}
+struct hostapd_iface * hostapd_alloc_iface(void)
+{
+ struct hostapd_iface *hapd_iface;
+
+ hapd_iface = os_zalloc(sizeof(*hapd_iface));
+ if (!hapd_iface)
+ return NULL;
+
+ dl_list_init(&hapd_iface->sta_seen);
+
+ return hapd_iface;
+}
+
+
/**
* hostapd_init - Allocate and initialize per-interface data
* @config_file: Path to the configuration file
struct hostapd_data *hapd;
size_t i;
- hapd_iface = os_zalloc(sizeof(*hapd_iface));
+ hapd_iface = hostapd_alloc_iface();
if (hapd_iface == NULL)
goto fail;
return NULL;
interfaces->iface = iface;
hapd_iface = interfaces->iface[interfaces->count] =
- os_zalloc(sizeof(*hapd_iface));
+ hostapd_alloc_iface();
if (hapd_iface == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
"the interface", __func__);
}
hostapd_prune_associations(hapd, sta->addr);
+ ap_sta_clear_disconnect_timeouts(hapd, sta);
/* IEEE 802.11F (IAPP) */
if (hapd->conf->ieee802_11f)
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
- wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
- "for " MACSTR " (%d seconds - ap_max_inactivity)",
- __func__, MAC2STR(sta->addr),
+ wpa_printf(MSG_DEBUG,
+ "%s: %s: reschedule ap_handle_timer timeout for "
+ MACSTR " (%d seconds - ap_max_inactivity)",
+ hapd->conf->iface, __func__, MAC2STR(sta->addr),
hapd->conf->ap_max_inactivity);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s)
{
wpa_printf(MSG_INFO, "%s: interface state %s->%s",
- iface->conf->bss[0]->iface, hostapd_state_text(iface->state),
- hostapd_state_text(s));
+ iface->conf ? iface->conf->bss[0]->iface : "N/A",
+ hostapd_state_text(iface->state), hostapd_state_text(s));
iface->state = s;
}
+int hostapd_csa_in_progress(struct hostapd_iface *iface)
+{
+ unsigned int i;
+
+ for (i = 0; i < iface->num_bss; i++)
+ if (iface->bss[i]->csa_in_progress)
+ return 1;
+ return 0;
+}
+
+
#ifdef NEED_AP_MLME
static void free_beacon_data(struct beacon_data *beacon)
/*
- * TODO: This flow currently supports only changing frequency within the
- * same hw_mode. Any other changes to MAC parameters or provided settings (even
- * width) are not supported.
+ * TODO: This flow currently supports only changing channel and width within
+ * the same hw_mode. Any other changes to MAC parameters or provided settings
+ * are not supported.
*/
static int hostapd_change_config_freq(struct hostapd_data *hapd,
struct hostapd_config *conf,
return -1;
/* if a pointer to old_params is provided we save previous state */
- if (old_params) {
- old_params->channel = conf->channel;
- old_params->ht_enabled = conf->ieee80211n;
- old_params->sec_channel_offset = conf->secondary_channel;
+ if (old_params &&
+ hostapd_set_freq_params(old_params, conf->hw_mode,
+ hostapd_hw_get_freq(hapd, conf->channel),
+ conf->channel, conf->ieee80211n,
+ conf->ieee80211ac,
+ conf->secondary_channel,
+ conf->vht_oper_chwidth,
+ conf->vht_oper_centr_freq_seg0_idx,
+ conf->vht_oper_centr_freq_seg1_idx,
+ conf->vht_capab))
+ return -1;
+
+ switch (params->bandwidth) {
+ case 0:
+ case 20:
+ case 40:
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+ break;
+ case 80:
+ if (params->center_freq2)
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
+ else
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+ break;
+ case 160:
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ;
+ break;
+ default:
+ return -1;
}
conf->channel = channel;
conf->ieee80211n = params->ht_enabled;
conf->secondary_channel = params->sec_channel_offset;
+ ieee80211_freq_to_chan(params->center_freq1,
+ &conf->vht_oper_centr_freq_seg0_idx);
+ ieee80211_freq_to_chan(params->center_freq2,
+ &conf->vht_oper_centr_freq_seg1_idx);
/* TODO: maybe call here hostapd_config_check here? */
struct hostapd_iface *iface = hapd->iface;
struct hostapd_freq_params old_freq;
int ret;
+ u8 chan, vht_bandwidth;
os_memset(&old_freq, 0, sizeof(old_freq));
if (!iface || !iface->freq || hapd->csa_in_progress)
return -1;
+ switch (settings->freq_params.bandwidth) {
+ case 80:
+ if (settings->freq_params.center_freq2)
+ vht_bandwidth = VHT_CHANWIDTH_80P80MHZ;
+ else
+ vht_bandwidth = VHT_CHANWIDTH_80MHZ;
+ break;
+ case 160:
+ vht_bandwidth = VHT_CHANWIDTH_160MHZ;
+ break;
+ default:
+ vht_bandwidth = VHT_CHANWIDTH_USE_HT;
+ break;
+ }
+
+ if (ieee80211_freq_to_channel_ext(
+ settings->freq_params.freq,
+ settings->freq_params.sec_channel_offset,
+ vht_bandwidth,
+ &hapd->iface->cs_oper_class,
+ &chan) == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_DEBUG,
+ "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d)",
+ settings->freq_params.freq,
+ settings->freq_params.sec_channel_offset,
+ settings->freq_params.vht_enabled);
+ return -1;
+ }
+
+ settings->freq_params.channel = chan;
+
ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
&settings->freq_params,
&old_freq);
return ret;
}
- settings->counter_offset_beacon = hapd->cs_c_off_beacon;
- settings->counter_offset_presp = hapd->cs_c_off_proberesp;
+ settings->counter_offset_beacon[0] = hapd->cs_c_off_beacon;
+ settings->counter_offset_presp[0] = hapd->cs_c_off_proberesp;
+ settings->counter_offset_beacon[1] = hapd->cs_c_off_ecsa_beacon;
+ settings->counter_offset_presp[1] = hapd->cs_c_off_ecsa_proberesp;
return 0;
}
hapd->cs_c_off_beacon = 0;
hapd->cs_c_off_proberesp = 0;
hapd->csa_in_progress = 0;
+ hapd->cs_c_off_ecsa_beacon = 0;
+ hapd->cs_c_off_ecsa_proberesp = 0;
}
hostapd_enable_iface(iface);
}
+#endif /* NEED_AP_MLME */
+
struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
const char *ifname)
return NULL;
}
-#endif /* NEED_AP_MLME */
-
void hostapd_periodic_iface(struct hostapd_iface *iface)
{