ap.c revision 337817
1214501Srpaulo/*
2214501Srpaulo * WPA Supplicant - Basic AP mode support routines
3214501Srpaulo * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
4214501Srpaulo * Copyright (c) 2009, Atheros Communications
5214501Srpaulo *
6252726Srpaulo * This software may be distributed under the terms of the BSD license.
7252726Srpaulo * See README for more details.
8214501Srpaulo */
9214501Srpaulo
10214501Srpaulo#include "utils/includes.h"
11214501Srpaulo
12214501Srpaulo#include "utils/common.h"
13252726Srpaulo#include "utils/eloop.h"
14252726Srpaulo#include "utils/uuid.h"
15214501Srpaulo#include "common/ieee802_11_defs.h"
16252726Srpaulo#include "common/wpa_ctrl.h"
17281806Srpaulo#include "eapol_supp/eapol_supp_sm.h"
18281806Srpaulo#include "crypto/dh_group5.h"
19214501Srpaulo#include "ap/hostapd.h"
20214501Srpaulo#include "ap/ap_config.h"
21252726Srpaulo#include "ap/ap_drv_ops.h"
22214501Srpaulo#ifdef NEED_AP_MLME
23214501Srpaulo#include "ap/ieee802_11.h"
24214501Srpaulo#endif /* NEED_AP_MLME */
25252726Srpaulo#include "ap/beacon.h"
26214501Srpaulo#include "ap/ieee802_1x.h"
27214501Srpaulo#include "ap/wps_hostapd.h"
28214501Srpaulo#include "ap/ctrl_iface_ap.h"
29281806Srpaulo#include "ap/dfs.h"
30214501Srpaulo#include "wps/wps.h"
31252726Srpaulo#include "common/ieee802_11_defs.h"
32214501Srpaulo#include "config_ssid.h"
33214501Srpaulo#include "config.h"
34214501Srpaulo#include "wpa_supplicant_i.h"
35214501Srpaulo#include "driver_i.h"
36252726Srpaulo#include "p2p_supplicant.h"
37214501Srpaulo#include "ap.h"
38252726Srpaulo#include "ap/sta_info.h"
39252726Srpaulo#include "notify.h"
40214501Srpaulo
41214501Srpaulo
42252726Srpaulo#ifdef CONFIG_WPS
43252726Srpaulostatic void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
44252726Srpaulo#endif /* CONFIG_WPS */
45252726Srpaulo
46252726Srpaulo
47281806Srpaulo#ifdef CONFIG_IEEE80211N
48281806Srpaulostatic void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
49281806Srpaulo			     struct hostapd_config *conf,
50281806Srpaulo			     struct hostapd_hw_modes *mode)
51214501Srpaulo{
52281806Srpaulo#ifdef CONFIG_P2P
53281806Srpaulo	u8 center_chan = 0;
54281806Srpaulo	u8 channel = conf->channel;
55214501Srpaulo
56281806Srpaulo	if (!conf->secondary_channel)
57281806Srpaulo		goto no_vht;
58214501Srpaulo
59337817Scy	switch (conf->vht_oper_chwidth) {
60337817Scy	case VHT_CHANWIDTH_80MHZ:
61337817Scy	case VHT_CHANWIDTH_80P80MHZ:
62337817Scy		center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
63337817Scy		break;
64337817Scy	case VHT_CHANWIDTH_160MHZ:
65337817Scy		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
66337817Scy		break;
67337817Scy	default:
68337817Scy		/*
69337817Scy		 * conf->vht_oper_chwidth might not be set for non-P2P GO cases,
70337817Scy		 * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is
71337817Scy		 * not supported.
72337817Scy		 */
73337817Scy		conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ;
74337817Scy		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
75337817Scy		if (!center_chan) {
76337817Scy			conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
77337817Scy			center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
78337817Scy								channel);
79337817Scy		}
80337817Scy		break;
81337817Scy	}
82281806Srpaulo	if (!center_chan)
83281806Srpaulo		goto no_vht;
84214501Srpaulo
85281806Srpaulo	conf->vht_oper_centr_freq_seg0_idx = center_chan;
86281806Srpaulo	return;
87214501Srpaulo
88281806Srpaulono_vht:
89281806Srpaulo	conf->vht_oper_centr_freq_seg0_idx =
90281806Srpaulo		channel + conf->secondary_channel * 2;
91281806Srpaulo#else /* CONFIG_P2P */
92281806Srpaulo	conf->vht_oper_centr_freq_seg0_idx =
93281806Srpaulo		conf->channel + conf->secondary_channel * 2;
94281806Srpaulo#endif /* CONFIG_P2P */
95337817Scy	conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
96281806Srpaulo}
97281806Srpaulo#endif /* CONFIG_IEEE80211N */
98281806Srpaulo
99281806Srpaulo
100337817Scyint wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
101337817Scy			      struct wpa_ssid *ssid,
102337817Scy			      struct hostapd_config *conf)
103281806Srpaulo{
104337817Scy	conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
105337817Scy					       &conf->channel);
106337817Scy
107337817Scy	if (conf->hw_mode == NUM_HOSTAPD_MODES) {
108337817Scy		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
109337817Scy			   ssid->frequency);
110337817Scy		return -1;
111337817Scy	}
112337817Scy
113252726Srpaulo	/* TODO: enable HT40 if driver supports it;
114214501Srpaulo	 * drop to 11b if driver does not support 11g */
115214501Srpaulo
116252726Srpaulo#ifdef CONFIG_IEEE80211N
117252726Srpaulo	/*
118252726Srpaulo	 * Enable HT20 if the driver supports it, by setting conf->ieee80211n
119252726Srpaulo	 * and a mask of allowed capabilities within conf->ht_capab.
120252726Srpaulo	 * Using default config settings for: conf->ht_op_mode_fixed,
121252726Srpaulo	 * conf->secondary_channel, conf->require_ht
122252726Srpaulo	 */
123252726Srpaulo	if (wpa_s->hw.modes) {
124252726Srpaulo		struct hostapd_hw_modes *mode = NULL;
125252726Srpaulo		int i, no_ht = 0;
126252726Srpaulo		for (i = 0; i < wpa_s->hw.num_modes; i++) {
127252726Srpaulo			if (wpa_s->hw.modes[i].mode == conf->hw_mode) {
128252726Srpaulo				mode = &wpa_s->hw.modes[i];
129252726Srpaulo				break;
130252726Srpaulo			}
131252726Srpaulo		}
132252726Srpaulo
133252726Srpaulo#ifdef CONFIG_HT_OVERRIDES
134252726Srpaulo		if (ssid->disable_ht) {
135252726Srpaulo			conf->ieee80211n = 0;
136252726Srpaulo			conf->ht_capab = 0;
137252726Srpaulo			no_ht = 1;
138252726Srpaulo		}
139252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */
140252726Srpaulo
141252726Srpaulo		if (!no_ht && mode && mode->ht_capab) {
142252726Srpaulo			conf->ieee80211n = 1;
143252726Srpaulo#ifdef CONFIG_P2P
144252726Srpaulo			if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&
145252726Srpaulo			    (mode->ht_capab &
146252726Srpaulo			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
147252726Srpaulo			    ssid->ht40)
148252726Srpaulo				conf->secondary_channel =
149252726Srpaulo					wpas_p2p_get_ht40_mode(wpa_s, mode,
150252726Srpaulo							       conf->channel);
151252726Srpaulo			if (conf->secondary_channel)
152252726Srpaulo				conf->ht_capab |=
153252726Srpaulo					HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
154252726Srpaulo#endif /* CONFIG_P2P */
155252726Srpaulo
156252726Srpaulo			/*
157252726Srpaulo			 * white-list capabilities that won't cause issues
158252726Srpaulo			 * to connecting stations, while leaving the current
159252726Srpaulo			 * capabilities intact (currently disabled SMPS).
160252726Srpaulo			 */
161252726Srpaulo			conf->ht_capab |= mode->ht_capab &
162252726Srpaulo				(HT_CAP_INFO_GREEN_FIELD |
163252726Srpaulo				 HT_CAP_INFO_SHORT_GI20MHZ |
164252726Srpaulo				 HT_CAP_INFO_SHORT_GI40MHZ |
165252726Srpaulo				 HT_CAP_INFO_RX_STBC_MASK |
166281806Srpaulo				 HT_CAP_INFO_TX_STBC |
167252726Srpaulo				 HT_CAP_INFO_MAX_AMSDU_SIZE);
168281806Srpaulo
169281806Srpaulo			if (mode->vht_capab && ssid->vht) {
170281806Srpaulo				conf->ieee80211ac = 1;
171281806Srpaulo				wpas_conf_ap_vht(wpa_s, conf, mode);
172281806Srpaulo			}
173252726Srpaulo		}
174252726Srpaulo	}
175289549Srpaulo
176289549Srpaulo	if (conf->secondary_channel) {
177289549Srpaulo		struct wpa_supplicant *iface;
178289549Srpaulo
179289549Srpaulo		for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
180289549Srpaulo		{
181289549Srpaulo			if (iface == wpa_s ||
182289549Srpaulo			    iface->wpa_state < WPA_AUTHENTICATING ||
183289549Srpaulo			    (int) iface->assoc_freq != ssid->frequency)
184289549Srpaulo				continue;
185289549Srpaulo
186289549Srpaulo			/*
187289549Srpaulo			 * Do not allow 40 MHz co-ex PRI/SEC switch to force us
188289549Srpaulo			 * to change our PRI channel since we have an existing,
189289549Srpaulo			 * concurrent connection on that channel and doing
190289549Srpaulo			 * multi-channel concurrency is likely to cause more
191289549Srpaulo			 * harm than using different PRI/SEC selection in
192289549Srpaulo			 * environment with multiple BSSes on these two channels
193289549Srpaulo			 * with mixed 20 MHz or PRI channel selection.
194289549Srpaulo			 */
195289549Srpaulo			conf->no_pri_sec_switch = 1;
196289549Srpaulo		}
197289549Srpaulo	}
198252726Srpaulo#endif /* CONFIG_IEEE80211N */
199337817Scy
200337817Scy	return 0;
201281806Srpaulo}
202252726Srpaulo
203281806Srpaulo
204281806Srpaulostatic int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
205281806Srpaulo				  struct wpa_ssid *ssid,
206281806Srpaulo				  struct hostapd_config *conf)
207281806Srpaulo{
208281806Srpaulo	struct hostapd_bss_config *bss = conf->bss[0];
209281806Srpaulo
210281806Srpaulo	conf->driver = wpa_s->driver;
211281806Srpaulo
212281806Srpaulo	os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
213281806Srpaulo
214337817Scy	if (wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf))
215281806Srpaulo		return -1;
216337817Scy
217337817Scy	if (ssid->pbss > 1) {
218337817Scy		wpa_printf(MSG_ERROR, "Invalid pbss value(%d) for AP mode",
219337817Scy			   ssid->pbss);
220337817Scy		return -1;
221281806Srpaulo	}
222337817Scy	bss->pbss = ssid->pbss;
223281806Srpaulo
224337817Scy#ifdef CONFIG_ACS
225337817Scy	if (ssid->acs) {
226337817Scy		/* Setting channel to 0 in order to enable ACS */
227337817Scy		conf->channel = 0;
228337817Scy		wpa_printf(MSG_DEBUG, "Use automatic channel selection");
229337817Scy	}
230337817Scy#endif /* CONFIG_ACS */
231281806Srpaulo
232281806Srpaulo	if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) {
233281806Srpaulo		conf->ieee80211h = 1;
234281806Srpaulo		conf->ieee80211d = 1;
235281806Srpaulo		conf->country[0] = wpa_s->conf->country[0];
236281806Srpaulo		conf->country[1] = wpa_s->conf->country[1];
237281806Srpaulo	}
238281806Srpaulo
239252726Srpaulo#ifdef CONFIG_P2P
240281806Srpaulo	if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
241281806Srpaulo	    (ssid->mode == WPAS_MODE_P2P_GO ||
242281806Srpaulo	     ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) {
243252726Srpaulo		/* Remove 802.11b rates from supported and basic rate sets */
244252726Srpaulo		int *list = os_malloc(4 * sizeof(int));
245252726Srpaulo		if (list) {
246252726Srpaulo			list[0] = 60;
247252726Srpaulo			list[1] = 120;
248252726Srpaulo			list[2] = 240;
249252726Srpaulo			list[3] = -1;
250252726Srpaulo		}
251252726Srpaulo		conf->basic_rates = list;
252252726Srpaulo
253252726Srpaulo		list = os_malloc(9 * sizeof(int));
254252726Srpaulo		if (list) {
255252726Srpaulo			list[0] = 60;
256252726Srpaulo			list[1] = 90;
257252726Srpaulo			list[2] = 120;
258252726Srpaulo			list[3] = 180;
259252726Srpaulo			list[4] = 240;
260252726Srpaulo			list[5] = 360;
261252726Srpaulo			list[6] = 480;
262252726Srpaulo			list[7] = 540;
263252726Srpaulo			list[8] = -1;
264252726Srpaulo		}
265252726Srpaulo		conf->supported_rates = list;
266252726Srpaulo	}
267252726Srpaulo
268252726Srpaulo	bss->isolate = !wpa_s->conf->p2p_intra_bss;
269281806Srpaulo	bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
270281806Srpaulo
271281806Srpaulo	if (ssid->p2p_group) {
272337817Scy		os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
273337817Scy		os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask,
274281806Srpaulo			  4);
275281806Srpaulo		os_memcpy(bss->ip_addr_start,
276337817Scy			  wpa_s->p2pdev->conf->ip_addr_start, 4);
277337817Scy		os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end,
278281806Srpaulo			  4);
279281806Srpaulo	}
280252726Srpaulo#endif /* CONFIG_P2P */
281252726Srpaulo
282214501Srpaulo	if (ssid->ssid_len == 0) {
283214501Srpaulo		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
284214501Srpaulo		return -1;
285214501Srpaulo	}
286214501Srpaulo	os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len);
287214501Srpaulo	bss->ssid.ssid_len = ssid->ssid_len;
288214501Srpaulo	bss->ssid.ssid_set = 1;
289214501Srpaulo
290252726Srpaulo	bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid;
291252726Srpaulo
292252726Srpaulo	if (ssid->auth_alg)
293252726Srpaulo		bss->auth_algs = ssid->auth_alg;
294252726Srpaulo
295214501Srpaulo	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt))
296214501Srpaulo		bss->wpa = ssid->proto;
297337817Scy	if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
298337817Scy		bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
299337817Scy	else
300337817Scy		bss->wpa_key_mgmt = ssid->key_mgmt;
301214501Srpaulo	bss->wpa_pairwise = ssid->pairwise_cipher;
302252726Srpaulo	if (ssid->psk_set) {
303281806Srpaulo		bin_clear_free(bss->ssid.wpa_psk, sizeof(*bss->ssid.wpa_psk));
304214501Srpaulo		bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
305214501Srpaulo		if (bss->ssid.wpa_psk == NULL)
306214501Srpaulo			return -1;
307214501Srpaulo		os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN);
308214501Srpaulo		bss->ssid.wpa_psk->group = 1;
309337817Scy		bss->ssid.wpa_psk_set = 1;
310252726Srpaulo	} else if (ssid->passphrase) {
311252726Srpaulo		bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
312252726Srpaulo	} else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] ||
313252726Srpaulo		   ssid->wep_key_len[2] || ssid->wep_key_len[3]) {
314252726Srpaulo		struct hostapd_wep_keys *wep = &bss->ssid.wep;
315252726Srpaulo		int i;
316252726Srpaulo		for (i = 0; i < NUM_WEP_KEYS; i++) {
317252726Srpaulo			if (ssid->wep_key_len[i] == 0)
318252726Srpaulo				continue;
319252726Srpaulo			wep->key[i] = os_malloc(ssid->wep_key_len[i]);
320252726Srpaulo			if (wep->key[i] == NULL)
321252726Srpaulo				return -1;
322252726Srpaulo			os_memcpy(wep->key[i], ssid->wep_key[i],
323252726Srpaulo				  ssid->wep_key_len[i]);
324252726Srpaulo			wep->len[i] = ssid->wep_key_len[i];
325252726Srpaulo		}
326252726Srpaulo		wep->idx = ssid->wep_tx_keyidx;
327252726Srpaulo		wep->keys_set = 1;
328214501Srpaulo	}
329214501Srpaulo
330252726Srpaulo	if (ssid->ap_max_inactivity)
331252726Srpaulo		bss->ap_max_inactivity = ssid->ap_max_inactivity;
332252726Srpaulo
333252726Srpaulo	if (ssid->dtim_period)
334252726Srpaulo		bss->dtim_period = ssid->dtim_period;
335281806Srpaulo	else if (wpa_s->conf->dtim_period)
336281806Srpaulo		bss->dtim_period = wpa_s->conf->dtim_period;
337252726Srpaulo
338281806Srpaulo	if (ssid->beacon_int)
339281806Srpaulo		conf->beacon_int = ssid->beacon_int;
340281806Srpaulo	else if (wpa_s->conf->beacon_int)
341281806Srpaulo		conf->beacon_int = wpa_s->conf->beacon_int;
342281806Srpaulo
343281806Srpaulo#ifdef CONFIG_P2P
344337817Scy	if (ssid->mode == WPAS_MODE_P2P_GO ||
345337817Scy	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
346337817Scy		if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) {
347337817Scy			wpa_printf(MSG_INFO,
348337817Scy				   "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it",
349337817Scy				   wpa_s->conf->p2p_go_ctwindow,
350337817Scy				   conf->beacon_int);
351337817Scy			conf->p2p_go_ctwindow = 0;
352337817Scy		} else {
353337817Scy			conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow;
354337817Scy		}
355214501Srpaulo	}
356281806Srpaulo#endif /* CONFIG_P2P */
357214501Srpaulo
358281806Srpaulo	if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
359281806Srpaulo		bss->rsn_pairwise = bss->wpa_pairwise;
360281806Srpaulo	bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise,
361281806Srpaulo						    bss->rsn_pairwise);
362281806Srpaulo
363214501Srpaulo	if (bss->wpa && bss->ieee802_1x)
364214501Srpaulo		bss->ssid.security_policy = SECURITY_WPA;
365214501Srpaulo	else if (bss->wpa)
366214501Srpaulo		bss->ssid.security_policy = SECURITY_WPA_PSK;
367214501Srpaulo	else if (bss->ieee802_1x) {
368252726Srpaulo		int cipher = WPA_CIPHER_NONE;
369214501Srpaulo		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
370214501Srpaulo		bss->ssid.wep.default_len = bss->default_wep_key_len;
371252726Srpaulo		if (bss->default_wep_key_len)
372252726Srpaulo			cipher = bss->default_wep_key_len >= 13 ?
373252726Srpaulo				WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
374252726Srpaulo		bss->wpa_group = cipher;
375252726Srpaulo		bss->wpa_pairwise = cipher;
376252726Srpaulo		bss->rsn_pairwise = cipher;
377252726Srpaulo	} else if (bss->ssid.wep.keys_set) {
378252726Srpaulo		int cipher = WPA_CIPHER_WEP40;
379252726Srpaulo		if (bss->ssid.wep.len[0] >= 13)
380252726Srpaulo			cipher = WPA_CIPHER_WEP104;
381214501Srpaulo		bss->ssid.security_policy = SECURITY_STATIC_WEP;
382252726Srpaulo		bss->wpa_group = cipher;
383252726Srpaulo		bss->wpa_pairwise = cipher;
384252726Srpaulo		bss->rsn_pairwise = cipher;
385252726Srpaulo	} else {
386214501Srpaulo		bss->ssid.security_policy = SECURITY_PLAINTEXT;
387252726Srpaulo		bss->wpa_group = WPA_CIPHER_NONE;
388252726Srpaulo		bss->wpa_pairwise = WPA_CIPHER_NONE;
389252726Srpaulo		bss->rsn_pairwise = WPA_CIPHER_NONE;
390252726Srpaulo	}
391214501Srpaulo
392281806Srpaulo	if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) &&
393281806Srpaulo	    (bss->wpa_group == WPA_CIPHER_CCMP ||
394281806Srpaulo	     bss->wpa_group == WPA_CIPHER_GCMP ||
395281806Srpaulo	     bss->wpa_group == WPA_CIPHER_CCMP_256 ||
396281806Srpaulo	     bss->wpa_group == WPA_CIPHER_GCMP_256)) {
397281806Srpaulo		/*
398281806Srpaulo		 * Strong ciphers do not need frequent rekeying, so increase
399281806Srpaulo		 * the default GTK rekeying period to 24 hours.
400281806Srpaulo		 */
401281806Srpaulo		bss->wpa_group_rekey = 86400;
402281806Srpaulo	}
403281806Srpaulo
404281806Srpaulo#ifdef CONFIG_IEEE80211W
405281806Srpaulo	if (ssid->ieee80211w != MGMT_FRAME_PROTECTION_DEFAULT)
406281806Srpaulo		bss->ieee80211w = ssid->ieee80211w;
407281806Srpaulo#endif /* CONFIG_IEEE80211W */
408281806Srpaulo
409214501Srpaulo#ifdef CONFIG_WPS
410214501Srpaulo	/*
411252726Srpaulo	 * Enable WPS by default for open and WPA/WPA2-Personal network, but
412252726Srpaulo	 * require user interaction to actually use it. Only the internal
413252726Srpaulo	 * Registrar is supported.
414214501Srpaulo	 */
415252726Srpaulo	if (bss->ssid.security_policy != SECURITY_WPA_PSK &&
416252726Srpaulo	    bss->ssid.security_policy != SECURITY_PLAINTEXT)
417252726Srpaulo		goto no_wps;
418252726Srpaulo	if (bss->ssid.security_policy == SECURITY_WPA_PSK &&
419281806Srpaulo	    (!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) ||
420281806Srpaulo	     !(bss->wpa & 2)))
421252726Srpaulo		goto no_wps; /* WPS2 does not allow WPA/TKIP-only
422252726Srpaulo			      * configuration */
423337817Scy	if (ssid->wps_disabled)
424337817Scy		goto no_wps;
425214501Srpaulo	bss->eap_server = 1;
426252726Srpaulo
427252726Srpaulo	if (!ssid->ignore_broadcast_ssid)
428252726Srpaulo		bss->wps_state = 2;
429252726Srpaulo
430252726Srpaulo	bss->ap_setup_locked = 2;
431214501Srpaulo	if (wpa_s->conf->config_methods)
432214501Srpaulo		bss->config_methods = os_strdup(wpa_s->conf->config_methods);
433252726Srpaulo	os_memcpy(bss->device_type, wpa_s->conf->device_type,
434252726Srpaulo		  WPS_DEV_TYPE_LEN);
435252726Srpaulo	if (wpa_s->conf->device_name) {
436252726Srpaulo		bss->device_name = os_strdup(wpa_s->conf->device_name);
437252726Srpaulo		bss->friendly_name = os_strdup(wpa_s->conf->device_name);
438252726Srpaulo	}
439252726Srpaulo	if (wpa_s->conf->manufacturer)
440252726Srpaulo		bss->manufacturer = os_strdup(wpa_s->conf->manufacturer);
441252726Srpaulo	if (wpa_s->conf->model_name)
442252726Srpaulo		bss->model_name = os_strdup(wpa_s->conf->model_name);
443252726Srpaulo	if (wpa_s->conf->model_number)
444252726Srpaulo		bss->model_number = os_strdup(wpa_s->conf->model_number);
445252726Srpaulo	if (wpa_s->conf->serial_number)
446252726Srpaulo		bss->serial_number = os_strdup(wpa_s->conf->serial_number);
447252726Srpaulo	if (is_nil_uuid(wpa_s->conf->uuid))
448252726Srpaulo		os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN);
449252726Srpaulo	else
450252726Srpaulo		os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
451252726Srpaulo	os_memcpy(bss->os_version, wpa_s->conf->os_version, 4);
452252726Srpaulo	bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1;
453337817Scy	if (ssid->eap.fragment_size != DEFAULT_FRAGMENT_SIZE)
454337817Scy		bss->fragment_size = ssid->eap.fragment_size;
455252726Srpaulono_wps:
456214501Srpaulo#endif /* CONFIG_WPS */
457214501Srpaulo
458252726Srpaulo	if (wpa_s->max_stations &&
459252726Srpaulo	    wpa_s->max_stations < wpa_s->conf->max_num_sta)
460252726Srpaulo		bss->max_num_sta = wpa_s->max_stations;
461252726Srpaulo	else
462252726Srpaulo		bss->max_num_sta = wpa_s->conf->max_num_sta;
463252726Srpaulo
464252726Srpaulo	bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack;
465252726Srpaulo
466281806Srpaulo	if (wpa_s->conf->ap_vendor_elements) {
467281806Srpaulo		bss->vendor_elements =
468281806Srpaulo			wpabuf_dup(wpa_s->conf->ap_vendor_elements);
469281806Srpaulo	}
470281806Srpaulo
471337817Scy	bss->ftm_responder = wpa_s->conf->ftm_responder;
472337817Scy	bss->ftm_initiator = wpa_s->conf->ftm_initiator;
473337817Scy
474214501Srpaulo	return 0;
475214501Srpaulo}
476214501Srpaulo
477214501Srpaulo
478214501Srpaulostatic void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
479214501Srpaulo{
480252726Srpaulo#ifdef CONFIG_P2P
481252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
482252726Srpaulo	const struct ieee80211_mgmt *mgmt;
483252726Srpaulo
484252726Srpaulo	mgmt = (const struct ieee80211_mgmt *) buf;
485281806Srpaulo	if (len < IEEE80211_HDRLEN + 1)
486252726Srpaulo		return;
487281806Srpaulo	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
488281806Srpaulo		return;
489252726Srpaulo	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
490252726Srpaulo			   mgmt->u.action.category,
491281806Srpaulo			   buf + IEEE80211_HDRLEN + 1,
492281806Srpaulo			   len - IEEE80211_HDRLEN - 1, freq);
493252726Srpaulo#endif /* CONFIG_P2P */
494214501Srpaulo}
495214501Srpaulo
496214501Srpaulo
497252726Srpaulostatic void ap_wps_event_cb(void *ctx, enum wps_event event,
498252726Srpaulo			    union wps_event_data *data)
499214501Srpaulo{
500252726Srpaulo#ifdef CONFIG_P2P
501252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
502252726Srpaulo
503252726Srpaulo	if (event == WPS_EV_FAIL) {
504252726Srpaulo		struct wps_event_fail *fail = &data->fail;
505252726Srpaulo
506337817Scy		if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s &&
507252726Srpaulo		    wpa_s == wpa_s->global->p2p_group_formation) {
508252726Srpaulo			/*
509252726Srpaulo			 * src/ap/wps_hostapd.c has already sent this on the
510252726Srpaulo			 * main interface, so only send on the parent interface
511252726Srpaulo			 * here if needed.
512252726Srpaulo			 */
513337817Scy			wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
514252726Srpaulo				"msg=%d config_error=%d",
515252726Srpaulo				fail->msg, fail->config_error);
516252726Srpaulo		}
517252726Srpaulo		wpas_p2p_wps_failed(wpa_s, fail);
518252726Srpaulo	}
519252726Srpaulo#endif /* CONFIG_P2P */
520252726Srpaulo}
521252726Srpaulo
522252726Srpaulo
523252726Srpaulostatic void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
524252726Srpaulo				 int authorized, const u8 *p2p_dev_addr)
525252726Srpaulo{
526252726Srpaulo	wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr);
527252726Srpaulo}
528252726Srpaulo
529252726Srpaulo
530281806Srpaulo#ifdef CONFIG_P2P
531281806Srpaulostatic void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
532281806Srpaulo			  const u8 *psk, size_t psk_len)
533281806Srpaulo{
534281806Srpaulo
535281806Srpaulo	struct wpa_supplicant *wpa_s = ctx;
536281806Srpaulo	if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL)
537281806Srpaulo		return;
538281806Srpaulo	wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len);
539281806Srpaulo}
540281806Srpaulo#endif /* CONFIG_P2P */
541281806Srpaulo
542281806Srpaulo
543252726Srpaulostatic int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
544252726Srpaulo{
545252726Srpaulo#ifdef CONFIG_P2P
546252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
547252726Srpaulo	const struct ieee80211_mgmt *mgmt;
548252726Srpaulo
549252726Srpaulo	mgmt = (const struct ieee80211_mgmt *) buf;
550281806Srpaulo	if (len < IEEE80211_HDRLEN + 1)
551252726Srpaulo		return -1;
552252726Srpaulo	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
553252726Srpaulo			   mgmt->u.action.category,
554281806Srpaulo			   buf + IEEE80211_HDRLEN + 1,
555281806Srpaulo			   len - IEEE80211_HDRLEN - 1, freq);
556252726Srpaulo#endif /* CONFIG_P2P */
557214501Srpaulo	return 0;
558214501Srpaulo}
559214501Srpaulo
560214501Srpaulo
561252726Srpaulostatic int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da,
562252726Srpaulo			   const u8 *bssid, const u8 *ie, size_t ie_len,
563252726Srpaulo			   int ssi_signal)
564252726Srpaulo{
565252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
566289549Srpaulo	unsigned int freq = 0;
567289549Srpaulo
568289549Srpaulo	if (wpa_s->ap_iface)
569289549Srpaulo		freq = wpa_s->ap_iface->freq;
570289549Srpaulo
571252726Srpaulo	return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len,
572289549Srpaulo				     freq, ssi_signal);
573252726Srpaulo}
574252726Srpaulo
575252726Srpaulo
576214501Srpaulostatic void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
577214501Srpaulo				  const u8 *uuid_e)
578214501Srpaulo{
579252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
580252726Srpaulo	wpas_p2p_wps_success(wpa_s, mac_addr, 1);
581214501Srpaulo}
582214501Srpaulo
583214501Srpaulo
584252726Srpaulostatic void wpas_ap_configured_cb(void *ctx)
585252726Srpaulo{
586252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
587252726Srpaulo
588337817Scy#ifdef CONFIG_ACS
589337817Scy	if (wpa_s->current_ssid && wpa_s->current_ssid->acs)
590337817Scy		wpa_s->assoc_freq = wpa_s->ap_iface->freq;
591337817Scy#endif /* CONFIG_ACS */
592337817Scy
593252726Srpaulo	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
594252726Srpaulo
595252726Srpaulo	if (wpa_s->ap_configured_cb)
596252726Srpaulo		wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
597252726Srpaulo					wpa_s->ap_configured_cb_data);
598252726Srpaulo}
599252726Srpaulo
600252726Srpaulo
601214501Srpauloint wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
602214501Srpaulo			     struct wpa_ssid *ssid)
603214501Srpaulo{
604214501Srpaulo	struct wpa_driver_associate_params params;
605214501Srpaulo	struct hostapd_iface *hapd_iface;
606214501Srpaulo	struct hostapd_config *conf;
607214501Srpaulo	size_t i;
608214501Srpaulo
609214501Srpaulo	if (ssid->ssid == NULL || ssid->ssid_len == 0) {
610214501Srpaulo		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
611214501Srpaulo		return -1;
612214501Srpaulo	}
613214501Srpaulo
614214501Srpaulo	wpa_supplicant_ap_deinit(wpa_s);
615214501Srpaulo
616214501Srpaulo	wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')",
617214501Srpaulo		   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
618214501Srpaulo
619214501Srpaulo	os_memset(&params, 0, sizeof(params));
620214501Srpaulo	params.ssid = ssid->ssid;
621214501Srpaulo	params.ssid_len = ssid->ssid_len;
622214501Srpaulo	switch (ssid->mode) {
623214501Srpaulo	case WPAS_MODE_AP:
624252726Srpaulo	case WPAS_MODE_P2P_GO:
625252726Srpaulo	case WPAS_MODE_P2P_GROUP_FORMATION:
626214501Srpaulo		params.mode = IEEE80211_MODE_AP;
627214501Srpaulo		break;
628281806Srpaulo	default:
629281806Srpaulo		return -1;
630214501Srpaulo	}
631281806Srpaulo	if (ssid->frequency == 0)
632281806Srpaulo		ssid->frequency = 2462; /* default channel 11 */
633281806Srpaulo	params.freq.freq = ssid->frequency;
634214501Srpaulo
635252726Srpaulo	params.wpa_proto = ssid->proto;
636214501Srpaulo	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
637214501Srpaulo		wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
638214501Srpaulo	else
639214501Srpaulo		wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
640281806Srpaulo	params.key_mgmt_suite = wpa_s->key_mgmt;
641214501Srpaulo
642281806Srpaulo	wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher,
643281806Srpaulo							  1);
644281806Srpaulo	if (wpa_s->pairwise_cipher < 0) {
645214501Srpaulo		wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise "
646214501Srpaulo			   "cipher.");
647214501Srpaulo		return -1;
648214501Srpaulo	}
649281806Srpaulo	params.pairwise_suite = wpa_s->pairwise_cipher;
650214501Srpaulo	params.group_suite = params.pairwise_suite;
651214501Srpaulo
652252726Srpaulo#ifdef CONFIG_P2P
653252726Srpaulo	if (ssid->mode == WPAS_MODE_P2P_GO ||
654252726Srpaulo	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
655252726Srpaulo		params.p2p = 1;
656252726Srpaulo#endif /* CONFIG_P2P */
657252726Srpaulo
658337817Scy	if (wpa_s->p2pdev->set_ap_uapsd)
659337817Scy		params.uapsd = wpa_s->p2pdev->ap_uapsd;
660281806Srpaulo	else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
661281806Srpaulo		params.uapsd = 1; /* mandatory for P2P GO */
662252726Srpaulo	else
663252726Srpaulo		params.uapsd = -1;
664252726Srpaulo
665281806Srpaulo	if (ieee80211_is_dfs(params.freq.freq))
666281806Srpaulo		params.freq.freq = 0; /* set channel after CAC */
667281806Srpaulo
668337817Scy	if (params.p2p)
669337817Scy		wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_GO);
670337817Scy	else
671337817Scy		wpa_drv_get_ext_capa(wpa_s, WPA_IF_AP_BSS);
672337817Scy
673214501Srpaulo	if (wpa_drv_associate(wpa_s, &params) < 0) {
674214501Srpaulo		wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
675214501Srpaulo		return -1;
676214501Srpaulo	}
677214501Srpaulo
678337817Scy	wpa_s->ap_iface = hapd_iface = hostapd_alloc_iface();
679214501Srpaulo	if (hapd_iface == NULL)
680214501Srpaulo		return -1;
681214501Srpaulo	hapd_iface->owner = wpa_s;
682252726Srpaulo	hapd_iface->drv_flags = wpa_s->drv_flags;
683281806Srpaulo	hapd_iface->smps_modes = wpa_s->drv_smps_modes;
684252726Srpaulo	hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
685281806Srpaulo	hapd_iface->extended_capa = wpa_s->extended_capa;
686281806Srpaulo	hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask;
687281806Srpaulo	hapd_iface->extended_capa_len = wpa_s->extended_capa_len;
688214501Srpaulo
689214501Srpaulo	wpa_s->ap_iface->conf = conf = hostapd_config_defaults();
690214501Srpaulo	if (conf == NULL) {
691214501Srpaulo		wpa_supplicant_ap_deinit(wpa_s);
692214501Srpaulo		return -1;
693214501Srpaulo	}
694214501Srpaulo
695337817Scy	/* Use the maximum oper channel width if it's given. */
696337817Scy	if (ssid->max_oper_chwidth)
697337817Scy		conf->vht_oper_chwidth = ssid->max_oper_chwidth;
698337817Scy
699337817Scy	ieee80211_freq_to_chan(ssid->vht_center_freq2,
700337817Scy			       &conf->vht_oper_centr_freq_seg1_idx);
701337817Scy
702252726Srpaulo	os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params,
703252726Srpaulo		  wpa_s->conf->wmm_ac_params,
704252726Srpaulo		  sizeof(wpa_s->conf->wmm_ac_params));
705252726Srpaulo
706252726Srpaulo	if (params.uapsd > 0) {
707281806Srpaulo		conf->bss[0]->wmm_enabled = 1;
708281806Srpaulo		conf->bss[0]->wmm_uapsd = 1;
709252726Srpaulo	}
710252726Srpaulo
711214501Srpaulo	if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) {
712214501Srpaulo		wpa_printf(MSG_ERROR, "Failed to create AP configuration");
713214501Srpaulo		wpa_supplicant_ap_deinit(wpa_s);
714214501Srpaulo		return -1;
715214501Srpaulo	}
716214501Srpaulo
717252726Srpaulo#ifdef CONFIG_P2P
718252726Srpaulo	if (ssid->mode == WPAS_MODE_P2P_GO)
719281806Srpaulo		conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
720252726Srpaulo	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
721281806Srpaulo		conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
722252726Srpaulo			P2P_GROUP_FORMATION;
723252726Srpaulo#endif /* CONFIG_P2P */
724252726Srpaulo
725214501Srpaulo	hapd_iface->num_bss = conf->num_bss;
726252726Srpaulo	hapd_iface->bss = os_calloc(conf->num_bss,
727214501Srpaulo				    sizeof(struct hostapd_data *));
728214501Srpaulo	if (hapd_iface->bss == NULL) {
729214501Srpaulo		wpa_supplicant_ap_deinit(wpa_s);
730214501Srpaulo		return -1;
731214501Srpaulo	}
732214501Srpaulo
733214501Srpaulo	for (i = 0; i < conf->num_bss; i++) {
734214501Srpaulo		hapd_iface->bss[i] =
735214501Srpaulo			hostapd_alloc_bss_data(hapd_iface, conf,
736281806Srpaulo					       conf->bss[i]);
737214501Srpaulo		if (hapd_iface->bss[i] == NULL) {
738214501Srpaulo			wpa_supplicant_ap_deinit(wpa_s);
739214501Srpaulo			return -1;
740214501Srpaulo		}
741214501Srpaulo
742214501Srpaulo		hapd_iface->bss[i]->msg_ctx = wpa_s;
743337817Scy		hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev;
744214501Srpaulo		hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
745214501Srpaulo		hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
746252726Srpaulo		hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
747252726Srpaulo		hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s;
748214501Srpaulo		hostapd_register_probereq_cb(hapd_iface->bss[i],
749214501Srpaulo					     ap_probe_req_rx, wpa_s);
750214501Srpaulo		hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb;
751214501Srpaulo		hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s;
752252726Srpaulo		hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb;
753252726Srpaulo		hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s;
754252726Srpaulo		hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb;
755252726Srpaulo		hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s;
756252726Srpaulo#ifdef CONFIG_P2P
757281806Srpaulo		hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb;
758281806Srpaulo		hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s;
759252726Srpaulo		hapd_iface->bss[i]->p2p = wpa_s->global->p2p;
760252726Srpaulo		hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s,
761252726Srpaulo								    ssid);
762252726Srpaulo#endif /* CONFIG_P2P */
763252726Srpaulo		hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb;
764252726Srpaulo		hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s;
765281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS
766281806Srpaulo		hapd_iface->bss[i]->ext_eapol_frame_io =
767281806Srpaulo			wpa_s->ext_eapol_frame_io;
768281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */
769214501Srpaulo	}
770214501Srpaulo
771214501Srpaulo	os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
772214501Srpaulo	hapd_iface->bss[0]->driver = wpa_s->driver;
773214501Srpaulo	hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv;
774214501Srpaulo
775252726Srpaulo	wpa_s->current_ssid = ssid;
776281806Srpaulo	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
777252726Srpaulo	os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
778252726Srpaulo	wpa_s->assoc_freq = ssid->frequency;
779252726Srpaulo
780214501Srpaulo	if (hostapd_setup_interface(wpa_s->ap_iface)) {
781214501Srpaulo		wpa_printf(MSG_ERROR, "Failed to initialize AP interface");
782214501Srpaulo		wpa_supplicant_ap_deinit(wpa_s);
783214501Srpaulo		return -1;
784214501Srpaulo	}
785214501Srpaulo
786214501Srpaulo	return 0;
787214501Srpaulo}
788214501Srpaulo
789214501Srpaulo
790214501Srpaulovoid wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s)
791214501Srpaulo{
792252726Srpaulo#ifdef CONFIG_WPS
793252726Srpaulo	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
794252726Srpaulo#endif /* CONFIG_WPS */
795252726Srpaulo
796214501Srpaulo	if (wpa_s->ap_iface == NULL)
797214501Srpaulo		return;
798214501Srpaulo
799214501Srpaulo	wpa_s->current_ssid = NULL;
800281806Srpaulo	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
801252726Srpaulo	wpa_s->assoc_freq = 0;
802281806Srpaulo	wpas_p2p_ap_deinit(wpa_s);
803281806Srpaulo	wpa_s->ap_iface->driver_ap_teardown =
804281806Srpaulo		!!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
805281806Srpaulo
806214501Srpaulo	hostapd_interface_deinit(wpa_s->ap_iface);
807214501Srpaulo	hostapd_interface_free(wpa_s->ap_iface);
808214501Srpaulo	wpa_s->ap_iface = NULL;
809214501Srpaulo	wpa_drv_deinit_ap(wpa_s);
810281806Srpaulo	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
811281806Srpaulo		" reason=%d locally_generated=1",
812281806Srpaulo		MAC2STR(wpa_s->own_addr), WLAN_REASON_DEAUTH_LEAVING);
813214501Srpaulo}
814214501Srpaulo
815214501Srpaulo
816214501Srpaulovoid ap_tx_status(void *ctx, const u8 *addr,
817214501Srpaulo		  const u8 *buf, size_t len, int ack)
818214501Srpaulo{
819214501Srpaulo#ifdef NEED_AP_MLME
820214501Srpaulo	struct wpa_supplicant *wpa_s = ctx;
821214501Srpaulo	hostapd_tx_status(wpa_s->ap_iface->bss[0], addr, buf, len, ack);
822214501Srpaulo#endif /* NEED_AP_MLME */
823214501Srpaulo}
824214501Srpaulo
825214501Srpaulo
826252726Srpaulovoid ap_eapol_tx_status(void *ctx, const u8 *dst,
827252726Srpaulo			const u8 *data, size_t len, int ack)
828214501Srpaulo{
829214501Srpaulo#ifdef NEED_AP_MLME
830214501Srpaulo	struct wpa_supplicant *wpa_s = ctx;
831281806Srpaulo	if (!wpa_s->ap_iface)
832281806Srpaulo		return;
833252726Srpaulo	hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
834214501Srpaulo#endif /* NEED_AP_MLME */
835214501Srpaulo}
836214501Srpaulo
837214501Srpaulo
838252726Srpaulovoid ap_client_poll_ok(void *ctx, const u8 *addr)
839252726Srpaulo{
840252726Srpaulo#ifdef NEED_AP_MLME
841252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
842252726Srpaulo	if (wpa_s->ap_iface)
843252726Srpaulo		hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr);
844252726Srpaulo#endif /* NEED_AP_MLME */
845252726Srpaulo}
846252726Srpaulo
847252726Srpaulo
848252726Srpaulovoid ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds)
849252726Srpaulo{
850252726Srpaulo#ifdef NEED_AP_MLME
851252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
852252726Srpaulo	ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds);
853252726Srpaulo#endif /* NEED_AP_MLME */
854252726Srpaulo}
855252726Srpaulo
856252726Srpaulo
857214501Srpaulovoid ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt)
858214501Srpaulo{
859214501Srpaulo#ifdef NEED_AP_MLME
860214501Srpaulo	struct wpa_supplicant *wpa_s = ctx;
861214501Srpaulo	struct hostapd_frame_info fi;
862214501Srpaulo	os_memset(&fi, 0, sizeof(fi));
863214501Srpaulo	fi.datarate = rx_mgmt->datarate;
864214501Srpaulo	fi.ssi_signal = rx_mgmt->ssi_signal;
865214501Srpaulo	ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame,
866214501Srpaulo			rx_mgmt->frame_len, &fi);
867214501Srpaulo#endif /* NEED_AP_MLME */
868214501Srpaulo}
869214501Srpaulo
870214501Srpaulo
871214501Srpaulovoid ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok)
872214501Srpaulo{
873214501Srpaulo#ifdef NEED_AP_MLME
874214501Srpaulo	struct wpa_supplicant *wpa_s = ctx;
875214501Srpaulo	ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok);
876214501Srpaulo#endif /* NEED_AP_MLME */
877214501Srpaulo}
878214501Srpaulo
879214501Srpaulo
880214501Srpaulovoid wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
881214501Srpaulo				const u8 *src_addr, const u8 *buf, size_t len)
882214501Srpaulo{
883214501Srpaulo	ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len);
884214501Srpaulo}
885214501Srpaulo
886214501Srpaulo
887214501Srpaulo#ifdef CONFIG_WPS
888214501Srpaulo
889252726Srpauloint wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
890252726Srpaulo			      const u8 *p2p_dev_addr)
891214501Srpaulo{
892214501Srpaulo	if (!wpa_s->ap_iface)
893214501Srpaulo		return -1;
894252726Srpaulo	return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0],
895252726Srpaulo					 p2p_dev_addr);
896214501Srpaulo}
897214501Srpaulo
898214501Srpaulo
899252726Srpauloint wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s)
900252726Srpaulo{
901252726Srpaulo	struct wps_registrar *reg;
902252726Srpaulo	int reg_sel = 0, wps_sta = 0;
903252726Srpaulo
904252726Srpaulo	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps)
905252726Srpaulo		return -1;
906252726Srpaulo
907252726Srpaulo	reg = wpa_s->ap_iface->bss[0]->wps->registrar;
908252726Srpaulo	reg_sel = wps_registrar_wps_cancel(reg);
909252726Srpaulo	wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0],
910252726Srpaulo				  ap_sta_wps_cancel, NULL);
911252726Srpaulo
912252726Srpaulo	if (!reg_sel && !wps_sta) {
913252726Srpaulo		wpa_printf(MSG_DEBUG, "No WPS operation in progress at this "
914252726Srpaulo			   "time");
915252726Srpaulo		return -1;
916252726Srpaulo	}
917252726Srpaulo
918252726Srpaulo	/*
919252726Srpaulo	 * There are 2 cases to return wps cancel as success:
920252726Srpaulo	 * 1. When wps cancel was initiated but no connection has been
921252726Srpaulo	 *    established with client yet.
922252726Srpaulo	 * 2. Client is in the middle of exchanging WPS messages.
923252726Srpaulo	 */
924252726Srpaulo
925252726Srpaulo	return 0;
926252726Srpaulo}
927252726Srpaulo
928252726Srpaulo
929214501Srpauloint wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
930252726Srpaulo			      const char *pin, char *buf, size_t buflen,
931252726Srpaulo			      int timeout)
932214501Srpaulo{
933214501Srpaulo	int ret, ret_len = 0;
934214501Srpaulo
935214501Srpaulo	if (!wpa_s->ap_iface)
936214501Srpaulo		return -1;
937214501Srpaulo
938214501Srpaulo	if (pin == NULL) {
939337817Scy		unsigned int rpin;
940337817Scy
941337817Scy		if (wps_generate_pin(&rpin) < 0)
942337817Scy			return -1;
943252726Srpaulo		ret_len = os_snprintf(buf, buflen, "%08d", rpin);
944281806Srpaulo		if (os_snprintf_error(buflen, ret_len))
945281806Srpaulo			return -1;
946214501Srpaulo		pin = buf;
947281806Srpaulo	} else if (buf) {
948252726Srpaulo		ret_len = os_snprintf(buf, buflen, "%s", pin);
949281806Srpaulo		if (os_snprintf_error(buflen, ret_len))
950281806Srpaulo			return -1;
951281806Srpaulo	}
952214501Srpaulo
953252726Srpaulo	ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin,
954252726Srpaulo				  timeout);
955214501Srpaulo	if (ret)
956214501Srpaulo		return -1;
957214501Srpaulo	return ret_len;
958214501Srpaulo}
959214501Srpaulo
960252726Srpaulo
961252726Srpaulostatic void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
962252726Srpaulo{
963252726Srpaulo	struct wpa_supplicant *wpa_s = eloop_data;
964252726Srpaulo	wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
965252726Srpaulo	wpas_wps_ap_pin_disable(wpa_s);
966252726Srpaulo}
967252726Srpaulo
968252726Srpaulo
969252726Srpaulostatic void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout)
970252726Srpaulo{
971252726Srpaulo	struct hostapd_data *hapd;
972252726Srpaulo
973252726Srpaulo	if (wpa_s->ap_iface == NULL)
974252726Srpaulo		return;
975252726Srpaulo	hapd = wpa_s->ap_iface->bss[0];
976252726Srpaulo	wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
977252726Srpaulo	hapd->ap_pin_failures = 0;
978252726Srpaulo	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
979252726Srpaulo	if (timeout > 0)
980252726Srpaulo		eloop_register_timeout(timeout, 0,
981252726Srpaulo				       wpas_wps_ap_pin_timeout, wpa_s, NULL);
982252726Srpaulo}
983252726Srpaulo
984252726Srpaulo
985252726Srpaulovoid wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s)
986252726Srpaulo{
987252726Srpaulo	struct hostapd_data *hapd;
988252726Srpaulo
989252726Srpaulo	if (wpa_s->ap_iface == NULL)
990252726Srpaulo		return;
991252726Srpaulo	wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
992252726Srpaulo	hapd = wpa_s->ap_iface->bss[0];
993252726Srpaulo	os_free(hapd->conf->ap_pin);
994252726Srpaulo	hapd->conf->ap_pin = NULL;
995252726Srpaulo	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
996252726Srpaulo}
997252726Srpaulo
998252726Srpaulo
999252726Srpauloconst char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
1000252726Srpaulo{
1001252726Srpaulo	struct hostapd_data *hapd;
1002252726Srpaulo	unsigned int pin;
1003252726Srpaulo	char pin_txt[9];
1004252726Srpaulo
1005252726Srpaulo	if (wpa_s->ap_iface == NULL)
1006252726Srpaulo		return NULL;
1007252726Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1008337817Scy	if (wps_generate_pin(&pin) < 0)
1009337817Scy		return NULL;
1010252726Srpaulo	os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
1011252726Srpaulo	os_free(hapd->conf->ap_pin);
1012252726Srpaulo	hapd->conf->ap_pin = os_strdup(pin_txt);
1013252726Srpaulo	if (hapd->conf->ap_pin == NULL)
1014252726Srpaulo		return NULL;
1015252726Srpaulo	wpas_wps_ap_pin_enable(wpa_s, timeout);
1016252726Srpaulo
1017252726Srpaulo	return hapd->conf->ap_pin;
1018252726Srpaulo}
1019252726Srpaulo
1020252726Srpaulo
1021252726Srpauloconst char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s)
1022252726Srpaulo{
1023252726Srpaulo	struct hostapd_data *hapd;
1024252726Srpaulo	if (wpa_s->ap_iface == NULL)
1025252726Srpaulo		return NULL;
1026252726Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1027252726Srpaulo	return hapd->conf->ap_pin;
1028252726Srpaulo}
1029252726Srpaulo
1030252726Srpaulo
1031252726Srpauloint wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin,
1032252726Srpaulo			int timeout)
1033252726Srpaulo{
1034252726Srpaulo	struct hostapd_data *hapd;
1035252726Srpaulo	char pin_txt[9];
1036252726Srpaulo	int ret;
1037252726Srpaulo
1038252726Srpaulo	if (wpa_s->ap_iface == NULL)
1039252726Srpaulo		return -1;
1040252726Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1041252726Srpaulo	ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin);
1042281806Srpaulo	if (os_snprintf_error(sizeof(pin_txt), ret))
1043252726Srpaulo		return -1;
1044252726Srpaulo	os_free(hapd->conf->ap_pin);
1045252726Srpaulo	hapd->conf->ap_pin = os_strdup(pin_txt);
1046252726Srpaulo	if (hapd->conf->ap_pin == NULL)
1047252726Srpaulo		return -1;
1048252726Srpaulo	wpas_wps_ap_pin_enable(wpa_s, timeout);
1049252726Srpaulo
1050252726Srpaulo	return 0;
1051252726Srpaulo}
1052252726Srpaulo
1053252726Srpaulo
1054252726Srpaulovoid wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s)
1055252726Srpaulo{
1056252726Srpaulo	struct hostapd_data *hapd;
1057252726Srpaulo
1058252726Srpaulo	if (wpa_s->ap_iface == NULL)
1059252726Srpaulo		return;
1060252726Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1061252726Srpaulo
1062252726Srpaulo	/*
1063252726Srpaulo	 * Registrar failed to prove its knowledge of the AP PIN. Disable AP
1064252726Srpaulo	 * PIN if this happens multiple times to slow down brute force attacks.
1065252726Srpaulo	 */
1066252726Srpaulo	hapd->ap_pin_failures++;
1067252726Srpaulo	wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
1068252726Srpaulo		   hapd->ap_pin_failures);
1069252726Srpaulo	if (hapd->ap_pin_failures < 3)
1070252726Srpaulo		return;
1071252726Srpaulo
1072252726Srpaulo	wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN");
1073252726Srpaulo	hapd->ap_pin_failures = 0;
1074252726Srpaulo	os_free(hapd->conf->ap_pin);
1075252726Srpaulo	hapd->conf->ap_pin = NULL;
1076252726Srpaulo}
1077252726Srpaulo
1078281806Srpaulo
1079281806Srpaulo#ifdef CONFIG_WPS_NFC
1080281806Srpaulo
1081281806Srpaulostruct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
1082281806Srpaulo					     int ndef)
1083281806Srpaulo{
1084281806Srpaulo	struct hostapd_data *hapd;
1085281806Srpaulo
1086281806Srpaulo	if (wpa_s->ap_iface == NULL)
1087281806Srpaulo		return NULL;
1088281806Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1089281806Srpaulo	return hostapd_wps_nfc_config_token(hapd, ndef);
1090281806Srpaulo}
1091281806Srpaulo
1092281806Srpaulo
1093281806Srpaulostruct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
1094281806Srpaulo					     int ndef)
1095281806Srpaulo{
1096281806Srpaulo	struct hostapd_data *hapd;
1097281806Srpaulo
1098281806Srpaulo	if (wpa_s->ap_iface == NULL)
1099281806Srpaulo		return NULL;
1100281806Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1101281806Srpaulo	return hostapd_wps_nfc_hs_cr(hapd, ndef);
1102281806Srpaulo}
1103281806Srpaulo
1104281806Srpaulo
1105281806Srpauloint wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
1106281806Srpaulo				    const struct wpabuf *req,
1107281806Srpaulo				    const struct wpabuf *sel)
1108281806Srpaulo{
1109281806Srpaulo	struct hostapd_data *hapd;
1110281806Srpaulo
1111281806Srpaulo	if (wpa_s->ap_iface == NULL)
1112281806Srpaulo		return -1;
1113281806Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1114281806Srpaulo	return hostapd_wps_nfc_report_handover(hapd, req, sel);
1115281806Srpaulo}
1116281806Srpaulo
1117281806Srpaulo#endif /* CONFIG_WPS_NFC */
1118281806Srpaulo
1119214501Srpaulo#endif /* CONFIG_WPS */
1120214501Srpaulo
1121214501Srpaulo
1122214501Srpaulo#ifdef CONFIG_CTRL_IFACE
1123214501Srpaulo
1124214501Srpauloint ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
1125214501Srpaulo			    char *buf, size_t buflen)
1126214501Srpaulo{
1127281806Srpaulo	struct hostapd_data *hapd;
1128281806Srpaulo
1129281806Srpaulo	if (wpa_s->ap_iface)
1130281806Srpaulo		hapd = wpa_s->ap_iface->bss[0];
1131281806Srpaulo	else if (wpa_s->ifmsh)
1132281806Srpaulo		hapd = wpa_s->ifmsh->bss[0];
1133281806Srpaulo	else
1134214501Srpaulo		return -1;
1135281806Srpaulo	return hostapd_ctrl_iface_sta_first(hapd, buf, buflen);
1136214501Srpaulo}
1137214501Srpaulo
1138214501Srpaulo
1139214501Srpauloint ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
1140214501Srpaulo		      char *buf, size_t buflen)
1141214501Srpaulo{
1142281806Srpaulo	struct hostapd_data *hapd;
1143281806Srpaulo
1144281806Srpaulo	if (wpa_s->ap_iface)
1145281806Srpaulo		hapd = wpa_s->ap_iface->bss[0];
1146281806Srpaulo	else if (wpa_s->ifmsh)
1147281806Srpaulo		hapd = wpa_s->ifmsh->bss[0];
1148281806Srpaulo	else
1149214501Srpaulo		return -1;
1150281806Srpaulo	return hostapd_ctrl_iface_sta(hapd, txtaddr, buf, buflen);
1151214501Srpaulo}
1152214501Srpaulo
1153214501Srpaulo
1154214501Srpauloint ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
1155214501Srpaulo			   char *buf, size_t buflen)
1156214501Srpaulo{
1157281806Srpaulo	struct hostapd_data *hapd;
1158281806Srpaulo
1159281806Srpaulo	if (wpa_s->ap_iface)
1160281806Srpaulo		hapd = wpa_s->ap_iface->bss[0];
1161281806Srpaulo	else if (wpa_s->ifmsh)
1162281806Srpaulo		hapd = wpa_s->ifmsh->bss[0];
1163281806Srpaulo	else
1164214501Srpaulo		return -1;
1165281806Srpaulo	return hostapd_ctrl_iface_sta_next(hapd, txtaddr, buf, buflen);
1166214501Srpaulo}
1167214501Srpaulo
1168214501Srpaulo
1169252726Srpauloint ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s,
1170252726Srpaulo				   const char *txtaddr)
1171252726Srpaulo{
1172252726Srpaulo	if (wpa_s->ap_iface == NULL)
1173252726Srpaulo		return -1;
1174252726Srpaulo	return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0],
1175252726Srpaulo					       txtaddr);
1176252726Srpaulo}
1177252726Srpaulo
1178252726Srpaulo
1179252726Srpauloint ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s,
1180252726Srpaulo				     const char *txtaddr)
1181252726Srpaulo{
1182252726Srpaulo	if (wpa_s->ap_iface == NULL)
1183252726Srpaulo		return -1;
1184252726Srpaulo	return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0],
1185252726Srpaulo						 txtaddr);
1186252726Srpaulo}
1187252726Srpaulo
1188252726Srpaulo
1189214501Srpauloint ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
1190214501Srpaulo				 size_t buflen, int verbose)
1191214501Srpaulo{
1192214501Srpaulo	char *pos = buf, *end = buf + buflen;
1193214501Srpaulo	int ret;
1194214501Srpaulo	struct hostapd_bss_config *conf;
1195214501Srpaulo
1196214501Srpaulo	if (wpa_s->ap_iface == NULL)
1197214501Srpaulo		return -1;
1198214501Srpaulo
1199214501Srpaulo	conf = wpa_s->ap_iface->bss[0]->conf;
1200214501Srpaulo	if (conf->wpa == 0)
1201214501Srpaulo		return 0;
1202214501Srpaulo
1203214501Srpaulo	ret = os_snprintf(pos, end - pos,
1204214501Srpaulo			  "pairwise_cipher=%s\n"
1205214501Srpaulo			  "group_cipher=%s\n"
1206214501Srpaulo			  "key_mgmt=%s\n",
1207214501Srpaulo			  wpa_cipher_txt(conf->rsn_pairwise),
1208214501Srpaulo			  wpa_cipher_txt(conf->wpa_group),
1209214501Srpaulo			  wpa_key_mgmt_txt(conf->wpa_key_mgmt,
1210214501Srpaulo					   conf->wpa));
1211281806Srpaulo	if (os_snprintf_error(end - pos, ret))
1212214501Srpaulo		return pos - buf;
1213214501Srpaulo	pos += ret;
1214214501Srpaulo	return pos - buf;
1215214501Srpaulo}
1216214501Srpaulo
1217214501Srpaulo#endif /* CONFIG_CTRL_IFACE */
1218214501Srpaulo
1219214501Srpaulo
1220252726Srpauloint wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
1221252726Srpaulo{
1222252726Srpaulo	struct hostapd_iface *iface = wpa_s->ap_iface;
1223252726Srpaulo	struct wpa_ssid *ssid = wpa_s->current_ssid;
1224252726Srpaulo	struct hostapd_data *hapd;
1225252726Srpaulo
1226252726Srpaulo	if (ssid == NULL || wpa_s->ap_iface == NULL ||
1227252726Srpaulo	    ssid->mode == WPAS_MODE_INFRA ||
1228252726Srpaulo	    ssid->mode == WPAS_MODE_IBSS)
1229252726Srpaulo		return -1;
1230252726Srpaulo
1231252726Srpaulo#ifdef CONFIG_P2P
1232252726Srpaulo	if (ssid->mode == WPAS_MODE_P2P_GO)
1233281806Srpaulo		iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
1234252726Srpaulo	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1235281806Srpaulo		iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
1236252726Srpaulo			P2P_GROUP_FORMATION;
1237252726Srpaulo#endif /* CONFIG_P2P */
1238252726Srpaulo
1239252726Srpaulo	hapd = iface->bss[0];
1240252726Srpaulo	if (hapd->drv_priv == NULL)
1241252726Srpaulo		return -1;
1242252726Srpaulo	ieee802_11_set_beacons(iface);
1243252726Srpaulo	hostapd_set_ap_wps_ie(hapd);
1244252726Srpaulo
1245252726Srpaulo	return 0;
1246252726Srpaulo}
1247252726Srpaulo
1248252726Srpaulo
1249281806Srpauloint ap_switch_channel(struct wpa_supplicant *wpa_s,
1250281806Srpaulo		      struct csa_settings *settings)
1251281806Srpaulo{
1252281806Srpaulo#ifdef NEED_AP_MLME
1253281806Srpaulo	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
1254281806Srpaulo		return -1;
1255281806Srpaulo
1256281806Srpaulo	return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings);
1257281806Srpaulo#else /* NEED_AP_MLME */
1258281806Srpaulo	return -1;
1259281806Srpaulo#endif /* NEED_AP_MLME */
1260281806Srpaulo}
1261281806Srpaulo
1262281806Srpaulo
1263289549Srpaulo#ifdef CONFIG_CTRL_IFACE
1264281806Srpauloint ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
1265281806Srpaulo{
1266281806Srpaulo	struct csa_settings settings;
1267281806Srpaulo	int ret = hostapd_parse_csa_settings(pos, &settings);
1268281806Srpaulo
1269281806Srpaulo	if (ret)
1270281806Srpaulo		return ret;
1271281806Srpaulo
1272281806Srpaulo	return ap_switch_channel(wpa_s, &settings);
1273281806Srpaulo}
1274289549Srpaulo#endif /* CONFIG_CTRL_IFACE */
1275281806Srpaulo
1276281806Srpaulo
1277252726Srpaulovoid wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
1278281806Srpaulo		       int offset, int width, int cf1, int cf2)
1279252726Srpaulo{
1280252726Srpaulo	if (!wpa_s->ap_iface)
1281252726Srpaulo		return;
1282252726Srpaulo
1283252726Srpaulo	wpa_s->assoc_freq = freq;
1284289549Srpaulo	if (wpa_s->current_ssid)
1285289549Srpaulo		wpa_s->current_ssid->frequency = freq;
1286289549Srpaulo	hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht,
1287289549Srpaulo				offset, width, cf1, cf2);
1288252726Srpaulo}
1289252726Srpaulo
1290252726Srpaulo
1291214501Srpauloint wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
1292214501Srpaulo				      const u8 *addr)
1293214501Srpaulo{
1294214501Srpaulo	struct hostapd_data *hapd;
1295214501Srpaulo	struct hostapd_bss_config *conf;
1296214501Srpaulo
1297214501Srpaulo	if (!wpa_s->ap_iface)
1298214501Srpaulo		return -1;
1299214501Srpaulo
1300214501Srpaulo	if (addr)
1301214501Srpaulo		wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR,
1302214501Srpaulo			   MAC2STR(addr));
1303214501Srpaulo	else
1304214501Srpaulo		wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter");
1305214501Srpaulo
1306214501Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1307214501Srpaulo	conf = hapd->conf;
1308214501Srpaulo
1309214501Srpaulo	os_free(conf->accept_mac);
1310214501Srpaulo	conf->accept_mac = NULL;
1311214501Srpaulo	conf->num_accept_mac = 0;
1312214501Srpaulo	os_free(conf->deny_mac);
1313214501Srpaulo	conf->deny_mac = NULL;
1314214501Srpaulo	conf->num_deny_mac = 0;
1315214501Srpaulo
1316214501Srpaulo	if (addr == NULL) {
1317214501Srpaulo		conf->macaddr_acl = ACCEPT_UNLESS_DENIED;
1318214501Srpaulo		return 0;
1319214501Srpaulo	}
1320214501Srpaulo
1321214501Srpaulo	conf->macaddr_acl = DENY_UNLESS_ACCEPTED;
1322214501Srpaulo	conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry));
1323214501Srpaulo	if (conf->accept_mac == NULL)
1324214501Srpaulo		return -1;
1325214501Srpaulo	os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN);
1326214501Srpaulo	conf->num_accept_mac = 1;
1327214501Srpaulo
1328214501Srpaulo	return 0;
1329214501Srpaulo}
1330281806Srpaulo
1331281806Srpaulo
1332281806Srpaulo#ifdef CONFIG_WPS_NFC
1333281806Srpauloint wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
1334281806Srpaulo			   const struct wpabuf *pw, const u8 *pubkey_hash)
1335281806Srpaulo{
1336281806Srpaulo	struct hostapd_data *hapd;
1337281806Srpaulo	struct wps_context *wps;
1338281806Srpaulo
1339281806Srpaulo	if (!wpa_s->ap_iface)
1340281806Srpaulo		return -1;
1341281806Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1342281806Srpaulo	wps = hapd->wps;
1343281806Srpaulo
1344337817Scy	if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL ||
1345337817Scy	    wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) {
1346281806Srpaulo		wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known");
1347281806Srpaulo		return -1;
1348281806Srpaulo	}
1349281806Srpaulo
1350281806Srpaulo	dh5_free(wps->dh_ctx);
1351281806Srpaulo	wpabuf_free(wps->dh_pubkey);
1352281806Srpaulo	wpabuf_free(wps->dh_privkey);
1353281806Srpaulo	wps->dh_privkey = wpabuf_dup(
1354337817Scy		wpa_s->p2pdev->conf->wps_nfc_dh_privkey);
1355281806Srpaulo	wps->dh_pubkey = wpabuf_dup(
1356337817Scy		wpa_s->p2pdev->conf->wps_nfc_dh_pubkey);
1357281806Srpaulo	if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
1358281806Srpaulo		wps->dh_ctx = NULL;
1359281806Srpaulo		wpabuf_free(wps->dh_pubkey);
1360281806Srpaulo		wps->dh_pubkey = NULL;
1361281806Srpaulo		wpabuf_free(wps->dh_privkey);
1362281806Srpaulo		wps->dh_privkey = NULL;
1363281806Srpaulo		return -1;
1364281806Srpaulo	}
1365281806Srpaulo	wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
1366281806Srpaulo	if (wps->dh_ctx == NULL)
1367281806Srpaulo		return -1;
1368281806Srpaulo
1369281806Srpaulo	return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash,
1370281806Srpaulo					      pw_id,
1371281806Srpaulo					      pw ? wpabuf_head(pw) : NULL,
1372281806Srpaulo					      pw ? wpabuf_len(pw) : 0, 1);
1373281806Srpaulo}
1374281806Srpaulo#endif /* CONFIG_WPS_NFC */
1375281806Srpaulo
1376281806Srpaulo
1377289549Srpaulo#ifdef CONFIG_CTRL_IFACE
1378281806Srpauloint wpas_ap_stop_ap(struct wpa_supplicant *wpa_s)
1379281806Srpaulo{
1380281806Srpaulo	struct hostapd_data *hapd;
1381281806Srpaulo
1382281806Srpaulo	if (!wpa_s->ap_iface)
1383281806Srpaulo		return -1;
1384281806Srpaulo	hapd = wpa_s->ap_iface->bss[0];
1385281806Srpaulo	return hostapd_ctrl_iface_stop_ap(hapd);
1386281806Srpaulo}
1387337817Scy
1388337817Scy
1389337817Scyint wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
1390337817Scy			     size_t len)
1391337817Scy{
1392337817Scy	size_t reply_len = 0, i;
1393337817Scy	char ap_delimiter[] = "---- AP ----\n";
1394337817Scy	char mesh_delimiter[] = "---- mesh ----\n";
1395337817Scy	size_t dlen;
1396337817Scy
1397337817Scy	if (wpa_s->ap_iface) {
1398337817Scy		dlen = os_strlen(ap_delimiter);
1399337817Scy		if (dlen > len - reply_len)
1400337817Scy			return reply_len;
1401337817Scy		os_memcpy(&buf[reply_len], ap_delimiter, dlen);
1402337817Scy		reply_len += dlen;
1403337817Scy
1404337817Scy		for (i = 0; i < wpa_s->ap_iface->num_bss; i++) {
1405337817Scy			reply_len += hostapd_ctrl_iface_pmksa_list(
1406337817Scy				wpa_s->ap_iface->bss[i],
1407337817Scy				&buf[reply_len], len - reply_len);
1408337817Scy		}
1409337817Scy	}
1410337817Scy
1411337817Scy	if (wpa_s->ifmsh) {
1412337817Scy		dlen = os_strlen(mesh_delimiter);
1413337817Scy		if (dlen > len - reply_len)
1414337817Scy			return reply_len;
1415337817Scy		os_memcpy(&buf[reply_len], mesh_delimiter, dlen);
1416337817Scy		reply_len += dlen;
1417337817Scy
1418337817Scy		reply_len += hostapd_ctrl_iface_pmksa_list(
1419337817Scy			wpa_s->ifmsh->bss[0], &buf[reply_len],
1420337817Scy			len - reply_len);
1421337817Scy	}
1422337817Scy
1423337817Scy	return reply_len;
1424337817Scy}
1425337817Scy
1426337817Scy
1427337817Scyvoid wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
1428337817Scy{
1429337817Scy	size_t i;
1430337817Scy
1431337817Scy	if (wpa_s->ap_iface) {
1432337817Scy		for (i = 0; i < wpa_s->ap_iface->num_bss; i++)
1433337817Scy			hostapd_ctrl_iface_pmksa_flush(wpa_s->ap_iface->bss[i]);
1434337817Scy	}
1435337817Scy
1436337817Scy	if (wpa_s->ifmsh)
1437337817Scy		hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]);
1438337817Scy}
1439289549Srpaulo#endif /* CONFIG_CTRL_IFACE */
1440281806Srpaulo
1441281806Srpaulo
1442281806Srpaulo#ifdef NEED_AP_MLME
1443281806Srpaulovoid wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
1444281806Srpaulo				   struct dfs_event *radar)
1445281806Srpaulo{
1446281806Srpaulo	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
1447281806Srpaulo		return;
1448281806Srpaulo	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
1449281806Srpaulo	hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq,
1450281806Srpaulo				   radar->ht_enabled, radar->chan_offset,
1451281806Srpaulo				   radar->chan_width,
1452281806Srpaulo				   radar->cf1, radar->cf2);
1453281806Srpaulo}
1454281806Srpaulo
1455281806Srpaulo
1456281806Srpaulovoid wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
1457281806Srpaulo				struct dfs_event *radar)
1458281806Srpaulo{
1459281806Srpaulo	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
1460281806Srpaulo		return;
1461281806Srpaulo	wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
1462281806Srpaulo	hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq,
1463281806Srpaulo			      radar->ht_enabled, radar->chan_offset,
1464281806Srpaulo			      radar->chan_width, radar->cf1, radar->cf2);
1465281806Srpaulo}
1466281806Srpaulo
1467281806Srpaulo
1468281806Srpaulovoid wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
1469281806Srpaulo				 struct dfs_event *radar)
1470281806Srpaulo{
1471281806Srpaulo	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
1472281806Srpaulo		return;
1473281806Srpaulo	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
1474281806Srpaulo	hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq,
1475281806Srpaulo				 radar->ht_enabled, radar->chan_offset,
1476281806Srpaulo				 radar->chan_width, radar->cf1, radar->cf2);
1477281806Srpaulo}
1478281806Srpaulo
1479281806Srpaulo
1480281806Srpaulovoid wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
1481281806Srpaulo				struct dfs_event *radar)
1482281806Srpaulo{
1483281806Srpaulo	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
1484281806Srpaulo		return;
1485281806Srpaulo	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
1486281806Srpaulo	hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq,
1487281806Srpaulo				 radar->ht_enabled, radar->chan_offset,
1488281806Srpaulo				 radar->chan_width, radar->cf1, radar->cf2);
1489281806Srpaulo}
1490281806Srpaulo
1491281806Srpaulo
1492281806Srpaulovoid wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
1493281806Srpaulo				     struct dfs_event *radar)
1494281806Srpaulo{
1495281806Srpaulo	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
1496281806Srpaulo		return;
1497281806Srpaulo	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
1498281806Srpaulo	hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq,
1499281806Srpaulo				 radar->ht_enabled, radar->chan_offset,
1500281806Srpaulo				 radar->chan_width, radar->cf1, radar->cf2);
1501281806Srpaulo}
1502281806Srpaulo#endif /* NEED_AP_MLME */
1503289549Srpaulo
1504289549Srpaulo
1505289549Srpaulovoid ap_periodic(struct wpa_supplicant *wpa_s)
1506289549Srpaulo{
1507289549Srpaulo	if (wpa_s->ap_iface)
1508289549Srpaulo		hostapd_periodic_iface(wpa_s->ap_iface);
1509289549Srpaulo}
1510