xref: /freebsd/contrib/wpa/wpa_supplicant/ap.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
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"
175b9c547cSRui Paulo #include "eapol_supp/eapol_supp_sm.h"
185b9c547cSRui 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"
295b9c547cSRui 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 
47c1d255d3SCy Schubert #ifdef CONFIG_P2P
is_chanwidth160_supported(struct hostapd_hw_modes * mode,struct hostapd_config * conf)48c1d255d3SCy Schubert static bool is_chanwidth160_supported(struct hostapd_hw_modes *mode,
49c1d255d3SCy Schubert 				      struct hostapd_config *conf)
50c1d255d3SCy Schubert {
51c1d255d3SCy Schubert #ifdef CONFIG_IEEE80211AX
52c1d255d3SCy Schubert 	if (conf->ieee80211ax) {
53c1d255d3SCy Schubert 		struct he_capabilities *he_cap;
54c1d255d3SCy Schubert 
55c1d255d3SCy Schubert 		he_cap = &mode->he_capab[IEEE80211_MODE_AP];
56c1d255d3SCy Schubert 		if (he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
57c1d255d3SCy Schubert 		    (HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G |
58c1d255d3SCy Schubert 		     HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G))
59c1d255d3SCy Schubert 			return true;
60c1d255d3SCy Schubert 	}
61c1d255d3SCy Schubert #endif /* CONFIG_IEEE80211AX */
62c1d255d3SCy Schubert 	if (mode->vht_capab & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
63c1d255d3SCy Schubert 			       VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
64c1d255d3SCy Schubert 		return true;
65c1d255d3SCy Schubert 	return false;
66c1d255d3SCy Schubert }
67c1d255d3SCy Schubert #endif /* CONFIG_P2P */
68c1d255d3SCy Schubert 
69c1d255d3SCy Schubert 
wpas_conf_ap_vht(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,struct hostapd_config * conf,struct hostapd_hw_modes * mode)705b9c547cSRui Paulo static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
7185732ac8SCy Schubert 			     struct wpa_ssid *ssid,
725b9c547cSRui Paulo 			     struct hostapd_config *conf,
735b9c547cSRui Paulo 			     struct hostapd_hw_modes *mode)
745b9c547cSRui Paulo {
755b9c547cSRui Paulo #ifdef CONFIG_P2P
765b9c547cSRui Paulo 	u8 center_chan = 0;
775b9c547cSRui Paulo 	u8 channel = conf->channel;
7885732ac8SCy Schubert #endif /* CONFIG_P2P */
79c1d255d3SCy Schubert 	u8 freq_seg_idx;
805b9c547cSRui Paulo 
815b9c547cSRui Paulo 	if (!conf->secondary_channel)
825b9c547cSRui Paulo 		goto no_vht;
835b9c547cSRui Paulo 
8485732ac8SCy Schubert 	/* Use the maximum oper channel width if it's given. */
8585732ac8SCy Schubert 	if (ssid->max_oper_chwidth)
86c1d255d3SCy Schubert 		hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
874b72b91aSCy Schubert 	if (hostapd_get_oper_chwidth(conf))
884b72b91aSCy Schubert 		ieee80211_freq_to_channel_ext(ssid->frequency, 0,
894b72b91aSCy Schubert 					      hostapd_get_oper_chwidth(conf),
904b72b91aSCy Schubert 					      &conf->op_class,
914b72b91aSCy Schubert 					      &conf->channel);
9285732ac8SCy Schubert 
93*a90b9d01SCy Schubert 	if (hostapd_get_oper_chwidth(conf) == CONF_OPER_CHWIDTH_80P80MHZ) {
9485732ac8SCy Schubert 		ieee80211_freq_to_chan(ssid->vht_center_freq2,
95c1d255d3SCy Schubert 				       &freq_seg_idx);
96c1d255d3SCy Schubert 		hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx);
97c1d255d3SCy Schubert 	}
9885732ac8SCy Schubert 
9985732ac8SCy Schubert 	if (!ssid->p2p_group) {
100c1d255d3SCy Schubert 		if (!ssid->vht_center_freq1)
10185732ac8SCy Schubert 			goto no_vht;
10285732ac8SCy Schubert 		ieee80211_freq_to_chan(ssid->vht_center_freq1,
103c1d255d3SCy Schubert 				       &freq_seg_idx);
104c1d255d3SCy Schubert 		hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx);
105c1d255d3SCy Schubert 
106c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
107c1d255d3SCy Schubert 			   "VHT seg0 index %d and seg1 index %d for AP",
108c1d255d3SCy Schubert 			   hostapd_get_oper_centr_freq_seg0_idx(conf),
109c1d255d3SCy Schubert 			   hostapd_get_oper_centr_freq_seg1_idx(conf));
11085732ac8SCy Schubert 		return;
11185732ac8SCy Schubert 	}
11285732ac8SCy Schubert 
11385732ac8SCy Schubert #ifdef CONFIG_P2P
114c1d255d3SCy Schubert 	switch (hostapd_get_oper_chwidth(conf)) {
115*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_80MHZ:
116*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_80P80MHZ:
117c1d255d3SCy Schubert 		center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel,
118c1d255d3SCy Schubert 							conf->op_class);
11985732ac8SCy Schubert 		wpa_printf(MSG_DEBUG,
12085732ac8SCy Schubert 			   "VHT center channel %u for 80 or 80+80 MHz bandwidth",
12185732ac8SCy Schubert 			   center_chan);
122780fb4a2SCy Schubert 		break;
123*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_160MHZ:
124c1d255d3SCy Schubert 		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel,
125c1d255d3SCy Schubert 							 conf->op_class);
12685732ac8SCy Schubert 		wpa_printf(MSG_DEBUG,
12785732ac8SCy Schubert 			   "VHT center channel %u for 160 MHz bandwidth",
12885732ac8SCy Schubert 			   center_chan);
129780fb4a2SCy Schubert 		break;
130780fb4a2SCy Schubert 	default:
131780fb4a2SCy Schubert 		/*
132780fb4a2SCy Schubert 		 * conf->vht_oper_chwidth might not be set for non-P2P GO cases,
133780fb4a2SCy Schubert 		 * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is
134780fb4a2SCy Schubert 		 * not supported.
135780fb4a2SCy Schubert 		 */
136*a90b9d01SCy Schubert 		hostapd_set_oper_chwidth(conf, CONF_OPER_CHWIDTH_160MHZ);
137c1d255d3SCy Schubert 		ieee80211_freq_to_channel_ext(ssid->frequency, 0,
138c1d255d3SCy Schubert 					      conf->vht_oper_chwidth,
139c1d255d3SCy Schubert 					      &conf->op_class,
140c1d255d3SCy Schubert 					      &conf->channel);
141c1d255d3SCy Schubert 		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel,
142c1d255d3SCy Schubert 							 conf->op_class);
143c1d255d3SCy Schubert 		if (center_chan && is_chanwidth160_supported(mode, conf)) {
14485732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
14585732ac8SCy Schubert 				   "VHT center channel %u for auto-selected 160 MHz bandwidth",
14685732ac8SCy Schubert 				   center_chan);
14785732ac8SCy Schubert 		} else {
148*a90b9d01SCy Schubert 			hostapd_set_oper_chwidth(conf, CONF_OPER_CHWIDTH_80MHZ);
149c1d255d3SCy Schubert 			ieee80211_freq_to_channel_ext(ssid->frequency, 0,
150c1d255d3SCy Schubert 						      conf->vht_oper_chwidth,
151c1d255d3SCy Schubert 						      &conf->op_class,
152c1d255d3SCy Schubert 						      &conf->channel);
153780fb4a2SCy Schubert 			center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
154c1d255d3SCy Schubert 								channel,
155c1d255d3SCy Schubert 								conf->op_class);
15685732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
15785732ac8SCy Schubert 				   "VHT center channel %u for auto-selected 80 MHz bandwidth",
15885732ac8SCy Schubert 				   center_chan);
159780fb4a2SCy Schubert 		}
160780fb4a2SCy Schubert 		break;
161780fb4a2SCy Schubert 	}
1625b9c547cSRui Paulo 	if (!center_chan)
1635b9c547cSRui Paulo 		goto no_vht;
1645b9c547cSRui Paulo 
165c1d255d3SCy Schubert 	hostapd_set_oper_centr_freq_seg0_idx(conf, center_chan);
16685732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO",
167c1d255d3SCy Schubert 		   hostapd_get_oper_centr_freq_seg0_idx(conf));
1685b9c547cSRui Paulo 	return;
16985732ac8SCy Schubert #endif /* CONFIG_P2P */
1705b9c547cSRui Paulo 
1715b9c547cSRui Paulo no_vht:
17285732ac8SCy Schubert 	wpa_printf(MSG_DEBUG,
17385732ac8SCy Schubert 		   "No VHT higher bandwidth support for the selected channel %d",
17485732ac8SCy Schubert 		   conf->channel);
175c1d255d3SCy Schubert 	hostapd_set_oper_centr_freq_seg0_idx(
176c1d255d3SCy Schubert 		conf, conf->channel + conf->secondary_channel * 2);
177*a90b9d01SCy Schubert 	hostapd_set_oper_chwidth(conf, CONF_OPER_CHWIDTH_USE_HT);
178*a90b9d01SCy Schubert 	ieee80211_freq_to_channel_ext(ssid->frequency, 0,
179*a90b9d01SCy Schubert 				      conf->vht_oper_chwidth,
180*a90b9d01SCy Schubert 				      &conf->op_class, &conf->channel);
1815b9c547cSRui Paulo }
182c1d255d3SCy Schubert 
183c1d255d3SCy Schubert 
184c1d255d3SCy Schubert static struct hostapd_hw_modes *
wpa_supplicant_find_hw_mode(struct wpa_supplicant * wpa_s,enum hostapd_hw_mode hw_mode)185c1d255d3SCy Schubert wpa_supplicant_find_hw_mode(struct wpa_supplicant *wpa_s,
186c1d255d3SCy Schubert 			    enum hostapd_hw_mode hw_mode)
187c1d255d3SCy Schubert {
188c1d255d3SCy Schubert 	struct hostapd_hw_modes *mode = NULL;
189c1d255d3SCy Schubert 	int i;
190c1d255d3SCy Schubert 
191c1d255d3SCy Schubert 	for (i = 0; i < wpa_s->hw.num_modes; i++) {
192c1d255d3SCy Schubert 		if (wpa_s->hw.modes[i].mode == hw_mode) {
193c1d255d3SCy Schubert 			mode = &wpa_s->hw.modes[i];
194c1d255d3SCy Schubert 			break;
195c1d255d3SCy Schubert 		}
196c1d255d3SCy Schubert 	}
197c1d255d3SCy Schubert 
198c1d255d3SCy Schubert 	return mode;
199c1d255d3SCy Schubert }
2005b9c547cSRui Paulo 
2015b9c547cSRui Paulo 
2024b72b91aSCy Schubert #ifdef CONFIG_P2P
2034b72b91aSCy Schubert 
get_max_oper_chwidth_6ghz(int chwidth)2044b72b91aSCy Schubert static int get_max_oper_chwidth_6ghz(int chwidth)
2054b72b91aSCy Schubert {
2064b72b91aSCy Schubert 	switch (chwidth) {
207*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_USE_HT:
2084b72b91aSCy Schubert 		return 20;
209*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_40MHZ_6GHZ:
2104b72b91aSCy Schubert 		return 40;
211*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_80MHZ:
2124b72b91aSCy Schubert 		return 80;
213*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_80P80MHZ:
214*a90b9d01SCy Schubert 	case CONF_OPER_CHWIDTH_160MHZ:
2154b72b91aSCy Schubert 		return 160;
2164b72b91aSCy Schubert 	default:
2174b72b91aSCy Schubert 		return 0;
2184b72b91aSCy Schubert 	}
2194b72b91aSCy Schubert }
2204b72b91aSCy Schubert 
2214b72b91aSCy Schubert 
wpas_conf_ap_he_6ghz(struct wpa_supplicant * wpa_s,struct hostapd_hw_modes * mode,struct wpa_ssid * ssid,struct hostapd_config * conf)2224b72b91aSCy Schubert static void wpas_conf_ap_he_6ghz(struct wpa_supplicant *wpa_s,
2234b72b91aSCy Schubert 				 struct hostapd_hw_modes *mode,
2244b72b91aSCy Schubert 				 struct wpa_ssid *ssid,
2254b72b91aSCy Schubert 				 struct hostapd_config *conf)
2264b72b91aSCy Schubert {
2274b72b91aSCy Schubert 	bool is_chanwidth_40_80, is_chanwidth_160;
2284b72b91aSCy Schubert 	int he_chanwidth;
2294b72b91aSCy Schubert 
2304b72b91aSCy Schubert 	he_chanwidth =
2314b72b91aSCy Schubert 		mode->he_capab[wpas_mode_to_ieee80211_mode(
2324b72b91aSCy Schubert 			ssid->mode)].phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
2334b72b91aSCy Schubert 	is_chanwidth_40_80 = he_chanwidth &
2344b72b91aSCy Schubert 		HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
2354b72b91aSCy Schubert 	is_chanwidth_160 = he_chanwidth &
2364b72b91aSCy Schubert 		HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
2374b72b91aSCy Schubert 
2384b72b91aSCy Schubert 	wpa_printf(MSG_DEBUG,
2394b72b91aSCy Schubert 		   "Enable HE support (p2p_group=%d he_chwidth_cap=%d)",
2404b72b91aSCy Schubert 		   ssid->p2p_group, he_chanwidth);
2414b72b91aSCy Schubert 
2424b72b91aSCy Schubert 	if (mode->he_capab[wpas_mode_to_ieee80211_mode(
2434b72b91aSCy Schubert 			    ssid->mode)].he_supported &&
2444b72b91aSCy Schubert 	    ssid->he)
2454b72b91aSCy Schubert 		conf->ieee80211ax = 1;
2464b72b91aSCy Schubert 
2474b72b91aSCy Schubert 	if (is_chanwidth_40_80 && ssid->p2p_group &&
2484b72b91aSCy Schubert 	    get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 40) {
2494b72b91aSCy Schubert 		conf->secondary_channel =
2504b72b91aSCy Schubert 			wpas_p2p_get_sec_channel_offset_40mhz(
2514b72b91aSCy Schubert 				wpa_s, mode, conf->channel);
2524b72b91aSCy Schubert 		wpa_printf(MSG_DEBUG,
2534b72b91aSCy Schubert 			   "Secondary channel offset %d for P2P group",
2544b72b91aSCy Schubert 			   conf->secondary_channel);
255*a90b9d01SCy Schubert 		if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_40MHZ_6GHZ)
256*a90b9d01SCy Schubert 			ssid->max_oper_chwidth = CONF_OPER_CHWIDTH_USE_HT;
2574b72b91aSCy Schubert 	}
2584b72b91aSCy Schubert 
2594b72b91aSCy Schubert 	if ((is_chanwidth_40_80 || is_chanwidth_160) && ssid->p2p_group &&
2604b72b91aSCy Schubert 	    get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 80)
2614b72b91aSCy Schubert 		wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
2624b72b91aSCy Schubert }
2634b72b91aSCy Schubert 
2644b72b91aSCy Schubert #endif /* CONFIG_P2P */
2654b72b91aSCy Schubert 
2664b72b91aSCy Schubert 
wpa_supplicant_conf_ap_ht(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,struct hostapd_config * conf)267780fb4a2SCy Schubert int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
268e28a4053SRui Paulo 			      struct wpa_ssid *ssid,
269e28a4053SRui Paulo 			      struct hostapd_config *conf)
270e28a4053SRui Paulo {
271c1d255d3SCy Schubert 	conf->hw_mode = ieee80211_freq_to_channel_ext(ssid->frequency, 0,
272*a90b9d01SCy Schubert 						      CONF_OPER_CHWIDTH_USE_HT,
273c1d255d3SCy Schubert 						      &conf->op_class,
274c1d255d3SCy Schubert 						      &conf->channel);
275780fb4a2SCy Schubert 	if (conf->hw_mode == NUM_HOSTAPD_MODES) {
276780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
277780fb4a2SCy Schubert 			   ssid->frequency);
278780fb4a2SCy Schubert 		return -1;
279780fb4a2SCy Schubert 	}
280780fb4a2SCy Schubert 
281f05cddf9SRui Paulo 	/*
282f05cddf9SRui Paulo 	 * Enable HT20 if the driver supports it, by setting conf->ieee80211n
283f05cddf9SRui Paulo 	 * and a mask of allowed capabilities within conf->ht_capab.
284f05cddf9SRui Paulo 	 * Using default config settings for: conf->ht_op_mode_fixed,
285f05cddf9SRui Paulo 	 * conf->secondary_channel, conf->require_ht
286f05cddf9SRui Paulo 	 */
287f05cddf9SRui Paulo 	if (wpa_s->hw.modes) {
288f05cddf9SRui Paulo 		struct hostapd_hw_modes *mode = NULL;
289c1d255d3SCy Schubert 		int no_ht = 0;
29085732ac8SCy Schubert 
29185732ac8SCy Schubert 		wpa_printf(MSG_DEBUG,
29285732ac8SCy Schubert 			   "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)",
29385732ac8SCy Schubert 			   ssid->frequency, conf->channel);
29485732ac8SCy Schubert 
2954b72b91aSCy Schubert 		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
2964b72b91aSCy Schubert 				conf->hw_mode, is_6ghz_freq(ssid->frequency));
297c1d255d3SCy Schubert 
298c1d255d3SCy Schubert 		/* May drop to IEEE 802.11b if the driver does not support IEEE
299c1d255d3SCy Schubert 		 * 802.11g */
300c1d255d3SCy Schubert 		if (!mode && conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
301c1d255d3SCy Schubert 			conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
302c1d255d3SCy Schubert 			wpa_printf(MSG_INFO,
303c1d255d3SCy Schubert 				   "Try downgrade to IEEE 802.11b as 802.11g is not supported by the current hardware");
304c1d255d3SCy Schubert 			mode = wpa_supplicant_find_hw_mode(wpa_s,
305c1d255d3SCy Schubert 							   conf->hw_mode);
306f05cddf9SRui Paulo 		}
307c1d255d3SCy Schubert 
308c1d255d3SCy Schubert 		if (!mode) {
309c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
310c1d255d3SCy Schubert 				   "No match between requested and supported hw modes found");
311c1d255d3SCy Schubert 			return -1;
312f05cddf9SRui Paulo 		}
313f05cddf9SRui Paulo 
314f05cddf9SRui Paulo #ifdef CONFIG_HT_OVERRIDES
31585732ac8SCy Schubert 		if (ssid->disable_ht)
31685732ac8SCy Schubert 			ssid->ht = 0;
317*a90b9d01SCy Schubert 		if (ssid->disable_ht40)
318*a90b9d01SCy Schubert 			ssid->ht40 = 0;
31985732ac8SCy Schubert #endif /* CONFIG_HT_OVERRIDES */
32085732ac8SCy Schubert 
321*a90b9d01SCy Schubert #ifdef CONFIG_VHT_OVERRIDES
322*a90b9d01SCy Schubert 		if (ssid->disable_vht)
323*a90b9d01SCy Schubert 			ssid->vht = 0;
324*a90b9d01SCy Schubert #endif /* CONFIG_VHT_OVERRIDES */
325*a90b9d01SCy Schubert 
326*a90b9d01SCy Schubert #ifdef CONFIG_HE_OVERRIDES
327*a90b9d01SCy Schubert 		if (ssid->disable_he)
328*a90b9d01SCy Schubert 			ssid->he = 0;
329*a90b9d01SCy Schubert #endif /* CONFIG_HE_OVERRIDES */
330*a90b9d01SCy Schubert 
33185732ac8SCy Schubert 		if (!ssid->ht) {
33285732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
33385732ac8SCy Schubert 				   "HT not enabled in network profile");
334f05cddf9SRui Paulo 			conf->ieee80211n = 0;
335f05cddf9SRui Paulo 			conf->ht_capab = 0;
336f05cddf9SRui Paulo 			no_ht = 1;
337f05cddf9SRui Paulo 		}
338f05cddf9SRui Paulo 
3394b72b91aSCy Schubert 		if (mode && is_6ghz_freq(ssid->frequency) &&
3404b72b91aSCy Schubert 		    conf->hw_mode == HOSTAPD_MODE_IEEE80211A) {
341*a90b9d01SCy Schubert 			if (mode->eht_capab[wpas_mode_to_ieee80211_mode(
342*a90b9d01SCy Schubert 					    ssid->mode)].eht_supported &&
343*a90b9d01SCy Schubert 			    ssid->eht)
344*a90b9d01SCy Schubert 				conf->ieee80211be = 1;
345*a90b9d01SCy Schubert 
346*a90b9d01SCy Schubert 			if (mode->he_capab[wpas_mode_to_ieee80211_mode(
347*a90b9d01SCy Schubert 					    ssid->mode)].he_supported &&
348*a90b9d01SCy Schubert 			    ssid->he)
349*a90b9d01SCy Schubert 				conf->ieee80211ax = 1;
350*a90b9d01SCy Schubert 
3514b72b91aSCy Schubert #ifdef CONFIG_P2P
3524b72b91aSCy Schubert 			wpas_conf_ap_he_6ghz(wpa_s, mode, ssid, conf);
3534b72b91aSCy Schubert #endif /* CONFIG_P2P */
3544b72b91aSCy Schubert 		} else if (!no_ht && mode && mode->ht_capab) {
35585732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
35685732ac8SCy Schubert 				   "Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)",
35785732ac8SCy Schubert 				   ssid->p2p_group,
35885732ac8SCy Schubert 				   conf->hw_mode == HOSTAPD_MODE_IEEE80211A,
35985732ac8SCy Schubert 				   !!(mode->ht_capab &
36085732ac8SCy Schubert 				      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET),
36185732ac8SCy Schubert 				   ssid->ht40);
362f05cddf9SRui Paulo 			conf->ieee80211n = 1;
363c1d255d3SCy Schubert 
364c1d255d3SCy Schubert 			if (ssid->ht40 &&
365c1d255d3SCy Schubert 			    (mode->ht_capab &
366c1d255d3SCy Schubert 			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
367c1d255d3SCy Schubert 				conf->secondary_channel = ssid->ht40;
368c1d255d3SCy Schubert 			else
369c1d255d3SCy Schubert 				conf->secondary_channel = 0;
370c1d255d3SCy Schubert 
371f05cddf9SRui Paulo #ifdef CONFIG_P2P
37285732ac8SCy Schubert 			if (ssid->p2p_group &&
37385732ac8SCy Schubert 			    conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&
374f05cddf9SRui Paulo 			    (mode->ht_capab &
375f05cddf9SRui Paulo 			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
37685732ac8SCy Schubert 			    ssid->ht40) {
377f05cddf9SRui Paulo 				conf->secondary_channel =
3784b72b91aSCy Schubert 					wpas_p2p_get_sec_channel_offset_40mhz(
3794b72b91aSCy Schubert 						wpa_s, mode, conf->channel);
38085732ac8SCy Schubert 				wpa_printf(MSG_DEBUG,
38185732ac8SCy Schubert 					   "HT secondary channel offset %d for P2P group",
38285732ac8SCy Schubert 					   conf->secondary_channel);
383c1d255d3SCy Schubert 			} else if (ssid->p2p_group && conf->secondary_channel &&
384c1d255d3SCy Schubert 				   conf->hw_mode != HOSTAPD_MODE_IEEE80211A) {
385c1d255d3SCy Schubert 				/* This ended up trying to configure invalid
386c1d255d3SCy Schubert 				 * 2.4 GHz channels (e.g., HT40+ on channel 11)
387c1d255d3SCy Schubert 				 * in some cases, so clear the secondary channel
388c1d255d3SCy Schubert 				 * configuration now to avoid such cases that
389c1d255d3SCy Schubert 				 * would lead to group formation failures. */
390c1d255d3SCy Schubert 				wpa_printf(MSG_DEBUG,
391c1d255d3SCy Schubert 					   "Disable HT secondary channel for P2P group on 2.4 GHz");
392c1d255d3SCy Schubert 				conf->secondary_channel = 0;
39385732ac8SCy Schubert 			}
39485732ac8SCy Schubert #endif /* CONFIG_P2P */
39585732ac8SCy Schubert 
39685732ac8SCy Schubert 			if (!ssid->p2p_group &&
39785732ac8SCy Schubert 			    (mode->ht_capab &
39885732ac8SCy Schubert 			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
39985732ac8SCy Schubert 				conf->secondary_channel = ssid->ht40;
40085732ac8SCy Schubert 				wpa_printf(MSG_DEBUG,
40185732ac8SCy Schubert 					   "HT secondary channel offset %d for AP",
40285732ac8SCy Schubert 					   conf->secondary_channel);
40385732ac8SCy Schubert 			}
40485732ac8SCy Schubert 
405f05cddf9SRui Paulo 			if (conf->secondary_channel)
406f05cddf9SRui Paulo 				conf->ht_capab |=
407f05cddf9SRui Paulo 					HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
408f05cddf9SRui Paulo 
409f05cddf9SRui Paulo 			/*
410*a90b9d01SCy Schubert 			 * include capabilities that won't cause issues
411f05cddf9SRui Paulo 			 * to connecting stations, while leaving the current
412f05cddf9SRui Paulo 			 * capabilities intact (currently disabled SMPS).
413f05cddf9SRui Paulo 			 */
414f05cddf9SRui Paulo 			conf->ht_capab |= mode->ht_capab &
415f05cddf9SRui Paulo 				(HT_CAP_INFO_GREEN_FIELD |
416f05cddf9SRui Paulo 				 HT_CAP_INFO_SHORT_GI20MHZ |
417f05cddf9SRui Paulo 				 HT_CAP_INFO_SHORT_GI40MHZ |
418f05cddf9SRui Paulo 				 HT_CAP_INFO_RX_STBC_MASK |
4195b9c547cSRui Paulo 				 HT_CAP_INFO_TX_STBC |
420f05cddf9SRui Paulo 				 HT_CAP_INFO_MAX_AMSDU_SIZE);
4215b9c547cSRui Paulo 
422c1d255d3SCy Schubert 			/* check this before VHT, because setting oper chan
423c1d255d3SCy Schubert 			 * width and friends is the same call for HE and VHT
424c1d255d3SCy Schubert 			 * and checks if conf->ieee8021ax == 1 */
425*a90b9d01SCy Schubert 			if (mode->eht_capab[wpas_mode_to_ieee80211_mode(
426*a90b9d01SCy Schubert 					    ssid->mode)].eht_supported &&
427*a90b9d01SCy Schubert 			    ssid->eht)
428*a90b9d01SCy Schubert 				conf->ieee80211be = 1;
429*a90b9d01SCy Schubert 
430c1d255d3SCy Schubert 			if (mode->he_capab[wpas_mode_to_ieee80211_mode(
431c1d255d3SCy Schubert 					    ssid->mode)].he_supported &&
432c1d255d3SCy Schubert 			    ssid->he)
433c1d255d3SCy Schubert 				conf->ieee80211ax = 1;
434c1d255d3SCy Schubert 
4355b9c547cSRui Paulo 			if (mode->vht_capab && ssid->vht) {
4365b9c547cSRui Paulo 				conf->ieee80211ac = 1;
43785732ac8SCy Schubert 				conf->vht_capab |= mode->vht_capab;
43885732ac8SCy Schubert 				wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
4395b9c547cSRui Paulo 			}
440f05cddf9SRui Paulo 		}
441f05cddf9SRui Paulo 	}
442325151a3SRui Paulo 
443*a90b9d01SCy Schubert #ifdef CONFIG_P2P
444*a90b9d01SCy Schubert 	if (ssid->p2p_group && wpa_s->p2p_go_no_pri_sec_switch) {
445*a90b9d01SCy Schubert 		conf->no_pri_sec_switch = 1;
446*a90b9d01SCy Schubert 		return 0;
447*a90b9d01SCy Schubert 	}
448*a90b9d01SCy Schubert #endif /* CONFIG_P2P */
449*a90b9d01SCy Schubert 
450325151a3SRui Paulo 	if (conf->secondary_channel) {
451325151a3SRui Paulo 		struct wpa_supplicant *iface;
452325151a3SRui Paulo 
453325151a3SRui Paulo 		for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
454325151a3SRui Paulo 		{
455325151a3SRui Paulo 			if (iface == wpa_s ||
456325151a3SRui Paulo 			    iface->wpa_state < WPA_AUTHENTICATING ||
457325151a3SRui Paulo 			    (int) iface->assoc_freq != ssid->frequency)
458325151a3SRui Paulo 				continue;
459325151a3SRui Paulo 
460325151a3SRui Paulo 			/*
461325151a3SRui Paulo 			 * Do not allow 40 MHz co-ex PRI/SEC switch to force us
462325151a3SRui Paulo 			 * to change our PRI channel since we have an existing,
463325151a3SRui Paulo 			 * concurrent connection on that channel and doing
464325151a3SRui Paulo 			 * multi-channel concurrency is likely to cause more
465325151a3SRui Paulo 			 * harm than using different PRI/SEC selection in
466325151a3SRui Paulo 			 * environment with multiple BSSes on these two channels
467325151a3SRui Paulo 			 * with mixed 20 MHz or PRI channel selection.
468325151a3SRui Paulo 			 */
469325151a3SRui Paulo 			conf->no_pri_sec_switch = 1;
470325151a3SRui Paulo 		}
471325151a3SRui Paulo 	}
472780fb4a2SCy Schubert 
473780fb4a2SCy Schubert 	return 0;
4745b9c547cSRui Paulo }
4755b9c547cSRui Paulo 
4765b9c547cSRui Paulo 
wpa_supplicant_conf_ap(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,struct hostapd_config * conf)4775b9c547cSRui Paulo static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
4785b9c547cSRui Paulo 				  struct wpa_ssid *ssid,
4795b9c547cSRui Paulo 				  struct hostapd_config *conf)
4805b9c547cSRui Paulo {
4815b9c547cSRui Paulo 	struct hostapd_bss_config *bss = conf->bss[0];
4825b9c547cSRui Paulo 
4835b9c547cSRui Paulo 	conf->driver = wpa_s->driver;
4845b9c547cSRui Paulo 
4855b9c547cSRui Paulo 	os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
4865b9c547cSRui Paulo 
487780fb4a2SCy Schubert 	if (wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf))
488780fb4a2SCy Schubert 		return -1;
489780fb4a2SCy Schubert 
490780fb4a2SCy Schubert 	if (ssid->pbss > 1) {
491780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "Invalid pbss value(%d) for AP mode",
492780fb4a2SCy Schubert 			   ssid->pbss);
4935b9c547cSRui Paulo 		return -1;
4945b9c547cSRui Paulo 	}
495780fb4a2SCy Schubert 	bss->pbss = ssid->pbss;
4965b9c547cSRui Paulo 
497780fb4a2SCy Schubert #ifdef CONFIG_ACS
498780fb4a2SCy Schubert 	if (ssid->acs) {
499780fb4a2SCy Schubert 		/* Setting channel to 0 in order to enable ACS */
500780fb4a2SCy Schubert 		conf->channel = 0;
501780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "Use automatic channel selection");
502780fb4a2SCy Schubert 	}
503780fb4a2SCy Schubert #endif /* CONFIG_ACS */
5045b9c547cSRui Paulo 
50585732ac8SCy Schubert 	if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
50685732ac8SCy Schubert 			     wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
5075b9c547cSRui Paulo 		conf->ieee80211h = 1;
5085b9c547cSRui Paulo 		conf->ieee80211d = 1;
5095b9c547cSRui Paulo 		conf->country[0] = wpa_s->conf->country[0];
5105b9c547cSRui Paulo 		conf->country[1] = wpa_s->conf->country[1];
51185732ac8SCy Schubert 		conf->country[2] = ' ';
5125b9c547cSRui Paulo 	}
513f05cddf9SRui Paulo 
514f05cddf9SRui Paulo #ifdef CONFIG_P2P
5155b9c547cSRui Paulo 	if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
5165b9c547cSRui Paulo 	    (ssid->mode == WPAS_MODE_P2P_GO ||
5175b9c547cSRui Paulo 	     ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) {
518f05cddf9SRui Paulo 		/* Remove 802.11b rates from supported and basic rate sets */
519f05cddf9SRui Paulo 		int *list = os_malloc(4 * sizeof(int));
520f05cddf9SRui Paulo 		if (list) {
521f05cddf9SRui Paulo 			list[0] = 60;
522f05cddf9SRui Paulo 			list[1] = 120;
523f05cddf9SRui Paulo 			list[2] = 240;
524f05cddf9SRui Paulo 			list[3] = -1;
525f05cddf9SRui Paulo 		}
526f05cddf9SRui Paulo 		conf->basic_rates = list;
527f05cddf9SRui Paulo 
528f05cddf9SRui Paulo 		list = os_malloc(9 * sizeof(int));
529f05cddf9SRui Paulo 		if (list) {
530f05cddf9SRui Paulo 			list[0] = 60;
531f05cddf9SRui Paulo 			list[1] = 90;
532f05cddf9SRui Paulo 			list[2] = 120;
533f05cddf9SRui Paulo 			list[3] = 180;
534f05cddf9SRui Paulo 			list[4] = 240;
535f05cddf9SRui Paulo 			list[5] = 360;
536f05cddf9SRui Paulo 			list[6] = 480;
537f05cddf9SRui Paulo 			list[7] = 540;
538f05cddf9SRui Paulo 			list[8] = -1;
539f05cddf9SRui Paulo 		}
540f05cddf9SRui Paulo 		conf->supported_rates = list;
541f05cddf9SRui Paulo 	}
542f05cddf9SRui Paulo 
5434bc52338SCy Schubert #ifdef CONFIG_IEEE80211AX
5444bc52338SCy Schubert 	if (ssid->mode == WPAS_MODE_P2P_GO ||
5454bc52338SCy Schubert 	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
5464bc52338SCy Schubert 		conf->ieee80211ax = ssid->he;
5474bc52338SCy Schubert #endif /* CONFIG_IEEE80211AX */
5484bc52338SCy Schubert 
549f05cddf9SRui Paulo 	bss->isolate = !wpa_s->conf->p2p_intra_bss;
550c1d255d3SCy Schubert 	bss->extended_key_id = wpa_s->conf->extended_key_id;
5515b9c547cSRui Paulo 	bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
552c1d255d3SCy Schubert 	bss->wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey;
5535b9c547cSRui Paulo 
5545b9c547cSRui Paulo 	if (ssid->p2p_group) {
555780fb4a2SCy Schubert 		os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
556780fb4a2SCy Schubert 		os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask,
5575b9c547cSRui Paulo 			  4);
5585b9c547cSRui Paulo 		os_memcpy(bss->ip_addr_start,
559780fb4a2SCy Schubert 			  wpa_s->p2pdev->conf->ip_addr_start, 4);
560780fb4a2SCy Schubert 		os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end,
5615b9c547cSRui Paulo 			  4);
5625b9c547cSRui Paulo 	}
563f05cddf9SRui Paulo #endif /* CONFIG_P2P */
564f05cddf9SRui Paulo 
565e28a4053SRui Paulo 	if (ssid->ssid_len == 0) {
566e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
567e28a4053SRui Paulo 		return -1;
568e28a4053SRui Paulo 	}
569e28a4053SRui Paulo 	os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len);
570e28a4053SRui Paulo 	bss->ssid.ssid_len = ssid->ssid_len;
571e28a4053SRui Paulo 	bss->ssid.ssid_set = 1;
572e28a4053SRui Paulo 
573f05cddf9SRui Paulo 	bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid;
574f05cddf9SRui Paulo 
575f05cddf9SRui Paulo 	if (ssid->auth_alg)
576f05cddf9SRui Paulo 		bss->auth_algs = ssid->auth_alg;
577f05cddf9SRui Paulo 
578e28a4053SRui Paulo 	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt))
579e28a4053SRui Paulo 		bss->wpa = ssid->proto;
580780fb4a2SCy Schubert 	if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
581780fb4a2SCy Schubert 		bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
582780fb4a2SCy Schubert 	else
583e28a4053SRui Paulo 		bss->wpa_key_mgmt = ssid->key_mgmt;
584e28a4053SRui Paulo 	bss->wpa_pairwise = ssid->pairwise_cipher;
585c1d255d3SCy Schubert 	if (wpa_key_mgmt_sae(bss->wpa_key_mgmt) && ssid->passphrase) {
586c1d255d3SCy Schubert 		bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
587c1d255d3SCy Schubert 	} else if (ssid->psk_set) {
5885b9c547cSRui Paulo 		bin_clear_free(bss->ssid.wpa_psk, sizeof(*bss->ssid.wpa_psk));
589e28a4053SRui Paulo 		bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
590e28a4053SRui Paulo 		if (bss->ssid.wpa_psk == NULL)
591e28a4053SRui Paulo 			return -1;
592e28a4053SRui Paulo 		os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN);
593e28a4053SRui Paulo 		bss->ssid.wpa_psk->group = 1;
594780fb4a2SCy Schubert 		bss->ssid.wpa_psk_set = 1;
595f05cddf9SRui Paulo 	} else if (ssid->passphrase) {
596f05cddf9SRui Paulo 		bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
597c1d255d3SCy Schubert #ifdef CONFIG_WEP
598f05cddf9SRui Paulo 	} else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] ||
599f05cddf9SRui Paulo 		   ssid->wep_key_len[2] || ssid->wep_key_len[3]) {
600f05cddf9SRui Paulo 		struct hostapd_wep_keys *wep = &bss->ssid.wep;
601f05cddf9SRui Paulo 		int i;
602f05cddf9SRui Paulo 		for (i = 0; i < NUM_WEP_KEYS; i++) {
603f05cddf9SRui Paulo 			if (ssid->wep_key_len[i] == 0)
604f05cddf9SRui Paulo 				continue;
60585732ac8SCy Schubert 			wep->key[i] = os_memdup(ssid->wep_key[i],
60685732ac8SCy Schubert 						ssid->wep_key_len[i]);
607f05cddf9SRui Paulo 			if (wep->key[i] == NULL)
608f05cddf9SRui Paulo 				return -1;
609f05cddf9SRui Paulo 			wep->len[i] = ssid->wep_key_len[i];
610e28a4053SRui Paulo 		}
611f05cddf9SRui Paulo 		wep->idx = ssid->wep_tx_keyidx;
612f05cddf9SRui Paulo 		wep->keys_set = 1;
613c1d255d3SCy Schubert #endif /* CONFIG_WEP */
614f05cddf9SRui Paulo 	}
615c1d255d3SCy Schubert #ifdef CONFIG_SAE
616c1d255d3SCy Schubert 	if (ssid->sae_password) {
617c1d255d3SCy Schubert 		struct sae_password_entry *pw;
618c1d255d3SCy Schubert 
619c1d255d3SCy Schubert 		pw = os_zalloc(sizeof(*pw));
620c1d255d3SCy Schubert 		if (!pw)
621c1d255d3SCy Schubert 			return -1;
622c1d255d3SCy Schubert 		os_memset(pw->peer_addr, 0xff, ETH_ALEN);
623c1d255d3SCy Schubert 		pw->password = os_strdup(ssid->sae_password);
624c1d255d3SCy Schubert 		if (!pw->password) {
625c1d255d3SCy Schubert 			os_free(pw);
626c1d255d3SCy Schubert 			return -1;
627c1d255d3SCy Schubert 		}
628c1d255d3SCy Schubert 		if (ssid->sae_password_id) {
629c1d255d3SCy Schubert 			pw->identifier = os_strdup(ssid->sae_password_id);
630c1d255d3SCy Schubert 			if (!pw->identifier) {
631c1d255d3SCy Schubert 				str_clear_free(pw->password);
632c1d255d3SCy Schubert 				os_free(pw);
633c1d255d3SCy Schubert 				return -1;
634c1d255d3SCy Schubert 			}
635c1d255d3SCy Schubert 		}
636c1d255d3SCy Schubert 
637c1d255d3SCy Schubert 		pw->next = bss->sae_passwords;
638c1d255d3SCy Schubert 		bss->sae_passwords = pw;
639c1d255d3SCy Schubert 	}
640c1d255d3SCy Schubert 
6414b72b91aSCy Schubert 	if (ssid->sae_pwe != DEFAULT_SAE_PWE)
6424b72b91aSCy Schubert 		bss->sae_pwe = ssid->sae_pwe;
6434b72b91aSCy Schubert 	else
644c1d255d3SCy Schubert 		bss->sae_pwe = wpa_s->conf->sae_pwe;
645c1d255d3SCy Schubert #endif /* CONFIG_SAE */
646f05cddf9SRui Paulo 
64785732ac8SCy Schubert 	if (wpa_s->conf->go_interworking) {
64885732ac8SCy Schubert 		wpa_printf(MSG_DEBUG,
64985732ac8SCy Schubert 			   "P2P: Enable Interworking with access_network_type: %d",
65085732ac8SCy Schubert 			   wpa_s->conf->go_access_network_type);
65185732ac8SCy Schubert 		bss->interworking = wpa_s->conf->go_interworking;
65285732ac8SCy Schubert 		bss->access_network_type = wpa_s->conf->go_access_network_type;
65385732ac8SCy Schubert 		bss->internet = wpa_s->conf->go_internet;
65485732ac8SCy Schubert 		if (wpa_s->conf->go_venue_group) {
65585732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
65685732ac8SCy Schubert 				   "P2P: Venue group: %d  Venue type: %d",
65785732ac8SCy Schubert 				   wpa_s->conf->go_venue_group,
65885732ac8SCy Schubert 				   wpa_s->conf->go_venue_type);
65985732ac8SCy Schubert 			bss->venue_group = wpa_s->conf->go_venue_group;
66085732ac8SCy Schubert 			bss->venue_type = wpa_s->conf->go_venue_type;
66185732ac8SCy Schubert 			bss->venue_info_set = 1;
66285732ac8SCy Schubert 		}
66385732ac8SCy Schubert 	}
66485732ac8SCy Schubert 
665f05cddf9SRui Paulo 	if (ssid->ap_max_inactivity)
666f05cddf9SRui Paulo 		bss->ap_max_inactivity = ssid->ap_max_inactivity;
667f05cddf9SRui Paulo 
668f05cddf9SRui Paulo 	if (ssid->dtim_period)
669f05cddf9SRui Paulo 		bss->dtim_period = ssid->dtim_period;
6705b9c547cSRui Paulo 	else if (wpa_s->conf->dtim_period)
6715b9c547cSRui Paulo 		bss->dtim_period = wpa_s->conf->dtim_period;
672e28a4053SRui Paulo 
6735b9c547cSRui Paulo 	if (ssid->beacon_int)
6745b9c547cSRui Paulo 		conf->beacon_int = ssid->beacon_int;
6755b9c547cSRui Paulo 	else if (wpa_s->conf->beacon_int)
6765b9c547cSRui Paulo 		conf->beacon_int = wpa_s->conf->beacon_int;
6775b9c547cSRui Paulo 
6785b9c547cSRui Paulo #ifdef CONFIG_P2P
679780fb4a2SCy Schubert 	if (ssid->mode == WPAS_MODE_P2P_GO ||
680780fb4a2SCy Schubert 	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
6815b9c547cSRui Paulo 		if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) {
6825b9c547cSRui Paulo 			wpa_printf(MSG_INFO,
6835b9c547cSRui Paulo 				   "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it",
684780fb4a2SCy Schubert 				   wpa_s->conf->p2p_go_ctwindow,
685780fb4a2SCy Schubert 				   conf->beacon_int);
6865b9c547cSRui Paulo 			conf->p2p_go_ctwindow = 0;
6875b9c547cSRui Paulo 		} else {
6885b9c547cSRui Paulo 			conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow;
689e28a4053SRui Paulo 		}
690780fb4a2SCy Schubert 	}
6915b9c547cSRui Paulo #endif /* CONFIG_P2P */
6925b9c547cSRui Paulo 
6935b9c547cSRui Paulo 	if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
6945b9c547cSRui Paulo 		bss->rsn_pairwise = bss->wpa_pairwise;
6955b9c547cSRui Paulo 	bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise,
6965b9c547cSRui Paulo 						    bss->rsn_pairwise);
697e28a4053SRui Paulo 
698c1d255d3SCy Schubert 	if (bss->wpa && bss->ieee802_1x) {
699e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_WPA;
700c1d255d3SCy Schubert 	} else if (bss->wpa) {
701e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_WPA_PSK;
702c1d255d3SCy Schubert #ifdef CONFIG_WEP
703c1d255d3SCy Schubert 	} else if (bss->ieee802_1x) {
704f05cddf9SRui Paulo 		int cipher = WPA_CIPHER_NONE;
705e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
706e28a4053SRui Paulo 		bss->ssid.wep.default_len = bss->default_wep_key_len;
707f05cddf9SRui Paulo 		if (bss->default_wep_key_len)
708f05cddf9SRui Paulo 			cipher = bss->default_wep_key_len >= 13 ?
709f05cddf9SRui Paulo 				WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
710f05cddf9SRui Paulo 		bss->wpa_group = cipher;
711f05cddf9SRui Paulo 		bss->wpa_pairwise = cipher;
712f05cddf9SRui Paulo 		bss->rsn_pairwise = cipher;
713f05cddf9SRui Paulo 	} else if (bss->ssid.wep.keys_set) {
714f05cddf9SRui Paulo 		int cipher = WPA_CIPHER_WEP40;
715f05cddf9SRui Paulo 		if (bss->ssid.wep.len[0] >= 13)
716f05cddf9SRui Paulo 			cipher = WPA_CIPHER_WEP104;
717e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_STATIC_WEP;
718f05cddf9SRui Paulo 		bss->wpa_group = cipher;
719f05cddf9SRui Paulo 		bss->wpa_pairwise = cipher;
720f05cddf9SRui Paulo 		bss->rsn_pairwise = cipher;
721c1d255d3SCy Schubert #endif /* CONFIG_WEP */
722f05cddf9SRui Paulo 	} else {
723e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_PLAINTEXT;
724f05cddf9SRui Paulo 		bss->wpa_group = WPA_CIPHER_NONE;
725f05cddf9SRui Paulo 		bss->wpa_pairwise = WPA_CIPHER_NONE;
726f05cddf9SRui Paulo 		bss->rsn_pairwise = WPA_CIPHER_NONE;
727f05cddf9SRui Paulo 	}
728e28a4053SRui Paulo 
7295b9c547cSRui Paulo 	if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) &&
7305b9c547cSRui Paulo 	    (bss->wpa_group == WPA_CIPHER_CCMP ||
7315b9c547cSRui Paulo 	     bss->wpa_group == WPA_CIPHER_GCMP ||
7325b9c547cSRui Paulo 	     bss->wpa_group == WPA_CIPHER_CCMP_256 ||
7335b9c547cSRui Paulo 	     bss->wpa_group == WPA_CIPHER_GCMP_256)) {
7345b9c547cSRui Paulo 		/*
7355b9c547cSRui Paulo 		 * Strong ciphers do not need frequent rekeying, so increase
7365b9c547cSRui Paulo 		 * the default GTK rekeying period to 24 hours.
7375b9c547cSRui Paulo 		 */
7385b9c547cSRui Paulo 		bss->wpa_group_rekey = 86400;
7395b9c547cSRui Paulo 	}
7405b9c547cSRui Paulo 
741*a90b9d01SCy Schubert 	if (ssid->ieee80211w != MGMT_FRAME_PROTECTION_DEFAULT) {
7425b9c547cSRui Paulo 		bss->ieee80211w = ssid->ieee80211w;
743*a90b9d01SCy Schubert 	} else if (wpa_s->conf->pmf != MGMT_FRAME_PROTECTION_DEFAULT) {
744*a90b9d01SCy Schubert 		if (ssid->mode == WPAS_MODE_AP)
745*a90b9d01SCy Schubert 			bss->ieee80211w = wpa_s->conf->pmf;
746*a90b9d01SCy Schubert 	}
7475b9c547cSRui Paulo 
7484bc52338SCy Schubert #ifdef CONFIG_OCV
7494bc52338SCy Schubert 	bss->ocv = ssid->ocv;
7504bc52338SCy Schubert #endif /* CONFIG_OCV */
7514bc52338SCy Schubert 
752e28a4053SRui Paulo #ifdef CONFIG_WPS
753e28a4053SRui Paulo 	/*
754f05cddf9SRui Paulo 	 * Enable WPS by default for open and WPA/WPA2-Personal network, but
755f05cddf9SRui Paulo 	 * require user interaction to actually use it. Only the internal
756f05cddf9SRui Paulo 	 * Registrar is supported.
757e28a4053SRui Paulo 	 */
758f05cddf9SRui Paulo 	if (bss->ssid.security_policy != SECURITY_WPA_PSK &&
759f05cddf9SRui Paulo 	    bss->ssid.security_policy != SECURITY_PLAINTEXT)
760f05cddf9SRui Paulo 		goto no_wps;
761f05cddf9SRui Paulo 	if (bss->ssid.security_policy == SECURITY_WPA_PSK &&
7625b9c547cSRui Paulo 	    (!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) ||
7635b9c547cSRui Paulo 	     !(bss->wpa & 2)))
764f05cddf9SRui Paulo 		goto no_wps; /* WPS2 does not allow WPA/TKIP-only
765f05cddf9SRui Paulo 			      * configuration */
766780fb4a2SCy Schubert 	if (ssid->wps_disabled)
767780fb4a2SCy Schubert 		goto no_wps;
768e28a4053SRui Paulo 	bss->eap_server = 1;
769f05cddf9SRui Paulo 
770f05cddf9SRui Paulo 	if (!ssid->ignore_broadcast_ssid)
771e28a4053SRui Paulo 		bss->wps_state = 2;
772f05cddf9SRui Paulo 
773f05cddf9SRui Paulo 	bss->ap_setup_locked = 2;
774e28a4053SRui Paulo 	if (wpa_s->conf->config_methods)
775e28a4053SRui Paulo 		bss->config_methods = os_strdup(wpa_s->conf->config_methods);
776f05cddf9SRui Paulo 	os_memcpy(bss->device_type, wpa_s->conf->device_type,
777f05cddf9SRui Paulo 		  WPS_DEV_TYPE_LEN);
778f05cddf9SRui Paulo 	if (wpa_s->conf->device_name) {
779f05cddf9SRui Paulo 		bss->device_name = os_strdup(wpa_s->conf->device_name);
780f05cddf9SRui Paulo 		bss->friendly_name = os_strdup(wpa_s->conf->device_name);
781f05cddf9SRui Paulo 	}
782f05cddf9SRui Paulo 	if (wpa_s->conf->manufacturer)
783f05cddf9SRui Paulo 		bss->manufacturer = os_strdup(wpa_s->conf->manufacturer);
784f05cddf9SRui Paulo 	if (wpa_s->conf->model_name)
785f05cddf9SRui Paulo 		bss->model_name = os_strdup(wpa_s->conf->model_name);
786f05cddf9SRui Paulo 	if (wpa_s->conf->model_number)
787f05cddf9SRui Paulo 		bss->model_number = os_strdup(wpa_s->conf->model_number);
788f05cddf9SRui Paulo 	if (wpa_s->conf->serial_number)
789f05cddf9SRui Paulo 		bss->serial_number = os_strdup(wpa_s->conf->serial_number);
790f05cddf9SRui Paulo 	if (is_nil_uuid(wpa_s->conf->uuid))
791f05cddf9SRui Paulo 		os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN);
792f05cddf9SRui Paulo 	else
793f05cddf9SRui Paulo 		os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
794f05cddf9SRui Paulo 	os_memcpy(bss->os_version, wpa_s->conf->os_version, 4);
795f05cddf9SRui Paulo 	bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1;
796780fb4a2SCy Schubert 	if (ssid->eap.fragment_size != DEFAULT_FRAGMENT_SIZE)
797780fb4a2SCy Schubert 		bss->fragment_size = ssid->eap.fragment_size;
798f05cddf9SRui Paulo no_wps:
799e28a4053SRui Paulo #endif /* CONFIG_WPS */
800e28a4053SRui Paulo 
801f05cddf9SRui Paulo 	if (wpa_s->max_stations &&
802f05cddf9SRui Paulo 	    wpa_s->max_stations < wpa_s->conf->max_num_sta)
803f05cddf9SRui Paulo 		bss->max_num_sta = wpa_s->max_stations;
804f05cddf9SRui Paulo 	else
805f05cddf9SRui Paulo 		bss->max_num_sta = wpa_s->conf->max_num_sta;
806f05cddf9SRui Paulo 
80785732ac8SCy Schubert 	if (!bss->isolate)
80885732ac8SCy Schubert 		bss->isolate = wpa_s->conf->ap_isolate;
80985732ac8SCy Schubert 
810f05cddf9SRui Paulo 	bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack;
811f05cddf9SRui Paulo 
8125b9c547cSRui Paulo 	if (wpa_s->conf->ap_vendor_elements) {
8135b9c547cSRui Paulo 		bss->vendor_elements =
8145b9c547cSRui Paulo 			wpabuf_dup(wpa_s->conf->ap_vendor_elements);
8155b9c547cSRui Paulo 	}
8164b72b91aSCy Schubert 	if (wpa_s->conf->ap_assocresp_elements) {
8174b72b91aSCy Schubert 		bss->assocresp_elements =
8184b72b91aSCy Schubert 			wpabuf_dup(wpa_s->conf->ap_assocresp_elements);
8194b72b91aSCy Schubert 	}
8205b9c547cSRui Paulo 
821780fb4a2SCy Schubert 	bss->ftm_responder = wpa_s->conf->ftm_responder;
822780fb4a2SCy Schubert 	bss->ftm_initiator = wpa_s->conf->ftm_initiator;
823780fb4a2SCy Schubert 
824c1d255d3SCy Schubert 	bss->transition_disable = ssid->transition_disable;
825c1d255d3SCy Schubert 
826e28a4053SRui Paulo 	return 0;
827e28a4053SRui Paulo }
828e28a4053SRui Paulo 
829e28a4053SRui Paulo 
ap_public_action_rx(void * ctx,const u8 * buf,size_t len,int freq)830e28a4053SRui Paulo static void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
831e28a4053SRui Paulo {
832f05cddf9SRui Paulo #ifdef CONFIG_P2P
833f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
834f05cddf9SRui Paulo 	const struct ieee80211_mgmt *mgmt;
835f05cddf9SRui Paulo 
836f05cddf9SRui Paulo 	mgmt = (const struct ieee80211_mgmt *) buf;
8375b9c547cSRui Paulo 	if (len < IEEE80211_HDRLEN + 1)
8385b9c547cSRui Paulo 		return;
8395b9c547cSRui Paulo 	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
840f05cddf9SRui Paulo 		return;
841f05cddf9SRui Paulo 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
842f05cddf9SRui Paulo 			   mgmt->u.action.category,
8435b9c547cSRui Paulo 			   buf + IEEE80211_HDRLEN + 1,
8445b9c547cSRui Paulo 			   len - IEEE80211_HDRLEN - 1, freq);
845f05cddf9SRui Paulo #endif /* CONFIG_P2P */
846e28a4053SRui Paulo }
847e28a4053SRui Paulo 
848e28a4053SRui Paulo 
ap_wps_event_cb(void * ctx,enum wps_event event,union wps_event_data * data)849f05cddf9SRui Paulo static void ap_wps_event_cb(void *ctx, enum wps_event event,
850f05cddf9SRui Paulo 			    union wps_event_data *data)
851e28a4053SRui Paulo {
852f05cddf9SRui Paulo #ifdef CONFIG_P2P
853f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
854f05cddf9SRui Paulo 
855f05cddf9SRui Paulo 	if (event == WPS_EV_FAIL) {
856f05cddf9SRui Paulo 		struct wps_event_fail *fail = &data->fail;
857f05cddf9SRui Paulo 
858780fb4a2SCy Schubert 		if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s &&
859f05cddf9SRui Paulo 		    wpa_s == wpa_s->global->p2p_group_formation) {
860f05cddf9SRui Paulo 			/*
861f05cddf9SRui Paulo 			 * src/ap/wps_hostapd.c has already sent this on the
862f05cddf9SRui Paulo 			 * main interface, so only send on the parent interface
863f05cddf9SRui Paulo 			 * here if needed.
864f05cddf9SRui Paulo 			 */
865780fb4a2SCy Schubert 			wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
866f05cddf9SRui Paulo 				"msg=%d config_error=%d",
867f05cddf9SRui Paulo 				fail->msg, fail->config_error);
868f05cddf9SRui Paulo 		}
869f05cddf9SRui Paulo 		wpas_p2p_wps_failed(wpa_s, fail);
870f05cddf9SRui Paulo 	}
871f05cddf9SRui Paulo #endif /* CONFIG_P2P */
872f05cddf9SRui Paulo }
873f05cddf9SRui Paulo 
874f05cddf9SRui Paulo 
ap_sta_authorized_cb(void * ctx,const u8 * mac_addr,int authorized,const u8 * p2p_dev_addr,const u8 * ip)875f05cddf9SRui Paulo static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
876*a90b9d01SCy Schubert 				 int authorized, const u8 *p2p_dev_addr,
877*a90b9d01SCy Schubert 				 const u8 *ip)
878f05cddf9SRui Paulo {
879*a90b9d01SCy Schubert 	wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr, ip);
880f05cddf9SRui Paulo }
881f05cddf9SRui Paulo 
882f05cddf9SRui Paulo 
8835b9c547cSRui Paulo #ifdef CONFIG_P2P
ap_new_psk_cb(void * ctx,const u8 * mac_addr,const u8 * p2p_dev_addr,const u8 * psk,size_t psk_len)8845b9c547cSRui Paulo static void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
8855b9c547cSRui Paulo 			  const u8 *psk, size_t psk_len)
8865b9c547cSRui Paulo {
8875b9c547cSRui Paulo 
8885b9c547cSRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
8895b9c547cSRui Paulo 	if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL)
8905b9c547cSRui Paulo 		return;
8915b9c547cSRui Paulo 	wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len);
8925b9c547cSRui Paulo }
8935b9c547cSRui Paulo #endif /* CONFIG_P2P */
8945b9c547cSRui Paulo 
8955b9c547cSRui Paulo 
ap_vendor_action_rx(void * ctx,const u8 * buf,size_t len,int freq)896f05cddf9SRui Paulo static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
897f05cddf9SRui Paulo {
898f05cddf9SRui Paulo #ifdef CONFIG_P2P
899f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
900f05cddf9SRui Paulo 	const struct ieee80211_mgmt *mgmt;
901f05cddf9SRui Paulo 
902f05cddf9SRui Paulo 	mgmt = (const struct ieee80211_mgmt *) buf;
9035b9c547cSRui Paulo 	if (len < IEEE80211_HDRLEN + 1)
904f05cddf9SRui Paulo 		return -1;
905f05cddf9SRui Paulo 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
906f05cddf9SRui Paulo 			   mgmt->u.action.category,
9075b9c547cSRui Paulo 			   buf + IEEE80211_HDRLEN + 1,
9085b9c547cSRui Paulo 			   len - IEEE80211_HDRLEN - 1, freq);
909f05cddf9SRui Paulo #endif /* CONFIG_P2P */
910e28a4053SRui Paulo 	return 0;
911e28a4053SRui Paulo }
912e28a4053SRui Paulo 
913e28a4053SRui Paulo 
ap_probe_req_rx(void * ctx,const u8 * sa,const u8 * da,const u8 * bssid,const u8 * ie,size_t ie_len,int ssi_signal)914f05cddf9SRui Paulo static int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da,
915f05cddf9SRui Paulo 			   const u8 *bssid, const u8 *ie, size_t ie_len,
916f05cddf9SRui Paulo 			   int ssi_signal)
917f05cddf9SRui Paulo {
918f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
919325151a3SRui Paulo 	unsigned int freq = 0;
920325151a3SRui Paulo 
921325151a3SRui Paulo 	if (wpa_s->ap_iface)
922325151a3SRui Paulo 		freq = wpa_s->ap_iface->freq;
923325151a3SRui Paulo 
924f05cddf9SRui Paulo 	return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len,
925325151a3SRui Paulo 				     freq, ssi_signal);
926f05cddf9SRui Paulo }
927f05cddf9SRui Paulo 
928f05cddf9SRui Paulo 
ap_wps_reg_success_cb(void * ctx,const u8 * mac_addr,const u8 * uuid_e)929e28a4053SRui Paulo static void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
930e28a4053SRui Paulo 				  const u8 *uuid_e)
931e28a4053SRui Paulo {
932f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
933f05cddf9SRui Paulo 	wpas_p2p_wps_success(wpa_s, mac_addr, 1);
934f05cddf9SRui Paulo }
935f05cddf9SRui Paulo 
936f05cddf9SRui Paulo 
wpas_ap_configured_cb(void * ctx)937f05cddf9SRui Paulo static void wpas_ap_configured_cb(void *ctx)
938f05cddf9SRui Paulo {
939f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
940f05cddf9SRui Paulo 
94185732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "AP interface setup completed - state %s",
94285732ac8SCy Schubert 		   hostapd_state_text(wpa_s->ap_iface->state));
94385732ac8SCy Schubert 	if (wpa_s->ap_iface->state == HAPD_IFACE_DISABLED) {
94485732ac8SCy Schubert 		wpa_supplicant_ap_deinit(wpa_s);
94585732ac8SCy Schubert 		return;
94685732ac8SCy Schubert 	}
94785732ac8SCy Schubert 
948*a90b9d01SCy Schubert 	if (wpa_s->current_ssid) {
949*a90b9d01SCy Schubert 		int acs = 0;
950*a90b9d01SCy Schubert 
951780fb4a2SCy Schubert #ifdef CONFIG_ACS
952*a90b9d01SCy Schubert 		acs = wpa_s->current_ssid->acs;
953*a90b9d01SCy Schubert #endif /* CONFIG_ACS */
954*a90b9d01SCy Schubert 		if (acs || (wpa_s->assoc_freq && wpa_s->ap_iface->freq &&
955*a90b9d01SCy Schubert 			    (int) wpa_s->assoc_freq != wpa_s->ap_iface->freq)) {
956780fb4a2SCy Schubert 			wpa_s->assoc_freq = wpa_s->ap_iface->freq;
95785732ac8SCy Schubert 			wpa_s->current_ssid->frequency = wpa_s->ap_iface->freq;
95885732ac8SCy Schubert 		}
959*a90b9d01SCy Schubert 	}
960780fb4a2SCy Schubert 
961f05cddf9SRui Paulo 	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
962f05cddf9SRui Paulo 
963f05cddf9SRui Paulo 	if (wpa_s->ap_configured_cb)
964f05cddf9SRui Paulo 		wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
965f05cddf9SRui Paulo 					wpa_s->ap_configured_cb_data);
966e28a4053SRui Paulo }
967e28a4053SRui Paulo 
968e28a4053SRui Paulo 
wpa_supplicant_create_ap(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)969e28a4053SRui Paulo int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
970e28a4053SRui Paulo 			     struct wpa_ssid *ssid)
971e28a4053SRui Paulo {
972e28a4053SRui Paulo 	struct wpa_driver_associate_params params;
973e28a4053SRui Paulo 	struct hostapd_iface *hapd_iface;
974e28a4053SRui Paulo 	struct hostapd_config *conf;
975e28a4053SRui Paulo 	size_t i;
976e28a4053SRui Paulo 
977e28a4053SRui Paulo 	if (ssid->ssid == NULL || ssid->ssid_len == 0) {
978e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
979e28a4053SRui Paulo 		return -1;
980e28a4053SRui Paulo 	}
981e28a4053SRui Paulo 
982e28a4053SRui Paulo 	wpa_supplicant_ap_deinit(wpa_s);
983e28a4053SRui Paulo 
984e28a4053SRui Paulo 	wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')",
985e28a4053SRui Paulo 		   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
986e28a4053SRui Paulo 
987e28a4053SRui Paulo 	os_memset(&params, 0, sizeof(params));
988e28a4053SRui Paulo 	params.ssid = ssid->ssid;
989e28a4053SRui Paulo 	params.ssid_len = ssid->ssid_len;
990e28a4053SRui Paulo 	switch (ssid->mode) {
991e28a4053SRui Paulo 	case WPAS_MODE_AP:
992f05cddf9SRui Paulo 	case WPAS_MODE_P2P_GO:
993f05cddf9SRui Paulo 	case WPAS_MODE_P2P_GROUP_FORMATION:
994e28a4053SRui Paulo 		params.mode = IEEE80211_MODE_AP;
995e28a4053SRui Paulo 		break;
9965b9c547cSRui Paulo 	default:
9975b9c547cSRui Paulo 		return -1;
998e28a4053SRui Paulo 	}
9995b9c547cSRui Paulo 	if (ssid->frequency == 0)
10005b9c547cSRui Paulo 		ssid->frequency = 2462; /* default channel 11 */
10015b9c547cSRui Paulo 	params.freq.freq = ssid->frequency;
1002e28a4053SRui Paulo 
1003c1d255d3SCy Schubert 	if ((ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO) &&
1004c1d255d3SCy Schubert 	    ssid->enable_edmg) {
1005c1d255d3SCy Schubert 		u8 primary_channel;
1006c1d255d3SCy Schubert 
1007c1d255d3SCy Schubert 		if (ieee80211_freq_to_chan(ssid->frequency, &primary_channel) ==
1008c1d255d3SCy Schubert 		    NUM_HOSTAPD_MODES) {
1009c1d255d3SCy Schubert 			wpa_printf(MSG_WARNING,
1010c1d255d3SCy Schubert 				   "EDMG: Failed to get the primary channel");
1011c1d255d3SCy Schubert 			return -1;
1012c1d255d3SCy Schubert 		}
1013c1d255d3SCy Schubert 
1014c1d255d3SCy Schubert 		hostapd_encode_edmg_chan(ssid->enable_edmg, ssid->edmg_channel,
1015c1d255d3SCy Schubert 					 primary_channel, &params.freq.edmg);
1016c1d255d3SCy Schubert 	}
1017c1d255d3SCy Schubert 
1018f05cddf9SRui Paulo 	params.wpa_proto = ssid->proto;
1019e28a4053SRui Paulo 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1020e28a4053SRui Paulo 		wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1021c1d255d3SCy Schubert 	else if (ssid->key_mgmt & WPA_KEY_MGMT_SAE)
1022c1d255d3SCy Schubert 		wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1023e28a4053SRui Paulo 	else
1024e28a4053SRui Paulo 		wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
10255b9c547cSRui Paulo 	params.key_mgmt_suite = wpa_s->key_mgmt;
1026e28a4053SRui Paulo 
10275b9c547cSRui Paulo 	wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher,
10285b9c547cSRui Paulo 							  1);
10295b9c547cSRui Paulo 	if (wpa_s->pairwise_cipher < 0) {
1030e28a4053SRui Paulo 		wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise "
1031e28a4053SRui Paulo 			   "cipher.");
1032e28a4053SRui Paulo 		return -1;
1033e28a4053SRui Paulo 	}
10345b9c547cSRui Paulo 	params.pairwise_suite = wpa_s->pairwise_cipher;
1035e28a4053SRui Paulo 	params.group_suite = params.pairwise_suite;
1036e28a4053SRui Paulo 
1037f05cddf9SRui Paulo #ifdef CONFIG_P2P
1038f05cddf9SRui Paulo 	if (ssid->mode == WPAS_MODE_P2P_GO ||
1039f05cddf9SRui Paulo 	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1040f05cddf9SRui Paulo 		params.p2p = 1;
1041f05cddf9SRui Paulo #endif /* CONFIG_P2P */
1042f05cddf9SRui Paulo 
1043780fb4a2SCy Schubert 	if (wpa_s->p2pdev->set_ap_uapsd)
1044780fb4a2SCy Schubert 		params.uapsd = wpa_s->p2pdev->ap_uapsd;
10455b9c547cSRui Paulo 	else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
10465b9c547cSRui Paulo 		params.uapsd = 1; /* mandatory for P2P GO */
1047f05cddf9SRui Paulo 	else
1048f05cddf9SRui Paulo 		params.uapsd = -1;
1049f05cddf9SRui Paulo 
105085732ac8SCy Schubert 	if (ieee80211_is_dfs(params.freq.freq, wpa_s->hw.modes,
105185732ac8SCy Schubert 			     wpa_s->hw.num_modes))
10525b9c547cSRui Paulo 		params.freq.freq = 0; /* set channel after CAC */
10535b9c547cSRui Paulo 
1054780fb4a2SCy Schubert 	if (params.p2p)
1055780fb4a2SCy Schubert 		wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_GO);
1056780fb4a2SCy Schubert 	else
1057780fb4a2SCy Schubert 		wpa_drv_get_ext_capa(wpa_s, WPA_IF_AP_BSS);
1058780fb4a2SCy Schubert 
1059e28a4053SRui Paulo 	if (wpa_drv_associate(wpa_s, &params) < 0) {
1060e28a4053SRui Paulo 		wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
1061e28a4053SRui Paulo 		return -1;
1062e28a4053SRui Paulo 	}
1063e28a4053SRui Paulo 
1064780fb4a2SCy Schubert 	wpa_s->ap_iface = hapd_iface = hostapd_alloc_iface();
1065e28a4053SRui Paulo 	if (hapd_iface == NULL)
1066e28a4053SRui Paulo 		return -1;
1067e28a4053SRui Paulo 	hapd_iface->owner = wpa_s;
1068f05cddf9SRui Paulo 	hapd_iface->drv_flags = wpa_s->drv_flags;
1069*a90b9d01SCy Schubert 	hapd_iface->drv_flags2 = wpa_s->drv_flags2;
1070f05cddf9SRui Paulo 	hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
10715b9c547cSRui Paulo 	hapd_iface->extended_capa = wpa_s->extended_capa;
10725b9c547cSRui Paulo 	hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask;
10735b9c547cSRui Paulo 	hapd_iface->extended_capa_len = wpa_s->extended_capa_len;
1074*a90b9d01SCy Schubert 	hapd_iface->drv_max_acl_mac_addrs = wpa_s->drv_max_acl_mac_addrs;
1075e28a4053SRui Paulo 
1076e28a4053SRui Paulo 	wpa_s->ap_iface->conf = conf = hostapd_config_defaults();
1077e28a4053SRui Paulo 	if (conf == NULL) {
1078e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
1079e28a4053SRui Paulo 		return -1;
1080e28a4053SRui Paulo 	}
1081e28a4053SRui Paulo 
1082f05cddf9SRui Paulo 	os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params,
1083f05cddf9SRui Paulo 		  wpa_s->conf->wmm_ac_params,
1084f05cddf9SRui Paulo 		  sizeof(wpa_s->conf->wmm_ac_params));
1085f05cddf9SRui Paulo 
1086c1d255d3SCy Schubert 	os_memcpy(wpa_s->ap_iface->conf->tx_queue, wpa_s->conf->tx_queue,
1087c1d255d3SCy Schubert 		  sizeof(wpa_s->conf->tx_queue));
1088c1d255d3SCy Schubert 
1089f05cddf9SRui Paulo 	if (params.uapsd > 0) {
10905b9c547cSRui Paulo 		conf->bss[0]->wmm_enabled = 1;
10915b9c547cSRui Paulo 		conf->bss[0]->wmm_uapsd = 1;
1092f05cddf9SRui Paulo 	}
1093f05cddf9SRui Paulo 
1094e28a4053SRui Paulo 	if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) {
1095e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Failed to create AP configuration");
1096e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
1097e28a4053SRui Paulo 		return -1;
1098e28a4053SRui Paulo 	}
1099e28a4053SRui Paulo 
1100f05cddf9SRui Paulo #ifdef CONFIG_P2P
1101f05cddf9SRui Paulo 	if (ssid->mode == WPAS_MODE_P2P_GO)
11025b9c547cSRui Paulo 		conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
1103f05cddf9SRui Paulo 	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
11045b9c547cSRui Paulo 		conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
1105f05cddf9SRui Paulo 			P2P_GROUP_FORMATION;
1106f05cddf9SRui Paulo #endif /* CONFIG_P2P */
1107f05cddf9SRui Paulo 
1108e28a4053SRui Paulo 	hapd_iface->num_bss = conf->num_bss;
1109f05cddf9SRui Paulo 	hapd_iface->bss = os_calloc(conf->num_bss,
1110e28a4053SRui Paulo 				    sizeof(struct hostapd_data *));
1111e28a4053SRui Paulo 	if (hapd_iface->bss == NULL) {
1112e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
1113e28a4053SRui Paulo 		return -1;
1114e28a4053SRui Paulo 	}
1115e28a4053SRui Paulo 
1116e28a4053SRui Paulo 	for (i = 0; i < conf->num_bss; i++) {
1117e28a4053SRui Paulo 		hapd_iface->bss[i] =
1118e28a4053SRui Paulo 			hostapd_alloc_bss_data(hapd_iface, conf,
11195b9c547cSRui Paulo 					       conf->bss[i]);
1120e28a4053SRui Paulo 		if (hapd_iface->bss[i] == NULL) {
1121e28a4053SRui Paulo 			wpa_supplicant_ap_deinit(wpa_s);
1122e28a4053SRui Paulo 			return -1;
1123e28a4053SRui Paulo 		}
1124e28a4053SRui Paulo 
1125e28a4053SRui Paulo 		hapd_iface->bss[i]->msg_ctx = wpa_s;
1126780fb4a2SCy Schubert 		hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev;
1127e28a4053SRui Paulo 		hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
1128e28a4053SRui Paulo 		hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
1129f05cddf9SRui Paulo 		hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
1130f05cddf9SRui Paulo 		hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s;
1131e28a4053SRui Paulo 		hostapd_register_probereq_cb(hapd_iface->bss[i],
1132e28a4053SRui Paulo 					     ap_probe_req_rx, wpa_s);
1133e28a4053SRui Paulo 		hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb;
1134e28a4053SRui Paulo 		hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s;
1135f05cddf9SRui Paulo 		hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb;
1136f05cddf9SRui Paulo 		hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s;
1137f05cddf9SRui Paulo 		hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb;
1138f05cddf9SRui Paulo 		hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s;
1139f05cddf9SRui Paulo #ifdef CONFIG_P2P
11405b9c547cSRui Paulo 		hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb;
11415b9c547cSRui Paulo 		hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s;
1142f05cddf9SRui Paulo 		hapd_iface->bss[i]->p2p = wpa_s->global->p2p;
1143f05cddf9SRui Paulo 		hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s,
1144f05cddf9SRui Paulo 								    ssid);
1145f05cddf9SRui Paulo #endif /* CONFIG_P2P */
1146f05cddf9SRui Paulo 		hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb;
1147f05cddf9SRui Paulo 		hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s;
11485b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS
11495b9c547cSRui Paulo 		hapd_iface->bss[i]->ext_eapol_frame_io =
11505b9c547cSRui Paulo 			wpa_s->ext_eapol_frame_io;
11515b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */
1152*a90b9d01SCy Schubert 
1153*a90b9d01SCy Schubert #ifdef CONFIG_WNM_AP
1154*a90b9d01SCy Schubert 		if (ssid->mode == WPAS_MODE_AP)
1155*a90b9d01SCy Schubert 			hapd_iface->bss[i]->conf->bss_transition = 1;
1156*a90b9d01SCy Schubert #endif /* CONFIG_WNM_AP */
1157e28a4053SRui Paulo 	}
1158e28a4053SRui Paulo 
1159e28a4053SRui Paulo 	os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
1160e28a4053SRui Paulo 	hapd_iface->bss[0]->driver = wpa_s->driver;
1161e28a4053SRui Paulo 	hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv;
1162e28a4053SRui Paulo 
1163f05cddf9SRui Paulo 	wpa_s->current_ssid = ssid;
11645b9c547cSRui Paulo 	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1165f05cddf9SRui Paulo 	os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
1166f05cddf9SRui Paulo 	wpa_s->assoc_freq = ssid->frequency;
1167c1d255d3SCy Schubert 	wpa_s->ap_iface->conf->enable_edmg = ssid->enable_edmg;
1168c1d255d3SCy Schubert 	wpa_s->ap_iface->conf->edmg_channel = ssid->edmg_channel;
1169f05cddf9SRui Paulo 
117085732ac8SCy Schubert #if defined(CONFIG_P2P) && defined(CONFIG_ACS)
117185732ac8SCy Schubert 	if (wpa_s->p2p_go_do_acs) {
117285732ac8SCy Schubert 		wpa_s->ap_iface->conf->channel = 0;
117385732ac8SCy Schubert 		wpa_s->ap_iface->conf->hw_mode = wpa_s->p2p_go_acs_band;
117485732ac8SCy Schubert 		ssid->acs = 1;
117585732ac8SCy Schubert 	}
117685732ac8SCy Schubert #endif /* CONFIG_P2P && CONFIG_ACS */
117785732ac8SCy Schubert 
1178e28a4053SRui Paulo 	if (hostapd_setup_interface(wpa_s->ap_iface)) {
1179e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Failed to initialize AP interface");
1180e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
1181e28a4053SRui Paulo 		return -1;
1182e28a4053SRui Paulo 	}
1183e28a4053SRui Paulo 
1184e28a4053SRui Paulo 	return 0;
1185e28a4053SRui Paulo }
1186e28a4053SRui Paulo 
1187e28a4053SRui Paulo 
wpa_supplicant_ap_deinit(struct wpa_supplicant * wpa_s)1188e28a4053SRui Paulo void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s)
1189e28a4053SRui Paulo {
1190f05cddf9SRui Paulo #ifdef CONFIG_WPS
1191f05cddf9SRui Paulo 	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
1192f05cddf9SRui Paulo #endif /* CONFIG_WPS */
1193f05cddf9SRui Paulo 
1194e28a4053SRui Paulo 	if (wpa_s->ap_iface == NULL)
1195e28a4053SRui Paulo 		return;
1196e28a4053SRui Paulo 
1197e28a4053SRui Paulo 	wpa_s->current_ssid = NULL;
11985b9c547cSRui Paulo 	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1199f05cddf9SRui Paulo 	wpa_s->assoc_freq = 0;
12005b9c547cSRui Paulo 	wpas_p2p_ap_deinit(wpa_s);
12015b9c547cSRui Paulo 	wpa_s->ap_iface->driver_ap_teardown =
12025b9c547cSRui Paulo 		!!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
12035b9c547cSRui Paulo 
1204e28a4053SRui Paulo 	hostapd_interface_deinit(wpa_s->ap_iface);
1205e28a4053SRui Paulo 	hostapd_interface_free(wpa_s->ap_iface);
1206e28a4053SRui Paulo 	wpa_s->ap_iface = NULL;
1207e28a4053SRui Paulo 	wpa_drv_deinit_ap(wpa_s);
12085b9c547cSRui Paulo 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
12095b9c547cSRui Paulo 		" reason=%d locally_generated=1",
12105b9c547cSRui Paulo 		MAC2STR(wpa_s->own_addr), WLAN_REASON_DEAUTH_LEAVING);
1211e28a4053SRui Paulo }
1212e28a4053SRui Paulo 
1213e28a4053SRui Paulo 
ap_tx_status(void * ctx,const u8 * addr,const u8 * buf,size_t len,int ack)1214e28a4053SRui Paulo void ap_tx_status(void *ctx, const u8 *addr,
1215e28a4053SRui Paulo 		  const u8 *buf, size_t len, int ack)
1216e28a4053SRui Paulo {
1217e28a4053SRui Paulo #ifdef NEED_AP_MLME
1218e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
1219e28a4053SRui Paulo 	hostapd_tx_status(wpa_s->ap_iface->bss[0], addr, buf, len, ack);
1220e28a4053SRui Paulo #endif /* NEED_AP_MLME */
1221e28a4053SRui Paulo }
1222e28a4053SRui Paulo 
1223e28a4053SRui Paulo 
ap_eapol_tx_status(void * ctx,const u8 * dst,const u8 * data,size_t len,int ack)1224f05cddf9SRui Paulo void ap_eapol_tx_status(void *ctx, const u8 *dst,
1225f05cddf9SRui Paulo 			const u8 *data, size_t len, int ack)
1226e28a4053SRui Paulo {
1227e28a4053SRui Paulo #ifdef NEED_AP_MLME
1228e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
12295b9c547cSRui Paulo 	if (!wpa_s->ap_iface)
12305b9c547cSRui Paulo 		return;
1231f05cddf9SRui Paulo 	hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
1232f05cddf9SRui Paulo #endif /* NEED_AP_MLME */
1233f05cddf9SRui Paulo }
1234f05cddf9SRui Paulo 
1235f05cddf9SRui Paulo 
ap_client_poll_ok(void * ctx,const u8 * addr)1236f05cddf9SRui Paulo void ap_client_poll_ok(void *ctx, const u8 *addr)
1237f05cddf9SRui Paulo {
1238f05cddf9SRui Paulo #ifdef NEED_AP_MLME
1239f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
1240f05cddf9SRui Paulo 	if (wpa_s->ap_iface)
1241f05cddf9SRui Paulo 		hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr);
1242f05cddf9SRui Paulo #endif /* NEED_AP_MLME */
1243f05cddf9SRui Paulo }
1244f05cddf9SRui Paulo 
1245f05cddf9SRui Paulo 
ap_rx_from_unknown_sta(void * ctx,const u8 * addr,int wds)1246f05cddf9SRui Paulo void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds)
1247f05cddf9SRui Paulo {
1248f05cddf9SRui Paulo #ifdef NEED_AP_MLME
1249f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
1250f05cddf9SRui Paulo 	ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds);
1251e28a4053SRui Paulo #endif /* NEED_AP_MLME */
1252e28a4053SRui Paulo }
1253e28a4053SRui Paulo 
1254e28a4053SRui Paulo 
ap_mgmt_rx(void * ctx,struct rx_mgmt * rx_mgmt)1255e28a4053SRui Paulo void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt)
1256e28a4053SRui Paulo {
1257e28a4053SRui Paulo #ifdef NEED_AP_MLME
1258e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
1259e28a4053SRui Paulo 	struct hostapd_frame_info fi;
1260e28a4053SRui Paulo 	os_memset(&fi, 0, sizeof(fi));
1261*a90b9d01SCy Schubert 	fi.freq = rx_mgmt->freq;
1262e28a4053SRui Paulo 	fi.datarate = rx_mgmt->datarate;
1263e28a4053SRui Paulo 	fi.ssi_signal = rx_mgmt->ssi_signal;
1264e28a4053SRui Paulo 	ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame,
1265e28a4053SRui Paulo 			rx_mgmt->frame_len, &fi);
1266e28a4053SRui Paulo #endif /* NEED_AP_MLME */
1267e28a4053SRui Paulo }
1268e28a4053SRui Paulo 
1269e28a4053SRui Paulo 
ap_mgmt_tx_cb(void * ctx,const u8 * buf,size_t len,u16 stype,int ok)1270e28a4053SRui Paulo void ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok)
1271e28a4053SRui Paulo {
1272e28a4053SRui Paulo #ifdef NEED_AP_MLME
1273e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
1274e28a4053SRui Paulo 	ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok);
1275e28a4053SRui Paulo #endif /* NEED_AP_MLME */
1276e28a4053SRui Paulo }
1277e28a4053SRui Paulo 
1278e28a4053SRui Paulo 
wpa_supplicant_ap_rx_eapol(struct wpa_supplicant * wpa_s,const u8 * src_addr,const u8 * buf,size_t len,enum frame_encryption encrypted)1279e28a4053SRui Paulo void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
1280*a90b9d01SCy Schubert 				const u8 *src_addr, const u8 *buf, size_t len,
1281*a90b9d01SCy Schubert 				enum frame_encryption encrypted)
1282e28a4053SRui Paulo {
1283*a90b9d01SCy Schubert 	ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len,
1284*a90b9d01SCy Schubert 			   encrypted);
1285e28a4053SRui Paulo }
1286e28a4053SRui Paulo 
1287e28a4053SRui Paulo 
1288e28a4053SRui Paulo #ifdef CONFIG_WPS
1289e28a4053SRui Paulo 
wpa_supplicant_ap_wps_pbc(struct wpa_supplicant * wpa_s,const u8 * bssid,const u8 * p2p_dev_addr)1290f05cddf9SRui Paulo int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
1291f05cddf9SRui Paulo 			      const u8 *p2p_dev_addr)
1292e28a4053SRui Paulo {
1293e28a4053SRui Paulo 	if (!wpa_s->ap_iface)
1294e28a4053SRui Paulo 		return -1;
1295f05cddf9SRui Paulo 	return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0],
1296f05cddf9SRui Paulo 					 p2p_dev_addr);
1297f05cddf9SRui Paulo }
1298f05cddf9SRui Paulo 
1299f05cddf9SRui Paulo 
wpa_supplicant_ap_wps_cancel(struct wpa_supplicant * wpa_s)1300f05cddf9SRui Paulo int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s)
1301f05cddf9SRui Paulo {
1302f05cddf9SRui Paulo 	struct wps_registrar *reg;
1303f05cddf9SRui Paulo 	int reg_sel = 0, wps_sta = 0;
1304f05cddf9SRui Paulo 
1305f05cddf9SRui Paulo 	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps)
1306f05cddf9SRui Paulo 		return -1;
1307f05cddf9SRui Paulo 
1308f05cddf9SRui Paulo 	reg = wpa_s->ap_iface->bss[0]->wps->registrar;
1309f05cddf9SRui Paulo 	reg_sel = wps_registrar_wps_cancel(reg);
1310f05cddf9SRui Paulo 	wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0],
1311f05cddf9SRui Paulo 				  ap_sta_wps_cancel, NULL);
1312f05cddf9SRui Paulo 
1313f05cddf9SRui Paulo 	if (!reg_sel && !wps_sta) {
1314f05cddf9SRui Paulo 		wpa_printf(MSG_DEBUG, "No WPS operation in progress at this "
1315f05cddf9SRui Paulo 			   "time");
1316f05cddf9SRui Paulo 		return -1;
1317f05cddf9SRui Paulo 	}
1318f05cddf9SRui Paulo 
1319f05cddf9SRui Paulo 	/*
1320f05cddf9SRui Paulo 	 * There are 2 cases to return wps cancel as success:
1321f05cddf9SRui Paulo 	 * 1. When wps cancel was initiated but no connection has been
1322f05cddf9SRui Paulo 	 *    established with client yet.
1323f05cddf9SRui Paulo 	 * 2. Client is in the middle of exchanging WPS messages.
1324f05cddf9SRui Paulo 	 */
1325f05cddf9SRui Paulo 
1326f05cddf9SRui Paulo 	return 0;
1327e28a4053SRui Paulo }
1328e28a4053SRui Paulo 
1329e28a4053SRui Paulo 
wpa_supplicant_ap_wps_pin(struct wpa_supplicant * wpa_s,const u8 * bssid,const char * pin,char * buf,size_t buflen,int timeout)1330e28a4053SRui Paulo int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
1331f05cddf9SRui Paulo 			      const char *pin, char *buf, size_t buflen,
1332f05cddf9SRui Paulo 			      int timeout)
1333e28a4053SRui Paulo {
1334e28a4053SRui Paulo 	int ret, ret_len = 0;
1335e28a4053SRui Paulo 
1336e28a4053SRui Paulo 	if (!wpa_s->ap_iface)
1337e28a4053SRui Paulo 		return -1;
1338e28a4053SRui Paulo 
1339e28a4053SRui Paulo 	if (pin == NULL) {
1340780fb4a2SCy Schubert 		unsigned int rpin;
1341780fb4a2SCy Schubert 
1342780fb4a2SCy Schubert 		if (wps_generate_pin(&rpin) < 0)
1343780fb4a2SCy Schubert 			return -1;
1344f05cddf9SRui Paulo 		ret_len = os_snprintf(buf, buflen, "%08d", rpin);
13455b9c547cSRui Paulo 		if (os_snprintf_error(buflen, ret_len))
13465b9c547cSRui Paulo 			return -1;
1347e28a4053SRui Paulo 		pin = buf;
13485b9c547cSRui Paulo 	} else if (buf) {
1349f05cddf9SRui Paulo 		ret_len = os_snprintf(buf, buflen, "%s", pin);
13505b9c547cSRui Paulo 		if (os_snprintf_error(buflen, ret_len))
13515b9c547cSRui Paulo 			return -1;
13525b9c547cSRui Paulo 	}
1353e28a4053SRui Paulo 
1354f05cddf9SRui Paulo 	ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin,
1355f05cddf9SRui Paulo 				  timeout);
1356e28a4053SRui Paulo 	if (ret)
1357e28a4053SRui Paulo 		return -1;
1358e28a4053SRui Paulo 	return ret_len;
1359e28a4053SRui Paulo }
1360e28a4053SRui Paulo 
1361f05cddf9SRui Paulo 
wpas_wps_ap_pin_timeout(void * eloop_data,void * user_ctx)1362f05cddf9SRui Paulo static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
1363f05cddf9SRui Paulo {
1364f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = eloop_data;
1365f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
1366f05cddf9SRui Paulo 	wpas_wps_ap_pin_disable(wpa_s);
1367f05cddf9SRui Paulo }
1368f05cddf9SRui Paulo 
1369f05cddf9SRui Paulo 
wpas_wps_ap_pin_enable(struct wpa_supplicant * wpa_s,int timeout)1370f05cddf9SRui Paulo static void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout)
1371f05cddf9SRui Paulo {
1372f05cddf9SRui Paulo 	struct hostapd_data *hapd;
1373f05cddf9SRui Paulo 
1374f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1375f05cddf9SRui Paulo 		return;
1376f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1377f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
1378f05cddf9SRui Paulo 	hapd->ap_pin_failures = 0;
1379f05cddf9SRui Paulo 	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
1380f05cddf9SRui Paulo 	if (timeout > 0)
1381f05cddf9SRui Paulo 		eloop_register_timeout(timeout, 0,
1382f05cddf9SRui Paulo 				       wpas_wps_ap_pin_timeout, wpa_s, NULL);
1383f05cddf9SRui Paulo }
1384f05cddf9SRui Paulo 
1385f05cddf9SRui Paulo 
wpas_wps_ap_pin_disable(struct wpa_supplicant * wpa_s)1386f05cddf9SRui Paulo void wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s)
1387f05cddf9SRui Paulo {
1388f05cddf9SRui Paulo 	struct hostapd_data *hapd;
1389f05cddf9SRui Paulo 
1390f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1391f05cddf9SRui Paulo 		return;
1392f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
1393f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1394f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
1395f05cddf9SRui Paulo 	hapd->conf->ap_pin = NULL;
1396f05cddf9SRui Paulo 	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
1397f05cddf9SRui Paulo }
1398f05cddf9SRui Paulo 
1399f05cddf9SRui Paulo 
wpas_wps_ap_pin_random(struct wpa_supplicant * wpa_s,int timeout)1400f05cddf9SRui Paulo const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
1401f05cddf9SRui Paulo {
1402f05cddf9SRui Paulo 	struct hostapd_data *hapd;
1403f05cddf9SRui Paulo 	unsigned int pin;
1404f05cddf9SRui Paulo 	char pin_txt[9];
1405f05cddf9SRui Paulo 
1406f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1407f05cddf9SRui Paulo 		return NULL;
1408f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1409780fb4a2SCy Schubert 	if (wps_generate_pin(&pin) < 0)
1410780fb4a2SCy Schubert 		return NULL;
1411f05cddf9SRui Paulo 	os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
1412f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
1413f05cddf9SRui Paulo 	hapd->conf->ap_pin = os_strdup(pin_txt);
1414f05cddf9SRui Paulo 	if (hapd->conf->ap_pin == NULL)
1415f05cddf9SRui Paulo 		return NULL;
1416f05cddf9SRui Paulo 	wpas_wps_ap_pin_enable(wpa_s, timeout);
1417f05cddf9SRui Paulo 
1418f05cddf9SRui Paulo 	return hapd->conf->ap_pin;
1419f05cddf9SRui Paulo }
1420f05cddf9SRui Paulo 
1421f05cddf9SRui Paulo 
wpas_wps_ap_pin_get(struct wpa_supplicant * wpa_s)1422f05cddf9SRui Paulo const char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s)
1423f05cddf9SRui Paulo {
1424f05cddf9SRui Paulo 	struct hostapd_data *hapd;
1425f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1426f05cddf9SRui Paulo 		return NULL;
1427f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1428f05cddf9SRui Paulo 	return hapd->conf->ap_pin;
1429f05cddf9SRui Paulo }
1430f05cddf9SRui Paulo 
1431f05cddf9SRui Paulo 
wpas_wps_ap_pin_set(struct wpa_supplicant * wpa_s,const char * pin,int timeout)1432f05cddf9SRui Paulo int wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin,
1433f05cddf9SRui Paulo 			int timeout)
1434f05cddf9SRui Paulo {
1435f05cddf9SRui Paulo 	struct hostapd_data *hapd;
1436f05cddf9SRui Paulo 	char pin_txt[9];
1437f05cddf9SRui Paulo 	int ret;
1438f05cddf9SRui Paulo 
1439f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1440f05cddf9SRui Paulo 		return -1;
1441f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1442f05cddf9SRui Paulo 	ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin);
14435b9c547cSRui Paulo 	if (os_snprintf_error(sizeof(pin_txt), ret))
1444f05cddf9SRui Paulo 		return -1;
1445f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
1446f05cddf9SRui Paulo 	hapd->conf->ap_pin = os_strdup(pin_txt);
1447f05cddf9SRui Paulo 	if (hapd->conf->ap_pin == NULL)
1448f05cddf9SRui Paulo 		return -1;
1449f05cddf9SRui Paulo 	wpas_wps_ap_pin_enable(wpa_s, timeout);
1450f05cddf9SRui Paulo 
1451f05cddf9SRui Paulo 	return 0;
1452f05cddf9SRui Paulo }
1453f05cddf9SRui Paulo 
1454f05cddf9SRui Paulo 
wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant * wpa_s)1455f05cddf9SRui Paulo void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s)
1456f05cddf9SRui Paulo {
1457f05cddf9SRui Paulo 	struct hostapd_data *hapd;
1458f05cddf9SRui Paulo 
1459f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1460f05cddf9SRui Paulo 		return;
1461f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1462f05cddf9SRui Paulo 
1463f05cddf9SRui Paulo 	/*
1464f05cddf9SRui Paulo 	 * Registrar failed to prove its knowledge of the AP PIN. Disable AP
1465f05cddf9SRui Paulo 	 * PIN if this happens multiple times to slow down brute force attacks.
1466f05cddf9SRui Paulo 	 */
1467f05cddf9SRui Paulo 	hapd->ap_pin_failures++;
1468f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
1469f05cddf9SRui Paulo 		   hapd->ap_pin_failures);
1470f05cddf9SRui Paulo 	if (hapd->ap_pin_failures < 3)
1471f05cddf9SRui Paulo 		return;
1472f05cddf9SRui Paulo 
1473f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN");
1474f05cddf9SRui Paulo 	hapd->ap_pin_failures = 0;
1475f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
1476f05cddf9SRui Paulo 	hapd->conf->ap_pin = NULL;
1477f05cddf9SRui Paulo }
1478f05cddf9SRui Paulo 
14795b9c547cSRui Paulo 
14805b9c547cSRui Paulo #ifdef CONFIG_WPS_NFC
14815b9c547cSRui Paulo 
wpas_ap_wps_nfc_config_token(struct wpa_supplicant * wpa_s,int ndef)14825b9c547cSRui Paulo struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
14835b9c547cSRui Paulo 					     int ndef)
14845b9c547cSRui Paulo {
14855b9c547cSRui Paulo 	struct hostapd_data *hapd;
14865b9c547cSRui Paulo 
14875b9c547cSRui Paulo 	if (wpa_s->ap_iface == NULL)
14885b9c547cSRui Paulo 		return NULL;
14895b9c547cSRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
14905b9c547cSRui Paulo 	return hostapd_wps_nfc_config_token(hapd, ndef);
14915b9c547cSRui Paulo }
14925b9c547cSRui Paulo 
14935b9c547cSRui Paulo 
wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant * wpa_s,int ndef)14945b9c547cSRui Paulo struct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
14955b9c547cSRui Paulo 					     int ndef)
14965b9c547cSRui Paulo {
14975b9c547cSRui Paulo 	struct hostapd_data *hapd;
14985b9c547cSRui Paulo 
14995b9c547cSRui Paulo 	if (wpa_s->ap_iface == NULL)
15005b9c547cSRui Paulo 		return NULL;
15015b9c547cSRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
15025b9c547cSRui Paulo 	return hostapd_wps_nfc_hs_cr(hapd, ndef);
15035b9c547cSRui Paulo }
15045b9c547cSRui Paulo 
15055b9c547cSRui Paulo 
wpas_ap_wps_nfc_report_handover(struct wpa_supplicant * wpa_s,const struct wpabuf * req,const struct wpabuf * sel)15065b9c547cSRui Paulo int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
15075b9c547cSRui Paulo 				    const struct wpabuf *req,
15085b9c547cSRui Paulo 				    const struct wpabuf *sel)
15095b9c547cSRui Paulo {
15105b9c547cSRui Paulo 	struct hostapd_data *hapd;
15115b9c547cSRui Paulo 
15125b9c547cSRui Paulo 	if (wpa_s->ap_iface == NULL)
15135b9c547cSRui Paulo 		return -1;
15145b9c547cSRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
15155b9c547cSRui Paulo 	return hostapd_wps_nfc_report_handover(hapd, req, sel);
15165b9c547cSRui Paulo }
15175b9c547cSRui Paulo 
15185b9c547cSRui Paulo #endif /* CONFIG_WPS_NFC */
15195b9c547cSRui Paulo 
1520e28a4053SRui Paulo #endif /* CONFIG_WPS */
1521e28a4053SRui Paulo 
1522e28a4053SRui Paulo 
1523e28a4053SRui Paulo #ifdef CONFIG_CTRL_IFACE
1524e28a4053SRui Paulo 
ap_ctrl_iface_sta_first(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1525e28a4053SRui Paulo int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
1526e28a4053SRui Paulo 			    char *buf, size_t buflen)
1527e28a4053SRui Paulo {
15285b9c547cSRui Paulo 	struct hostapd_data *hapd;
15295b9c547cSRui Paulo 
15305b9c547cSRui Paulo 	if (wpa_s->ap_iface)
15315b9c547cSRui Paulo 		hapd = wpa_s->ap_iface->bss[0];
15325b9c547cSRui Paulo 	else if (wpa_s->ifmsh)
15335b9c547cSRui Paulo 		hapd = wpa_s->ifmsh->bss[0];
15345b9c547cSRui Paulo 	else
1535e28a4053SRui Paulo 		return -1;
15365b9c547cSRui Paulo 	return hostapd_ctrl_iface_sta_first(hapd, buf, buflen);
1537e28a4053SRui Paulo }
1538e28a4053SRui Paulo 
1539e28a4053SRui Paulo 
ap_ctrl_iface_sta(struct wpa_supplicant * wpa_s,const char * txtaddr,char * buf,size_t buflen)1540e28a4053SRui Paulo int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
1541e28a4053SRui Paulo 		      char *buf, size_t buflen)
1542e28a4053SRui Paulo {
15435b9c547cSRui Paulo 	struct hostapd_data *hapd;
15445b9c547cSRui Paulo 
15455b9c547cSRui Paulo 	if (wpa_s->ap_iface)
15465b9c547cSRui Paulo 		hapd = wpa_s->ap_iface->bss[0];
15475b9c547cSRui Paulo 	else if (wpa_s->ifmsh)
15485b9c547cSRui Paulo 		hapd = wpa_s->ifmsh->bss[0];
15495b9c547cSRui Paulo 	else
1550e28a4053SRui Paulo 		return -1;
15515b9c547cSRui Paulo 	return hostapd_ctrl_iface_sta(hapd, txtaddr, buf, buflen);
1552e28a4053SRui Paulo }
1553e28a4053SRui Paulo 
1554e28a4053SRui Paulo 
ap_ctrl_iface_sta_next(struct wpa_supplicant * wpa_s,const char * txtaddr,char * buf,size_t buflen)1555e28a4053SRui Paulo int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
1556e28a4053SRui Paulo 			   char *buf, size_t buflen)
1557e28a4053SRui Paulo {
15585b9c547cSRui Paulo 	struct hostapd_data *hapd;
15595b9c547cSRui Paulo 
15605b9c547cSRui Paulo 	if (wpa_s->ap_iface)
15615b9c547cSRui Paulo 		hapd = wpa_s->ap_iface->bss[0];
15625b9c547cSRui Paulo 	else if (wpa_s->ifmsh)
15635b9c547cSRui Paulo 		hapd = wpa_s->ifmsh->bss[0];
15645b9c547cSRui Paulo 	else
1565e28a4053SRui Paulo 		return -1;
15665b9c547cSRui Paulo 	return hostapd_ctrl_iface_sta_next(hapd, txtaddr, buf, buflen);
1567e28a4053SRui Paulo }
1568e28a4053SRui Paulo 
1569e28a4053SRui Paulo 
ap_ctrl_iface_sta_disassociate(struct wpa_supplicant * wpa_s,const char * txtaddr)1570f05cddf9SRui Paulo int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s,
1571f05cddf9SRui Paulo 				   const char *txtaddr)
1572f05cddf9SRui Paulo {
1573f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1574f05cddf9SRui Paulo 		return -1;
1575f05cddf9SRui Paulo 	return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0],
1576f05cddf9SRui Paulo 					       txtaddr);
1577f05cddf9SRui Paulo }
1578f05cddf9SRui Paulo 
1579f05cddf9SRui Paulo 
ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant * wpa_s,const char * txtaddr)1580f05cddf9SRui Paulo int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s,
1581f05cddf9SRui Paulo 				     const char *txtaddr)
1582f05cddf9SRui Paulo {
1583f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
1584f05cddf9SRui Paulo 		return -1;
1585f05cddf9SRui Paulo 	return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0],
1586f05cddf9SRui Paulo 						 txtaddr);
1587f05cddf9SRui Paulo }
1588f05cddf9SRui Paulo 
1589f05cddf9SRui Paulo 
ap_ctrl_iface_wpa_get_status(struct wpa_supplicant * wpa_s,char * buf,size_t buflen,int verbose)1590e28a4053SRui Paulo int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
1591e28a4053SRui Paulo 				 size_t buflen, int verbose)
1592e28a4053SRui Paulo {
1593e28a4053SRui Paulo 	char *pos = buf, *end = buf + buflen;
1594e28a4053SRui Paulo 	int ret;
1595e28a4053SRui Paulo 	struct hostapd_bss_config *conf;
1596e28a4053SRui Paulo 
1597e28a4053SRui Paulo 	if (wpa_s->ap_iface == NULL)
1598e28a4053SRui Paulo 		return -1;
1599e28a4053SRui Paulo 
1600e28a4053SRui Paulo 	conf = wpa_s->ap_iface->bss[0]->conf;
1601e28a4053SRui Paulo 	if (conf->wpa == 0)
1602e28a4053SRui Paulo 		return 0;
1603e28a4053SRui Paulo 
1604e28a4053SRui Paulo 	ret = os_snprintf(pos, end - pos,
1605e28a4053SRui Paulo 			  "pairwise_cipher=%s\n"
1606e28a4053SRui Paulo 			  "group_cipher=%s\n"
1607e28a4053SRui Paulo 			  "key_mgmt=%s\n",
1608e28a4053SRui Paulo 			  wpa_cipher_txt(conf->rsn_pairwise),
1609e28a4053SRui Paulo 			  wpa_cipher_txt(conf->wpa_group),
1610e28a4053SRui Paulo 			  wpa_key_mgmt_txt(conf->wpa_key_mgmt,
1611e28a4053SRui Paulo 					   conf->wpa));
16125b9c547cSRui Paulo 	if (os_snprintf_error(end - pos, ret))
1613e28a4053SRui Paulo 		return pos - buf;
1614e28a4053SRui Paulo 	pos += ret;
1615e28a4053SRui Paulo 	return pos - buf;
1616e28a4053SRui Paulo }
1617e28a4053SRui Paulo 
1618*a90b9d01SCy Schubert 
1619*a90b9d01SCy Schubert #ifdef CONFIG_WNM_AP
1620*a90b9d01SCy Schubert 
ap_ctrl_iface_disassoc_imminent(struct wpa_supplicant * wpa_s,const char * buf)1621*a90b9d01SCy Schubert int ap_ctrl_iface_disassoc_imminent(struct wpa_supplicant *wpa_s,
1622*a90b9d01SCy Schubert 				    const char *buf)
1623*a90b9d01SCy Schubert {
1624*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1625*a90b9d01SCy Schubert 
1626*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1627*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1628*a90b9d01SCy Schubert 	else
1629*a90b9d01SCy Schubert 		return -1;
1630*a90b9d01SCy Schubert 	return hostapd_ctrl_iface_disassoc_imminent(hapd, buf);
1631*a90b9d01SCy Schubert }
1632*a90b9d01SCy Schubert 
1633*a90b9d01SCy Schubert 
ap_ctrl_iface_ess_disassoc(struct wpa_supplicant * wpa_s,const char * buf)1634*a90b9d01SCy Schubert int ap_ctrl_iface_ess_disassoc(struct wpa_supplicant *wpa_s, const char *buf)
1635*a90b9d01SCy Schubert {
1636*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1637*a90b9d01SCy Schubert 
1638*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1639*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1640*a90b9d01SCy Schubert 	else
1641*a90b9d01SCy Schubert 		return -1;
1642*a90b9d01SCy Schubert 	return hostapd_ctrl_iface_ess_disassoc(hapd, buf);
1643*a90b9d01SCy Schubert }
1644*a90b9d01SCy Schubert 
1645*a90b9d01SCy Schubert 
ap_ctrl_iface_bss_tm_req(struct wpa_supplicant * wpa_s,const char * buf)1646*a90b9d01SCy Schubert int ap_ctrl_iface_bss_tm_req(struct wpa_supplicant *wpa_s, const char *buf)
1647*a90b9d01SCy Schubert {
1648*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1649*a90b9d01SCy Schubert 
1650*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1651*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1652*a90b9d01SCy Schubert 	else
1653*a90b9d01SCy Schubert 		return -1;
1654*a90b9d01SCy Schubert 	return hostapd_ctrl_iface_bss_tm_req(hapd, buf);
1655*a90b9d01SCy Schubert }
1656*a90b9d01SCy Schubert 
1657*a90b9d01SCy Schubert #endif /* CONFIG_WNM_AP */
1658*a90b9d01SCy Schubert 
1659*a90b9d01SCy Schubert 
ap_ctrl_iface_acl_add_mac(struct wpa_supplicant * wpa_s,enum macaddr_acl acl_type,const char * buf)1660*a90b9d01SCy Schubert int ap_ctrl_iface_acl_add_mac(struct wpa_supplicant *wpa_s,
1661*a90b9d01SCy Schubert 			      enum macaddr_acl acl_type,
1662*a90b9d01SCy Schubert 			      const char *buf)
1663*a90b9d01SCy Schubert {
1664*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1665*a90b9d01SCy Schubert 
1666*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1667*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1668*a90b9d01SCy Schubert 	else
1669*a90b9d01SCy Schubert 		return -1;
1670*a90b9d01SCy Schubert 
1671*a90b9d01SCy Schubert 	hapd->conf->macaddr_acl = acl_type;
1672*a90b9d01SCy Schubert 
1673*a90b9d01SCy Schubert 	if (acl_type == ACCEPT_UNLESS_DENIED)
1674*a90b9d01SCy Schubert 		return hostapd_ctrl_iface_acl_add_mac(&hapd->conf->deny_mac,
1675*a90b9d01SCy Schubert 						      &hapd->conf->num_deny_mac,
1676*a90b9d01SCy Schubert 						      buf);
1677*a90b9d01SCy Schubert 	if (acl_type == DENY_UNLESS_ACCEPTED)
1678*a90b9d01SCy Schubert 		return hostapd_ctrl_iface_acl_add_mac(
1679*a90b9d01SCy Schubert 			&hapd->conf->accept_mac,
1680*a90b9d01SCy Schubert 			&hapd->conf->num_accept_mac, buf);
1681*a90b9d01SCy Schubert 
1682*a90b9d01SCy Schubert 	return -1;
1683*a90b9d01SCy Schubert }
1684*a90b9d01SCy Schubert 
1685*a90b9d01SCy Schubert 
ap_ctrl_iface_acl_del_mac(struct wpa_supplicant * wpa_s,enum macaddr_acl acl_type,const char * buf)1686*a90b9d01SCy Schubert int ap_ctrl_iface_acl_del_mac(struct wpa_supplicant *wpa_s,
1687*a90b9d01SCy Schubert 			      enum macaddr_acl acl_type,
1688*a90b9d01SCy Schubert 			      const char *buf)
1689*a90b9d01SCy Schubert {
1690*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1691*a90b9d01SCy Schubert 
1692*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1693*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1694*a90b9d01SCy Schubert 	else
1695*a90b9d01SCy Schubert 		return -1;
1696*a90b9d01SCy Schubert 
1697*a90b9d01SCy Schubert 	hapd->conf->macaddr_acl = acl_type;
1698*a90b9d01SCy Schubert 
1699*a90b9d01SCy Schubert 	if (acl_type == ACCEPT_UNLESS_DENIED)
1700*a90b9d01SCy Schubert 		return hostapd_ctrl_iface_acl_del_mac(&hapd->conf->deny_mac,
1701*a90b9d01SCy Schubert 						      &hapd->conf->num_deny_mac,
1702*a90b9d01SCy Schubert 						      buf);
1703*a90b9d01SCy Schubert 	if (acl_type == DENY_UNLESS_ACCEPTED)
1704*a90b9d01SCy Schubert 		return hostapd_ctrl_iface_acl_del_mac(
1705*a90b9d01SCy Schubert 			&hapd->conf->accept_mac, &hapd->conf->num_accept_mac,
1706*a90b9d01SCy Schubert 			buf);
1707*a90b9d01SCy Schubert 
1708*a90b9d01SCy Schubert 	return -1;
1709*a90b9d01SCy Schubert }
1710*a90b9d01SCy Schubert 
1711*a90b9d01SCy Schubert 
ap_ctrl_iface_acl_show_mac(struct wpa_supplicant * wpa_s,enum macaddr_acl acl_type,char * buf,size_t buflen)1712*a90b9d01SCy Schubert int ap_ctrl_iface_acl_show_mac(struct wpa_supplicant *wpa_s,
1713*a90b9d01SCy Schubert 			       enum macaddr_acl acl_type, char *buf,
1714*a90b9d01SCy Schubert 			       size_t buflen)
1715*a90b9d01SCy Schubert {
1716*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1717*a90b9d01SCy Schubert 
1718*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1719*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1720*a90b9d01SCy Schubert 	else
1721*a90b9d01SCy Schubert 		return -1;
1722*a90b9d01SCy Schubert 
1723*a90b9d01SCy Schubert 	if (acl_type == ACCEPT_UNLESS_DENIED)
1724*a90b9d01SCy Schubert 		return hostapd_ctrl_iface_acl_show_mac(hapd->conf->deny_mac,
1725*a90b9d01SCy Schubert 						       hapd->conf->num_deny_mac,
1726*a90b9d01SCy Schubert 						       buf, buflen);
1727*a90b9d01SCy Schubert 	if (acl_type == DENY_UNLESS_ACCEPTED)
1728*a90b9d01SCy Schubert 		return hostapd_ctrl_iface_acl_show_mac(
1729*a90b9d01SCy Schubert 			hapd->conf->accept_mac,	hapd->conf->num_accept_mac,
1730*a90b9d01SCy Schubert 			buf, buflen);
1731*a90b9d01SCy Schubert 
1732*a90b9d01SCy Schubert 	return -1;
1733*a90b9d01SCy Schubert }
1734*a90b9d01SCy Schubert 
1735*a90b9d01SCy Schubert 
ap_ctrl_iface_acl_clear_list(struct wpa_supplicant * wpa_s,enum macaddr_acl acl_type)1736*a90b9d01SCy Schubert void ap_ctrl_iface_acl_clear_list(struct wpa_supplicant *wpa_s,
1737*a90b9d01SCy Schubert 				  enum macaddr_acl acl_type)
1738*a90b9d01SCy Schubert {
1739*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1740*a90b9d01SCy Schubert 
1741*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1742*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1743*a90b9d01SCy Schubert 	else
1744*a90b9d01SCy Schubert 		return;
1745*a90b9d01SCy Schubert 
1746*a90b9d01SCy Schubert 	hapd->conf->macaddr_acl = acl_type;
1747*a90b9d01SCy Schubert 
1748*a90b9d01SCy Schubert 	if (acl_type == ACCEPT_UNLESS_DENIED)
1749*a90b9d01SCy Schubert 		hostapd_ctrl_iface_acl_clear_list(&hapd->conf->deny_mac,
1750*a90b9d01SCy Schubert 						  &hapd->conf->num_deny_mac);
1751*a90b9d01SCy Schubert 	else if (acl_type == DENY_UNLESS_ACCEPTED)
1752*a90b9d01SCy Schubert 		hostapd_ctrl_iface_acl_clear_list(&hapd->conf->accept_mac,
1753*a90b9d01SCy Schubert 						  &hapd->conf->num_accept_mac);
1754*a90b9d01SCy Schubert }
1755*a90b9d01SCy Schubert 
1756*a90b9d01SCy Schubert 
ap_ctrl_iface_disassoc_deny_mac(struct wpa_supplicant * wpa_s)1757*a90b9d01SCy Schubert int ap_ctrl_iface_disassoc_deny_mac(struct wpa_supplicant *wpa_s)
1758*a90b9d01SCy Schubert {
1759*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1760*a90b9d01SCy Schubert 
1761*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1762*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1763*a90b9d01SCy Schubert 	else
1764*a90b9d01SCy Schubert 		return -1;
1765*a90b9d01SCy Schubert 
1766*a90b9d01SCy Schubert 	return hostapd_disassoc_deny_mac(hapd);
1767*a90b9d01SCy Schubert }
1768*a90b9d01SCy Schubert 
1769*a90b9d01SCy Schubert 
ap_ctrl_iface_disassoc_accept_mac(struct wpa_supplicant * wpa_s)1770*a90b9d01SCy Schubert int ap_ctrl_iface_disassoc_accept_mac(struct wpa_supplicant *wpa_s)
1771*a90b9d01SCy Schubert {
1772*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1773*a90b9d01SCy Schubert 
1774*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1775*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1776*a90b9d01SCy Schubert 	else
1777*a90b9d01SCy Schubert 		return -1;
1778*a90b9d01SCy Schubert 
1779*a90b9d01SCy Schubert 	return hostapd_disassoc_accept_mac(hapd);
1780*a90b9d01SCy Schubert }
1781*a90b9d01SCy Schubert 
1782*a90b9d01SCy Schubert 
ap_ctrl_iface_set_acl(struct wpa_supplicant * wpa_s)1783*a90b9d01SCy Schubert int ap_ctrl_iface_set_acl(struct wpa_supplicant *wpa_s)
1784*a90b9d01SCy Schubert {
1785*a90b9d01SCy Schubert 	struct hostapd_data *hapd;
1786*a90b9d01SCy Schubert 
1787*a90b9d01SCy Schubert 	if (wpa_s->ap_iface)
1788*a90b9d01SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
1789*a90b9d01SCy Schubert 	else
1790*a90b9d01SCy Schubert 		return -1;
1791*a90b9d01SCy Schubert 
1792*a90b9d01SCy Schubert 	return hostapd_set_acl(hapd);
1793*a90b9d01SCy Schubert }
1794*a90b9d01SCy Schubert 
1795e28a4053SRui Paulo #endif /* CONFIG_CTRL_IFACE */
1796e28a4053SRui Paulo 
1797e28a4053SRui Paulo 
wpa_supplicant_ap_update_beacon(struct wpa_supplicant * wpa_s)1798f05cddf9SRui Paulo int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
1799f05cddf9SRui Paulo {
1800f05cddf9SRui Paulo 	struct hostapd_iface *iface = wpa_s->ap_iface;
1801f05cddf9SRui Paulo 	struct wpa_ssid *ssid = wpa_s->current_ssid;
1802f05cddf9SRui Paulo 	struct hostapd_data *hapd;
1803f05cddf9SRui Paulo 
1804f05cddf9SRui Paulo 	if (ssid == NULL || wpa_s->ap_iface == NULL ||
1805f05cddf9SRui Paulo 	    ssid->mode == WPAS_MODE_INFRA ||
1806f05cddf9SRui Paulo 	    ssid->mode == WPAS_MODE_IBSS)
1807f05cddf9SRui Paulo 		return -1;
1808f05cddf9SRui Paulo 
1809f05cddf9SRui Paulo #ifdef CONFIG_P2P
1810f05cddf9SRui Paulo 	if (ssid->mode == WPAS_MODE_P2P_GO)
18115b9c547cSRui Paulo 		iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
1812f05cddf9SRui Paulo 	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
18135b9c547cSRui Paulo 		iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
1814f05cddf9SRui Paulo 			P2P_GROUP_FORMATION;
1815f05cddf9SRui Paulo #endif /* CONFIG_P2P */
1816f05cddf9SRui Paulo 
1817f05cddf9SRui Paulo 	hapd = iface->bss[0];
1818f05cddf9SRui Paulo 	if (hapd->drv_priv == NULL)
1819f05cddf9SRui Paulo 		return -1;
1820f05cddf9SRui Paulo 	ieee802_11_set_beacons(iface);
1821f05cddf9SRui Paulo 	hostapd_set_ap_wps_ie(hapd);
1822f05cddf9SRui Paulo 
1823f05cddf9SRui Paulo 	return 0;
1824f05cddf9SRui Paulo }
1825f05cddf9SRui Paulo 
1826f05cddf9SRui Paulo 
ap_switch_channel(struct wpa_supplicant * wpa_s,struct csa_settings * settings)18275b9c547cSRui Paulo int ap_switch_channel(struct wpa_supplicant *wpa_s,
18285b9c547cSRui Paulo 		      struct csa_settings *settings)
18295b9c547cSRui Paulo {
18305b9c547cSRui Paulo #ifdef NEED_AP_MLME
1831c1d255d3SCy Schubert 	struct hostapd_iface *iface = NULL;
1832c1d255d3SCy Schubert 
1833c1d255d3SCy Schubert 	if (wpa_s->ap_iface)
1834c1d255d3SCy Schubert 		iface = wpa_s->ap_iface;
1835c1d255d3SCy Schubert 	else if (wpa_s->ifmsh)
1836c1d255d3SCy Schubert 		iface = wpa_s->ifmsh;
1837c1d255d3SCy Schubert 
1838c1d255d3SCy Schubert 	if (!iface || !iface->bss[0])
18395b9c547cSRui Paulo 		return -1;
18405b9c547cSRui Paulo 
1841c1d255d3SCy Schubert 	return hostapd_switch_channel(iface->bss[0], settings);
18425b9c547cSRui Paulo #else /* NEED_AP_MLME */
18435b9c547cSRui Paulo 	return -1;
18445b9c547cSRui Paulo #endif /* NEED_AP_MLME */
18455b9c547cSRui Paulo }
18465b9c547cSRui Paulo 
18475b9c547cSRui Paulo 
1848325151a3SRui Paulo #ifdef CONFIG_CTRL_IFACE
ap_ctrl_iface_chanswitch(struct wpa_supplicant * wpa_s,const char * pos)18495b9c547cSRui Paulo int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
18505b9c547cSRui Paulo {
18515b9c547cSRui Paulo 	struct csa_settings settings;
18525b9c547cSRui Paulo 	int ret = hostapd_parse_csa_settings(pos, &settings);
18535b9c547cSRui Paulo 
18545b9c547cSRui Paulo 	if (ret)
18555b9c547cSRui Paulo 		return ret;
18565b9c547cSRui Paulo 
1857*a90b9d01SCy Schubert 	settings.link_id = -1;
1858*a90b9d01SCy Schubert 
18595b9c547cSRui Paulo 	return ap_switch_channel(wpa_s, &settings);
18605b9c547cSRui Paulo }
1861325151a3SRui Paulo #endif /* CONFIG_CTRL_IFACE */
18625b9c547cSRui Paulo 
18635b9c547cSRui Paulo 
wpas_ap_ch_switch(struct wpa_supplicant * wpa_s,int freq,int ht,int offset,int width,int cf1,int cf2,u16 punct_bitmap,int finished)1864f05cddf9SRui Paulo void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
1865*a90b9d01SCy Schubert 		       int offset, int width, int cf1, int cf2,
1866*a90b9d01SCy Schubert 		       u16 punct_bitmap, int finished)
1867f05cddf9SRui Paulo {
18684bc52338SCy Schubert 	struct hostapd_iface *iface = wpa_s->ap_iface;
1869f05cddf9SRui Paulo 
18704bc52338SCy Schubert 	if (!iface)
18714bc52338SCy Schubert 		iface = wpa_s->ifmsh;
18724bc52338SCy Schubert 	if (!iface)
18734bc52338SCy Schubert 		return;
1874f05cddf9SRui Paulo 	wpa_s->assoc_freq = freq;
1875325151a3SRui Paulo 	if (wpa_s->current_ssid)
1876325151a3SRui Paulo 		wpa_s->current_ssid->frequency = freq;
18774bc52338SCy Schubert 	hostapd_event_ch_switch(iface->bss[0], freq, ht,
1878*a90b9d01SCy Schubert 				offset, width, cf1, cf2, punct_bitmap,
1879*a90b9d01SCy Schubert 				finished);
1880f05cddf9SRui Paulo }
1881f05cddf9SRui Paulo 
1882f05cddf9SRui Paulo 
wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant * wpa_s,const u8 * addr)1883e28a4053SRui Paulo int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
1884e28a4053SRui Paulo 				      const u8 *addr)
1885e28a4053SRui Paulo {
1886e28a4053SRui Paulo 	struct hostapd_data *hapd;
1887e28a4053SRui Paulo 	struct hostapd_bss_config *conf;
1888e28a4053SRui Paulo 
1889e28a4053SRui Paulo 	if (!wpa_s->ap_iface)
1890e28a4053SRui Paulo 		return -1;
1891e28a4053SRui Paulo 
1892e28a4053SRui Paulo 	if (addr)
1893e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR,
1894e28a4053SRui Paulo 			   MAC2STR(addr));
1895e28a4053SRui Paulo 	else
1896e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter");
1897e28a4053SRui Paulo 
1898e28a4053SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1899e28a4053SRui Paulo 	conf = hapd->conf;
1900e28a4053SRui Paulo 
1901e28a4053SRui Paulo 	os_free(conf->accept_mac);
1902e28a4053SRui Paulo 	conf->accept_mac = NULL;
1903e28a4053SRui Paulo 	conf->num_accept_mac = 0;
1904e28a4053SRui Paulo 	os_free(conf->deny_mac);
1905e28a4053SRui Paulo 	conf->deny_mac = NULL;
1906e28a4053SRui Paulo 	conf->num_deny_mac = 0;
1907e28a4053SRui Paulo 
1908e28a4053SRui Paulo 	if (addr == NULL) {
1909e28a4053SRui Paulo 		conf->macaddr_acl = ACCEPT_UNLESS_DENIED;
1910e28a4053SRui Paulo 		return 0;
1911e28a4053SRui Paulo 	}
1912e28a4053SRui Paulo 
1913e28a4053SRui Paulo 	conf->macaddr_acl = DENY_UNLESS_ACCEPTED;
1914e28a4053SRui Paulo 	conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry));
1915e28a4053SRui Paulo 	if (conf->accept_mac == NULL)
1916e28a4053SRui Paulo 		return -1;
1917e28a4053SRui Paulo 	os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN);
1918e28a4053SRui Paulo 	conf->num_accept_mac = 1;
1919e28a4053SRui Paulo 
1920e28a4053SRui Paulo 	return 0;
1921e28a4053SRui Paulo }
19225b9c547cSRui Paulo 
19235b9c547cSRui Paulo 
19245b9c547cSRui Paulo #ifdef CONFIG_WPS_NFC
wpas_ap_wps_add_nfc_pw(struct wpa_supplicant * wpa_s,u16 pw_id,const struct wpabuf * pw,const u8 * pubkey_hash)19255b9c547cSRui Paulo int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
19265b9c547cSRui Paulo 			   const struct wpabuf *pw, const u8 *pubkey_hash)
19275b9c547cSRui Paulo {
19285b9c547cSRui Paulo 	struct hostapd_data *hapd;
19295b9c547cSRui Paulo 	struct wps_context *wps;
19305b9c547cSRui Paulo 
19315b9c547cSRui Paulo 	if (!wpa_s->ap_iface)
19325b9c547cSRui Paulo 		return -1;
19335b9c547cSRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
19345b9c547cSRui Paulo 	wps = hapd->wps;
19355b9c547cSRui Paulo 
1936780fb4a2SCy Schubert 	if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL ||
1937780fb4a2SCy Schubert 	    wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) {
19385b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known");
19395b9c547cSRui Paulo 		return -1;
19405b9c547cSRui Paulo 	}
19415b9c547cSRui Paulo 
19425b9c547cSRui Paulo 	dh5_free(wps->dh_ctx);
19435b9c547cSRui Paulo 	wpabuf_free(wps->dh_pubkey);
19445b9c547cSRui Paulo 	wpabuf_free(wps->dh_privkey);
19455b9c547cSRui Paulo 	wps->dh_privkey = wpabuf_dup(
1946780fb4a2SCy Schubert 		wpa_s->p2pdev->conf->wps_nfc_dh_privkey);
19475b9c547cSRui Paulo 	wps->dh_pubkey = wpabuf_dup(
1948780fb4a2SCy Schubert 		wpa_s->p2pdev->conf->wps_nfc_dh_pubkey);
19495b9c547cSRui Paulo 	if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
19505b9c547cSRui Paulo 		wps->dh_ctx = NULL;
19515b9c547cSRui Paulo 		wpabuf_free(wps->dh_pubkey);
19525b9c547cSRui Paulo 		wps->dh_pubkey = NULL;
19535b9c547cSRui Paulo 		wpabuf_free(wps->dh_privkey);
19545b9c547cSRui Paulo 		wps->dh_privkey = NULL;
19555b9c547cSRui Paulo 		return -1;
19565b9c547cSRui Paulo 	}
19575b9c547cSRui Paulo 	wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
19585b9c547cSRui Paulo 	if (wps->dh_ctx == NULL)
19595b9c547cSRui Paulo 		return -1;
19605b9c547cSRui Paulo 
19615b9c547cSRui Paulo 	return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash,
19625b9c547cSRui Paulo 					      pw_id,
19635b9c547cSRui Paulo 					      pw ? wpabuf_head(pw) : NULL,
19645b9c547cSRui Paulo 					      pw ? wpabuf_len(pw) : 0, 1);
19655b9c547cSRui Paulo }
19665b9c547cSRui Paulo #endif /* CONFIG_WPS_NFC */
19675b9c547cSRui Paulo 
19685b9c547cSRui Paulo 
1969325151a3SRui Paulo #ifdef CONFIG_CTRL_IFACE
wpas_ap_stop_ap(struct wpa_supplicant * wpa_s)19705b9c547cSRui Paulo int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s)
19715b9c547cSRui Paulo {
19725b9c547cSRui Paulo 	struct hostapd_data *hapd;
19735b9c547cSRui Paulo 
19745b9c547cSRui Paulo 	if (!wpa_s->ap_iface)
19755b9c547cSRui Paulo 		return -1;
19765b9c547cSRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
19775b9c547cSRui Paulo 	return hostapd_ctrl_iface_stop_ap(hapd);
19785b9c547cSRui Paulo }
1979780fb4a2SCy Schubert 
1980780fb4a2SCy Schubert 
wpas_ap_pmksa_cache_list(struct wpa_supplicant * wpa_s,char * buf,size_t len)1981780fb4a2SCy Schubert int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
1982780fb4a2SCy Schubert 			     size_t len)
1983780fb4a2SCy Schubert {
1984780fb4a2SCy Schubert 	size_t reply_len = 0, i;
1985780fb4a2SCy Schubert 	char ap_delimiter[] = "---- AP ----\n";
1986780fb4a2SCy Schubert 	char mesh_delimiter[] = "---- mesh ----\n";
1987780fb4a2SCy Schubert 	size_t dlen;
1988780fb4a2SCy Schubert 
1989780fb4a2SCy Schubert 	if (wpa_s->ap_iface) {
1990780fb4a2SCy Schubert 		dlen = os_strlen(ap_delimiter);
1991780fb4a2SCy Schubert 		if (dlen > len - reply_len)
1992780fb4a2SCy Schubert 			return reply_len;
1993780fb4a2SCy Schubert 		os_memcpy(&buf[reply_len], ap_delimiter, dlen);
1994780fb4a2SCy Schubert 		reply_len += dlen;
1995780fb4a2SCy Schubert 
1996780fb4a2SCy Schubert 		for (i = 0; i < wpa_s->ap_iface->num_bss; i++) {
1997780fb4a2SCy Schubert 			reply_len += hostapd_ctrl_iface_pmksa_list(
1998780fb4a2SCy Schubert 				wpa_s->ap_iface->bss[i],
1999780fb4a2SCy Schubert 				&buf[reply_len], len - reply_len);
2000780fb4a2SCy Schubert 		}
2001780fb4a2SCy Schubert 	}
2002780fb4a2SCy Schubert 
2003780fb4a2SCy Schubert 	if (wpa_s->ifmsh) {
2004780fb4a2SCy Schubert 		dlen = os_strlen(mesh_delimiter);
2005780fb4a2SCy Schubert 		if (dlen > len - reply_len)
2006780fb4a2SCy Schubert 			return reply_len;
2007780fb4a2SCy Schubert 		os_memcpy(&buf[reply_len], mesh_delimiter, dlen);
2008780fb4a2SCy Schubert 		reply_len += dlen;
2009780fb4a2SCy Schubert 
2010780fb4a2SCy Schubert 		reply_len += hostapd_ctrl_iface_pmksa_list(
2011780fb4a2SCy Schubert 			wpa_s->ifmsh->bss[0], &buf[reply_len],
2012780fb4a2SCy Schubert 			len - reply_len);
2013780fb4a2SCy Schubert 	}
2014780fb4a2SCy Schubert 
2015780fb4a2SCy Schubert 	return reply_len;
2016780fb4a2SCy Schubert }
2017780fb4a2SCy Schubert 
2018780fb4a2SCy Schubert 
wpas_ap_pmksa_cache_flush(struct wpa_supplicant * wpa_s)2019780fb4a2SCy Schubert void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
2020780fb4a2SCy Schubert {
2021780fb4a2SCy Schubert 	size_t i;
2022780fb4a2SCy Schubert 
2023780fb4a2SCy Schubert 	if (wpa_s->ap_iface) {
2024780fb4a2SCy Schubert 		for (i = 0; i < wpa_s->ap_iface->num_bss; i++)
2025780fb4a2SCy Schubert 			hostapd_ctrl_iface_pmksa_flush(wpa_s->ap_iface->bss[i]);
2026780fb4a2SCy Schubert 	}
2027780fb4a2SCy Schubert 
2028780fb4a2SCy Schubert 	if (wpa_s->ifmsh)
2029780fb4a2SCy Schubert 		hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]);
2030780fb4a2SCy Schubert }
203185732ac8SCy Schubert 
203285732ac8SCy Schubert 
203385732ac8SCy Schubert #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
203485732ac8SCy Schubert #ifdef CONFIG_MESH
203585732ac8SCy Schubert 
wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant * wpa_s,const u8 * addr,char * buf,size_t len)203685732ac8SCy Schubert int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
203785732ac8SCy Schubert 				  char *buf, size_t len)
203885732ac8SCy Schubert {
203985732ac8SCy Schubert 	return hostapd_ctrl_iface_pmksa_list_mesh(wpa_s->ifmsh->bss[0], addr,
204085732ac8SCy Schubert 						  &buf[0], len);
204185732ac8SCy Schubert }
204285732ac8SCy Schubert 
204385732ac8SCy Schubert 
wpas_ap_pmksa_cache_add_external(struct wpa_supplicant * wpa_s,char * cmd)204485732ac8SCy Schubert int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd)
204585732ac8SCy Schubert {
204685732ac8SCy Schubert 	struct external_pmksa_cache *entry;
204785732ac8SCy Schubert 	void *pmksa_cache;
204885732ac8SCy Schubert 
204985732ac8SCy Schubert 	pmksa_cache = hostapd_ctrl_iface_pmksa_create_entry(wpa_s->own_addr,
205085732ac8SCy Schubert 							    cmd);
205185732ac8SCy Schubert 	if (!pmksa_cache)
205285732ac8SCy Schubert 		return -1;
205385732ac8SCy Schubert 
205485732ac8SCy Schubert 	entry = os_zalloc(sizeof(struct external_pmksa_cache));
205585732ac8SCy Schubert 	if (!entry)
205685732ac8SCy Schubert 		return -1;
205785732ac8SCy Schubert 
205885732ac8SCy Schubert 	entry->pmksa_cache = pmksa_cache;
205985732ac8SCy Schubert 
206085732ac8SCy Schubert 	dl_list_add(&wpa_s->mesh_external_pmksa_cache, &entry->list);
206185732ac8SCy Schubert 
206285732ac8SCy Schubert 	return 0;
206385732ac8SCy Schubert }
206485732ac8SCy Schubert 
206585732ac8SCy Schubert #endif /* CONFIG_MESH */
206685732ac8SCy Schubert #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
206785732ac8SCy Schubert 
20684b72b91aSCy Schubert 
wpas_ap_update_beacon(struct wpa_supplicant * wpa_s)20694b72b91aSCy Schubert int wpas_ap_update_beacon(struct wpa_supplicant *wpa_s)
20704b72b91aSCy Schubert {
20714b72b91aSCy Schubert 	struct hostapd_data *hapd;
20724b72b91aSCy Schubert 
20734b72b91aSCy Schubert 	if (!wpa_s->ap_iface)
20744b72b91aSCy Schubert 		return -1;
20754b72b91aSCy Schubert 	hapd = wpa_s->ap_iface->bss[0];
20764b72b91aSCy Schubert 
20774b72b91aSCy Schubert 	wpabuf_free(hapd->conf->assocresp_elements);
20784b72b91aSCy Schubert 	hapd->conf->assocresp_elements = NULL;
20794b72b91aSCy Schubert 	if (wpa_s->conf->ap_assocresp_elements) {
20804b72b91aSCy Schubert 		hapd->conf->assocresp_elements =
20814b72b91aSCy Schubert 			wpabuf_dup(wpa_s->conf->ap_assocresp_elements);
20824b72b91aSCy Schubert 	}
20834b72b91aSCy Schubert 
20844b72b91aSCy Schubert 	wpabuf_free(hapd->conf->vendor_elements);
20854b72b91aSCy Schubert 	hapd->conf->vendor_elements = NULL;
20864b72b91aSCy Schubert 	if (wpa_s->conf->ap_vendor_elements) {
20874b72b91aSCy Schubert 		hapd->conf->vendor_elements =
20884b72b91aSCy Schubert 			wpabuf_dup(wpa_s->conf->ap_vendor_elements);
20894b72b91aSCy Schubert 	}
20904b72b91aSCy Schubert 
20914b72b91aSCy Schubert 	return ieee802_11_set_beacon(hapd);
20924b72b91aSCy Schubert }
20934b72b91aSCy Schubert 
2094325151a3SRui Paulo #endif /* CONFIG_CTRL_IFACE */
20955b9c547cSRui Paulo 
20965b9c547cSRui Paulo 
20975b9c547cSRui Paulo #ifdef NEED_AP_MLME
wpas_ap_event_dfs_radar_detected(struct wpa_supplicant * wpa_s,struct dfs_event * radar)209885732ac8SCy Schubert void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
20995b9c547cSRui Paulo 				      struct dfs_event *radar)
21005b9c547cSRui Paulo {
21014bc52338SCy Schubert 	struct hostapd_iface *iface = wpa_s->ap_iface;
21024bc52338SCy Schubert 
21034bc52338SCy Schubert 	if (!iface)
21044bc52338SCy Schubert 		iface = wpa_s->ifmsh;
21054bc52338SCy Schubert 	if (!iface || !iface->bss[0])
21065b9c547cSRui Paulo 		return;
21075b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
21084bc52338SCy Schubert 	hostapd_dfs_radar_detected(iface, radar->freq,
21095b9c547cSRui Paulo 				   radar->ht_enabled, radar->chan_offset,
21105b9c547cSRui Paulo 				   radar->chan_width,
21115b9c547cSRui Paulo 				   radar->cf1, radar->cf2);
21125b9c547cSRui Paulo }
21135b9c547cSRui Paulo 
21145b9c547cSRui Paulo 
wpas_ap_event_dfs_cac_started(struct wpa_supplicant * wpa_s,struct dfs_event * radar)211585732ac8SCy Schubert void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
21165b9c547cSRui Paulo 				   struct dfs_event *radar)
21175b9c547cSRui Paulo {
21184bc52338SCy Schubert 	struct hostapd_iface *iface = wpa_s->ap_iface;
21194bc52338SCy Schubert 
21204bc52338SCy Schubert 	if (!iface)
21214bc52338SCy Schubert 		iface = wpa_s->ifmsh;
21224bc52338SCy Schubert 	if (!iface || !iface->bss[0])
21235b9c547cSRui Paulo 		return;
21245b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
21254bc52338SCy Schubert 	hostapd_dfs_start_cac(iface, radar->freq,
21265b9c547cSRui Paulo 			      radar->ht_enabled, radar->chan_offset,
21275b9c547cSRui Paulo 			      radar->chan_width, radar->cf1, radar->cf2);
21285b9c547cSRui Paulo }
21295b9c547cSRui Paulo 
21305b9c547cSRui Paulo 
wpas_ap_event_dfs_cac_finished(struct wpa_supplicant * wpa_s,struct dfs_event * radar)213185732ac8SCy Schubert void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
21325b9c547cSRui Paulo 				    struct dfs_event *radar)
21335b9c547cSRui Paulo {
21344bc52338SCy Schubert 	struct hostapd_iface *iface = wpa_s->ap_iface;
21354bc52338SCy Schubert 
21364bc52338SCy Schubert 	if (!iface)
21374bc52338SCy Schubert 		iface = wpa_s->ifmsh;
21384bc52338SCy Schubert 	if (!iface || !iface->bss[0])
21395b9c547cSRui Paulo 		return;
21405b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
21414bc52338SCy Schubert 	hostapd_dfs_complete_cac(iface, 1, radar->freq,
21425b9c547cSRui Paulo 				 radar->ht_enabled, radar->chan_offset,
21435b9c547cSRui Paulo 				 radar->chan_width, radar->cf1, radar->cf2);
21445b9c547cSRui Paulo }
21455b9c547cSRui Paulo 
21465b9c547cSRui Paulo 
wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant * wpa_s,struct dfs_event * radar)214785732ac8SCy Schubert void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
21485b9c547cSRui Paulo 				   struct dfs_event *radar)
21495b9c547cSRui Paulo {
21504bc52338SCy Schubert 	struct hostapd_iface *iface = wpa_s->ap_iface;
21514bc52338SCy Schubert 
21524bc52338SCy Schubert 	if (!iface)
21534bc52338SCy Schubert 		iface = wpa_s->ifmsh;
21544bc52338SCy Schubert 	if (!iface || !iface->bss[0])
21555b9c547cSRui Paulo 		return;
21565b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
21574bc52338SCy Schubert 	hostapd_dfs_complete_cac(iface, 0, radar->freq,
21585b9c547cSRui Paulo 				 radar->ht_enabled, radar->chan_offset,
21595b9c547cSRui Paulo 				 radar->chan_width, radar->cf1, radar->cf2);
21605b9c547cSRui Paulo }
21615b9c547cSRui Paulo 
21625b9c547cSRui Paulo 
wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant * wpa_s,struct dfs_event * radar)216385732ac8SCy Schubert void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
21645b9c547cSRui Paulo 					struct dfs_event *radar)
21655b9c547cSRui Paulo {
21664bc52338SCy Schubert 	struct hostapd_iface *iface = wpa_s->ap_iface;
21674bc52338SCy Schubert 
21684bc52338SCy Schubert 	if (!iface)
21694bc52338SCy Schubert 		iface = wpa_s->ifmsh;
21704bc52338SCy Schubert 	if (!iface || !iface->bss[0])
21715b9c547cSRui Paulo 		return;
21725b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
21734bc52338SCy Schubert 	hostapd_dfs_nop_finished(iface, radar->freq,
21745b9c547cSRui Paulo 				 radar->ht_enabled, radar->chan_offset,
21755b9c547cSRui Paulo 				 radar->chan_width, radar->cf1, radar->cf2);
21765b9c547cSRui Paulo }
21775b9c547cSRui Paulo #endif /* NEED_AP_MLME */
2178325151a3SRui Paulo 
2179325151a3SRui Paulo 
ap_periodic(struct wpa_supplicant * wpa_s)2180325151a3SRui Paulo void ap_periodic(struct wpa_supplicant *wpa_s)
2181325151a3SRui Paulo {
2182325151a3SRui Paulo 	if (wpa_s->ap_iface)
2183325151a3SRui Paulo 		hostapd_periodic_iface(wpa_s->ap_iface);
2184325151a3SRui Paulo }
2185