1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * WPA Supplicant - Basic AP mode support routines
3e5b75505Sopenharmony_ci * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci * Copyright (c) 2009, Atheros Communications
5e5b75505Sopenharmony_ci *
6e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
7e5b75505Sopenharmony_ci * See README for more details.
8e5b75505Sopenharmony_ci */
9e5b75505Sopenharmony_ci
10e5b75505Sopenharmony_ci#include "utils/includes.h"
11e5b75505Sopenharmony_ci
12e5b75505Sopenharmony_ci#include "utils/common.h"
13e5b75505Sopenharmony_ci#include "utils/eloop.h"
14e5b75505Sopenharmony_ci#include "utils/uuid.h"
15e5b75505Sopenharmony_ci#include "common/ieee802_11_defs.h"
16e5b75505Sopenharmony_ci#include "common/wpa_ctrl.h"
17e5b75505Sopenharmony_ci#include "eapol_supp/eapol_supp_sm.h"
18e5b75505Sopenharmony_ci#include "crypto/dh_group5.h"
19e5b75505Sopenharmony_ci#include "ap/hostapd.h"
20e5b75505Sopenharmony_ci#include "ap/ap_config.h"
21e5b75505Sopenharmony_ci#include "ap/ap_drv_ops.h"
22e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
23e5b75505Sopenharmony_ci#include "ap/ieee802_11.h"
24e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
25e5b75505Sopenharmony_ci#include "ap/beacon.h"
26e5b75505Sopenharmony_ci#include "ap/ieee802_1x.h"
27e5b75505Sopenharmony_ci#include "ap/wps_hostapd.h"
28e5b75505Sopenharmony_ci#include "ap/ctrl_iface_ap.h"
29e5b75505Sopenharmony_ci#include "ap/dfs.h"
30e5b75505Sopenharmony_ci#include "wps/wps.h"
31e5b75505Sopenharmony_ci#include "common/ieee802_11_defs.h"
32e5b75505Sopenharmony_ci#include "config_ssid.h"
33e5b75505Sopenharmony_ci#include "config.h"
34e5b75505Sopenharmony_ci#include "wpa_supplicant_i.h"
35e5b75505Sopenharmony_ci#include "driver_i.h"
36e5b75505Sopenharmony_ci#include "p2p_supplicant.h"
37e5b75505Sopenharmony_ci#include "ap.h"
38e5b75505Sopenharmony_ci#include "ap/sta_info.h"
39e5b75505Sopenharmony_ci#include "notify.h"
40e5b75505Sopenharmony_ci
41e5b75505Sopenharmony_ci
42e5b75505Sopenharmony_ci#ifdef CONFIG_WPS
43e5b75505Sopenharmony_cistatic void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
44e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */
45e5b75505Sopenharmony_ci
46e5b75505Sopenharmony_ci
47e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211N
48e5b75505Sopenharmony_cistatic void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
49e5b75505Sopenharmony_ci			     struct wpa_ssid *ssid,
50e5b75505Sopenharmony_ci			     struct hostapd_config *conf,
51e5b75505Sopenharmony_ci			     struct hostapd_hw_modes *mode)
52e5b75505Sopenharmony_ci{
53e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
54e5b75505Sopenharmony_ci	u8 center_chan = 0;
55e5b75505Sopenharmony_ci	u8 channel = conf->channel;
56e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
57e5b75505Sopenharmony_ci
58e5b75505Sopenharmony_ci	if (!conf->secondary_channel)
59e5b75505Sopenharmony_ci		goto no_vht;
60e5b75505Sopenharmony_ci
61e5b75505Sopenharmony_ci	/* Use the maximum oper channel width if it's given. */
62e5b75505Sopenharmony_ci	if (ssid->max_oper_chwidth)
63e5b75505Sopenharmony_ci		conf->vht_oper_chwidth = ssid->max_oper_chwidth;
64e5b75505Sopenharmony_ci
65e5b75505Sopenharmony_ci	ieee80211_freq_to_chan(ssid->vht_center_freq2,
66e5b75505Sopenharmony_ci			       &conf->vht_oper_centr_freq_seg1_idx);
67e5b75505Sopenharmony_ci
68e5b75505Sopenharmony_ci	if (!ssid->p2p_group) {
69e5b75505Sopenharmony_ci		if (!ssid->vht_center_freq1 ||
70e5b75505Sopenharmony_ci		    conf->vht_oper_chwidth == CHANWIDTH_USE_HT)
71e5b75505Sopenharmony_ci			goto no_vht;
72e5b75505Sopenharmony_ci		ieee80211_freq_to_chan(ssid->vht_center_freq1,
73e5b75505Sopenharmony_ci				       &conf->vht_oper_centr_freq_seg0_idx);
74e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP",
75e5b75505Sopenharmony_ci			   conf->vht_oper_centr_freq_seg0_idx);
76e5b75505Sopenharmony_ci		return;
77e5b75505Sopenharmony_ci	}
78e5b75505Sopenharmony_ci
79e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
80e5b75505Sopenharmony_ci	switch (conf->vht_oper_chwidth) {
81e5b75505Sopenharmony_ci	case CHANWIDTH_80MHZ:
82e5b75505Sopenharmony_ci	case CHANWIDTH_80P80MHZ:
83e5b75505Sopenharmony_ci		center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
84e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
85e5b75505Sopenharmony_ci			   "VHT center channel %u for 80 or 80+80 MHz bandwidth",
86e5b75505Sopenharmony_ci			   center_chan);
87e5b75505Sopenharmony_ci		break;
88e5b75505Sopenharmony_ci	case CHANWIDTH_160MHZ:
89e5b75505Sopenharmony_ci		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
90e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
91e5b75505Sopenharmony_ci			   "VHT center channel %u for 160 MHz bandwidth",
92e5b75505Sopenharmony_ci			   center_chan);
93e5b75505Sopenharmony_ci		break;
94e5b75505Sopenharmony_ci	default:
95e5b75505Sopenharmony_ci		/*
96e5b75505Sopenharmony_ci		 * conf->vht_oper_chwidth might not be set for non-P2P GO cases,
97e5b75505Sopenharmony_ci		 * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is
98e5b75505Sopenharmony_ci		 * not supported.
99e5b75505Sopenharmony_ci		 */
100e5b75505Sopenharmony_ci		conf->vht_oper_chwidth = CHANWIDTH_160MHZ;
101e5b75505Sopenharmony_ci		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
102e5b75505Sopenharmony_ci		if (center_chan) {
103e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
104e5b75505Sopenharmony_ci				   "VHT center channel %u for auto-selected 160 MHz bandwidth",
105e5b75505Sopenharmony_ci				   center_chan);
106e5b75505Sopenharmony_ci		} else {
107e5b75505Sopenharmony_ci			conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
108e5b75505Sopenharmony_ci			center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
109e5b75505Sopenharmony_ci								channel);
110e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
111e5b75505Sopenharmony_ci				   "VHT center channel %u for auto-selected 80 MHz bandwidth",
112e5b75505Sopenharmony_ci				   center_chan);
113e5b75505Sopenharmony_ci		}
114e5b75505Sopenharmony_ci		break;
115e5b75505Sopenharmony_ci	}
116e5b75505Sopenharmony_ci	if (!center_chan)
117e5b75505Sopenharmony_ci		goto no_vht;
118e5b75505Sopenharmony_ci
119e5b75505Sopenharmony_ci	conf->vht_oper_centr_freq_seg0_idx = center_chan;
120e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO",
121e5b75505Sopenharmony_ci		   conf->vht_oper_centr_freq_seg0_idx);
122e5b75505Sopenharmony_ci	return;
123e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
124e5b75505Sopenharmony_ci
125e5b75505Sopenharmony_cino_vht:
126e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
127e5b75505Sopenharmony_ci		   "No VHT higher bandwidth support for the selected channel %d",
128e5b75505Sopenharmony_ci		   conf->channel);
129e5b75505Sopenharmony_ci	conf->vht_oper_centr_freq_seg0_idx =
130e5b75505Sopenharmony_ci		conf->channel + conf->secondary_channel * 2;
131e5b75505Sopenharmony_ci	conf->vht_oper_chwidth = CHANWIDTH_USE_HT;
132e5b75505Sopenharmony_ci}
133e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211N */
134e5b75505Sopenharmony_ci
135e5b75505Sopenharmony_ci
136e5b75505Sopenharmony_ciint wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
137e5b75505Sopenharmony_ci			      struct wpa_ssid *ssid,
138e5b75505Sopenharmony_ci			      struct hostapd_config *conf)
139e5b75505Sopenharmony_ci{
140e5b75505Sopenharmony_ci	conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
141e5b75505Sopenharmony_ci					       &conf->channel);
142e5b75505Sopenharmony_ci
143e5b75505Sopenharmony_ci	if (conf->hw_mode == NUM_HOSTAPD_MODES) {
144e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
145e5b75505Sopenharmony_ci			   ssid->frequency);
146e5b75505Sopenharmony_ci		return -1;
147e5b75505Sopenharmony_ci	}
148e5b75505Sopenharmony_ci
149e5b75505Sopenharmony_ci	/* TODO: enable HT40 if driver supports it;
150e5b75505Sopenharmony_ci	 * drop to 11b if driver does not support 11g */
151e5b75505Sopenharmony_ci
152e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211N
153e5b75505Sopenharmony_ci	/*
154e5b75505Sopenharmony_ci	 * Enable HT20 if the driver supports it, by setting conf->ieee80211n
155e5b75505Sopenharmony_ci	 * and a mask of allowed capabilities within conf->ht_capab.
156e5b75505Sopenharmony_ci	 * Using default config settings for: conf->ht_op_mode_fixed,
157e5b75505Sopenharmony_ci	 * conf->secondary_channel, conf->require_ht
158e5b75505Sopenharmony_ci	 */
159e5b75505Sopenharmony_ci	if (wpa_s->hw.modes) {
160e5b75505Sopenharmony_ci		struct hostapd_hw_modes *mode = NULL;
161e5b75505Sopenharmony_ci		int i, no_ht = 0;
162e5b75505Sopenharmony_ci
163e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
164e5b75505Sopenharmony_ci			   "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)",
165e5b75505Sopenharmony_ci			   ssid->frequency, conf->channel);
166e5b75505Sopenharmony_ci
167e5b75505Sopenharmony_ci		for (i = 0; i < wpa_s->hw.num_modes; i++) {
168e5b75505Sopenharmony_ci			if (wpa_s->hw.modes[i].mode == conf->hw_mode) {
169e5b75505Sopenharmony_ci				mode = &wpa_s->hw.modes[i];
170e5b75505Sopenharmony_ci				break;
171e5b75505Sopenharmony_ci			}
172e5b75505Sopenharmony_ci		}
173e5b75505Sopenharmony_ci
174e5b75505Sopenharmony_ci#ifdef CONFIG_HT_OVERRIDES
175e5b75505Sopenharmony_ci		if (ssid->disable_ht)
176e5b75505Sopenharmony_ci			ssid->ht = 0;
177e5b75505Sopenharmony_ci#endif /* CONFIG_HT_OVERRIDES */
178e5b75505Sopenharmony_ci
179e5b75505Sopenharmony_ci		if (!ssid->ht) {
180e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
181e5b75505Sopenharmony_ci				   "HT not enabled in network profile");
182e5b75505Sopenharmony_ci			conf->ieee80211n = 0;
183e5b75505Sopenharmony_ci			conf->ht_capab = 0;
184e5b75505Sopenharmony_ci			no_ht = 1;
185e5b75505Sopenharmony_ci		}
186e5b75505Sopenharmony_ci
187e5b75505Sopenharmony_ci		if (!no_ht && mode && mode->ht_capab) {
188e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
189e5b75505Sopenharmony_ci				   "Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)",
190e5b75505Sopenharmony_ci				   ssid->p2p_group,
191e5b75505Sopenharmony_ci				   conf->hw_mode == HOSTAPD_MODE_IEEE80211A,
192e5b75505Sopenharmony_ci				   !!(mode->ht_capab &
193e5b75505Sopenharmony_ci				      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET),
194e5b75505Sopenharmony_ci				   ssid->ht40);
195e5b75505Sopenharmony_ci			conf->ieee80211n = 1;
196e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
197e5b75505Sopenharmony_ci			if (ssid->p2p_group &&
198e5b75505Sopenharmony_ci			    conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&
199e5b75505Sopenharmony_ci			    (mode->ht_capab &
200e5b75505Sopenharmony_ci			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
201e5b75505Sopenharmony_ci			    ssid->ht40) {
202e5b75505Sopenharmony_ci				conf->secondary_channel =
203e5b75505Sopenharmony_ci					wpas_p2p_get_ht40_mode(wpa_s, mode,
204e5b75505Sopenharmony_ci							       conf->channel);
205e5b75505Sopenharmony_ci				wpa_printf(MSG_DEBUG,
206e5b75505Sopenharmony_ci					   "HT secondary channel offset %d for P2P group",
207e5b75505Sopenharmony_ci					   conf->secondary_channel);
208e5b75505Sopenharmony_ci			}
209e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
210e5b75505Sopenharmony_ci
211e5b75505Sopenharmony_ci			if (!ssid->p2p_group &&
212e5b75505Sopenharmony_ci			    (mode->ht_capab &
213e5b75505Sopenharmony_ci			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
214e5b75505Sopenharmony_ci				conf->secondary_channel = ssid->ht40;
215e5b75505Sopenharmony_ci				wpa_printf(MSG_DEBUG,
216e5b75505Sopenharmony_ci					   "HT secondary channel offset %d for AP",
217e5b75505Sopenharmony_ci					   conf->secondary_channel);
218e5b75505Sopenharmony_ci			}
219e5b75505Sopenharmony_ci
220e5b75505Sopenharmony_ci			if (conf->secondary_channel)
221e5b75505Sopenharmony_ci				conf->ht_capab |=
222e5b75505Sopenharmony_ci					HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
223e5b75505Sopenharmony_ci
224e5b75505Sopenharmony_ci			/*
225e5b75505Sopenharmony_ci			 * white-list capabilities that won't cause issues
226e5b75505Sopenharmony_ci			 * to connecting stations, while leaving the current
227e5b75505Sopenharmony_ci			 * capabilities intact (currently disabled SMPS).
228e5b75505Sopenharmony_ci			 */
229e5b75505Sopenharmony_ci			conf->ht_capab |= mode->ht_capab &
230e5b75505Sopenharmony_ci				(HT_CAP_INFO_GREEN_FIELD |
231e5b75505Sopenharmony_ci				 HT_CAP_INFO_SHORT_GI20MHZ |
232e5b75505Sopenharmony_ci				 HT_CAP_INFO_SHORT_GI40MHZ |
233e5b75505Sopenharmony_ci				 HT_CAP_INFO_RX_STBC_MASK |
234e5b75505Sopenharmony_ci				 HT_CAP_INFO_TX_STBC |
235e5b75505Sopenharmony_ci				 HT_CAP_INFO_MAX_AMSDU_SIZE);
236e5b75505Sopenharmony_ci
237e5b75505Sopenharmony_ci			if (mode->vht_capab && ssid->vht) {
238e5b75505Sopenharmony_ci				conf->ieee80211ac = 1;
239e5b75505Sopenharmony_ci				conf->vht_capab |= mode->vht_capab;
240e5b75505Sopenharmony_ci				wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
241e5b75505Sopenharmony_ci			}
242e5b75505Sopenharmony_ci
243e5b75505Sopenharmony_ci			if (mode->he_capab[wpas_mode_to_ieee80211_mode(
244e5b75505Sopenharmony_ci					    ssid->mode)].he_supported &&
245e5b75505Sopenharmony_ci			    ssid->he)
246e5b75505Sopenharmony_ci				conf->ieee80211ax = 1;
247e5b75505Sopenharmony_ci		}
248e5b75505Sopenharmony_ci	}
249e5b75505Sopenharmony_ci
250e5b75505Sopenharmony_ci	if (conf->secondary_channel) {
251e5b75505Sopenharmony_ci		struct wpa_supplicant *iface;
252e5b75505Sopenharmony_ci
253e5b75505Sopenharmony_ci		for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
254e5b75505Sopenharmony_ci		{
255e5b75505Sopenharmony_ci			if (iface == wpa_s ||
256e5b75505Sopenharmony_ci			    iface->wpa_state < WPA_AUTHENTICATING ||
257e5b75505Sopenharmony_ci			    (int) iface->assoc_freq != ssid->frequency)
258e5b75505Sopenharmony_ci				continue;
259e5b75505Sopenharmony_ci
260e5b75505Sopenharmony_ci			/*
261e5b75505Sopenharmony_ci			 * Do not allow 40 MHz co-ex PRI/SEC switch to force us
262e5b75505Sopenharmony_ci			 * to change our PRI channel since we have an existing,
263e5b75505Sopenharmony_ci			 * concurrent connection on that channel and doing
264e5b75505Sopenharmony_ci			 * multi-channel concurrency is likely to cause more
265e5b75505Sopenharmony_ci			 * harm than using different PRI/SEC selection in
266e5b75505Sopenharmony_ci			 * environment with multiple BSSes on these two channels
267e5b75505Sopenharmony_ci			 * with mixed 20 MHz or PRI channel selection.
268e5b75505Sopenharmony_ci			 */
269e5b75505Sopenharmony_ci			conf->no_pri_sec_switch = 1;
270e5b75505Sopenharmony_ci		}
271e5b75505Sopenharmony_ci	}
272e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211N */
273e5b75505Sopenharmony_ci
274e5b75505Sopenharmony_ci	return 0;
275e5b75505Sopenharmony_ci}
276e5b75505Sopenharmony_ci
277e5b75505Sopenharmony_ci
278e5b75505Sopenharmony_cistatic int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
279e5b75505Sopenharmony_ci				  struct wpa_ssid *ssid,
280e5b75505Sopenharmony_ci				  struct hostapd_config *conf)
281e5b75505Sopenharmony_ci{
282e5b75505Sopenharmony_ci	struct hostapd_bss_config *bss = conf->bss[0];
283e5b75505Sopenharmony_ci
284e5b75505Sopenharmony_ci	conf->driver = wpa_s->driver;
285e5b75505Sopenharmony_ci
286e5b75505Sopenharmony_ci	os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
287e5b75505Sopenharmony_ci
288e5b75505Sopenharmony_ci	if (wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf))
289e5b75505Sopenharmony_ci		return -1;
290e5b75505Sopenharmony_ci
291e5b75505Sopenharmony_ci	if (ssid->pbss > 1) {
292e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "Invalid pbss value(%d) for AP mode",
293e5b75505Sopenharmony_ci			   ssid->pbss);
294e5b75505Sopenharmony_ci		return -1;
295e5b75505Sopenharmony_ci	}
296e5b75505Sopenharmony_ci	bss->pbss = ssid->pbss;
297e5b75505Sopenharmony_ci
298e5b75505Sopenharmony_ci#ifdef CONFIG_ACS
299e5b75505Sopenharmony_ci	if (ssid->acs) {
300e5b75505Sopenharmony_ci		/* Setting channel to 0 in order to enable ACS */
301e5b75505Sopenharmony_ci		conf->channel = 0;
302e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "Use automatic channel selection");
303e5b75505Sopenharmony_ci	}
304e5b75505Sopenharmony_ci#endif /* CONFIG_ACS */
305e5b75505Sopenharmony_ci
306e5b75505Sopenharmony_ci	if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
307e5b75505Sopenharmony_ci			     wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
308e5b75505Sopenharmony_ci		conf->ieee80211h = 1;
309e5b75505Sopenharmony_ci		conf->ieee80211d = 1;
310e5b75505Sopenharmony_ci		conf->country[0] = wpa_s->conf->country[0];
311e5b75505Sopenharmony_ci		conf->country[1] = wpa_s->conf->country[1];
312e5b75505Sopenharmony_ci		conf->country[2] = ' ';
313e5b75505Sopenharmony_ci	}
314e5b75505Sopenharmony_ci
315e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
316e5b75505Sopenharmony_ci	if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
317e5b75505Sopenharmony_ci	    (ssid->mode == WPAS_MODE_P2P_GO ||
318e5b75505Sopenharmony_ci	     ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) {
319e5b75505Sopenharmony_ci		/* Remove 802.11b rates from supported and basic rate sets */
320e5b75505Sopenharmony_ci		int *list = os_malloc(4 * sizeof(int));
321e5b75505Sopenharmony_ci		if (list) {
322e5b75505Sopenharmony_ci			list[0] = 60;
323e5b75505Sopenharmony_ci			list[1] = 120;
324e5b75505Sopenharmony_ci			list[2] = 240;
325e5b75505Sopenharmony_ci			list[3] = -1;
326e5b75505Sopenharmony_ci		}
327e5b75505Sopenharmony_ci		conf->basic_rates = list;
328e5b75505Sopenharmony_ci
329e5b75505Sopenharmony_ci		list = os_malloc(9 * sizeof(int));
330e5b75505Sopenharmony_ci		if (list) {
331e5b75505Sopenharmony_ci			list[0] = 60;
332e5b75505Sopenharmony_ci			list[1] = 90;
333e5b75505Sopenharmony_ci			list[2] = 120;
334e5b75505Sopenharmony_ci			list[3] = 180;
335e5b75505Sopenharmony_ci			list[4] = 240;
336e5b75505Sopenharmony_ci			list[5] = 360;
337e5b75505Sopenharmony_ci			list[6] = 480;
338e5b75505Sopenharmony_ci			list[7] = 540;
339e5b75505Sopenharmony_ci			list[8] = -1;
340e5b75505Sopenharmony_ci		}
341e5b75505Sopenharmony_ci		conf->supported_rates = list;
342e5b75505Sopenharmony_ci	}
343e5b75505Sopenharmony_ci
344e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211AX
345e5b75505Sopenharmony_ci	if (ssid->mode == WPAS_MODE_P2P_GO ||
346e5b75505Sopenharmony_ci	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
347e5b75505Sopenharmony_ci		conf->ieee80211ax = ssid->he;
348e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211AX */
349e5b75505Sopenharmony_ci
350e5b75505Sopenharmony_ci	bss->isolate = !wpa_s->conf->p2p_intra_bss;
351e5b75505Sopenharmony_ci	bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
352e5b75505Sopenharmony_ci
353e5b75505Sopenharmony_ci	if (ssid->p2p_group) {
354e5b75505Sopenharmony_ci		os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
355e5b75505Sopenharmony_ci		os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask,
356e5b75505Sopenharmony_ci			  4);
357e5b75505Sopenharmony_ci		os_memcpy(bss->ip_addr_start,
358e5b75505Sopenharmony_ci			  wpa_s->p2pdev->conf->ip_addr_start, 4);
359e5b75505Sopenharmony_ci		os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end,
360e5b75505Sopenharmony_ci			  4);
361e5b75505Sopenharmony_ci	}
362e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
363e5b75505Sopenharmony_ci
364e5b75505Sopenharmony_ci	if (ssid->ssid_len == 0) {
365e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
366e5b75505Sopenharmony_ci		return -1;
367e5b75505Sopenharmony_ci	}
368e5b75505Sopenharmony_ci	os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len);
369e5b75505Sopenharmony_ci	bss->ssid.ssid_len = ssid->ssid_len;
370e5b75505Sopenharmony_ci	bss->ssid.ssid_set = 1;
371e5b75505Sopenharmony_ci
372e5b75505Sopenharmony_ci	bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid;
373e5b75505Sopenharmony_ci
374e5b75505Sopenharmony_ci	if (ssid->auth_alg)
375e5b75505Sopenharmony_ci		bss->auth_algs = ssid->auth_alg;
376e5b75505Sopenharmony_ci
377e5b75505Sopenharmony_ci	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt))
378e5b75505Sopenharmony_ci		bss->wpa = ssid->proto;
379e5b75505Sopenharmony_ci	if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
380e5b75505Sopenharmony_ci		bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
381e5b75505Sopenharmony_ci	else
382e5b75505Sopenharmony_ci		bss->wpa_key_mgmt = ssid->key_mgmt;
383e5b75505Sopenharmony_ci	bss->wpa_pairwise = ssid->pairwise_cipher;
384e5b75505Sopenharmony_ci	if (ssid->psk_set) {
385e5b75505Sopenharmony_ci		bin_clear_free(bss->ssid.wpa_psk, sizeof(*bss->ssid.wpa_psk));
386e5b75505Sopenharmony_ci		bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
387e5b75505Sopenharmony_ci		if (bss->ssid.wpa_psk == NULL)
388e5b75505Sopenharmony_ci			return -1;
389e5b75505Sopenharmony_ci		os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN);
390e5b75505Sopenharmony_ci		bss->ssid.wpa_psk->group = 1;
391e5b75505Sopenharmony_ci		bss->ssid.wpa_psk_set = 1;
392e5b75505Sopenharmony_ci	} else if (ssid->passphrase) {
393e5b75505Sopenharmony_ci		bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
394e5b75505Sopenharmony_ci	} else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] ||
395e5b75505Sopenharmony_ci		   ssid->wep_key_len[2] || ssid->wep_key_len[3]) {
396e5b75505Sopenharmony_ci		struct hostapd_wep_keys *wep = &bss->ssid.wep;
397e5b75505Sopenharmony_ci		int i;
398e5b75505Sopenharmony_ci		for (i = 0; i < NUM_WEP_KEYS; i++) {
399e5b75505Sopenharmony_ci			if (ssid->wep_key_len[i] == 0)
400e5b75505Sopenharmony_ci				continue;
401e5b75505Sopenharmony_ci			wep->key[i] = os_memdup(ssid->wep_key[i],
402e5b75505Sopenharmony_ci						ssid->wep_key_len[i]);
403e5b75505Sopenharmony_ci			if (wep->key[i] == NULL)
404e5b75505Sopenharmony_ci				return -1;
405e5b75505Sopenharmony_ci			wep->len[i] = ssid->wep_key_len[i];
406e5b75505Sopenharmony_ci		}
407e5b75505Sopenharmony_ci		wep->idx = ssid->wep_tx_keyidx;
408e5b75505Sopenharmony_ci		wep->keys_set = 1;
409e5b75505Sopenharmony_ci	}
410e5b75505Sopenharmony_ci
411e5b75505Sopenharmony_ci	if (wpa_s->conf->go_interworking) {
412e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
413e5b75505Sopenharmony_ci			   "P2P: Enable Interworking with access_network_type: %d",
414e5b75505Sopenharmony_ci			   wpa_s->conf->go_access_network_type);
415e5b75505Sopenharmony_ci		bss->interworking = wpa_s->conf->go_interworking;
416e5b75505Sopenharmony_ci		bss->access_network_type = wpa_s->conf->go_access_network_type;
417e5b75505Sopenharmony_ci		bss->internet = wpa_s->conf->go_internet;
418e5b75505Sopenharmony_ci		if (wpa_s->conf->go_venue_group) {
419e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
420e5b75505Sopenharmony_ci				   "P2P: Venue group: %d  Venue type: %d",
421e5b75505Sopenharmony_ci				   wpa_s->conf->go_venue_group,
422e5b75505Sopenharmony_ci				   wpa_s->conf->go_venue_type);
423e5b75505Sopenharmony_ci			bss->venue_group = wpa_s->conf->go_venue_group;
424e5b75505Sopenharmony_ci			bss->venue_type = wpa_s->conf->go_venue_type;
425e5b75505Sopenharmony_ci			bss->venue_info_set = 1;
426e5b75505Sopenharmony_ci		}
427e5b75505Sopenharmony_ci	}
428e5b75505Sopenharmony_ci
429e5b75505Sopenharmony_ci	if (ssid->ap_max_inactivity)
430e5b75505Sopenharmony_ci		bss->ap_max_inactivity = ssid->ap_max_inactivity;
431e5b75505Sopenharmony_ci
432e5b75505Sopenharmony_ci	if (ssid->dtim_period)
433e5b75505Sopenharmony_ci		bss->dtim_period = ssid->dtim_period;
434e5b75505Sopenharmony_ci	else if (wpa_s->conf->dtim_period)
435e5b75505Sopenharmony_ci		bss->dtim_period = wpa_s->conf->dtim_period;
436e5b75505Sopenharmony_ci
437e5b75505Sopenharmony_ci	if (ssid->beacon_int)
438e5b75505Sopenharmony_ci		conf->beacon_int = ssid->beacon_int;
439e5b75505Sopenharmony_ci	else if (wpa_s->conf->beacon_int)
440e5b75505Sopenharmony_ci		conf->beacon_int = wpa_s->conf->beacon_int;
441e5b75505Sopenharmony_ci
442e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
443e5b75505Sopenharmony_ci	if (ssid->mode == WPAS_MODE_P2P_GO ||
444e5b75505Sopenharmony_ci	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
445e5b75505Sopenharmony_ci		if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) {
446e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
447e5b75505Sopenharmony_ci				   "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it",
448e5b75505Sopenharmony_ci				   wpa_s->conf->p2p_go_ctwindow,
449e5b75505Sopenharmony_ci				   conf->beacon_int);
450e5b75505Sopenharmony_ci			conf->p2p_go_ctwindow = 0;
451e5b75505Sopenharmony_ci		} else {
452e5b75505Sopenharmony_ci			conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow;
453e5b75505Sopenharmony_ci		}
454e5b75505Sopenharmony_ci	}
455e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
456e5b75505Sopenharmony_ci
457e5b75505Sopenharmony_ci	if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
458e5b75505Sopenharmony_ci		bss->rsn_pairwise = bss->wpa_pairwise;
459e5b75505Sopenharmony_ci	bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise,
460e5b75505Sopenharmony_ci						    bss->rsn_pairwise);
461e5b75505Sopenharmony_ci
462e5b75505Sopenharmony_ci	if (bss->wpa && bss->ieee802_1x)
463e5b75505Sopenharmony_ci		bss->ssid.security_policy = SECURITY_WPA;
464e5b75505Sopenharmony_ci	else if (bss->wpa)
465e5b75505Sopenharmony_ci		bss->ssid.security_policy = SECURITY_WPA_PSK;
466e5b75505Sopenharmony_ci	else if (bss->ieee802_1x) {
467e5b75505Sopenharmony_ci		int cipher = WPA_CIPHER_NONE;
468e5b75505Sopenharmony_ci		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
469e5b75505Sopenharmony_ci		bss->ssid.wep.default_len = bss->default_wep_key_len;
470e5b75505Sopenharmony_ci		if (bss->default_wep_key_len)
471e5b75505Sopenharmony_ci			cipher = bss->default_wep_key_len >= 13 ?
472e5b75505Sopenharmony_ci				WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
473e5b75505Sopenharmony_ci		bss->wpa_group = cipher;
474e5b75505Sopenharmony_ci		bss->wpa_pairwise = cipher;
475e5b75505Sopenharmony_ci		bss->rsn_pairwise = cipher;
476e5b75505Sopenharmony_ci	} else if (bss->ssid.wep.keys_set) {
477e5b75505Sopenharmony_ci		int cipher = WPA_CIPHER_WEP40;
478e5b75505Sopenharmony_ci		if (bss->ssid.wep.len[0] >= 13)
479e5b75505Sopenharmony_ci			cipher = WPA_CIPHER_WEP104;
480e5b75505Sopenharmony_ci		bss->ssid.security_policy = SECURITY_STATIC_WEP;
481e5b75505Sopenharmony_ci		bss->wpa_group = cipher;
482e5b75505Sopenharmony_ci		bss->wpa_pairwise = cipher;
483e5b75505Sopenharmony_ci		bss->rsn_pairwise = cipher;
484e5b75505Sopenharmony_ci	} else {
485e5b75505Sopenharmony_ci		bss->ssid.security_policy = SECURITY_PLAINTEXT;
486e5b75505Sopenharmony_ci		bss->wpa_group = WPA_CIPHER_NONE;
487e5b75505Sopenharmony_ci		bss->wpa_pairwise = WPA_CIPHER_NONE;
488e5b75505Sopenharmony_ci		bss->rsn_pairwise = WPA_CIPHER_NONE;
489e5b75505Sopenharmony_ci	}
490e5b75505Sopenharmony_ci
491e5b75505Sopenharmony_ci	if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) &&
492e5b75505Sopenharmony_ci	    (bss->wpa_group == WPA_CIPHER_CCMP ||
493e5b75505Sopenharmony_ci	     bss->wpa_group == WPA_CIPHER_GCMP ||
494e5b75505Sopenharmony_ci	     bss->wpa_group == WPA_CIPHER_CCMP_256 ||
495e5b75505Sopenharmony_ci	     bss->wpa_group == WPA_CIPHER_GCMP_256)) {
496e5b75505Sopenharmony_ci		/*
497e5b75505Sopenharmony_ci		 * Strong ciphers do not need frequent rekeying, so increase
498e5b75505Sopenharmony_ci		 * the default GTK rekeying period to 24 hours.
499e5b75505Sopenharmony_ci		 */
500e5b75505Sopenharmony_ci		bss->wpa_group_rekey = 86400;
501e5b75505Sopenharmony_ci	}
502e5b75505Sopenharmony_ci
503e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W
504e5b75505Sopenharmony_ci	if (ssid->ieee80211w != MGMT_FRAME_PROTECTION_DEFAULT)
505e5b75505Sopenharmony_ci		bss->ieee80211w = ssid->ieee80211w;
506e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */
507e5b75505Sopenharmony_ci
508e5b75505Sopenharmony_ci#ifdef CONFIG_OCV
509e5b75505Sopenharmony_ci	bss->ocv = ssid->ocv;
510e5b75505Sopenharmony_ci#endif /* CONFIG_OCV */
511e5b75505Sopenharmony_ci
512e5b75505Sopenharmony_ci#ifdef CONFIG_WPS
513e5b75505Sopenharmony_ci	/*
514e5b75505Sopenharmony_ci	 * Enable WPS by default for open and WPA/WPA2-Personal network, but
515e5b75505Sopenharmony_ci	 * require user interaction to actually use it. Only the internal
516e5b75505Sopenharmony_ci	 * Registrar is supported.
517e5b75505Sopenharmony_ci	 */
518e5b75505Sopenharmony_ci	if (bss->ssid.security_policy != SECURITY_WPA_PSK &&
519e5b75505Sopenharmony_ci	    bss->ssid.security_policy != SECURITY_PLAINTEXT)
520e5b75505Sopenharmony_ci		goto no_wps;
521e5b75505Sopenharmony_ci	if (bss->ssid.security_policy == SECURITY_WPA_PSK &&
522e5b75505Sopenharmony_ci	    (!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) ||
523e5b75505Sopenharmony_ci	     !(bss->wpa & 2)))
524e5b75505Sopenharmony_ci		goto no_wps; /* WPS2 does not allow WPA/TKIP-only
525e5b75505Sopenharmony_ci			      * configuration */
526e5b75505Sopenharmony_ci	if (ssid->wps_disabled)
527e5b75505Sopenharmony_ci		goto no_wps;
528e5b75505Sopenharmony_ci	bss->eap_server = 1;
529e5b75505Sopenharmony_ci
530e5b75505Sopenharmony_ci	if (!ssid->ignore_broadcast_ssid)
531e5b75505Sopenharmony_ci		bss->wps_state = 2;
532e5b75505Sopenharmony_ci
533e5b75505Sopenharmony_ci	bss->ap_setup_locked = 2;
534e5b75505Sopenharmony_ci	if (wpa_s->conf->config_methods)
535e5b75505Sopenharmony_ci		bss->config_methods = os_strdup(wpa_s->conf->config_methods);
536e5b75505Sopenharmony_ci	os_memcpy(bss->device_type, wpa_s->conf->device_type,
537e5b75505Sopenharmony_ci		  WPS_DEV_TYPE_LEN);
538e5b75505Sopenharmony_ci	if (wpa_s->conf->device_name) {
539e5b75505Sopenharmony_ci		bss->device_name = os_strdup(wpa_s->conf->device_name);
540e5b75505Sopenharmony_ci		bss->friendly_name = os_strdup(wpa_s->conf->device_name);
541e5b75505Sopenharmony_ci	}
542e5b75505Sopenharmony_ci	if (wpa_s->conf->manufacturer)
543e5b75505Sopenharmony_ci		bss->manufacturer = os_strdup(wpa_s->conf->manufacturer);
544e5b75505Sopenharmony_ci	if (wpa_s->conf->model_name)
545e5b75505Sopenharmony_ci		bss->model_name = os_strdup(wpa_s->conf->model_name);
546e5b75505Sopenharmony_ci	if (wpa_s->conf->model_number)
547e5b75505Sopenharmony_ci		bss->model_number = os_strdup(wpa_s->conf->model_number);
548e5b75505Sopenharmony_ci	if (wpa_s->conf->serial_number)
549e5b75505Sopenharmony_ci		bss->serial_number = os_strdup(wpa_s->conf->serial_number);
550e5b75505Sopenharmony_ci	if (is_nil_uuid(wpa_s->conf->uuid))
551e5b75505Sopenharmony_ci		os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN);
552e5b75505Sopenharmony_ci	else
553e5b75505Sopenharmony_ci		os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
554e5b75505Sopenharmony_ci	os_memcpy(bss->os_version, wpa_s->conf->os_version, 4);
555e5b75505Sopenharmony_ci	bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1;
556e5b75505Sopenharmony_ci	if (ssid->eap.fragment_size != DEFAULT_FRAGMENT_SIZE)
557e5b75505Sopenharmony_ci		bss->fragment_size = ssid->eap.fragment_size;
558e5b75505Sopenharmony_cino_wps:
559e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */
560e5b75505Sopenharmony_ci
561e5b75505Sopenharmony_ci	if (wpa_s->max_stations &&
562e5b75505Sopenharmony_ci	    wpa_s->max_stations < wpa_s->conf->max_num_sta)
563e5b75505Sopenharmony_ci		bss->max_num_sta = wpa_s->max_stations;
564e5b75505Sopenharmony_ci	else
565e5b75505Sopenharmony_ci		bss->max_num_sta = wpa_s->conf->max_num_sta;
566e5b75505Sopenharmony_ci
567e5b75505Sopenharmony_ci	if (!bss->isolate)
568e5b75505Sopenharmony_ci		bss->isolate = wpa_s->conf->ap_isolate;
569e5b75505Sopenharmony_ci
570e5b75505Sopenharmony_ci	bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack;
571e5b75505Sopenharmony_ci
572e5b75505Sopenharmony_ci	if (wpa_s->conf->ap_vendor_elements) {
573e5b75505Sopenharmony_ci		bss->vendor_elements =
574e5b75505Sopenharmony_ci			wpabuf_dup(wpa_s->conf->ap_vendor_elements);
575e5b75505Sopenharmony_ci	}
576e5b75505Sopenharmony_ci
577e5b75505Sopenharmony_ci	bss->ftm_responder = wpa_s->conf->ftm_responder;
578e5b75505Sopenharmony_ci	bss->ftm_initiator = wpa_s->conf->ftm_initiator;
579e5b75505Sopenharmony_ci
580e5b75505Sopenharmony_ci	return 0;
581e5b75505Sopenharmony_ci}
582e5b75505Sopenharmony_ci
583e5b75505Sopenharmony_ci
584e5b75505Sopenharmony_cistatic void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
585e5b75505Sopenharmony_ci{
586e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
587e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
588e5b75505Sopenharmony_ci	const struct ieee80211_mgmt *mgmt;
589e5b75505Sopenharmony_ci
590e5b75505Sopenharmony_ci	mgmt = (const struct ieee80211_mgmt *) buf;
591e5b75505Sopenharmony_ci	if (len < IEEE80211_HDRLEN + 1)
592e5b75505Sopenharmony_ci		return;
593e5b75505Sopenharmony_ci	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
594e5b75505Sopenharmony_ci		return;
595e5b75505Sopenharmony_ci	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
596e5b75505Sopenharmony_ci			   mgmt->u.action.category,
597e5b75505Sopenharmony_ci			   buf + IEEE80211_HDRLEN + 1,
598e5b75505Sopenharmony_ci			   len - IEEE80211_HDRLEN - 1, freq);
599e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
600e5b75505Sopenharmony_ci}
601e5b75505Sopenharmony_ci
602e5b75505Sopenharmony_ci
603e5b75505Sopenharmony_cistatic void ap_wps_event_cb(void *ctx, enum wps_event event,
604e5b75505Sopenharmony_ci			    union wps_event_data *data)
605e5b75505Sopenharmony_ci{
606e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
607e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
608e5b75505Sopenharmony_ci
609e5b75505Sopenharmony_ci	if (event == WPS_EV_FAIL) {
610e5b75505Sopenharmony_ci		struct wps_event_fail *fail = &data->fail;
611e5b75505Sopenharmony_ci
612e5b75505Sopenharmony_ci		if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s &&
613e5b75505Sopenharmony_ci		    wpa_s == wpa_s->global->p2p_group_formation) {
614e5b75505Sopenharmony_ci			/*
615e5b75505Sopenharmony_ci			 * src/ap/wps_hostapd.c has already sent this on the
616e5b75505Sopenharmony_ci			 * main interface, so only send on the parent interface
617e5b75505Sopenharmony_ci			 * here if needed.
618e5b75505Sopenharmony_ci			 */
619e5b75505Sopenharmony_ci			wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
620e5b75505Sopenharmony_ci				"msg=%d config_error=%d",
621e5b75505Sopenharmony_ci				fail->msg, fail->config_error);
622e5b75505Sopenharmony_ci		}
623e5b75505Sopenharmony_ci		wpas_p2p_wps_failed(wpa_s, fail);
624e5b75505Sopenharmony_ci	}
625e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
626e5b75505Sopenharmony_ci}
627e5b75505Sopenharmony_ci
628e5b75505Sopenharmony_ci
629e5b75505Sopenharmony_cistatic void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
630e5b75505Sopenharmony_ci				 int authorized, const u8 *p2p_dev_addr)
631e5b75505Sopenharmony_ci{
632e5b75505Sopenharmony_ci	wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr);
633e5b75505Sopenharmony_ci}
634e5b75505Sopenharmony_ci
635e5b75505Sopenharmony_ci
636e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
637e5b75505Sopenharmony_cistatic void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
638e5b75505Sopenharmony_ci			  const u8 *psk, size_t psk_len)
639e5b75505Sopenharmony_ci{
640e5b75505Sopenharmony_ci
641e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
642e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL)
643e5b75505Sopenharmony_ci		return;
644e5b75505Sopenharmony_ci	wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len);
645e5b75505Sopenharmony_ci}
646e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
647e5b75505Sopenharmony_ci
648e5b75505Sopenharmony_ci
649e5b75505Sopenharmony_cistatic int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
650e5b75505Sopenharmony_ci{
651e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
652e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
653e5b75505Sopenharmony_ci	const struct ieee80211_mgmt *mgmt;
654e5b75505Sopenharmony_ci
655e5b75505Sopenharmony_ci	mgmt = (const struct ieee80211_mgmt *) buf;
656e5b75505Sopenharmony_ci	if (len < IEEE80211_HDRLEN + 1)
657e5b75505Sopenharmony_ci		return -1;
658e5b75505Sopenharmony_ci	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
659e5b75505Sopenharmony_ci			   mgmt->u.action.category,
660e5b75505Sopenharmony_ci			   buf + IEEE80211_HDRLEN + 1,
661e5b75505Sopenharmony_ci			   len - IEEE80211_HDRLEN - 1, freq);
662e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
663e5b75505Sopenharmony_ci	return 0;
664e5b75505Sopenharmony_ci}
665e5b75505Sopenharmony_ci
666e5b75505Sopenharmony_ci
667e5b75505Sopenharmony_cistatic int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da,
668e5b75505Sopenharmony_ci			   const u8 *bssid, const u8 *ie, size_t ie_len,
669e5b75505Sopenharmony_ci			   int ssi_signal)
670e5b75505Sopenharmony_ci{
671e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
672e5b75505Sopenharmony_ci	unsigned int freq = 0;
673e5b75505Sopenharmony_ci
674e5b75505Sopenharmony_ci	if (wpa_s->ap_iface)
675e5b75505Sopenharmony_ci		freq = wpa_s->ap_iface->freq;
676e5b75505Sopenharmony_ci
677e5b75505Sopenharmony_ci	return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len,
678e5b75505Sopenharmony_ci				     freq, ssi_signal);
679e5b75505Sopenharmony_ci}
680e5b75505Sopenharmony_ci
681e5b75505Sopenharmony_ci
682e5b75505Sopenharmony_cistatic void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
683e5b75505Sopenharmony_ci				  const u8 *uuid_e)
684e5b75505Sopenharmony_ci{
685e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
686e5b75505Sopenharmony_ci	wpas_p2p_wps_success(wpa_s, mac_addr, 1);
687e5b75505Sopenharmony_ci}
688e5b75505Sopenharmony_ci
689e5b75505Sopenharmony_ci
690e5b75505Sopenharmony_cistatic void wpas_ap_configured_cb(void *ctx)
691e5b75505Sopenharmony_ci{
692e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
693e5b75505Sopenharmony_ci
694e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "AP interface setup completed - state %s",
695e5b75505Sopenharmony_ci		   hostapd_state_text(wpa_s->ap_iface->state));
696e5b75505Sopenharmony_ci	if (wpa_s->ap_iface->state == HAPD_IFACE_DISABLED) {
697e5b75505Sopenharmony_ci		wpa_supplicant_ap_deinit(wpa_s);
698e5b75505Sopenharmony_ci		return;
699e5b75505Sopenharmony_ci	}
700e5b75505Sopenharmony_ci
701e5b75505Sopenharmony_ci#ifdef CONFIG_ACS
702e5b75505Sopenharmony_ci	if (wpa_s->current_ssid && wpa_s->current_ssid->acs) {
703e5b75505Sopenharmony_ci		wpa_s->assoc_freq = wpa_s->ap_iface->freq;
704e5b75505Sopenharmony_ci		wpa_s->current_ssid->frequency = wpa_s->ap_iface->freq;
705e5b75505Sopenharmony_ci	}
706e5b75505Sopenharmony_ci#endif /* CONFIG_ACS */
707e5b75505Sopenharmony_ci
708e5b75505Sopenharmony_ci	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
709e5b75505Sopenharmony_ci
710e5b75505Sopenharmony_ci	if (wpa_s->ap_configured_cb)
711e5b75505Sopenharmony_ci		wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
712e5b75505Sopenharmony_ci					wpa_s->ap_configured_cb_data);
713e5b75505Sopenharmony_ci}
714e5b75505Sopenharmony_ci
715e5b75505Sopenharmony_ci
716e5b75505Sopenharmony_ciint wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
717e5b75505Sopenharmony_ci			     struct wpa_ssid *ssid)
718e5b75505Sopenharmony_ci{
719e5b75505Sopenharmony_ci	struct wpa_driver_associate_params params;
720e5b75505Sopenharmony_ci	struct hostapd_iface *hapd_iface;
721e5b75505Sopenharmony_ci	struct hostapd_config *conf;
722e5b75505Sopenharmony_ci	size_t i;
723e5b75505Sopenharmony_ci
724e5b75505Sopenharmony_ci	if (ssid->ssid == NULL || ssid->ssid_len == 0) {
725e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
726e5b75505Sopenharmony_ci		return -1;
727e5b75505Sopenharmony_ci	}
728e5b75505Sopenharmony_ci
729e5b75505Sopenharmony_ci	wpa_supplicant_ap_deinit(wpa_s);
730e5b75505Sopenharmony_ci
731e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')",
732e5b75505Sopenharmony_ci		   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
733e5b75505Sopenharmony_ci
734e5b75505Sopenharmony_ci	os_memset(&params, 0, sizeof(params));
735e5b75505Sopenharmony_ci	params.ssid = ssid->ssid;
736e5b75505Sopenharmony_ci	params.ssid_len = ssid->ssid_len;
737e5b75505Sopenharmony_ci	switch (ssid->mode) {
738e5b75505Sopenharmony_ci	case WPAS_MODE_AP:
739e5b75505Sopenharmony_ci	case WPAS_MODE_P2P_GO:
740e5b75505Sopenharmony_ci	case WPAS_MODE_P2P_GROUP_FORMATION:
741e5b75505Sopenharmony_ci		params.mode = IEEE80211_MODE_AP;
742e5b75505Sopenharmony_ci		break;
743e5b75505Sopenharmony_ci	default:
744e5b75505Sopenharmony_ci		return -1;
745e5b75505Sopenharmony_ci	}
746e5b75505Sopenharmony_ci	if (ssid->frequency == 0)
747e5b75505Sopenharmony_ci		ssid->frequency = 2462; /* default channel 11 */
748e5b75505Sopenharmony_ci	params.freq.freq = ssid->frequency;
749e5b75505Sopenharmony_ci
750e5b75505Sopenharmony_ci	params.wpa_proto = ssid->proto;
751e5b75505Sopenharmony_ci	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
752e5b75505Sopenharmony_ci		wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
753e5b75505Sopenharmony_ci	else
754e5b75505Sopenharmony_ci		wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
755e5b75505Sopenharmony_ci	params.key_mgmt_suite = wpa_s->key_mgmt;
756e5b75505Sopenharmony_ci
757e5b75505Sopenharmony_ci	wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher,
758e5b75505Sopenharmony_ci							  1);
759e5b75505Sopenharmony_ci	if (wpa_s->pairwise_cipher < 0) {
760e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise "
761e5b75505Sopenharmony_ci			   "cipher.");
762e5b75505Sopenharmony_ci		return -1;
763e5b75505Sopenharmony_ci	}
764e5b75505Sopenharmony_ci	params.pairwise_suite = wpa_s->pairwise_cipher;
765e5b75505Sopenharmony_ci	params.group_suite = params.pairwise_suite;
766e5b75505Sopenharmony_ci
767e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
768e5b75505Sopenharmony_ci	if (ssid->mode == WPAS_MODE_P2P_GO ||
769e5b75505Sopenharmony_ci	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
770e5b75505Sopenharmony_ci		params.p2p = 1;
771e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
772e5b75505Sopenharmony_ci
773e5b75505Sopenharmony_ci	if (wpa_s->p2pdev->set_ap_uapsd)
774e5b75505Sopenharmony_ci		params.uapsd = wpa_s->p2pdev->ap_uapsd;
775e5b75505Sopenharmony_ci	else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
776e5b75505Sopenharmony_ci		params.uapsd = 1; /* mandatory for P2P GO */
777e5b75505Sopenharmony_ci	else
778e5b75505Sopenharmony_ci		params.uapsd = -1;
779e5b75505Sopenharmony_ci
780e5b75505Sopenharmony_ci	if (ieee80211_is_dfs(params.freq.freq, wpa_s->hw.modes,
781e5b75505Sopenharmony_ci			     wpa_s->hw.num_modes))
782e5b75505Sopenharmony_ci		params.freq.freq = 0; /* set channel after CAC */
783e5b75505Sopenharmony_ci
784e5b75505Sopenharmony_ci	if (params.p2p)
785e5b75505Sopenharmony_ci		wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_GO);
786e5b75505Sopenharmony_ci	else
787e5b75505Sopenharmony_ci		wpa_drv_get_ext_capa(wpa_s, WPA_IF_AP_BSS);
788e5b75505Sopenharmony_ci
789e5b75505Sopenharmony_ci	if (wpa_drv_associate(wpa_s, &params) < 0) {
790e5b75505Sopenharmony_ci		wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
791e5b75505Sopenharmony_ci		return -1;
792e5b75505Sopenharmony_ci	}
793e5b75505Sopenharmony_ci
794e5b75505Sopenharmony_ci	wpa_s->ap_iface = hapd_iface = hostapd_alloc_iface();
795e5b75505Sopenharmony_ci	if (hapd_iface == NULL)
796e5b75505Sopenharmony_ci		return -1;
797e5b75505Sopenharmony_ci	hapd_iface->owner = wpa_s;
798e5b75505Sopenharmony_ci	hapd_iface->drv_flags = wpa_s->drv_flags;
799e5b75505Sopenharmony_ci	hapd_iface->smps_modes = wpa_s->drv_smps_modes;
800e5b75505Sopenharmony_ci	hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
801e5b75505Sopenharmony_ci	hapd_iface->extended_capa = wpa_s->extended_capa;
802e5b75505Sopenharmony_ci	hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask;
803e5b75505Sopenharmony_ci	hapd_iface->extended_capa_len = wpa_s->extended_capa_len;
804e5b75505Sopenharmony_ci
805e5b75505Sopenharmony_ci	wpa_s->ap_iface->conf = conf = hostapd_config_defaults();
806e5b75505Sopenharmony_ci	if (conf == NULL) {
807e5b75505Sopenharmony_ci		wpa_supplicant_ap_deinit(wpa_s);
808e5b75505Sopenharmony_ci		return -1;
809e5b75505Sopenharmony_ci	}
810e5b75505Sopenharmony_ci
811e5b75505Sopenharmony_ci	os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params,
812e5b75505Sopenharmony_ci		  wpa_s->conf->wmm_ac_params,
813e5b75505Sopenharmony_ci		  sizeof(wpa_s->conf->wmm_ac_params));
814e5b75505Sopenharmony_ci
815e5b75505Sopenharmony_ci	if (params.uapsd > 0) {
816e5b75505Sopenharmony_ci		conf->bss[0]->wmm_enabled = 1;
817e5b75505Sopenharmony_ci		conf->bss[0]->wmm_uapsd = 1;
818e5b75505Sopenharmony_ci	}
819e5b75505Sopenharmony_ci
820e5b75505Sopenharmony_ci	if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) {
821e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "Failed to create AP configuration");
822e5b75505Sopenharmony_ci		wpa_supplicant_ap_deinit(wpa_s);
823e5b75505Sopenharmony_ci		return -1;
824e5b75505Sopenharmony_ci	}
825e5b75505Sopenharmony_ci
826e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
827e5b75505Sopenharmony_ci	if (ssid->mode == WPAS_MODE_P2P_GO)
828e5b75505Sopenharmony_ci		conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
829e5b75505Sopenharmony_ci	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
830e5b75505Sopenharmony_ci		conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
831e5b75505Sopenharmony_ci			P2P_GROUP_FORMATION;
832e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
833e5b75505Sopenharmony_ci
834e5b75505Sopenharmony_ci	hapd_iface->num_bss = conf->num_bss;
835e5b75505Sopenharmony_ci	hapd_iface->bss = os_calloc(conf->num_bss,
836e5b75505Sopenharmony_ci				    sizeof(struct hostapd_data *));
837e5b75505Sopenharmony_ci	if (hapd_iface->bss == NULL) {
838e5b75505Sopenharmony_ci		wpa_supplicant_ap_deinit(wpa_s);
839e5b75505Sopenharmony_ci		return -1;
840e5b75505Sopenharmony_ci	}
841e5b75505Sopenharmony_ci
842e5b75505Sopenharmony_ci	for (i = 0; i < conf->num_bss; i++) {
843e5b75505Sopenharmony_ci		hapd_iface->bss[i] =
844e5b75505Sopenharmony_ci			hostapd_alloc_bss_data(hapd_iface, conf,
845e5b75505Sopenharmony_ci					       conf->bss[i]);
846e5b75505Sopenharmony_ci		if (hapd_iface->bss[i] == NULL) {
847e5b75505Sopenharmony_ci			wpa_supplicant_ap_deinit(wpa_s);
848e5b75505Sopenharmony_ci			return -1;
849e5b75505Sopenharmony_ci		}
850e5b75505Sopenharmony_ci
851e5b75505Sopenharmony_ci		hapd_iface->bss[i]->msg_ctx = wpa_s;
852e5b75505Sopenharmony_ci		hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev;
853e5b75505Sopenharmony_ci		hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
854e5b75505Sopenharmony_ci		hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
855e5b75505Sopenharmony_ci		hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
856e5b75505Sopenharmony_ci		hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s;
857e5b75505Sopenharmony_ci		hostapd_register_probereq_cb(hapd_iface->bss[i],
858e5b75505Sopenharmony_ci					     ap_probe_req_rx, wpa_s);
859e5b75505Sopenharmony_ci		hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb;
860e5b75505Sopenharmony_ci		hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s;
861e5b75505Sopenharmony_ci		hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb;
862e5b75505Sopenharmony_ci		hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s;
863e5b75505Sopenharmony_ci		hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb;
864e5b75505Sopenharmony_ci		hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s;
865e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
866e5b75505Sopenharmony_ci		hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb;
867e5b75505Sopenharmony_ci		hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s;
868e5b75505Sopenharmony_ci		hapd_iface->bss[i]->p2p = wpa_s->global->p2p;
869e5b75505Sopenharmony_ci		hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s,
870e5b75505Sopenharmony_ci								    ssid);
871e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
872e5b75505Sopenharmony_ci		hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb;
873e5b75505Sopenharmony_ci		hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s;
874e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS
875e5b75505Sopenharmony_ci		hapd_iface->bss[i]->ext_eapol_frame_io =
876e5b75505Sopenharmony_ci			wpa_s->ext_eapol_frame_io;
877e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */
878e5b75505Sopenharmony_ci	}
879e5b75505Sopenharmony_ci
880e5b75505Sopenharmony_ci	os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
881e5b75505Sopenharmony_ci	hapd_iface->bss[0]->driver = wpa_s->driver;
882e5b75505Sopenharmony_ci	hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv;
883e5b75505Sopenharmony_ci
884e5b75505Sopenharmony_ci	wpa_s->current_ssid = ssid;
885e5b75505Sopenharmony_ci	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
886e5b75505Sopenharmony_ci	os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
887e5b75505Sopenharmony_ci	wpa_s->assoc_freq = ssid->frequency;
888e5b75505Sopenharmony_ci
889e5b75505Sopenharmony_ci#if defined(CONFIG_P2P) && defined(CONFIG_ACS)
890e5b75505Sopenharmony_ci	if (wpa_s->p2p_go_do_acs) {
891e5b75505Sopenharmony_ci		wpa_s->ap_iface->conf->channel = 0;
892e5b75505Sopenharmony_ci		wpa_s->ap_iface->conf->hw_mode = wpa_s->p2p_go_acs_band;
893e5b75505Sopenharmony_ci		ssid->acs = 1;
894e5b75505Sopenharmony_ci	}
895e5b75505Sopenharmony_ci#endif /* CONFIG_P2P && CONFIG_ACS */
896e5b75505Sopenharmony_ci
897e5b75505Sopenharmony_ci	if (hostapd_setup_interface(wpa_s->ap_iface)) {
898e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "Failed to initialize AP interface");
899e5b75505Sopenharmony_ci		wpa_supplicant_ap_deinit(wpa_s);
900e5b75505Sopenharmony_ci		return -1;
901e5b75505Sopenharmony_ci	}
902e5b75505Sopenharmony_ci
903e5b75505Sopenharmony_ci	return 0;
904e5b75505Sopenharmony_ci}
905e5b75505Sopenharmony_ci
906e5b75505Sopenharmony_ci
907e5b75505Sopenharmony_civoid wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s)
908e5b75505Sopenharmony_ci{
909e5b75505Sopenharmony_ci#ifdef CONFIG_WPS
910e5b75505Sopenharmony_ci	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
911e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */
912e5b75505Sopenharmony_ci
913e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
914e5b75505Sopenharmony_ci		return;
915e5b75505Sopenharmony_ci
916e5b75505Sopenharmony_ci	wpa_s->current_ssid = NULL;
917e5b75505Sopenharmony_ci	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
918e5b75505Sopenharmony_ci	wpa_s->assoc_freq = 0;
919e5b75505Sopenharmony_ci	wpas_p2p_ap_deinit(wpa_s);
920e5b75505Sopenharmony_ci	wpa_s->ap_iface->driver_ap_teardown =
921e5b75505Sopenharmony_ci		!!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
922e5b75505Sopenharmony_ci
923e5b75505Sopenharmony_ci	hostapd_interface_deinit(wpa_s->ap_iface);
924e5b75505Sopenharmony_ci	hostapd_interface_free(wpa_s->ap_iface);
925e5b75505Sopenharmony_ci	wpa_s->ap_iface = NULL;
926e5b75505Sopenharmony_ci	wpa_drv_deinit_ap(wpa_s);
927e5b75505Sopenharmony_ci	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
928e5b75505Sopenharmony_ci		" reason=%d locally_generated=1",
929e5b75505Sopenharmony_ci		MAC2STR(wpa_s->own_addr), WLAN_REASON_DEAUTH_LEAVING);
930e5b75505Sopenharmony_ci}
931e5b75505Sopenharmony_ci
932e5b75505Sopenharmony_ci
933e5b75505Sopenharmony_civoid ap_tx_status(void *ctx, const u8 *addr,
934e5b75505Sopenharmony_ci		  const u8 *buf, size_t len, int ack)
935e5b75505Sopenharmony_ci{
936e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
937e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
938e5b75505Sopenharmony_ci	hostapd_tx_status(wpa_s->ap_iface->bss[0], addr, buf, len, ack);
939e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
940e5b75505Sopenharmony_ci}
941e5b75505Sopenharmony_ci
942e5b75505Sopenharmony_ci
943e5b75505Sopenharmony_civoid ap_eapol_tx_status(void *ctx, const u8 *dst,
944e5b75505Sopenharmony_ci			const u8 *data, size_t len, int ack)
945e5b75505Sopenharmony_ci{
946e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
947e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
948e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface)
949e5b75505Sopenharmony_ci		return;
950e5b75505Sopenharmony_ci	hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
951e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
952e5b75505Sopenharmony_ci}
953e5b75505Sopenharmony_ci
954e5b75505Sopenharmony_ci
955e5b75505Sopenharmony_civoid ap_client_poll_ok(void *ctx, const u8 *addr)
956e5b75505Sopenharmony_ci{
957e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
958e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
959e5b75505Sopenharmony_ci	if (wpa_s->ap_iface)
960e5b75505Sopenharmony_ci		hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr);
961e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
962e5b75505Sopenharmony_ci}
963e5b75505Sopenharmony_ci
964e5b75505Sopenharmony_ci
965e5b75505Sopenharmony_civoid ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds)
966e5b75505Sopenharmony_ci{
967e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
968e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
969e5b75505Sopenharmony_ci	ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds);
970e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
971e5b75505Sopenharmony_ci}
972e5b75505Sopenharmony_ci
973e5b75505Sopenharmony_ci
974e5b75505Sopenharmony_civoid ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt)
975e5b75505Sopenharmony_ci{
976e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
977e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
978e5b75505Sopenharmony_ci	struct hostapd_frame_info fi;
979e5b75505Sopenharmony_ci	os_memset(&fi, 0, sizeof(fi));
980e5b75505Sopenharmony_ci	fi.datarate = rx_mgmt->datarate;
981e5b75505Sopenharmony_ci	fi.ssi_signal = rx_mgmt->ssi_signal;
982e5b75505Sopenharmony_ci	ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame,
983e5b75505Sopenharmony_ci			rx_mgmt->frame_len, &fi);
984e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
985e5b75505Sopenharmony_ci}
986e5b75505Sopenharmony_ci
987e5b75505Sopenharmony_ci
988e5b75505Sopenharmony_civoid ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok)
989e5b75505Sopenharmony_ci{
990e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
991e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = ctx;
992e5b75505Sopenharmony_ci	ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok);
993e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
994e5b75505Sopenharmony_ci}
995e5b75505Sopenharmony_ci
996e5b75505Sopenharmony_ci
997e5b75505Sopenharmony_civoid wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
998e5b75505Sopenharmony_ci				const u8 *src_addr, const u8 *buf, size_t len)
999e5b75505Sopenharmony_ci{
1000e5b75505Sopenharmony_ci	ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len);
1001e5b75505Sopenharmony_ci}
1002e5b75505Sopenharmony_ci
1003e5b75505Sopenharmony_ci
1004e5b75505Sopenharmony_ci#ifdef CONFIG_WPS
1005e5b75505Sopenharmony_ci
1006e5b75505Sopenharmony_ciint wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
1007e5b75505Sopenharmony_ci			      const u8 *p2p_dev_addr)
1008e5b75505Sopenharmony_ci{
1009e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface)
1010e5b75505Sopenharmony_ci		return -1;
1011e5b75505Sopenharmony_ci	return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0],
1012e5b75505Sopenharmony_ci					 p2p_dev_addr);
1013e5b75505Sopenharmony_ci}
1014e5b75505Sopenharmony_ci
1015e5b75505Sopenharmony_ci
1016e5b75505Sopenharmony_ciint wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s)
1017e5b75505Sopenharmony_ci{
1018e5b75505Sopenharmony_ci	struct wps_registrar *reg;
1019e5b75505Sopenharmony_ci	int reg_sel = 0, wps_sta = 0;
1020e5b75505Sopenharmony_ci
1021e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps)
1022e5b75505Sopenharmony_ci		return -1;
1023e5b75505Sopenharmony_ci
1024e5b75505Sopenharmony_ci	reg = wpa_s->ap_iface->bss[0]->wps->registrar;
1025e5b75505Sopenharmony_ci	reg_sel = wps_registrar_wps_cancel(reg);
1026e5b75505Sopenharmony_ci	wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0],
1027e5b75505Sopenharmony_ci				  ap_sta_wps_cancel, NULL);
1028e5b75505Sopenharmony_ci
1029e5b75505Sopenharmony_ci	if (!reg_sel && !wps_sta) {
1030e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "No WPS operation in progress at this "
1031e5b75505Sopenharmony_ci			   "time");
1032e5b75505Sopenharmony_ci		return -1;
1033e5b75505Sopenharmony_ci	}
1034e5b75505Sopenharmony_ci
1035e5b75505Sopenharmony_ci	/*
1036e5b75505Sopenharmony_ci	 * There are 2 cases to return wps cancel as success:
1037e5b75505Sopenharmony_ci	 * 1. When wps cancel was initiated but no connection has been
1038e5b75505Sopenharmony_ci	 *    established with client yet.
1039e5b75505Sopenharmony_ci	 * 2. Client is in the middle of exchanging WPS messages.
1040e5b75505Sopenharmony_ci	 */
1041e5b75505Sopenharmony_ci
1042e5b75505Sopenharmony_ci	return 0;
1043e5b75505Sopenharmony_ci}
1044e5b75505Sopenharmony_ci
1045e5b75505Sopenharmony_ci
1046e5b75505Sopenharmony_ciint wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
1047e5b75505Sopenharmony_ci			      const char *pin, char *buf, size_t buflen,
1048e5b75505Sopenharmony_ci			      int timeout)
1049e5b75505Sopenharmony_ci{
1050e5b75505Sopenharmony_ci	int ret, ret_len = 0;
1051e5b75505Sopenharmony_ci
1052e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface)
1053e5b75505Sopenharmony_ci		return -1;
1054e5b75505Sopenharmony_ci
1055e5b75505Sopenharmony_ci	if (pin == NULL) {
1056e5b75505Sopenharmony_ci		unsigned int rpin;
1057e5b75505Sopenharmony_ci
1058e5b75505Sopenharmony_ci		if (wps_generate_pin(&rpin) < 0)
1059e5b75505Sopenharmony_ci			return -1;
1060e5b75505Sopenharmony_ci		ret_len = os_snprintf(buf, buflen, "%08d", rpin);
1061e5b75505Sopenharmony_ci		if (os_snprintf_error(buflen, ret_len))
1062e5b75505Sopenharmony_ci			return -1;
1063e5b75505Sopenharmony_ci		pin = buf;
1064e5b75505Sopenharmony_ci	} else if (buf) {
1065e5b75505Sopenharmony_ci		ret_len = os_snprintf(buf, buflen, "%s", pin);
1066e5b75505Sopenharmony_ci		if (os_snprintf_error(buflen, ret_len))
1067e5b75505Sopenharmony_ci			return -1;
1068e5b75505Sopenharmony_ci	}
1069e5b75505Sopenharmony_ci
1070e5b75505Sopenharmony_ci	ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin,
1071e5b75505Sopenharmony_ci				  timeout);
1072e5b75505Sopenharmony_ci	if (ret)
1073e5b75505Sopenharmony_ci		return -1;
1074e5b75505Sopenharmony_ci	return ret_len;
1075e5b75505Sopenharmony_ci}
1076e5b75505Sopenharmony_ci
1077e5b75505Sopenharmony_ci
1078e5b75505Sopenharmony_cistatic void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
1079e5b75505Sopenharmony_ci{
1080e5b75505Sopenharmony_ci	struct wpa_supplicant *wpa_s = eloop_data;
1081e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
1082e5b75505Sopenharmony_ci	wpas_wps_ap_pin_disable(wpa_s);
1083e5b75505Sopenharmony_ci}
1084e5b75505Sopenharmony_ci
1085e5b75505Sopenharmony_ci
1086e5b75505Sopenharmony_cistatic void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout)
1087e5b75505Sopenharmony_ci{
1088e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1089e5b75505Sopenharmony_ci
1090e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1091e5b75505Sopenharmony_ci		return;
1092e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1093e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
1094e5b75505Sopenharmony_ci	hapd->ap_pin_failures = 0;
1095e5b75505Sopenharmony_ci	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
1096e5b75505Sopenharmony_ci	if (timeout > 0)
1097e5b75505Sopenharmony_ci		eloop_register_timeout(timeout, 0,
1098e5b75505Sopenharmony_ci				       wpas_wps_ap_pin_timeout, wpa_s, NULL);
1099e5b75505Sopenharmony_ci}
1100e5b75505Sopenharmony_ci
1101e5b75505Sopenharmony_ci
1102e5b75505Sopenharmony_civoid wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s)
1103e5b75505Sopenharmony_ci{
1104e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1105e5b75505Sopenharmony_ci
1106e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1107e5b75505Sopenharmony_ci		return;
1108e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
1109e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1110e5b75505Sopenharmony_ci	os_free(hapd->conf->ap_pin);
1111e5b75505Sopenharmony_ci	hapd->conf->ap_pin = NULL;
1112e5b75505Sopenharmony_ci	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
1113e5b75505Sopenharmony_ci}
1114e5b75505Sopenharmony_ci
1115e5b75505Sopenharmony_ci
1116e5b75505Sopenharmony_ciconst char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
1117e5b75505Sopenharmony_ci{
1118e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1119e5b75505Sopenharmony_ci	unsigned int pin;
1120e5b75505Sopenharmony_ci	char pin_txt[9];
1121e5b75505Sopenharmony_ci
1122e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1123e5b75505Sopenharmony_ci		return NULL;
1124e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1125e5b75505Sopenharmony_ci	if (wps_generate_pin(&pin) < 0)
1126e5b75505Sopenharmony_ci		return NULL;
1127e5b75505Sopenharmony_ci	os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
1128e5b75505Sopenharmony_ci	os_free(hapd->conf->ap_pin);
1129e5b75505Sopenharmony_ci	hapd->conf->ap_pin = os_strdup(pin_txt);
1130e5b75505Sopenharmony_ci	if (hapd->conf->ap_pin == NULL)
1131e5b75505Sopenharmony_ci		return NULL;
1132e5b75505Sopenharmony_ci	wpas_wps_ap_pin_enable(wpa_s, timeout);
1133e5b75505Sopenharmony_ci
1134e5b75505Sopenharmony_ci	return hapd->conf->ap_pin;
1135e5b75505Sopenharmony_ci}
1136e5b75505Sopenharmony_ci
1137e5b75505Sopenharmony_ci
1138e5b75505Sopenharmony_ciconst char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s)
1139e5b75505Sopenharmony_ci{
1140e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1141e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1142e5b75505Sopenharmony_ci		return NULL;
1143e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1144e5b75505Sopenharmony_ci	return hapd->conf->ap_pin;
1145e5b75505Sopenharmony_ci}
1146e5b75505Sopenharmony_ci
1147e5b75505Sopenharmony_ci
1148e5b75505Sopenharmony_ciint wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin,
1149e5b75505Sopenharmony_ci			int timeout)
1150e5b75505Sopenharmony_ci{
1151e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1152e5b75505Sopenharmony_ci	char pin_txt[9];
1153e5b75505Sopenharmony_ci	int ret;
1154e5b75505Sopenharmony_ci
1155e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1156e5b75505Sopenharmony_ci		return -1;
1157e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1158e5b75505Sopenharmony_ci	ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin);
1159e5b75505Sopenharmony_ci	if (os_snprintf_error(sizeof(pin_txt), ret))
1160e5b75505Sopenharmony_ci		return -1;
1161e5b75505Sopenharmony_ci	os_free(hapd->conf->ap_pin);
1162e5b75505Sopenharmony_ci	hapd->conf->ap_pin = os_strdup(pin_txt);
1163e5b75505Sopenharmony_ci	if (hapd->conf->ap_pin == NULL)
1164e5b75505Sopenharmony_ci		return -1;
1165e5b75505Sopenharmony_ci	wpas_wps_ap_pin_enable(wpa_s, timeout);
1166e5b75505Sopenharmony_ci
1167e5b75505Sopenharmony_ci	return 0;
1168e5b75505Sopenharmony_ci}
1169e5b75505Sopenharmony_ci
1170e5b75505Sopenharmony_ci
1171e5b75505Sopenharmony_civoid wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s)
1172e5b75505Sopenharmony_ci{
1173e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1174e5b75505Sopenharmony_ci
1175e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1176e5b75505Sopenharmony_ci		return;
1177e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1178e5b75505Sopenharmony_ci
1179e5b75505Sopenharmony_ci	/*
1180e5b75505Sopenharmony_ci	 * Registrar failed to prove its knowledge of the AP PIN. Disable AP
1181e5b75505Sopenharmony_ci	 * PIN if this happens multiple times to slow down brute force attacks.
1182e5b75505Sopenharmony_ci	 */
1183e5b75505Sopenharmony_ci	hapd->ap_pin_failures++;
1184e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
1185e5b75505Sopenharmony_ci		   hapd->ap_pin_failures);
1186e5b75505Sopenharmony_ci	if (hapd->ap_pin_failures < 3)
1187e5b75505Sopenharmony_ci		return;
1188e5b75505Sopenharmony_ci
1189e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN");
1190e5b75505Sopenharmony_ci	hapd->ap_pin_failures = 0;
1191e5b75505Sopenharmony_ci	os_free(hapd->conf->ap_pin);
1192e5b75505Sopenharmony_ci	hapd->conf->ap_pin = NULL;
1193e5b75505Sopenharmony_ci}
1194e5b75505Sopenharmony_ci
1195e5b75505Sopenharmony_ci
1196e5b75505Sopenharmony_ci#ifdef CONFIG_WPS_NFC
1197e5b75505Sopenharmony_ci
1198e5b75505Sopenharmony_cistruct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
1199e5b75505Sopenharmony_ci					     int ndef)
1200e5b75505Sopenharmony_ci{
1201e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1202e5b75505Sopenharmony_ci
1203e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1204e5b75505Sopenharmony_ci		return NULL;
1205e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1206e5b75505Sopenharmony_ci	return hostapd_wps_nfc_config_token(hapd, ndef);
1207e5b75505Sopenharmony_ci}
1208e5b75505Sopenharmony_ci
1209e5b75505Sopenharmony_ci
1210e5b75505Sopenharmony_cistruct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
1211e5b75505Sopenharmony_ci					     int ndef)
1212e5b75505Sopenharmony_ci{
1213e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1214e5b75505Sopenharmony_ci
1215e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1216e5b75505Sopenharmony_ci		return NULL;
1217e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1218e5b75505Sopenharmony_ci	return hostapd_wps_nfc_hs_cr(hapd, ndef);
1219e5b75505Sopenharmony_ci}
1220e5b75505Sopenharmony_ci
1221e5b75505Sopenharmony_ci
1222e5b75505Sopenharmony_ciint wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
1223e5b75505Sopenharmony_ci				    const struct wpabuf *req,
1224e5b75505Sopenharmony_ci				    const struct wpabuf *sel)
1225e5b75505Sopenharmony_ci{
1226e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1227e5b75505Sopenharmony_ci
1228e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1229e5b75505Sopenharmony_ci		return -1;
1230e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1231e5b75505Sopenharmony_ci	return hostapd_wps_nfc_report_handover(hapd, req, sel);
1232e5b75505Sopenharmony_ci}
1233e5b75505Sopenharmony_ci
1234e5b75505Sopenharmony_ci#endif /* CONFIG_WPS_NFC */
1235e5b75505Sopenharmony_ci
1236e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */
1237e5b75505Sopenharmony_ci
1238e5b75505Sopenharmony_ci
1239e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE
1240e5b75505Sopenharmony_ci
1241e5b75505Sopenharmony_ciint ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
1242e5b75505Sopenharmony_ci			    char *buf, size_t buflen)
1243e5b75505Sopenharmony_ci{
1244e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1245e5b75505Sopenharmony_ci
1246e5b75505Sopenharmony_ci	if (wpa_s->ap_iface)
1247e5b75505Sopenharmony_ci		hapd = wpa_s->ap_iface->bss[0];
1248e5b75505Sopenharmony_ci	else if (wpa_s->ifmsh)
1249e5b75505Sopenharmony_ci		hapd = wpa_s->ifmsh->bss[0];
1250e5b75505Sopenharmony_ci	else
1251e5b75505Sopenharmony_ci		return -1;
1252e5b75505Sopenharmony_ci	return hostapd_ctrl_iface_sta_first(hapd, buf, buflen);
1253e5b75505Sopenharmony_ci}
1254e5b75505Sopenharmony_ci
1255e5b75505Sopenharmony_ci
1256e5b75505Sopenharmony_ciint ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
1257e5b75505Sopenharmony_ci		      char *buf, size_t buflen)
1258e5b75505Sopenharmony_ci{
1259e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1260e5b75505Sopenharmony_ci
1261e5b75505Sopenharmony_ci	if (wpa_s->ap_iface)
1262e5b75505Sopenharmony_ci		hapd = wpa_s->ap_iface->bss[0];
1263e5b75505Sopenharmony_ci	else if (wpa_s->ifmsh)
1264e5b75505Sopenharmony_ci		hapd = wpa_s->ifmsh->bss[0];
1265e5b75505Sopenharmony_ci	else
1266e5b75505Sopenharmony_ci		return -1;
1267e5b75505Sopenharmony_ci	return hostapd_ctrl_iface_sta(hapd, txtaddr, buf, buflen);
1268e5b75505Sopenharmony_ci}
1269e5b75505Sopenharmony_ci
1270e5b75505Sopenharmony_ci
1271e5b75505Sopenharmony_ciint ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
1272e5b75505Sopenharmony_ci			   char *buf, size_t buflen)
1273e5b75505Sopenharmony_ci{
1274e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1275e5b75505Sopenharmony_ci
1276e5b75505Sopenharmony_ci	if (wpa_s->ap_iface)
1277e5b75505Sopenharmony_ci		hapd = wpa_s->ap_iface->bss[0];
1278e5b75505Sopenharmony_ci	else if (wpa_s->ifmsh)
1279e5b75505Sopenharmony_ci		hapd = wpa_s->ifmsh->bss[0];
1280e5b75505Sopenharmony_ci	else
1281e5b75505Sopenharmony_ci		return -1;
1282e5b75505Sopenharmony_ci	return hostapd_ctrl_iface_sta_next(hapd, txtaddr, buf, buflen);
1283e5b75505Sopenharmony_ci}
1284e5b75505Sopenharmony_ci
1285e5b75505Sopenharmony_ci
1286e5b75505Sopenharmony_ciint ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s,
1287e5b75505Sopenharmony_ci				   const char *txtaddr)
1288e5b75505Sopenharmony_ci{
1289e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1290e5b75505Sopenharmony_ci		return -1;
1291e5b75505Sopenharmony_ci	return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0],
1292e5b75505Sopenharmony_ci					       txtaddr);
1293e5b75505Sopenharmony_ci}
1294e5b75505Sopenharmony_ci
1295e5b75505Sopenharmony_ci
1296e5b75505Sopenharmony_ciint ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s,
1297e5b75505Sopenharmony_ci				     const char *txtaddr)
1298e5b75505Sopenharmony_ci{
1299e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1300e5b75505Sopenharmony_ci		return -1;
1301e5b75505Sopenharmony_ci	return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0],
1302e5b75505Sopenharmony_ci						 txtaddr);
1303e5b75505Sopenharmony_ci}
1304e5b75505Sopenharmony_ci
1305e5b75505Sopenharmony_ci
1306e5b75505Sopenharmony_ciint ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
1307e5b75505Sopenharmony_ci				 size_t buflen, int verbose)
1308e5b75505Sopenharmony_ci{
1309e5b75505Sopenharmony_ci	char *pos = buf, *end = buf + buflen;
1310e5b75505Sopenharmony_ci	int ret;
1311e5b75505Sopenharmony_ci	struct hostapd_bss_config *conf;
1312e5b75505Sopenharmony_ci
1313e5b75505Sopenharmony_ci	if (wpa_s->ap_iface == NULL)
1314e5b75505Sopenharmony_ci		return -1;
1315e5b75505Sopenharmony_ci
1316e5b75505Sopenharmony_ci	conf = wpa_s->ap_iface->bss[0]->conf;
1317e5b75505Sopenharmony_ci	if (conf->wpa == 0)
1318e5b75505Sopenharmony_ci		return 0;
1319e5b75505Sopenharmony_ci
1320e5b75505Sopenharmony_ci	ret = os_snprintf(pos, end - pos,
1321e5b75505Sopenharmony_ci			  "pairwise_cipher=%s\n"
1322e5b75505Sopenharmony_ci			  "group_cipher=%s\n"
1323e5b75505Sopenharmony_ci			  "key_mgmt=%s\n",
1324e5b75505Sopenharmony_ci			  wpa_cipher_txt(conf->rsn_pairwise),
1325e5b75505Sopenharmony_ci			  wpa_cipher_txt(conf->wpa_group),
1326e5b75505Sopenharmony_ci			  wpa_key_mgmt_txt(conf->wpa_key_mgmt,
1327e5b75505Sopenharmony_ci					   conf->wpa));
1328e5b75505Sopenharmony_ci	if (os_snprintf_error(end - pos, ret))
1329e5b75505Sopenharmony_ci		return pos - buf;
1330e5b75505Sopenharmony_ci	pos += ret;
1331e5b75505Sopenharmony_ci	return pos - buf;
1332e5b75505Sopenharmony_ci}
1333e5b75505Sopenharmony_ci
1334e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE */
1335e5b75505Sopenharmony_ci
1336e5b75505Sopenharmony_ci
1337e5b75505Sopenharmony_ciint wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
1338e5b75505Sopenharmony_ci{
1339e5b75505Sopenharmony_ci	struct hostapd_iface *iface = wpa_s->ap_iface;
1340e5b75505Sopenharmony_ci	struct wpa_ssid *ssid = wpa_s->current_ssid;
1341e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1342e5b75505Sopenharmony_ci
1343e5b75505Sopenharmony_ci	if (ssid == NULL || wpa_s->ap_iface == NULL ||
1344e5b75505Sopenharmony_ci	    ssid->mode == WPAS_MODE_INFRA ||
1345e5b75505Sopenharmony_ci	    ssid->mode == WPAS_MODE_IBSS)
1346e5b75505Sopenharmony_ci		return -1;
1347e5b75505Sopenharmony_ci
1348e5b75505Sopenharmony_ci#ifdef CONFIG_P2P
1349e5b75505Sopenharmony_ci	if (ssid->mode == WPAS_MODE_P2P_GO)
1350e5b75505Sopenharmony_ci		iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
1351e5b75505Sopenharmony_ci	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1352e5b75505Sopenharmony_ci		iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
1353e5b75505Sopenharmony_ci			P2P_GROUP_FORMATION;
1354e5b75505Sopenharmony_ci#endif /* CONFIG_P2P */
1355e5b75505Sopenharmony_ci
1356e5b75505Sopenharmony_ci	hapd = iface->bss[0];
1357e5b75505Sopenharmony_ci	if (hapd->drv_priv == NULL)
1358e5b75505Sopenharmony_ci		return -1;
1359e5b75505Sopenharmony_ci	ieee802_11_set_beacons(iface);
1360e5b75505Sopenharmony_ci	hostapd_set_ap_wps_ie(hapd);
1361e5b75505Sopenharmony_ci
1362e5b75505Sopenharmony_ci	return 0;
1363e5b75505Sopenharmony_ci}
1364e5b75505Sopenharmony_ci
1365e5b75505Sopenharmony_ci
1366e5b75505Sopenharmony_ciint ap_switch_channel(struct wpa_supplicant *wpa_s,
1367e5b75505Sopenharmony_ci		      struct csa_settings *settings)
1368e5b75505Sopenharmony_ci{
1369e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
1370e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
1371e5b75505Sopenharmony_ci		return -1;
1372e5b75505Sopenharmony_ci
1373e5b75505Sopenharmony_ci	return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings);
1374e5b75505Sopenharmony_ci#else /* NEED_AP_MLME */
1375e5b75505Sopenharmony_ci	return -1;
1376e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
1377e5b75505Sopenharmony_ci}
1378e5b75505Sopenharmony_ci
1379e5b75505Sopenharmony_ci
1380e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE
1381e5b75505Sopenharmony_ciint ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
1382e5b75505Sopenharmony_ci{
1383e5b75505Sopenharmony_ci	struct csa_settings settings;
1384e5b75505Sopenharmony_ci	int ret = hostapd_parse_csa_settings(pos, &settings);
1385e5b75505Sopenharmony_ci
1386e5b75505Sopenharmony_ci	if (ret)
1387e5b75505Sopenharmony_ci		return ret;
1388e5b75505Sopenharmony_ci
1389e5b75505Sopenharmony_ci	return ap_switch_channel(wpa_s, &settings);
1390e5b75505Sopenharmony_ci}
1391e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE */
1392e5b75505Sopenharmony_ci
1393e5b75505Sopenharmony_ci
1394e5b75505Sopenharmony_civoid wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
1395e5b75505Sopenharmony_ci		       int offset, int width, int cf1, int cf2, int finished)
1396e5b75505Sopenharmony_ci{
1397e5b75505Sopenharmony_ci	struct hostapd_iface *iface = wpa_s->ap_iface;
1398e5b75505Sopenharmony_ci
1399e5b75505Sopenharmony_ci	if (!iface)
1400e5b75505Sopenharmony_ci		iface = wpa_s->ifmsh;
1401e5b75505Sopenharmony_ci	if (!iface)
1402e5b75505Sopenharmony_ci		return;
1403e5b75505Sopenharmony_ci	wpa_s->assoc_freq = freq;
1404e5b75505Sopenharmony_ci	if (wpa_s->current_ssid)
1405e5b75505Sopenharmony_ci		wpa_s->current_ssid->frequency = freq;
1406e5b75505Sopenharmony_ci	hostapd_event_ch_switch(iface->bss[0], freq, ht,
1407e5b75505Sopenharmony_ci				offset, width, cf1, cf2, finished);
1408e5b75505Sopenharmony_ci}
1409e5b75505Sopenharmony_ci
1410e5b75505Sopenharmony_ci
1411e5b75505Sopenharmony_ciint wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
1412e5b75505Sopenharmony_ci				      const u8 *addr)
1413e5b75505Sopenharmony_ci{
1414e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1415e5b75505Sopenharmony_ci	struct hostapd_bss_config *conf;
1416e5b75505Sopenharmony_ci
1417e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface)
1418e5b75505Sopenharmony_ci		return -1;
1419e5b75505Sopenharmony_ci
1420e5b75505Sopenharmony_ci	if (addr)
1421e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR,
1422e5b75505Sopenharmony_ci			   MAC2STR(addr));
1423e5b75505Sopenharmony_ci	else
1424e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter");
1425e5b75505Sopenharmony_ci
1426e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1427e5b75505Sopenharmony_ci	conf = hapd->conf;
1428e5b75505Sopenharmony_ci
1429e5b75505Sopenharmony_ci	os_free(conf->accept_mac);
1430e5b75505Sopenharmony_ci	conf->accept_mac = NULL;
1431e5b75505Sopenharmony_ci	conf->num_accept_mac = 0;
1432e5b75505Sopenharmony_ci	os_free(conf->deny_mac);
1433e5b75505Sopenharmony_ci	conf->deny_mac = NULL;
1434e5b75505Sopenharmony_ci	conf->num_deny_mac = 0;
1435e5b75505Sopenharmony_ci
1436e5b75505Sopenharmony_ci	if (addr == NULL) {
1437e5b75505Sopenharmony_ci		conf->macaddr_acl = ACCEPT_UNLESS_DENIED;
1438e5b75505Sopenharmony_ci		return 0;
1439e5b75505Sopenharmony_ci	}
1440e5b75505Sopenharmony_ci
1441e5b75505Sopenharmony_ci	conf->macaddr_acl = DENY_UNLESS_ACCEPTED;
1442e5b75505Sopenharmony_ci	conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry));
1443e5b75505Sopenharmony_ci	if (conf->accept_mac == NULL)
1444e5b75505Sopenharmony_ci		return -1;
1445e5b75505Sopenharmony_ci	os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN);
1446e5b75505Sopenharmony_ci	conf->num_accept_mac = 1;
1447e5b75505Sopenharmony_ci
1448e5b75505Sopenharmony_ci	return 0;
1449e5b75505Sopenharmony_ci}
1450e5b75505Sopenharmony_ci
1451e5b75505Sopenharmony_ci
1452e5b75505Sopenharmony_ci#ifdef CONFIG_WPS_NFC
1453e5b75505Sopenharmony_ciint wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
1454e5b75505Sopenharmony_ci			   const struct wpabuf *pw, const u8 *pubkey_hash)
1455e5b75505Sopenharmony_ci{
1456e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1457e5b75505Sopenharmony_ci	struct wps_context *wps;
1458e5b75505Sopenharmony_ci
1459e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface)
1460e5b75505Sopenharmony_ci		return -1;
1461e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1462e5b75505Sopenharmony_ci	wps = hapd->wps;
1463e5b75505Sopenharmony_ci
1464e5b75505Sopenharmony_ci	if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL ||
1465e5b75505Sopenharmony_ci	    wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) {
1466e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known");
1467e5b75505Sopenharmony_ci		return -1;
1468e5b75505Sopenharmony_ci	}
1469e5b75505Sopenharmony_ci
1470e5b75505Sopenharmony_ci	dh5_free(wps->dh_ctx);
1471e5b75505Sopenharmony_ci	wpabuf_free(wps->dh_pubkey);
1472e5b75505Sopenharmony_ci	wpabuf_free(wps->dh_privkey);
1473e5b75505Sopenharmony_ci	wps->dh_privkey = wpabuf_dup(
1474e5b75505Sopenharmony_ci		wpa_s->p2pdev->conf->wps_nfc_dh_privkey);
1475e5b75505Sopenharmony_ci	wps->dh_pubkey = wpabuf_dup(
1476e5b75505Sopenharmony_ci		wpa_s->p2pdev->conf->wps_nfc_dh_pubkey);
1477e5b75505Sopenharmony_ci	if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
1478e5b75505Sopenharmony_ci		wps->dh_ctx = NULL;
1479e5b75505Sopenharmony_ci		wpabuf_free(wps->dh_pubkey);
1480e5b75505Sopenharmony_ci		wps->dh_pubkey = NULL;
1481e5b75505Sopenharmony_ci		wpabuf_free(wps->dh_privkey);
1482e5b75505Sopenharmony_ci		wps->dh_privkey = NULL;
1483e5b75505Sopenharmony_ci		return -1;
1484e5b75505Sopenharmony_ci	}
1485e5b75505Sopenharmony_ci	wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
1486e5b75505Sopenharmony_ci	if (wps->dh_ctx == NULL)
1487e5b75505Sopenharmony_ci		return -1;
1488e5b75505Sopenharmony_ci
1489e5b75505Sopenharmony_ci	return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash,
1490e5b75505Sopenharmony_ci					      pw_id,
1491e5b75505Sopenharmony_ci					      pw ? wpabuf_head(pw) : NULL,
1492e5b75505Sopenharmony_ci					      pw ? wpabuf_len(pw) : 0, 1);
1493e5b75505Sopenharmony_ci}
1494e5b75505Sopenharmony_ci#endif /* CONFIG_WPS_NFC */
1495e5b75505Sopenharmony_ci
1496e5b75505Sopenharmony_ci
1497e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE
1498e5b75505Sopenharmony_ciint wpas_ap_stop_ap(struct wpa_supplicant *wpa_s)
1499e5b75505Sopenharmony_ci{
1500e5b75505Sopenharmony_ci	struct hostapd_data *hapd;
1501e5b75505Sopenharmony_ci
1502e5b75505Sopenharmony_ci	if (!wpa_s->ap_iface)
1503e5b75505Sopenharmony_ci		return -1;
1504e5b75505Sopenharmony_ci	hapd = wpa_s->ap_iface->bss[0];
1505e5b75505Sopenharmony_ci	return hostapd_ctrl_iface_stop_ap(hapd);
1506e5b75505Sopenharmony_ci}
1507e5b75505Sopenharmony_ci
1508e5b75505Sopenharmony_ci
1509e5b75505Sopenharmony_ciint wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
1510e5b75505Sopenharmony_ci			     size_t len)
1511e5b75505Sopenharmony_ci{
1512e5b75505Sopenharmony_ci	size_t reply_len = 0, i;
1513e5b75505Sopenharmony_ci	char ap_delimiter[] = "---- AP ----\n";
1514e5b75505Sopenharmony_ci	char mesh_delimiter[] = "---- mesh ----\n";
1515e5b75505Sopenharmony_ci	size_t dlen;
1516e5b75505Sopenharmony_ci
1517e5b75505Sopenharmony_ci	if (wpa_s->ap_iface) {
1518e5b75505Sopenharmony_ci		dlen = os_strlen(ap_delimiter);
1519e5b75505Sopenharmony_ci		if (dlen > len - reply_len)
1520e5b75505Sopenharmony_ci			return reply_len;
1521e5b75505Sopenharmony_ci		os_memcpy(&buf[reply_len], ap_delimiter, dlen);
1522e5b75505Sopenharmony_ci		reply_len += dlen;
1523e5b75505Sopenharmony_ci
1524e5b75505Sopenharmony_ci		for (i = 0; i < wpa_s->ap_iface->num_bss; i++) {
1525e5b75505Sopenharmony_ci			reply_len += hostapd_ctrl_iface_pmksa_list(
1526e5b75505Sopenharmony_ci				wpa_s->ap_iface->bss[i],
1527e5b75505Sopenharmony_ci				&buf[reply_len], len - reply_len);
1528e5b75505Sopenharmony_ci		}
1529e5b75505Sopenharmony_ci	}
1530e5b75505Sopenharmony_ci
1531e5b75505Sopenharmony_ci	if (wpa_s->ifmsh) {
1532e5b75505Sopenharmony_ci		dlen = os_strlen(mesh_delimiter);
1533e5b75505Sopenharmony_ci		if (dlen > len - reply_len)
1534e5b75505Sopenharmony_ci			return reply_len;
1535e5b75505Sopenharmony_ci		os_memcpy(&buf[reply_len], mesh_delimiter, dlen);
1536e5b75505Sopenharmony_ci		reply_len += dlen;
1537e5b75505Sopenharmony_ci
1538e5b75505Sopenharmony_ci		reply_len += hostapd_ctrl_iface_pmksa_list(
1539e5b75505Sopenharmony_ci			wpa_s->ifmsh->bss[0], &buf[reply_len],
1540e5b75505Sopenharmony_ci			len - reply_len);
1541e5b75505Sopenharmony_ci	}
1542e5b75505Sopenharmony_ci
1543e5b75505Sopenharmony_ci	return reply_len;
1544e5b75505Sopenharmony_ci}
1545e5b75505Sopenharmony_ci
1546e5b75505Sopenharmony_ci
1547e5b75505Sopenharmony_civoid wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
1548e5b75505Sopenharmony_ci{
1549e5b75505Sopenharmony_ci	size_t i;
1550e5b75505Sopenharmony_ci
1551e5b75505Sopenharmony_ci	if (wpa_s->ap_iface) {
1552e5b75505Sopenharmony_ci		for (i = 0; i < wpa_s->ap_iface->num_bss; i++)
1553e5b75505Sopenharmony_ci			hostapd_ctrl_iface_pmksa_flush(wpa_s->ap_iface->bss[i]);
1554e5b75505Sopenharmony_ci	}
1555e5b75505Sopenharmony_ci
1556e5b75505Sopenharmony_ci	if (wpa_s->ifmsh)
1557e5b75505Sopenharmony_ci		hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]);
1558e5b75505Sopenharmony_ci}
1559e5b75505Sopenharmony_ci
1560e5b75505Sopenharmony_ci
1561e5b75505Sopenharmony_ci#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
1562e5b75505Sopenharmony_ci#ifdef CONFIG_MESH
1563e5b75505Sopenharmony_ci
1564e5b75505Sopenharmony_ciint wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
1565e5b75505Sopenharmony_ci				  char *buf, size_t len)
1566e5b75505Sopenharmony_ci{
1567e5b75505Sopenharmony_ci	return hostapd_ctrl_iface_pmksa_list_mesh(wpa_s->ifmsh->bss[0], addr,
1568e5b75505Sopenharmony_ci						  &buf[0], len);
1569e5b75505Sopenharmony_ci}
1570e5b75505Sopenharmony_ci
1571e5b75505Sopenharmony_ci
1572e5b75505Sopenharmony_ciint wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd)
1573e5b75505Sopenharmony_ci{
1574e5b75505Sopenharmony_ci	struct external_pmksa_cache *entry;
1575e5b75505Sopenharmony_ci	void *pmksa_cache;
1576e5b75505Sopenharmony_ci
1577e5b75505Sopenharmony_ci	pmksa_cache = hostapd_ctrl_iface_pmksa_create_entry(wpa_s->own_addr,
1578e5b75505Sopenharmony_ci							    cmd);
1579e5b75505Sopenharmony_ci	if (!pmksa_cache)
1580e5b75505Sopenharmony_ci		return -1;
1581e5b75505Sopenharmony_ci
1582e5b75505Sopenharmony_ci	entry = os_zalloc(sizeof(struct external_pmksa_cache));
1583e5b75505Sopenharmony_ci	if (!entry)
1584e5b75505Sopenharmony_ci		return -1;
1585e5b75505Sopenharmony_ci
1586e5b75505Sopenharmony_ci	entry->pmksa_cache = pmksa_cache;
1587e5b75505Sopenharmony_ci
1588e5b75505Sopenharmony_ci	dl_list_add(&wpa_s->mesh_external_pmksa_cache, &entry->list);
1589e5b75505Sopenharmony_ci
1590e5b75505Sopenharmony_ci	return 0;
1591e5b75505Sopenharmony_ci}
1592e5b75505Sopenharmony_ci
1593e5b75505Sopenharmony_ci#endif /* CONFIG_MESH */
1594e5b75505Sopenharmony_ci#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
1595e5b75505Sopenharmony_ci
1596e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE */
1597e5b75505Sopenharmony_ci
1598e5b75505Sopenharmony_ci
1599e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME
1600e5b75505Sopenharmony_civoid wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
1601e5b75505Sopenharmony_ci				      struct dfs_event *radar)
1602e5b75505Sopenharmony_ci{
1603e5b75505Sopenharmony_ci	struct hostapd_iface *iface = wpa_s->ap_iface;
1604e5b75505Sopenharmony_ci
1605e5b75505Sopenharmony_ci	if (!iface)
1606e5b75505Sopenharmony_ci		iface = wpa_s->ifmsh;
1607e5b75505Sopenharmony_ci	if (!iface || !iface->bss[0])
1608e5b75505Sopenharmony_ci		return;
1609e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
1610e5b75505Sopenharmony_ci	hostapd_dfs_radar_detected(iface, radar->freq,
1611e5b75505Sopenharmony_ci				   radar->ht_enabled, radar->chan_offset,
1612e5b75505Sopenharmony_ci				   radar->chan_width,
1613e5b75505Sopenharmony_ci				   radar->cf1, radar->cf2);
1614e5b75505Sopenharmony_ci}
1615e5b75505Sopenharmony_ci
1616e5b75505Sopenharmony_ci
1617e5b75505Sopenharmony_civoid wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
1618e5b75505Sopenharmony_ci				   struct dfs_event *radar)
1619e5b75505Sopenharmony_ci{
1620e5b75505Sopenharmony_ci	struct hostapd_iface *iface = wpa_s->ap_iface;
1621e5b75505Sopenharmony_ci
1622e5b75505Sopenharmony_ci	if (!iface)
1623e5b75505Sopenharmony_ci		iface = wpa_s->ifmsh;
1624e5b75505Sopenharmony_ci	if (!iface || !iface->bss[0])
1625e5b75505Sopenharmony_ci		return;
1626e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
1627e5b75505Sopenharmony_ci	hostapd_dfs_start_cac(iface, radar->freq,
1628e5b75505Sopenharmony_ci			      radar->ht_enabled, radar->chan_offset,
1629e5b75505Sopenharmony_ci			      radar->chan_width, radar->cf1, radar->cf2);
1630e5b75505Sopenharmony_ci}
1631e5b75505Sopenharmony_ci
1632e5b75505Sopenharmony_ci
1633e5b75505Sopenharmony_civoid wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
1634e5b75505Sopenharmony_ci				    struct dfs_event *radar)
1635e5b75505Sopenharmony_ci{
1636e5b75505Sopenharmony_ci	struct hostapd_iface *iface = wpa_s->ap_iface;
1637e5b75505Sopenharmony_ci
1638e5b75505Sopenharmony_ci	if (!iface)
1639e5b75505Sopenharmony_ci		iface = wpa_s->ifmsh;
1640e5b75505Sopenharmony_ci	if (!iface || !iface->bss[0])
1641e5b75505Sopenharmony_ci		return;
1642e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
1643e5b75505Sopenharmony_ci	hostapd_dfs_complete_cac(iface, 1, radar->freq,
1644e5b75505Sopenharmony_ci				 radar->ht_enabled, radar->chan_offset,
1645e5b75505Sopenharmony_ci				 radar->chan_width, radar->cf1, radar->cf2);
1646e5b75505Sopenharmony_ci}
1647e5b75505Sopenharmony_ci
1648e5b75505Sopenharmony_ci
1649e5b75505Sopenharmony_civoid wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
1650e5b75505Sopenharmony_ci				   struct dfs_event *radar)
1651e5b75505Sopenharmony_ci{
1652e5b75505Sopenharmony_ci	struct hostapd_iface *iface = wpa_s->ap_iface;
1653e5b75505Sopenharmony_ci
1654e5b75505Sopenharmony_ci	if (!iface)
1655e5b75505Sopenharmony_ci		iface = wpa_s->ifmsh;
1656e5b75505Sopenharmony_ci	if (!iface || !iface->bss[0])
1657e5b75505Sopenharmony_ci		return;
1658e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
1659e5b75505Sopenharmony_ci	hostapd_dfs_complete_cac(iface, 0, radar->freq,
1660e5b75505Sopenharmony_ci				 radar->ht_enabled, radar->chan_offset,
1661e5b75505Sopenharmony_ci				 radar->chan_width, radar->cf1, radar->cf2);
1662e5b75505Sopenharmony_ci}
1663e5b75505Sopenharmony_ci
1664e5b75505Sopenharmony_ci
1665e5b75505Sopenharmony_civoid wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
1666e5b75505Sopenharmony_ci					struct dfs_event *radar)
1667e5b75505Sopenharmony_ci{
1668e5b75505Sopenharmony_ci	struct hostapd_iface *iface = wpa_s->ap_iface;
1669e5b75505Sopenharmony_ci
1670e5b75505Sopenharmony_ci	if (!iface)
1671e5b75505Sopenharmony_ci		iface = wpa_s->ifmsh;
1672e5b75505Sopenharmony_ci	if (!iface || !iface->bss[0])
1673e5b75505Sopenharmony_ci		return;
1674e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
1675e5b75505Sopenharmony_ci	hostapd_dfs_nop_finished(iface, radar->freq,
1676e5b75505Sopenharmony_ci				 radar->ht_enabled, radar->chan_offset,
1677e5b75505Sopenharmony_ci				 radar->chan_width, radar->cf1, radar->cf2);
1678e5b75505Sopenharmony_ci}
1679e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */
1680e5b75505Sopenharmony_ci
1681e5b75505Sopenharmony_ci
1682e5b75505Sopenharmony_civoid ap_periodic(struct wpa_supplicant *wpa_s)
1683e5b75505Sopenharmony_ci{
1684e5b75505Sopenharmony_ci	if (wpa_s->ap_iface)
1685e5b75505Sopenharmony_ci		hostapd_periodic_iface(wpa_s->ap_iface);
1686e5b75505Sopenharmony_ci}
1687