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