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