xref: /freebsd/contrib/wpa/wpa_supplicant/ap.c (revision f05cddf940dbfc5b657f5e9beb9de2c31e509e5b)
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  *
6*f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
7*f05cddf9SRui Paulo  * See README for more details.
8e28a4053SRui Paulo  */
9e28a4053SRui Paulo 
10e28a4053SRui Paulo #include "utils/includes.h"
11e28a4053SRui Paulo 
12e28a4053SRui Paulo #include "utils/common.h"
13*f05cddf9SRui Paulo #include "utils/eloop.h"
14*f05cddf9SRui Paulo #include "utils/uuid.h"
15e28a4053SRui Paulo #include "common/ieee802_11_defs.h"
16*f05cddf9SRui Paulo #include "common/wpa_ctrl.h"
17e28a4053SRui Paulo #include "ap/hostapd.h"
18e28a4053SRui Paulo #include "ap/ap_config.h"
19*f05cddf9SRui Paulo #include "ap/ap_drv_ops.h"
20e28a4053SRui Paulo #ifdef NEED_AP_MLME
21e28a4053SRui Paulo #include "ap/ieee802_11.h"
22e28a4053SRui Paulo #endif /* NEED_AP_MLME */
23*f05cddf9SRui Paulo #include "ap/beacon.h"
24e28a4053SRui Paulo #include "ap/ieee802_1x.h"
25e28a4053SRui Paulo #include "ap/wps_hostapd.h"
26e28a4053SRui Paulo #include "ap/ctrl_iface_ap.h"
27e28a4053SRui Paulo #include "wps/wps.h"
28*f05cddf9SRui Paulo #include "common/ieee802_11_defs.h"
29e28a4053SRui Paulo #include "config_ssid.h"
30e28a4053SRui Paulo #include "config.h"
31e28a4053SRui Paulo #include "wpa_supplicant_i.h"
32e28a4053SRui Paulo #include "driver_i.h"
33*f05cddf9SRui Paulo #include "p2p_supplicant.h"
34e28a4053SRui Paulo #include "ap.h"
35*f05cddf9SRui Paulo #include "ap/sta_info.h"
36*f05cddf9SRui Paulo #include "notify.h"
37*f05cddf9SRui Paulo 
38*f05cddf9SRui Paulo 
39*f05cddf9SRui Paulo #ifdef CONFIG_WPS
40*f05cddf9SRui Paulo static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
41*f05cddf9SRui Paulo #endif /* CONFIG_WPS */
42e28a4053SRui Paulo 
43e28a4053SRui Paulo 
44e28a4053SRui Paulo static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
45e28a4053SRui Paulo 				  struct wpa_ssid *ssid,
46e28a4053SRui Paulo 				  struct hostapd_config *conf)
47e28a4053SRui Paulo {
48e28a4053SRui Paulo 	struct hostapd_bss_config *bss = &conf->bss[0];
49e28a4053SRui Paulo 	int pairwise;
50e28a4053SRui Paulo 
51e28a4053SRui Paulo 	conf->driver = wpa_s->driver;
52e28a4053SRui Paulo 
53e28a4053SRui Paulo 	os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
54e28a4053SRui Paulo 
55e28a4053SRui Paulo 	if (ssid->frequency == 0) {
56e28a4053SRui Paulo 		/* default channel 11 */
57e28a4053SRui Paulo 		conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
58e28a4053SRui Paulo 		conf->channel = 11;
59e28a4053SRui Paulo 	} else if (ssid->frequency >= 2412 && ssid->frequency <= 2472) {
60e28a4053SRui Paulo 		conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
61e28a4053SRui Paulo 		conf->channel = (ssid->frequency - 2407) / 5;
62e28a4053SRui Paulo 	} else if ((ssid->frequency >= 5180 && ssid->frequency <= 5240) ||
63e28a4053SRui Paulo 		   (ssid->frequency >= 5745 && ssid->frequency <= 5825)) {
64e28a4053SRui Paulo 		conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
65e28a4053SRui Paulo 		conf->channel = (ssid->frequency - 5000) / 5;
66*f05cddf9SRui Paulo 	} else if (ssid->frequency >= 56160 + 2160 * 1 &&
67*f05cddf9SRui Paulo 		   ssid->frequency <= 56160 + 2160 * 4) {
68*f05cddf9SRui Paulo 		conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
69*f05cddf9SRui Paulo 		conf->channel = (ssid->frequency - 56160) / 2160;
70e28a4053SRui Paulo 	} else {
71e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
72e28a4053SRui Paulo 			   ssid->frequency);
73e28a4053SRui Paulo 		return -1;
74e28a4053SRui Paulo 	}
75e28a4053SRui Paulo 
76*f05cddf9SRui Paulo 	/* TODO: enable HT40 if driver supports it;
77e28a4053SRui Paulo 	 * drop to 11b if driver does not support 11g */
78e28a4053SRui Paulo 
79*f05cddf9SRui Paulo #ifdef CONFIG_IEEE80211N
80*f05cddf9SRui Paulo 	/*
81*f05cddf9SRui Paulo 	 * Enable HT20 if the driver supports it, by setting conf->ieee80211n
82*f05cddf9SRui Paulo 	 * and a mask of allowed capabilities within conf->ht_capab.
83*f05cddf9SRui Paulo 	 * Using default config settings for: conf->ht_op_mode_fixed,
84*f05cddf9SRui Paulo 	 * conf->secondary_channel, conf->require_ht
85*f05cddf9SRui Paulo 	 */
86*f05cddf9SRui Paulo 	if (wpa_s->hw.modes) {
87*f05cddf9SRui Paulo 		struct hostapd_hw_modes *mode = NULL;
88*f05cddf9SRui Paulo 		int i, no_ht = 0;
89*f05cddf9SRui Paulo 		for (i = 0; i < wpa_s->hw.num_modes; i++) {
90*f05cddf9SRui Paulo 			if (wpa_s->hw.modes[i].mode == conf->hw_mode) {
91*f05cddf9SRui Paulo 				mode = &wpa_s->hw.modes[i];
92*f05cddf9SRui Paulo 				break;
93*f05cddf9SRui Paulo 			}
94*f05cddf9SRui Paulo 		}
95*f05cddf9SRui Paulo 
96*f05cddf9SRui Paulo #ifdef CONFIG_HT_OVERRIDES
97*f05cddf9SRui Paulo 		if (ssid->disable_ht) {
98*f05cddf9SRui Paulo 			conf->ieee80211n = 0;
99*f05cddf9SRui Paulo 			conf->ht_capab = 0;
100*f05cddf9SRui Paulo 			no_ht = 1;
101*f05cddf9SRui Paulo 		}
102*f05cddf9SRui Paulo #endif /* CONFIG_HT_OVERRIDES */
103*f05cddf9SRui Paulo 
104*f05cddf9SRui Paulo 		if (!no_ht && mode && mode->ht_capab) {
105*f05cddf9SRui Paulo 			conf->ieee80211n = 1;
106*f05cddf9SRui Paulo #ifdef CONFIG_P2P
107*f05cddf9SRui Paulo 			if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&
108*f05cddf9SRui Paulo 			    (mode->ht_capab &
109*f05cddf9SRui Paulo 			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
110*f05cddf9SRui Paulo 			    ssid->ht40)
111*f05cddf9SRui Paulo 				conf->secondary_channel =
112*f05cddf9SRui Paulo 					wpas_p2p_get_ht40_mode(wpa_s, mode,
113*f05cddf9SRui Paulo 							       conf->channel);
114*f05cddf9SRui Paulo 			if (conf->secondary_channel)
115*f05cddf9SRui Paulo 				conf->ht_capab |=
116*f05cddf9SRui Paulo 					HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
117*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
118*f05cddf9SRui Paulo 
119*f05cddf9SRui Paulo 			/*
120*f05cddf9SRui Paulo 			 * white-list capabilities that won't cause issues
121*f05cddf9SRui Paulo 			 * to connecting stations, while leaving the current
122*f05cddf9SRui Paulo 			 * capabilities intact (currently disabled SMPS).
123*f05cddf9SRui Paulo 			 */
124*f05cddf9SRui Paulo 			conf->ht_capab |= mode->ht_capab &
125*f05cddf9SRui Paulo 				(HT_CAP_INFO_GREEN_FIELD |
126*f05cddf9SRui Paulo 				 HT_CAP_INFO_SHORT_GI20MHZ |
127*f05cddf9SRui Paulo 				 HT_CAP_INFO_SHORT_GI40MHZ |
128*f05cddf9SRui Paulo 				 HT_CAP_INFO_RX_STBC_MASK |
129*f05cddf9SRui Paulo 				 HT_CAP_INFO_MAX_AMSDU_SIZE);
130*f05cddf9SRui Paulo 		}
131*f05cddf9SRui Paulo 	}
132*f05cddf9SRui Paulo #endif /* CONFIG_IEEE80211N */
133*f05cddf9SRui Paulo 
134*f05cddf9SRui Paulo #ifdef CONFIG_P2P
135*f05cddf9SRui Paulo 	if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
136*f05cddf9SRui Paulo 		/* Remove 802.11b rates from supported and basic rate sets */
137*f05cddf9SRui Paulo 		int *list = os_malloc(4 * sizeof(int));
138*f05cddf9SRui Paulo 		if (list) {
139*f05cddf9SRui Paulo 			list[0] = 60;
140*f05cddf9SRui Paulo 			list[1] = 120;
141*f05cddf9SRui Paulo 			list[2] = 240;
142*f05cddf9SRui Paulo 			list[3] = -1;
143*f05cddf9SRui Paulo 		}
144*f05cddf9SRui Paulo 		conf->basic_rates = list;
145*f05cddf9SRui Paulo 
146*f05cddf9SRui Paulo 		list = os_malloc(9 * sizeof(int));
147*f05cddf9SRui Paulo 		if (list) {
148*f05cddf9SRui Paulo 			list[0] = 60;
149*f05cddf9SRui Paulo 			list[1] = 90;
150*f05cddf9SRui Paulo 			list[2] = 120;
151*f05cddf9SRui Paulo 			list[3] = 180;
152*f05cddf9SRui Paulo 			list[4] = 240;
153*f05cddf9SRui Paulo 			list[5] = 360;
154*f05cddf9SRui Paulo 			list[6] = 480;
155*f05cddf9SRui Paulo 			list[7] = 540;
156*f05cddf9SRui Paulo 			list[8] = -1;
157*f05cddf9SRui Paulo 		}
158*f05cddf9SRui Paulo 		conf->supported_rates = list;
159*f05cddf9SRui Paulo 	}
160*f05cddf9SRui Paulo 
161*f05cddf9SRui Paulo 	bss->isolate = !wpa_s->conf->p2p_intra_bss;
162*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
163*f05cddf9SRui Paulo 
164e28a4053SRui Paulo 	if (ssid->ssid_len == 0) {
165e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
166e28a4053SRui Paulo 		return -1;
167e28a4053SRui Paulo 	}
168e28a4053SRui Paulo 	os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len);
169e28a4053SRui Paulo 	bss->ssid.ssid_len = ssid->ssid_len;
170e28a4053SRui Paulo 	bss->ssid.ssid_set = 1;
171e28a4053SRui Paulo 
172*f05cddf9SRui Paulo 	bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid;
173*f05cddf9SRui Paulo 
174*f05cddf9SRui Paulo 	if (ssid->auth_alg)
175*f05cddf9SRui Paulo 		bss->auth_algs = ssid->auth_alg;
176*f05cddf9SRui Paulo 
177e28a4053SRui Paulo 	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt))
178e28a4053SRui Paulo 		bss->wpa = ssid->proto;
179e28a4053SRui Paulo 	bss->wpa_key_mgmt = ssid->key_mgmt;
180e28a4053SRui Paulo 	bss->wpa_pairwise = ssid->pairwise_cipher;
181*f05cddf9SRui Paulo 	if (ssid->psk_set) {
182e28a4053SRui Paulo 		os_free(bss->ssid.wpa_psk);
183e28a4053SRui Paulo 		bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
184e28a4053SRui Paulo 		if (bss->ssid.wpa_psk == NULL)
185e28a4053SRui Paulo 			return -1;
186e28a4053SRui Paulo 		os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN);
187e28a4053SRui Paulo 		bss->ssid.wpa_psk->group = 1;
188*f05cddf9SRui Paulo 	} else if (ssid->passphrase) {
189*f05cddf9SRui Paulo 		bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
190*f05cddf9SRui Paulo 	} else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] ||
191*f05cddf9SRui Paulo 		   ssid->wep_key_len[2] || ssid->wep_key_len[3]) {
192*f05cddf9SRui Paulo 		struct hostapd_wep_keys *wep = &bss->ssid.wep;
193*f05cddf9SRui Paulo 		int i;
194*f05cddf9SRui Paulo 		for (i = 0; i < NUM_WEP_KEYS; i++) {
195*f05cddf9SRui Paulo 			if (ssid->wep_key_len[i] == 0)
196*f05cddf9SRui Paulo 				continue;
197*f05cddf9SRui Paulo 			wep->key[i] = os_malloc(ssid->wep_key_len[i]);
198*f05cddf9SRui Paulo 			if (wep->key[i] == NULL)
199*f05cddf9SRui Paulo 				return -1;
200*f05cddf9SRui Paulo 			os_memcpy(wep->key[i], ssid->wep_key[i],
201*f05cddf9SRui Paulo 				  ssid->wep_key_len[i]);
202*f05cddf9SRui Paulo 			wep->len[i] = ssid->wep_key_len[i];
203e28a4053SRui Paulo 		}
204*f05cddf9SRui Paulo 		wep->idx = ssid->wep_tx_keyidx;
205*f05cddf9SRui Paulo 		wep->keys_set = 1;
206*f05cddf9SRui Paulo 	}
207*f05cddf9SRui Paulo 
208*f05cddf9SRui Paulo 	if (ssid->ap_max_inactivity)
209*f05cddf9SRui Paulo 		bss->ap_max_inactivity = ssid->ap_max_inactivity;
210*f05cddf9SRui Paulo 
211*f05cddf9SRui Paulo 	if (ssid->dtim_period)
212*f05cddf9SRui Paulo 		bss->dtim_period = ssid->dtim_period;
213e28a4053SRui Paulo 
214e28a4053SRui Paulo 	/* Select group cipher based on the enabled pairwise cipher suites */
215e28a4053SRui Paulo 	pairwise = 0;
216e28a4053SRui Paulo 	if (bss->wpa & 1)
217e28a4053SRui Paulo 		pairwise |= bss->wpa_pairwise;
218e28a4053SRui Paulo 	if (bss->wpa & 2) {
219e28a4053SRui Paulo 		if (bss->rsn_pairwise == 0)
220e28a4053SRui Paulo 			bss->rsn_pairwise = bss->wpa_pairwise;
221e28a4053SRui Paulo 		pairwise |= bss->rsn_pairwise;
222e28a4053SRui Paulo 	}
223e28a4053SRui Paulo 	if (pairwise & WPA_CIPHER_TKIP)
224e28a4053SRui Paulo 		bss->wpa_group = WPA_CIPHER_TKIP;
225*f05cddf9SRui Paulo 	else if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) ==
226*f05cddf9SRui Paulo 		 WPA_CIPHER_GCMP)
227*f05cddf9SRui Paulo 		bss->wpa_group = WPA_CIPHER_GCMP;
228e28a4053SRui Paulo 	else
229e28a4053SRui Paulo 		bss->wpa_group = WPA_CIPHER_CCMP;
230e28a4053SRui Paulo 
231e28a4053SRui Paulo 	if (bss->wpa && bss->ieee802_1x)
232e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_WPA;
233e28a4053SRui Paulo 	else if (bss->wpa)
234e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_WPA_PSK;
235e28a4053SRui Paulo 	else if (bss->ieee802_1x) {
236*f05cddf9SRui Paulo 		int cipher = WPA_CIPHER_NONE;
237e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
238e28a4053SRui Paulo 		bss->ssid.wep.default_len = bss->default_wep_key_len;
239*f05cddf9SRui Paulo 		if (bss->default_wep_key_len)
240*f05cddf9SRui Paulo 			cipher = bss->default_wep_key_len >= 13 ?
241*f05cddf9SRui Paulo 				WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
242*f05cddf9SRui Paulo 		bss->wpa_group = cipher;
243*f05cddf9SRui Paulo 		bss->wpa_pairwise = cipher;
244*f05cddf9SRui Paulo 		bss->rsn_pairwise = cipher;
245*f05cddf9SRui Paulo 	} else if (bss->ssid.wep.keys_set) {
246*f05cddf9SRui Paulo 		int cipher = WPA_CIPHER_WEP40;
247*f05cddf9SRui Paulo 		if (bss->ssid.wep.len[0] >= 13)
248*f05cddf9SRui Paulo 			cipher = WPA_CIPHER_WEP104;
249e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_STATIC_WEP;
250*f05cddf9SRui Paulo 		bss->wpa_group = cipher;
251*f05cddf9SRui Paulo 		bss->wpa_pairwise = cipher;
252*f05cddf9SRui Paulo 		bss->rsn_pairwise = cipher;
253*f05cddf9SRui Paulo 	} else {
254e28a4053SRui Paulo 		bss->ssid.security_policy = SECURITY_PLAINTEXT;
255*f05cddf9SRui Paulo 		bss->wpa_group = WPA_CIPHER_NONE;
256*f05cddf9SRui Paulo 		bss->wpa_pairwise = WPA_CIPHER_NONE;
257*f05cddf9SRui Paulo 		bss->rsn_pairwise = WPA_CIPHER_NONE;
258*f05cddf9SRui Paulo 	}
259e28a4053SRui Paulo 
260e28a4053SRui Paulo #ifdef CONFIG_WPS
261e28a4053SRui Paulo 	/*
262*f05cddf9SRui Paulo 	 * Enable WPS by default for open and WPA/WPA2-Personal network, but
263*f05cddf9SRui Paulo 	 * require user interaction to actually use it. Only the internal
264*f05cddf9SRui Paulo 	 * Registrar is supported.
265e28a4053SRui Paulo 	 */
266*f05cddf9SRui Paulo 	if (bss->ssid.security_policy != SECURITY_WPA_PSK &&
267*f05cddf9SRui Paulo 	    bss->ssid.security_policy != SECURITY_PLAINTEXT)
268*f05cddf9SRui Paulo 		goto no_wps;
269*f05cddf9SRui Paulo #ifdef CONFIG_WPS2
270*f05cddf9SRui Paulo 	if (bss->ssid.security_policy == SECURITY_WPA_PSK &&
271*f05cddf9SRui Paulo 	    (!(pairwise & WPA_CIPHER_CCMP) || !(bss->wpa & 2)))
272*f05cddf9SRui Paulo 		goto no_wps; /* WPS2 does not allow WPA/TKIP-only
273*f05cddf9SRui Paulo 			      * configuration */
274*f05cddf9SRui Paulo #endif /* CONFIG_WPS2 */
275e28a4053SRui Paulo 	bss->eap_server = 1;
276*f05cddf9SRui Paulo 
277*f05cddf9SRui Paulo 	if (!ssid->ignore_broadcast_ssid)
278e28a4053SRui Paulo 		bss->wps_state = 2;
279*f05cddf9SRui Paulo 
280*f05cddf9SRui Paulo 	bss->ap_setup_locked = 2;
281e28a4053SRui Paulo 	if (wpa_s->conf->config_methods)
282e28a4053SRui Paulo 		bss->config_methods = os_strdup(wpa_s->conf->config_methods);
283*f05cddf9SRui Paulo 	os_memcpy(bss->device_type, wpa_s->conf->device_type,
284*f05cddf9SRui Paulo 		  WPS_DEV_TYPE_LEN);
285*f05cddf9SRui Paulo 	if (wpa_s->conf->device_name) {
286*f05cddf9SRui Paulo 		bss->device_name = os_strdup(wpa_s->conf->device_name);
287*f05cddf9SRui Paulo 		bss->friendly_name = os_strdup(wpa_s->conf->device_name);
288*f05cddf9SRui Paulo 	}
289*f05cddf9SRui Paulo 	if (wpa_s->conf->manufacturer)
290*f05cddf9SRui Paulo 		bss->manufacturer = os_strdup(wpa_s->conf->manufacturer);
291*f05cddf9SRui Paulo 	if (wpa_s->conf->model_name)
292*f05cddf9SRui Paulo 		bss->model_name = os_strdup(wpa_s->conf->model_name);
293*f05cddf9SRui Paulo 	if (wpa_s->conf->model_number)
294*f05cddf9SRui Paulo 		bss->model_number = os_strdup(wpa_s->conf->model_number);
295*f05cddf9SRui Paulo 	if (wpa_s->conf->serial_number)
296*f05cddf9SRui Paulo 		bss->serial_number = os_strdup(wpa_s->conf->serial_number);
297*f05cddf9SRui Paulo 	if (is_nil_uuid(wpa_s->conf->uuid))
298*f05cddf9SRui Paulo 		os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN);
299*f05cddf9SRui Paulo 	else
300*f05cddf9SRui Paulo 		os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
301*f05cddf9SRui Paulo 	os_memcpy(bss->os_version, wpa_s->conf->os_version, 4);
302*f05cddf9SRui Paulo 	bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1;
303*f05cddf9SRui Paulo no_wps:
304e28a4053SRui Paulo #endif /* CONFIG_WPS */
305e28a4053SRui Paulo 
306*f05cddf9SRui Paulo 	if (wpa_s->max_stations &&
307*f05cddf9SRui Paulo 	    wpa_s->max_stations < wpa_s->conf->max_num_sta)
308*f05cddf9SRui Paulo 		bss->max_num_sta = wpa_s->max_stations;
309*f05cddf9SRui Paulo 	else
310*f05cddf9SRui Paulo 		bss->max_num_sta = wpa_s->conf->max_num_sta;
311*f05cddf9SRui Paulo 
312*f05cddf9SRui Paulo 	bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack;
313*f05cddf9SRui Paulo 
314e28a4053SRui Paulo 	return 0;
315e28a4053SRui Paulo }
316e28a4053SRui Paulo 
317e28a4053SRui Paulo 
318e28a4053SRui Paulo static void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
319e28a4053SRui Paulo {
320*f05cddf9SRui Paulo #ifdef CONFIG_P2P
321*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
322*f05cddf9SRui Paulo 	const struct ieee80211_mgmt *mgmt;
323*f05cddf9SRui Paulo 	size_t hdr_len;
324*f05cddf9SRui Paulo 
325*f05cddf9SRui Paulo 	mgmt = (const struct ieee80211_mgmt *) buf;
326*f05cddf9SRui Paulo 	hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
327*f05cddf9SRui Paulo 	if (hdr_len > len)
328*f05cddf9SRui Paulo 		return;
329*f05cddf9SRui Paulo 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
330*f05cddf9SRui Paulo 			   mgmt->u.action.category,
331*f05cddf9SRui Paulo 			   &mgmt->u.action.u.vs_public_action.action,
332*f05cddf9SRui Paulo 			   len - hdr_len, freq);
333*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
334e28a4053SRui Paulo }
335e28a4053SRui Paulo 
336e28a4053SRui Paulo 
337*f05cddf9SRui Paulo static void ap_wps_event_cb(void *ctx, enum wps_event event,
338*f05cddf9SRui Paulo 			    union wps_event_data *data)
339e28a4053SRui Paulo {
340*f05cddf9SRui Paulo #ifdef CONFIG_P2P
341*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
342*f05cddf9SRui Paulo 
343*f05cddf9SRui Paulo 	if (event == WPS_EV_FAIL) {
344*f05cddf9SRui Paulo 		struct wps_event_fail *fail = &data->fail;
345*f05cddf9SRui Paulo 
346*f05cddf9SRui Paulo 		if (wpa_s->parent && wpa_s->parent != wpa_s &&
347*f05cddf9SRui Paulo 		    wpa_s == wpa_s->global->p2p_group_formation) {
348*f05cddf9SRui Paulo 			/*
349*f05cddf9SRui Paulo 			 * src/ap/wps_hostapd.c has already sent this on the
350*f05cddf9SRui Paulo 			 * main interface, so only send on the parent interface
351*f05cddf9SRui Paulo 			 * here if needed.
352*f05cddf9SRui Paulo 			 */
353*f05cddf9SRui Paulo 			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
354*f05cddf9SRui Paulo 				"msg=%d config_error=%d",
355*f05cddf9SRui Paulo 				fail->msg, fail->config_error);
356*f05cddf9SRui Paulo 		}
357*f05cddf9SRui Paulo 		wpas_p2p_wps_failed(wpa_s, fail);
358*f05cddf9SRui Paulo 	}
359*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
360*f05cddf9SRui Paulo }
361*f05cddf9SRui Paulo 
362*f05cddf9SRui Paulo 
363*f05cddf9SRui Paulo static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
364*f05cddf9SRui Paulo 				 int authorized, const u8 *p2p_dev_addr)
365*f05cddf9SRui Paulo {
366*f05cddf9SRui Paulo 	wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr);
367*f05cddf9SRui Paulo }
368*f05cddf9SRui Paulo 
369*f05cddf9SRui Paulo 
370*f05cddf9SRui Paulo static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
371*f05cddf9SRui Paulo {
372*f05cddf9SRui Paulo #ifdef CONFIG_P2P
373*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
374*f05cddf9SRui Paulo 	const struct ieee80211_mgmt *mgmt;
375*f05cddf9SRui Paulo 	size_t hdr_len;
376*f05cddf9SRui Paulo 
377*f05cddf9SRui Paulo 	mgmt = (const struct ieee80211_mgmt *) buf;
378*f05cddf9SRui Paulo 	hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
379*f05cddf9SRui Paulo 	if (hdr_len > len)
380*f05cddf9SRui Paulo 		return -1;
381*f05cddf9SRui Paulo 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
382*f05cddf9SRui Paulo 			   mgmt->u.action.category,
383*f05cddf9SRui Paulo 			   &mgmt->u.action.u.vs_public_action.action,
384*f05cddf9SRui Paulo 			   len - hdr_len, freq);
385*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
386e28a4053SRui Paulo 	return 0;
387e28a4053SRui Paulo }
388e28a4053SRui Paulo 
389e28a4053SRui Paulo 
390*f05cddf9SRui Paulo static int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da,
391*f05cddf9SRui Paulo 			   const u8 *bssid, const u8 *ie, size_t ie_len,
392*f05cddf9SRui Paulo 			   int ssi_signal)
393*f05cddf9SRui Paulo {
394*f05cddf9SRui Paulo #ifdef CONFIG_P2P
395*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
396*f05cddf9SRui Paulo 	return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len,
397*f05cddf9SRui Paulo 				     ssi_signal);
398*f05cddf9SRui Paulo #else /* CONFIG_P2P */
399*f05cddf9SRui Paulo 	return 0;
400*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
401*f05cddf9SRui Paulo }
402*f05cddf9SRui Paulo 
403*f05cddf9SRui Paulo 
404e28a4053SRui Paulo static void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
405e28a4053SRui Paulo 				  const u8 *uuid_e)
406e28a4053SRui Paulo {
407*f05cddf9SRui Paulo #ifdef CONFIG_P2P
408*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
409*f05cddf9SRui Paulo 	wpas_p2p_wps_success(wpa_s, mac_addr, 1);
410*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
411*f05cddf9SRui Paulo }
412*f05cddf9SRui Paulo 
413*f05cddf9SRui Paulo 
414*f05cddf9SRui Paulo static void wpas_ap_configured_cb(void *ctx)
415*f05cddf9SRui Paulo {
416*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
417*f05cddf9SRui Paulo 
418*f05cddf9SRui Paulo 	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
419*f05cddf9SRui Paulo 
420*f05cddf9SRui Paulo 	if (wpa_s->ap_configured_cb)
421*f05cddf9SRui Paulo 		wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
422*f05cddf9SRui Paulo 					wpa_s->ap_configured_cb_data);
423e28a4053SRui Paulo }
424e28a4053SRui Paulo 
425e28a4053SRui Paulo 
426e28a4053SRui Paulo int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
427e28a4053SRui Paulo 			     struct wpa_ssid *ssid)
428e28a4053SRui Paulo {
429e28a4053SRui Paulo 	struct wpa_driver_associate_params params;
430e28a4053SRui Paulo 	struct hostapd_iface *hapd_iface;
431e28a4053SRui Paulo 	struct hostapd_config *conf;
432e28a4053SRui Paulo 	size_t i;
433e28a4053SRui Paulo 
434e28a4053SRui Paulo 	if (ssid->ssid == NULL || ssid->ssid_len == 0) {
435e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
436e28a4053SRui Paulo 		return -1;
437e28a4053SRui Paulo 	}
438e28a4053SRui Paulo 
439e28a4053SRui Paulo 	wpa_supplicant_ap_deinit(wpa_s);
440e28a4053SRui Paulo 
441e28a4053SRui Paulo 	wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')",
442e28a4053SRui Paulo 		   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
443e28a4053SRui Paulo 
444e28a4053SRui Paulo 	os_memset(&params, 0, sizeof(params));
445e28a4053SRui Paulo 	params.ssid = ssid->ssid;
446e28a4053SRui Paulo 	params.ssid_len = ssid->ssid_len;
447e28a4053SRui Paulo 	switch (ssid->mode) {
448e28a4053SRui Paulo 	case WPAS_MODE_INFRA:
449e28a4053SRui Paulo 		params.mode = IEEE80211_MODE_INFRA;
450e28a4053SRui Paulo 		break;
451e28a4053SRui Paulo 	case WPAS_MODE_IBSS:
452e28a4053SRui Paulo 		params.mode = IEEE80211_MODE_IBSS;
453e28a4053SRui Paulo 		break;
454e28a4053SRui Paulo 	case WPAS_MODE_AP:
455*f05cddf9SRui Paulo 	case WPAS_MODE_P2P_GO:
456*f05cddf9SRui Paulo 	case WPAS_MODE_P2P_GROUP_FORMATION:
457e28a4053SRui Paulo 		params.mode = IEEE80211_MODE_AP;
458e28a4053SRui Paulo 		break;
459e28a4053SRui Paulo 	}
460e28a4053SRui Paulo 	params.freq = ssid->frequency;
461e28a4053SRui Paulo 
462*f05cddf9SRui Paulo 	params.wpa_proto = ssid->proto;
463e28a4053SRui Paulo 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
464e28a4053SRui Paulo 		wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
465e28a4053SRui Paulo 	else
466e28a4053SRui Paulo 		wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
467e28a4053SRui Paulo 	params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
468e28a4053SRui Paulo 
469e28a4053SRui Paulo 	if (ssid->pairwise_cipher & WPA_CIPHER_CCMP)
470e28a4053SRui Paulo 		wpa_s->pairwise_cipher = WPA_CIPHER_CCMP;
471*f05cddf9SRui Paulo 	else if (ssid->pairwise_cipher & WPA_CIPHER_GCMP)
472*f05cddf9SRui Paulo 		wpa_s->pairwise_cipher = WPA_CIPHER_GCMP;
473e28a4053SRui Paulo 	else if (ssid->pairwise_cipher & WPA_CIPHER_TKIP)
474e28a4053SRui Paulo 		wpa_s->pairwise_cipher = WPA_CIPHER_TKIP;
475e28a4053SRui Paulo 	else if (ssid->pairwise_cipher & WPA_CIPHER_NONE)
476e28a4053SRui Paulo 		wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
477e28a4053SRui Paulo 	else {
478e28a4053SRui Paulo 		wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise "
479e28a4053SRui Paulo 			   "cipher.");
480e28a4053SRui Paulo 		return -1;
481e28a4053SRui Paulo 	}
482e28a4053SRui Paulo 	params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher);
483e28a4053SRui Paulo 	params.group_suite = params.pairwise_suite;
484e28a4053SRui Paulo 
485*f05cddf9SRui Paulo #ifdef CONFIG_P2P
486*f05cddf9SRui Paulo 	if (ssid->mode == WPAS_MODE_P2P_GO ||
487*f05cddf9SRui Paulo 	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
488*f05cddf9SRui Paulo 		params.p2p = 1;
489*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
490*f05cddf9SRui Paulo 
491*f05cddf9SRui Paulo 	if (wpa_s->parent->set_ap_uapsd)
492*f05cddf9SRui Paulo 		params.uapsd = wpa_s->parent->ap_uapsd;
493*f05cddf9SRui Paulo 	else
494*f05cddf9SRui Paulo 		params.uapsd = -1;
495*f05cddf9SRui Paulo 
496e28a4053SRui Paulo 	if (wpa_drv_associate(wpa_s, &params) < 0) {
497e28a4053SRui Paulo 		wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
498e28a4053SRui Paulo 		return -1;
499e28a4053SRui Paulo 	}
500e28a4053SRui Paulo 
501e28a4053SRui Paulo 	wpa_s->ap_iface = hapd_iface = os_zalloc(sizeof(*wpa_s->ap_iface));
502e28a4053SRui Paulo 	if (hapd_iface == NULL)
503e28a4053SRui Paulo 		return -1;
504e28a4053SRui Paulo 	hapd_iface->owner = wpa_s;
505*f05cddf9SRui Paulo 	hapd_iface->drv_flags = wpa_s->drv_flags;
506*f05cddf9SRui Paulo 	hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
507e28a4053SRui Paulo 
508e28a4053SRui Paulo 	wpa_s->ap_iface->conf = conf = hostapd_config_defaults();
509e28a4053SRui Paulo 	if (conf == NULL) {
510e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
511e28a4053SRui Paulo 		return -1;
512e28a4053SRui Paulo 	}
513e28a4053SRui Paulo 
514*f05cddf9SRui Paulo 	os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params,
515*f05cddf9SRui Paulo 		  wpa_s->conf->wmm_ac_params,
516*f05cddf9SRui Paulo 		  sizeof(wpa_s->conf->wmm_ac_params));
517*f05cddf9SRui Paulo 
518*f05cddf9SRui Paulo 	if (params.uapsd > 0) {
519*f05cddf9SRui Paulo 		conf->bss->wmm_enabled = 1;
520*f05cddf9SRui Paulo 		conf->bss->wmm_uapsd = 1;
521*f05cddf9SRui Paulo 	}
522*f05cddf9SRui Paulo 
523e28a4053SRui Paulo 	if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) {
524e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Failed to create AP configuration");
525e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
526e28a4053SRui Paulo 		return -1;
527e28a4053SRui Paulo 	}
528e28a4053SRui Paulo 
529*f05cddf9SRui Paulo #ifdef CONFIG_P2P
530*f05cddf9SRui Paulo 	if (ssid->mode == WPAS_MODE_P2P_GO)
531*f05cddf9SRui Paulo 		conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER;
532*f05cddf9SRui Paulo 	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
533*f05cddf9SRui Paulo 		conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER |
534*f05cddf9SRui Paulo 			P2P_GROUP_FORMATION;
535*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
536*f05cddf9SRui Paulo 
537e28a4053SRui Paulo 	hapd_iface->num_bss = conf->num_bss;
538*f05cddf9SRui Paulo 	hapd_iface->bss = os_calloc(conf->num_bss,
539e28a4053SRui Paulo 				    sizeof(struct hostapd_data *));
540e28a4053SRui Paulo 	if (hapd_iface->bss == NULL) {
541e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
542e28a4053SRui Paulo 		return -1;
543e28a4053SRui Paulo 	}
544e28a4053SRui Paulo 
545e28a4053SRui Paulo 	for (i = 0; i < conf->num_bss; i++) {
546e28a4053SRui Paulo 		hapd_iface->bss[i] =
547e28a4053SRui Paulo 			hostapd_alloc_bss_data(hapd_iface, conf,
548e28a4053SRui Paulo 					       &conf->bss[i]);
549e28a4053SRui Paulo 		if (hapd_iface->bss[i] == NULL) {
550e28a4053SRui Paulo 			wpa_supplicant_ap_deinit(wpa_s);
551e28a4053SRui Paulo 			return -1;
552e28a4053SRui Paulo 		}
553e28a4053SRui Paulo 
554e28a4053SRui Paulo 		hapd_iface->bss[i]->msg_ctx = wpa_s;
555*f05cddf9SRui Paulo 		hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent;
556e28a4053SRui Paulo 		hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
557e28a4053SRui Paulo 		hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
558*f05cddf9SRui Paulo 		hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
559*f05cddf9SRui Paulo 		hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s;
560e28a4053SRui Paulo 		hostapd_register_probereq_cb(hapd_iface->bss[i],
561e28a4053SRui Paulo 					     ap_probe_req_rx, wpa_s);
562e28a4053SRui Paulo 		hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb;
563e28a4053SRui Paulo 		hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s;
564*f05cddf9SRui Paulo 		hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb;
565*f05cddf9SRui Paulo 		hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s;
566*f05cddf9SRui Paulo 		hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb;
567*f05cddf9SRui Paulo 		hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s;
568*f05cddf9SRui Paulo #ifdef CONFIG_P2P
569*f05cddf9SRui Paulo 		hapd_iface->bss[i]->p2p = wpa_s->global->p2p;
570*f05cddf9SRui Paulo 		hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s,
571*f05cddf9SRui Paulo 								    ssid);
572*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
573*f05cddf9SRui Paulo 		hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb;
574*f05cddf9SRui Paulo 		hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s;
575e28a4053SRui Paulo 	}
576e28a4053SRui Paulo 
577e28a4053SRui Paulo 	os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
578e28a4053SRui Paulo 	hapd_iface->bss[0]->driver = wpa_s->driver;
579e28a4053SRui Paulo 	hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv;
580e28a4053SRui Paulo 
581*f05cddf9SRui Paulo 	wpa_s->current_ssid = ssid;
582*f05cddf9SRui Paulo 	os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
583*f05cddf9SRui Paulo 	wpa_s->assoc_freq = ssid->frequency;
584*f05cddf9SRui Paulo 
585e28a4053SRui Paulo 	if (hostapd_setup_interface(wpa_s->ap_iface)) {
586e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Failed to initialize AP interface");
587e28a4053SRui Paulo 		wpa_supplicant_ap_deinit(wpa_s);
588e28a4053SRui Paulo 		return -1;
589e28a4053SRui Paulo 	}
590e28a4053SRui Paulo 
591e28a4053SRui Paulo 	return 0;
592e28a4053SRui Paulo }
593e28a4053SRui Paulo 
594e28a4053SRui Paulo 
595e28a4053SRui Paulo void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s)
596e28a4053SRui Paulo {
597*f05cddf9SRui Paulo #ifdef CONFIG_WPS
598*f05cddf9SRui Paulo 	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
599*f05cddf9SRui Paulo #endif /* CONFIG_WPS */
600*f05cddf9SRui Paulo 
601e28a4053SRui Paulo 	if (wpa_s->ap_iface == NULL)
602e28a4053SRui Paulo 		return;
603e28a4053SRui Paulo 
604e28a4053SRui Paulo 	wpa_s->current_ssid = NULL;
605*f05cddf9SRui Paulo 	wpa_s->assoc_freq = 0;
606*f05cddf9SRui Paulo #ifdef CONFIG_P2P
607*f05cddf9SRui Paulo 	if (wpa_s->ap_iface->bss)
608*f05cddf9SRui Paulo 		wpa_s->ap_iface->bss[0]->p2p_group = NULL;
609*f05cddf9SRui Paulo 	wpas_p2p_group_deinit(wpa_s);
610*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
611e28a4053SRui Paulo 	hostapd_interface_deinit(wpa_s->ap_iface);
612e28a4053SRui Paulo 	hostapd_interface_free(wpa_s->ap_iface);
613e28a4053SRui Paulo 	wpa_s->ap_iface = NULL;
614e28a4053SRui Paulo 	wpa_drv_deinit_ap(wpa_s);
615e28a4053SRui Paulo }
616e28a4053SRui Paulo 
617e28a4053SRui Paulo 
618e28a4053SRui Paulo void ap_tx_status(void *ctx, const u8 *addr,
619e28a4053SRui Paulo 		  const u8 *buf, size_t len, int ack)
620e28a4053SRui Paulo {
621e28a4053SRui Paulo #ifdef NEED_AP_MLME
622e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
623e28a4053SRui Paulo 	hostapd_tx_status(wpa_s->ap_iface->bss[0], addr, buf, len, ack);
624e28a4053SRui Paulo #endif /* NEED_AP_MLME */
625e28a4053SRui Paulo }
626e28a4053SRui Paulo 
627e28a4053SRui Paulo 
628*f05cddf9SRui Paulo void ap_eapol_tx_status(void *ctx, const u8 *dst,
629*f05cddf9SRui Paulo 			const u8 *data, size_t len, int ack)
630e28a4053SRui Paulo {
631e28a4053SRui Paulo #ifdef NEED_AP_MLME
632e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
633*f05cddf9SRui Paulo 	hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
634*f05cddf9SRui Paulo #endif /* NEED_AP_MLME */
635*f05cddf9SRui Paulo }
636*f05cddf9SRui Paulo 
637*f05cddf9SRui Paulo 
638*f05cddf9SRui Paulo void ap_client_poll_ok(void *ctx, const u8 *addr)
639*f05cddf9SRui Paulo {
640*f05cddf9SRui Paulo #ifdef NEED_AP_MLME
641*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
642*f05cddf9SRui Paulo 	if (wpa_s->ap_iface)
643*f05cddf9SRui Paulo 		hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr);
644*f05cddf9SRui Paulo #endif /* NEED_AP_MLME */
645*f05cddf9SRui Paulo }
646*f05cddf9SRui Paulo 
647*f05cddf9SRui Paulo 
648*f05cddf9SRui Paulo void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds)
649*f05cddf9SRui Paulo {
650*f05cddf9SRui Paulo #ifdef NEED_AP_MLME
651*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
652*f05cddf9SRui Paulo 	ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds);
653e28a4053SRui Paulo #endif /* NEED_AP_MLME */
654e28a4053SRui Paulo }
655e28a4053SRui Paulo 
656e28a4053SRui Paulo 
657e28a4053SRui Paulo void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt)
658e28a4053SRui Paulo {
659e28a4053SRui Paulo #ifdef NEED_AP_MLME
660e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
661e28a4053SRui Paulo 	struct hostapd_frame_info fi;
662e28a4053SRui Paulo 	os_memset(&fi, 0, sizeof(fi));
663e28a4053SRui Paulo 	fi.datarate = rx_mgmt->datarate;
664e28a4053SRui Paulo 	fi.ssi_signal = rx_mgmt->ssi_signal;
665e28a4053SRui Paulo 	ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame,
666e28a4053SRui Paulo 			rx_mgmt->frame_len, &fi);
667e28a4053SRui Paulo #endif /* NEED_AP_MLME */
668e28a4053SRui Paulo }
669e28a4053SRui Paulo 
670e28a4053SRui Paulo 
671e28a4053SRui Paulo void ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok)
672e28a4053SRui Paulo {
673e28a4053SRui Paulo #ifdef NEED_AP_MLME
674e28a4053SRui Paulo 	struct wpa_supplicant *wpa_s = ctx;
675e28a4053SRui Paulo 	ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok);
676e28a4053SRui Paulo #endif /* NEED_AP_MLME */
677e28a4053SRui Paulo }
678e28a4053SRui Paulo 
679e28a4053SRui Paulo 
680e28a4053SRui Paulo void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
681e28a4053SRui Paulo 				const u8 *src_addr, const u8 *buf, size_t len)
682e28a4053SRui Paulo {
683e28a4053SRui Paulo 	ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len);
684e28a4053SRui Paulo }
685e28a4053SRui Paulo 
686e28a4053SRui Paulo 
687e28a4053SRui Paulo #ifdef CONFIG_WPS
688e28a4053SRui Paulo 
689*f05cddf9SRui Paulo int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
690*f05cddf9SRui Paulo 			      const u8 *p2p_dev_addr)
691e28a4053SRui Paulo {
692e28a4053SRui Paulo 	if (!wpa_s->ap_iface)
693e28a4053SRui Paulo 		return -1;
694*f05cddf9SRui Paulo 	return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0],
695*f05cddf9SRui Paulo 					 p2p_dev_addr);
696*f05cddf9SRui Paulo }
697*f05cddf9SRui Paulo 
698*f05cddf9SRui Paulo 
699*f05cddf9SRui Paulo int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s)
700*f05cddf9SRui Paulo {
701*f05cddf9SRui Paulo 	struct wps_registrar *reg;
702*f05cddf9SRui Paulo 	int reg_sel = 0, wps_sta = 0;
703*f05cddf9SRui Paulo 
704*f05cddf9SRui Paulo 	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps)
705*f05cddf9SRui Paulo 		return -1;
706*f05cddf9SRui Paulo 
707*f05cddf9SRui Paulo 	reg = wpa_s->ap_iface->bss[0]->wps->registrar;
708*f05cddf9SRui Paulo 	reg_sel = wps_registrar_wps_cancel(reg);
709*f05cddf9SRui Paulo 	wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0],
710*f05cddf9SRui Paulo 				  ap_sta_wps_cancel, NULL);
711*f05cddf9SRui Paulo 
712*f05cddf9SRui Paulo 	if (!reg_sel && !wps_sta) {
713*f05cddf9SRui Paulo 		wpa_printf(MSG_DEBUG, "No WPS operation in progress at this "
714*f05cddf9SRui Paulo 			   "time");
715*f05cddf9SRui Paulo 		return -1;
716*f05cddf9SRui Paulo 	}
717*f05cddf9SRui Paulo 
718*f05cddf9SRui Paulo 	/*
719*f05cddf9SRui Paulo 	 * There are 2 cases to return wps cancel as success:
720*f05cddf9SRui Paulo 	 * 1. When wps cancel was initiated but no connection has been
721*f05cddf9SRui Paulo 	 *    established with client yet.
722*f05cddf9SRui Paulo 	 * 2. Client is in the middle of exchanging WPS messages.
723*f05cddf9SRui Paulo 	 */
724*f05cddf9SRui Paulo 
725*f05cddf9SRui Paulo 	return 0;
726e28a4053SRui Paulo }
727e28a4053SRui Paulo 
728e28a4053SRui Paulo 
729e28a4053SRui Paulo int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
730*f05cddf9SRui Paulo 			      const char *pin, char *buf, size_t buflen,
731*f05cddf9SRui Paulo 			      int timeout)
732e28a4053SRui Paulo {
733e28a4053SRui Paulo 	int ret, ret_len = 0;
734e28a4053SRui Paulo 
735e28a4053SRui Paulo 	if (!wpa_s->ap_iface)
736e28a4053SRui Paulo 		return -1;
737e28a4053SRui Paulo 
738e28a4053SRui Paulo 	if (pin == NULL) {
739e28a4053SRui Paulo 		unsigned int rpin = wps_generate_pin();
740*f05cddf9SRui Paulo 		ret_len = os_snprintf(buf, buflen, "%08d", rpin);
741e28a4053SRui Paulo 		pin = buf;
742*f05cddf9SRui Paulo 	} else
743*f05cddf9SRui Paulo 		ret_len = os_snprintf(buf, buflen, "%s", pin);
744e28a4053SRui Paulo 
745*f05cddf9SRui Paulo 	ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin,
746*f05cddf9SRui Paulo 				  timeout);
747e28a4053SRui Paulo 	if (ret)
748e28a4053SRui Paulo 		return -1;
749e28a4053SRui Paulo 	return ret_len;
750e28a4053SRui Paulo }
751e28a4053SRui Paulo 
752*f05cddf9SRui Paulo 
753*f05cddf9SRui Paulo static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
754*f05cddf9SRui Paulo {
755*f05cddf9SRui Paulo 	struct wpa_supplicant *wpa_s = eloop_data;
756*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
757*f05cddf9SRui Paulo 	wpas_wps_ap_pin_disable(wpa_s);
758*f05cddf9SRui Paulo }
759*f05cddf9SRui Paulo 
760*f05cddf9SRui Paulo 
761*f05cddf9SRui Paulo static void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout)
762*f05cddf9SRui Paulo {
763*f05cddf9SRui Paulo 	struct hostapd_data *hapd;
764*f05cddf9SRui Paulo 
765*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
766*f05cddf9SRui Paulo 		return;
767*f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
768*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
769*f05cddf9SRui Paulo 	hapd->ap_pin_failures = 0;
770*f05cddf9SRui Paulo 	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
771*f05cddf9SRui Paulo 	if (timeout > 0)
772*f05cddf9SRui Paulo 		eloop_register_timeout(timeout, 0,
773*f05cddf9SRui Paulo 				       wpas_wps_ap_pin_timeout, wpa_s, NULL);
774*f05cddf9SRui Paulo }
775*f05cddf9SRui Paulo 
776*f05cddf9SRui Paulo 
777*f05cddf9SRui Paulo void wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s)
778*f05cddf9SRui Paulo {
779*f05cddf9SRui Paulo 	struct hostapd_data *hapd;
780*f05cddf9SRui Paulo 
781*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
782*f05cddf9SRui Paulo 		return;
783*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
784*f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
785*f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
786*f05cddf9SRui Paulo 	hapd->conf->ap_pin = NULL;
787*f05cddf9SRui Paulo 	eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
788*f05cddf9SRui Paulo }
789*f05cddf9SRui Paulo 
790*f05cddf9SRui Paulo 
791*f05cddf9SRui Paulo const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
792*f05cddf9SRui Paulo {
793*f05cddf9SRui Paulo 	struct hostapd_data *hapd;
794*f05cddf9SRui Paulo 	unsigned int pin;
795*f05cddf9SRui Paulo 	char pin_txt[9];
796*f05cddf9SRui Paulo 
797*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
798*f05cddf9SRui Paulo 		return NULL;
799*f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
800*f05cddf9SRui Paulo 	pin = wps_generate_pin();
801*f05cddf9SRui Paulo 	os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
802*f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
803*f05cddf9SRui Paulo 	hapd->conf->ap_pin = os_strdup(pin_txt);
804*f05cddf9SRui Paulo 	if (hapd->conf->ap_pin == NULL)
805*f05cddf9SRui Paulo 		return NULL;
806*f05cddf9SRui Paulo 	wpas_wps_ap_pin_enable(wpa_s, timeout);
807*f05cddf9SRui Paulo 
808*f05cddf9SRui Paulo 	return hapd->conf->ap_pin;
809*f05cddf9SRui Paulo }
810*f05cddf9SRui Paulo 
811*f05cddf9SRui Paulo 
812*f05cddf9SRui Paulo const char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s)
813*f05cddf9SRui Paulo {
814*f05cddf9SRui Paulo 	struct hostapd_data *hapd;
815*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
816*f05cddf9SRui Paulo 		return NULL;
817*f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
818*f05cddf9SRui Paulo 	return hapd->conf->ap_pin;
819*f05cddf9SRui Paulo }
820*f05cddf9SRui Paulo 
821*f05cddf9SRui Paulo 
822*f05cddf9SRui Paulo int wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin,
823*f05cddf9SRui Paulo 			int timeout)
824*f05cddf9SRui Paulo {
825*f05cddf9SRui Paulo 	struct hostapd_data *hapd;
826*f05cddf9SRui Paulo 	char pin_txt[9];
827*f05cddf9SRui Paulo 	int ret;
828*f05cddf9SRui Paulo 
829*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
830*f05cddf9SRui Paulo 		return -1;
831*f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
832*f05cddf9SRui Paulo 	ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin);
833*f05cddf9SRui Paulo 	if (ret < 0 || ret >= (int) sizeof(pin_txt))
834*f05cddf9SRui Paulo 		return -1;
835*f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
836*f05cddf9SRui Paulo 	hapd->conf->ap_pin = os_strdup(pin_txt);
837*f05cddf9SRui Paulo 	if (hapd->conf->ap_pin == NULL)
838*f05cddf9SRui Paulo 		return -1;
839*f05cddf9SRui Paulo 	wpas_wps_ap_pin_enable(wpa_s, timeout);
840*f05cddf9SRui Paulo 
841*f05cddf9SRui Paulo 	return 0;
842*f05cddf9SRui Paulo }
843*f05cddf9SRui Paulo 
844*f05cddf9SRui Paulo 
845*f05cddf9SRui Paulo void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s)
846*f05cddf9SRui Paulo {
847*f05cddf9SRui Paulo 	struct hostapd_data *hapd;
848*f05cddf9SRui Paulo 
849*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
850*f05cddf9SRui Paulo 		return;
851*f05cddf9SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
852*f05cddf9SRui Paulo 
853*f05cddf9SRui Paulo 	/*
854*f05cddf9SRui Paulo 	 * Registrar failed to prove its knowledge of the AP PIN. Disable AP
855*f05cddf9SRui Paulo 	 * PIN if this happens multiple times to slow down brute force attacks.
856*f05cddf9SRui Paulo 	 */
857*f05cddf9SRui Paulo 	hapd->ap_pin_failures++;
858*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
859*f05cddf9SRui Paulo 		   hapd->ap_pin_failures);
860*f05cddf9SRui Paulo 	if (hapd->ap_pin_failures < 3)
861*f05cddf9SRui Paulo 		return;
862*f05cddf9SRui Paulo 
863*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN");
864*f05cddf9SRui Paulo 	hapd->ap_pin_failures = 0;
865*f05cddf9SRui Paulo 	os_free(hapd->conf->ap_pin);
866*f05cddf9SRui Paulo 	hapd->conf->ap_pin = NULL;
867*f05cddf9SRui Paulo }
868*f05cddf9SRui Paulo 
869e28a4053SRui Paulo #endif /* CONFIG_WPS */
870e28a4053SRui Paulo 
871e28a4053SRui Paulo 
872e28a4053SRui Paulo #ifdef CONFIG_CTRL_IFACE
873e28a4053SRui Paulo 
874e28a4053SRui Paulo int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
875e28a4053SRui Paulo 			    char *buf, size_t buflen)
876e28a4053SRui Paulo {
877e28a4053SRui Paulo 	if (wpa_s->ap_iface == NULL)
878e28a4053SRui Paulo 		return -1;
879e28a4053SRui Paulo 	return hostapd_ctrl_iface_sta_first(wpa_s->ap_iface->bss[0],
880e28a4053SRui Paulo 					    buf, buflen);
881e28a4053SRui Paulo }
882e28a4053SRui Paulo 
883e28a4053SRui Paulo 
884e28a4053SRui Paulo int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
885e28a4053SRui Paulo 		      char *buf, size_t buflen)
886e28a4053SRui Paulo {
887e28a4053SRui Paulo 	if (wpa_s->ap_iface == NULL)
888e28a4053SRui Paulo 		return -1;
889e28a4053SRui Paulo 	return hostapd_ctrl_iface_sta(wpa_s->ap_iface->bss[0], txtaddr,
890e28a4053SRui Paulo 				      buf, buflen);
891e28a4053SRui Paulo }
892e28a4053SRui Paulo 
893e28a4053SRui Paulo 
894e28a4053SRui Paulo int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
895e28a4053SRui Paulo 			   char *buf, size_t buflen)
896e28a4053SRui Paulo {
897e28a4053SRui Paulo 	if (wpa_s->ap_iface == NULL)
898e28a4053SRui Paulo 		return -1;
899e28a4053SRui Paulo 	return hostapd_ctrl_iface_sta_next(wpa_s->ap_iface->bss[0], txtaddr,
900e28a4053SRui Paulo 					   buf, buflen);
901e28a4053SRui Paulo }
902e28a4053SRui Paulo 
903e28a4053SRui Paulo 
904*f05cddf9SRui Paulo int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s,
905*f05cddf9SRui Paulo 				   const char *txtaddr)
906*f05cddf9SRui Paulo {
907*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
908*f05cddf9SRui Paulo 		return -1;
909*f05cddf9SRui Paulo 	return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0],
910*f05cddf9SRui Paulo 					       txtaddr);
911*f05cddf9SRui Paulo }
912*f05cddf9SRui Paulo 
913*f05cddf9SRui Paulo 
914*f05cddf9SRui Paulo int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s,
915*f05cddf9SRui Paulo 				     const char *txtaddr)
916*f05cddf9SRui Paulo {
917*f05cddf9SRui Paulo 	if (wpa_s->ap_iface == NULL)
918*f05cddf9SRui Paulo 		return -1;
919*f05cddf9SRui Paulo 	return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0],
920*f05cddf9SRui Paulo 						 txtaddr);
921*f05cddf9SRui Paulo }
922*f05cddf9SRui Paulo 
923*f05cddf9SRui Paulo 
924e28a4053SRui Paulo int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
925e28a4053SRui Paulo 				 size_t buflen, int verbose)
926e28a4053SRui Paulo {
927e28a4053SRui Paulo 	char *pos = buf, *end = buf + buflen;
928e28a4053SRui Paulo 	int ret;
929e28a4053SRui Paulo 	struct hostapd_bss_config *conf;
930e28a4053SRui Paulo 
931e28a4053SRui Paulo 	if (wpa_s->ap_iface == NULL)
932e28a4053SRui Paulo 		return -1;
933e28a4053SRui Paulo 
934e28a4053SRui Paulo 	conf = wpa_s->ap_iface->bss[0]->conf;
935e28a4053SRui Paulo 	if (conf->wpa == 0)
936e28a4053SRui Paulo 		return 0;
937e28a4053SRui Paulo 
938e28a4053SRui Paulo 	ret = os_snprintf(pos, end - pos,
939e28a4053SRui Paulo 			  "pairwise_cipher=%s\n"
940e28a4053SRui Paulo 			  "group_cipher=%s\n"
941e28a4053SRui Paulo 			  "key_mgmt=%s\n",
942e28a4053SRui Paulo 			  wpa_cipher_txt(conf->rsn_pairwise),
943e28a4053SRui Paulo 			  wpa_cipher_txt(conf->wpa_group),
944e28a4053SRui Paulo 			  wpa_key_mgmt_txt(conf->wpa_key_mgmt,
945e28a4053SRui Paulo 					   conf->wpa));
946e28a4053SRui Paulo 	if (ret < 0 || ret >= end - pos)
947e28a4053SRui Paulo 		return pos - buf;
948e28a4053SRui Paulo 	pos += ret;
949e28a4053SRui Paulo 	return pos - buf;
950e28a4053SRui Paulo }
951e28a4053SRui Paulo 
952e28a4053SRui Paulo #endif /* CONFIG_CTRL_IFACE */
953e28a4053SRui Paulo 
954e28a4053SRui Paulo 
955*f05cddf9SRui Paulo int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
956*f05cddf9SRui Paulo {
957*f05cddf9SRui Paulo 	struct hostapd_iface *iface = wpa_s->ap_iface;
958*f05cddf9SRui Paulo 	struct wpa_ssid *ssid = wpa_s->current_ssid;
959*f05cddf9SRui Paulo 	struct hostapd_data *hapd;
960*f05cddf9SRui Paulo 
961*f05cddf9SRui Paulo 	if (ssid == NULL || wpa_s->ap_iface == NULL ||
962*f05cddf9SRui Paulo 	    ssid->mode == WPAS_MODE_INFRA ||
963*f05cddf9SRui Paulo 	    ssid->mode == WPAS_MODE_IBSS)
964*f05cddf9SRui Paulo 		return -1;
965*f05cddf9SRui Paulo 
966*f05cddf9SRui Paulo #ifdef CONFIG_P2P
967*f05cddf9SRui Paulo 	if (ssid->mode == WPAS_MODE_P2P_GO)
968*f05cddf9SRui Paulo 		iface->conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER;
969*f05cddf9SRui Paulo 	else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
970*f05cddf9SRui Paulo 		iface->conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER |
971*f05cddf9SRui Paulo 			P2P_GROUP_FORMATION;
972*f05cddf9SRui Paulo #endif /* CONFIG_P2P */
973*f05cddf9SRui Paulo 
974*f05cddf9SRui Paulo 	hapd = iface->bss[0];
975*f05cddf9SRui Paulo 	if (hapd->drv_priv == NULL)
976*f05cddf9SRui Paulo 		return -1;
977*f05cddf9SRui Paulo 	ieee802_11_set_beacons(iface);
978*f05cddf9SRui Paulo 	hostapd_set_ap_wps_ie(hapd);
979*f05cddf9SRui Paulo 
980*f05cddf9SRui Paulo 	return 0;
981*f05cddf9SRui Paulo }
982*f05cddf9SRui Paulo 
983*f05cddf9SRui Paulo 
984*f05cddf9SRui Paulo void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
985*f05cddf9SRui Paulo 		       int offset)
986*f05cddf9SRui Paulo {
987*f05cddf9SRui Paulo 	if (!wpa_s->ap_iface)
988*f05cddf9SRui Paulo 		return;
989*f05cddf9SRui Paulo 
990*f05cddf9SRui Paulo 	wpa_s->assoc_freq = freq;
991*f05cddf9SRui Paulo 	hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht, offset);
992*f05cddf9SRui Paulo }
993*f05cddf9SRui Paulo 
994*f05cddf9SRui Paulo 
995e28a4053SRui Paulo int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
996e28a4053SRui Paulo 				      const u8 *addr)
997e28a4053SRui Paulo {
998e28a4053SRui Paulo 	struct hostapd_data *hapd;
999e28a4053SRui Paulo 	struct hostapd_bss_config *conf;
1000e28a4053SRui Paulo 
1001e28a4053SRui Paulo 	if (!wpa_s->ap_iface)
1002e28a4053SRui Paulo 		return -1;
1003e28a4053SRui Paulo 
1004e28a4053SRui Paulo 	if (addr)
1005e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR,
1006e28a4053SRui Paulo 			   MAC2STR(addr));
1007e28a4053SRui Paulo 	else
1008e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter");
1009e28a4053SRui Paulo 
1010e28a4053SRui Paulo 	hapd = wpa_s->ap_iface->bss[0];
1011e28a4053SRui Paulo 	conf = hapd->conf;
1012e28a4053SRui Paulo 
1013e28a4053SRui Paulo 	os_free(conf->accept_mac);
1014e28a4053SRui Paulo 	conf->accept_mac = NULL;
1015e28a4053SRui Paulo 	conf->num_accept_mac = 0;
1016e28a4053SRui Paulo 	os_free(conf->deny_mac);
1017e28a4053SRui Paulo 	conf->deny_mac = NULL;
1018e28a4053SRui Paulo 	conf->num_deny_mac = 0;
1019e28a4053SRui Paulo 
1020e28a4053SRui Paulo 	if (addr == NULL) {
1021e28a4053SRui Paulo 		conf->macaddr_acl = ACCEPT_UNLESS_DENIED;
1022e28a4053SRui Paulo 		return 0;
1023e28a4053SRui Paulo 	}
1024e28a4053SRui Paulo 
1025e28a4053SRui Paulo 	conf->macaddr_acl = DENY_UNLESS_ACCEPTED;
1026e28a4053SRui Paulo 	conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry));
1027e28a4053SRui Paulo 	if (conf->accept_mac == NULL)
1028e28a4053SRui Paulo 		return -1;
1029e28a4053SRui Paulo 	os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN);
1030e28a4053SRui Paulo 	conf->num_accept_mac = 1;
1031e28a4053SRui Paulo 
1032e28a4053SRui Paulo 	return 0;
1033e28a4053SRui Paulo }
1034