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