xref: /aosp_15_r20/external/wpa_supplicant_8/hostapd/ctrl_iface.c (revision 03f9172ca588f91df233974f4258bab95191f931)
1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker  * hostapd / UNIX domain socket -based control interface
3*03f9172cSAndroid Build Coastguard Worker  * Copyright (c) 2004-2018, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker  *
5*03f9172cSAndroid Build Coastguard Worker  * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker  * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker  */
8*03f9172cSAndroid Build Coastguard Worker 
9*03f9172cSAndroid Build Coastguard Worker #include "utils/includes.h"
10*03f9172cSAndroid Build Coastguard Worker 
11*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_NATIVE_WINDOWS
12*03f9172cSAndroid Build Coastguard Worker 
13*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
14*03f9172cSAndroid Build Coastguard Worker #ifdef __NetBSD__
15*03f9172cSAndroid Build Coastguard Worker #include <net/if_ether.h>
16*03f9172cSAndroid Build Coastguard Worker #else
17*03f9172cSAndroid Build Coastguard Worker #include <net/ethernet.h>
18*03f9172cSAndroid Build Coastguard Worker #endif
19*03f9172cSAndroid Build Coastguard Worker #include <netinet/ip.h>
20*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
21*03f9172cSAndroid Build Coastguard Worker 
22*03f9172cSAndroid Build Coastguard Worker #include <sys/un.h>
23*03f9172cSAndroid Build Coastguard Worker #include <sys/stat.h>
24*03f9172cSAndroid Build Coastguard Worker #include <stddef.h>
25*03f9172cSAndroid Build Coastguard Worker 
26*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
27*03f9172cSAndroid Build Coastguard Worker #include <netdb.h>
28*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
29*03f9172cSAndroid Build Coastguard Worker 
30*03f9172cSAndroid Build Coastguard Worker #include "utils/common.h"
31*03f9172cSAndroid Build Coastguard Worker #include "utils/eloop.h"
32*03f9172cSAndroid Build Coastguard Worker #include "utils/module_tests.h"
33*03f9172cSAndroid Build Coastguard Worker #include "common/version.h"
34*03f9172cSAndroid Build Coastguard Worker #include "common/ieee802_11_defs.h"
35*03f9172cSAndroid Build Coastguard Worker #include "common/ctrl_iface_common.h"
36*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
37*03f9172cSAndroid Build Coastguard Worker #include "common/dpp.h"
38*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
39*03f9172cSAndroid Build Coastguard Worker #include "common/wpa_ctrl.h"
40*03f9172cSAndroid Build Coastguard Worker #include "common/ptksa_cache.h"
41*03f9172cSAndroid Build Coastguard Worker #include "common/hw_features_common.h"
42*03f9172cSAndroid Build Coastguard Worker #include "common/nan_de.h"
43*03f9172cSAndroid Build Coastguard Worker #include "crypto/tls.h"
44*03f9172cSAndroid Build Coastguard Worker #include "drivers/driver.h"
45*03f9172cSAndroid Build Coastguard Worker #include "eapol_auth/eapol_auth_sm.h"
46*03f9172cSAndroid Build Coastguard Worker #include "radius/radius_client.h"
47*03f9172cSAndroid Build Coastguard Worker #include "radius/radius_server.h"
48*03f9172cSAndroid Build Coastguard Worker #include "l2_packet/l2_packet.h"
49*03f9172cSAndroid Build Coastguard Worker #include "ap/hostapd.h"
50*03f9172cSAndroid Build Coastguard Worker #include "ap/ap_config.h"
51*03f9172cSAndroid Build Coastguard Worker #include "ap/ieee802_1x.h"
52*03f9172cSAndroid Build Coastguard Worker #include "ap/wpa_auth.h"
53*03f9172cSAndroid Build Coastguard Worker #include "ap/pmksa_cache_auth.h"
54*03f9172cSAndroid Build Coastguard Worker #include "ap/ieee802_11.h"
55*03f9172cSAndroid Build Coastguard Worker #include "ap/sta_info.h"
56*03f9172cSAndroid Build Coastguard Worker #include "ap/wps_hostapd.h"
57*03f9172cSAndroid Build Coastguard Worker #include "ap/ctrl_iface_ap.h"
58*03f9172cSAndroid Build Coastguard Worker #include "ap/ap_drv_ops.h"
59*03f9172cSAndroid Build Coastguard Worker #include "ap/hs20.h"
60*03f9172cSAndroid Build Coastguard Worker #include "ap/wnm_ap.h"
61*03f9172cSAndroid Build Coastguard Worker #include "ap/wpa_auth.h"
62*03f9172cSAndroid Build Coastguard Worker #include "ap/beacon.h"
63*03f9172cSAndroid Build Coastguard Worker #include "ap/neighbor_db.h"
64*03f9172cSAndroid Build Coastguard Worker #include "ap/rrm.h"
65*03f9172cSAndroid Build Coastguard Worker #include "ap/dpp_hostapd.h"
66*03f9172cSAndroid Build Coastguard Worker #include "ap/dfs.h"
67*03f9172cSAndroid Build Coastguard Worker #include "ap/nan_usd_ap.h"
68*03f9172cSAndroid Build Coastguard Worker #include "wps/wps_defs.h"
69*03f9172cSAndroid Build Coastguard Worker #include "wps/wps.h"
70*03f9172cSAndroid Build Coastguard Worker #include "fst/fst_ctrl_iface.h"
71*03f9172cSAndroid Build Coastguard Worker #include "config_file.h"
72*03f9172cSAndroid Build Coastguard Worker #include "ctrl_iface.h"
73*03f9172cSAndroid Build Coastguard Worker 
74*03f9172cSAndroid Build Coastguard Worker 
75*03f9172cSAndroid Build Coastguard Worker #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
76*03f9172cSAndroid Build Coastguard Worker 
77*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
78*03f9172cSAndroid Build Coastguard Worker #define HOSTAPD_CTRL_IFACE_PORT		8877
79*03f9172cSAndroid Build Coastguard Worker #define HOSTAPD_CTRL_IFACE_PORT_LIMIT	50
80*03f9172cSAndroid Build Coastguard Worker #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT		8878
81*03f9172cSAndroid Build Coastguard Worker #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT	50
82*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
83*03f9172cSAndroid Build Coastguard Worker 
84*03f9172cSAndroid Build Coastguard Worker static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
85*03f9172cSAndroid Build Coastguard Worker 				    enum wpa_msg_type type,
86*03f9172cSAndroid Build Coastguard Worker 				    const char *buf, size_t len);
87*03f9172cSAndroid Build Coastguard Worker 
88*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_attach(struct hostapd_data * hapd,struct sockaddr_storage * from,socklen_t fromlen,const char * input)89*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
90*03f9172cSAndroid Build Coastguard Worker 				     struct sockaddr_storage *from,
91*03f9172cSAndroid Build Coastguard Worker 				     socklen_t fromlen, const char *input)
92*03f9172cSAndroid Build Coastguard Worker {
93*03f9172cSAndroid Build Coastguard Worker 	return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen, input);
94*03f9172cSAndroid Build Coastguard Worker }
95*03f9172cSAndroid Build Coastguard Worker 
96*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_detach(struct hostapd_data * hapd,struct sockaddr_storage * from,socklen_t fromlen)97*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
98*03f9172cSAndroid Build Coastguard Worker 				     struct sockaddr_storage *from,
99*03f9172cSAndroid Build Coastguard Worker 				     socklen_t fromlen)
100*03f9172cSAndroid Build Coastguard Worker {
101*03f9172cSAndroid Build Coastguard Worker 	return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
102*03f9172cSAndroid Build Coastguard Worker }
103*03f9172cSAndroid Build Coastguard Worker 
104*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_level(struct hostapd_data * hapd,struct sockaddr_storage * from,socklen_t fromlen,char * level)105*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
106*03f9172cSAndroid Build Coastguard Worker 				    struct sockaddr_storage *from,
107*03f9172cSAndroid Build Coastguard Worker 				    socklen_t fromlen,
108*03f9172cSAndroid Build Coastguard Worker 				    char *level)
109*03f9172cSAndroid Build Coastguard Worker {
110*03f9172cSAndroid Build Coastguard Worker 	return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
111*03f9172cSAndroid Build Coastguard Worker }
112*03f9172cSAndroid Build Coastguard Worker 
113*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_new_sta(struct hostapd_data * hapd,const char * txtaddr)114*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
115*03f9172cSAndroid Build Coastguard Worker 				      const char *txtaddr)
116*03f9172cSAndroid Build Coastguard Worker {
117*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
118*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
119*03f9172cSAndroid Build Coastguard Worker 
120*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
121*03f9172cSAndroid Build Coastguard Worker 
122*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(txtaddr, addr))
123*03f9172cSAndroid Build Coastguard Worker 		return -1;
124*03f9172cSAndroid Build Coastguard Worker 
125*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
126*03f9172cSAndroid Build Coastguard Worker 	if (sta)
127*03f9172cSAndroid Build Coastguard Worker 		return 0;
128*03f9172cSAndroid Build Coastguard Worker 
129*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
130*03f9172cSAndroid Build Coastguard Worker 		   "notification", MAC2STR(addr));
131*03f9172cSAndroid Build Coastguard Worker 	sta = ap_sta_add(hapd, addr);
132*03f9172cSAndroid Build Coastguard Worker 	if (sta == NULL)
133*03f9172cSAndroid Build Coastguard Worker 		return -1;
134*03f9172cSAndroid Build Coastguard Worker 
135*03f9172cSAndroid Build Coastguard Worker 	hostapd_new_assoc_sta(hapd, sta, 0);
136*03f9172cSAndroid Build Coastguard Worker 	return 0;
137*03f9172cSAndroid Build Coastguard Worker }
138*03f9172cSAndroid Build Coastguard Worker 
139*03f9172cSAndroid Build Coastguard Worker 
140*03f9172cSAndroid Build Coastguard Worker #ifdef NEED_AP_MLME
hostapd_ctrl_iface_sa_query(struct hostapd_data * hapd,const char * txtaddr)141*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
142*03f9172cSAndroid Build Coastguard Worker 				       const char *txtaddr)
143*03f9172cSAndroid Build Coastguard Worker {
144*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
145*03f9172cSAndroid Build Coastguard Worker 	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
146*03f9172cSAndroid Build Coastguard Worker 
147*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
148*03f9172cSAndroid Build Coastguard Worker 
149*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(txtaddr, addr) ||
150*03f9172cSAndroid Build Coastguard Worker 	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
151*03f9172cSAndroid Build Coastguard Worker 		return -1;
152*03f9172cSAndroid Build Coastguard Worker 
153*03f9172cSAndroid Build Coastguard Worker 	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
154*03f9172cSAndroid Build Coastguard Worker 
155*03f9172cSAndroid Build Coastguard Worker 	return 0;
156*03f9172cSAndroid Build Coastguard Worker }
157*03f9172cSAndroid Build Coastguard Worker #endif /* NEED_AP_MLME */
158*03f9172cSAndroid Build Coastguard Worker 
159*03f9172cSAndroid Build Coastguard Worker 
160*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS
hostapd_ctrl_iface_wps_pin(struct hostapd_data * hapd,char * txt)161*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
162*03f9172cSAndroid Build Coastguard Worker {
163*03f9172cSAndroid Build Coastguard Worker 	char *pin = os_strchr(txt, ' ');
164*03f9172cSAndroid Build Coastguard Worker 	char *timeout_txt;
165*03f9172cSAndroid Build Coastguard Worker 	int timeout;
166*03f9172cSAndroid Build Coastguard Worker 	u8 addr_buf[ETH_ALEN], *addr = NULL;
167*03f9172cSAndroid Build Coastguard Worker 	char *pos;
168*03f9172cSAndroid Build Coastguard Worker 
169*03f9172cSAndroid Build Coastguard Worker 	if (pin == NULL)
170*03f9172cSAndroid Build Coastguard Worker 		return -1;
171*03f9172cSAndroid Build Coastguard Worker 	*pin++ = '\0';
172*03f9172cSAndroid Build Coastguard Worker 
173*03f9172cSAndroid Build Coastguard Worker 	timeout_txt = os_strchr(pin, ' ');
174*03f9172cSAndroid Build Coastguard Worker 	if (timeout_txt) {
175*03f9172cSAndroid Build Coastguard Worker 		*timeout_txt++ = '\0';
176*03f9172cSAndroid Build Coastguard Worker 		timeout = atoi(timeout_txt);
177*03f9172cSAndroid Build Coastguard Worker 		pos = os_strchr(timeout_txt, ' ');
178*03f9172cSAndroid Build Coastguard Worker 		if (pos) {
179*03f9172cSAndroid Build Coastguard Worker 			*pos++ = '\0';
180*03f9172cSAndroid Build Coastguard Worker 			if (hwaddr_aton(pos, addr_buf) == 0)
181*03f9172cSAndroid Build Coastguard Worker 				addr = addr_buf;
182*03f9172cSAndroid Build Coastguard Worker 		}
183*03f9172cSAndroid Build Coastguard Worker 	} else
184*03f9172cSAndroid Build Coastguard Worker 		timeout = 0;
185*03f9172cSAndroid Build Coastguard Worker 
186*03f9172cSAndroid Build Coastguard Worker 	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
187*03f9172cSAndroid Build Coastguard Worker }
188*03f9172cSAndroid Build Coastguard Worker 
189*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_wps_check_pin(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)190*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_check_pin(
191*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
192*03f9172cSAndroid Build Coastguard Worker {
193*03f9172cSAndroid Build Coastguard Worker 	char pin[9];
194*03f9172cSAndroid Build Coastguard Worker 	size_t len;
195*03f9172cSAndroid Build Coastguard Worker 	char *pos;
196*03f9172cSAndroid Build Coastguard Worker 	int ret;
197*03f9172cSAndroid Build Coastguard Worker 
198*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
199*03f9172cSAndroid Build Coastguard Worker 			      (u8 *) cmd, os_strlen(cmd));
200*03f9172cSAndroid Build Coastguard Worker 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
201*03f9172cSAndroid Build Coastguard Worker 		if (*pos < '0' || *pos > '9')
202*03f9172cSAndroid Build Coastguard Worker 			continue;
203*03f9172cSAndroid Build Coastguard Worker 		pin[len++] = *pos;
204*03f9172cSAndroid Build Coastguard Worker 		if (len == 9) {
205*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
206*03f9172cSAndroid Build Coastguard Worker 			return -1;
207*03f9172cSAndroid Build Coastguard Worker 		}
208*03f9172cSAndroid Build Coastguard Worker 	}
209*03f9172cSAndroid Build Coastguard Worker 	if (len != 4 && len != 8) {
210*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
211*03f9172cSAndroid Build Coastguard Worker 		return -1;
212*03f9172cSAndroid Build Coastguard Worker 	}
213*03f9172cSAndroid Build Coastguard Worker 	pin[len] = '\0';
214*03f9172cSAndroid Build Coastguard Worker 
215*03f9172cSAndroid Build Coastguard Worker 	if (len == 8) {
216*03f9172cSAndroid Build Coastguard Worker 		unsigned int pin_val;
217*03f9172cSAndroid Build Coastguard Worker 		pin_val = atoi(pin);
218*03f9172cSAndroid Build Coastguard Worker 		if (!wps_pin_valid(pin_val)) {
219*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
220*03f9172cSAndroid Build Coastguard Worker 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
221*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(buflen, ret))
222*03f9172cSAndroid Build Coastguard Worker 				return -1;
223*03f9172cSAndroid Build Coastguard Worker 			return ret;
224*03f9172cSAndroid Build Coastguard Worker 		}
225*03f9172cSAndroid Build Coastguard Worker 	}
226*03f9172cSAndroid Build Coastguard Worker 
227*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(buf, buflen, "%s", pin);
228*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(buflen, ret))
229*03f9172cSAndroid Build Coastguard Worker 		return -1;
230*03f9172cSAndroid Build Coastguard Worker 
231*03f9172cSAndroid Build Coastguard Worker 	return ret;
232*03f9172cSAndroid Build Coastguard Worker }
233*03f9172cSAndroid Build Coastguard Worker 
234*03f9172cSAndroid Build Coastguard Worker 
235*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS_NFC
hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data * hapd,char * pos)236*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
237*03f9172cSAndroid Build Coastguard Worker 					       char *pos)
238*03f9172cSAndroid Build Coastguard Worker {
239*03f9172cSAndroid Build Coastguard Worker 	size_t len;
240*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *buf;
241*03f9172cSAndroid Build Coastguard Worker 	int ret;
242*03f9172cSAndroid Build Coastguard Worker 
243*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(pos);
244*03f9172cSAndroid Build Coastguard Worker 	if (len & 0x01)
245*03f9172cSAndroid Build Coastguard Worker 		return -1;
246*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
247*03f9172cSAndroid Build Coastguard Worker 
248*03f9172cSAndroid Build Coastguard Worker 	buf = wpabuf_alloc(len);
249*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
250*03f9172cSAndroid Build Coastguard Worker 		return -1;
251*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
252*03f9172cSAndroid Build Coastguard Worker 		wpabuf_free(buf);
253*03f9172cSAndroid Build Coastguard Worker 		return -1;
254*03f9172cSAndroid Build Coastguard Worker 	}
255*03f9172cSAndroid Build Coastguard Worker 
256*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_wps_nfc_tag_read(hapd, buf);
257*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(buf);
258*03f9172cSAndroid Build Coastguard Worker 
259*03f9172cSAndroid Build Coastguard Worker 	return ret;
260*03f9172cSAndroid Build Coastguard Worker }
261*03f9172cSAndroid Build Coastguard Worker 
262*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data * hapd,char * cmd,char * reply,size_t max_len)263*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
264*03f9172cSAndroid Build Coastguard Worker 						   char *cmd, char *reply,
265*03f9172cSAndroid Build Coastguard Worker 						   size_t max_len)
266*03f9172cSAndroid Build Coastguard Worker {
267*03f9172cSAndroid Build Coastguard Worker 	int ndef;
268*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *buf;
269*03f9172cSAndroid Build Coastguard Worker 	int res;
270*03f9172cSAndroid Build Coastguard Worker 
271*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "WPS") == 0)
272*03f9172cSAndroid Build Coastguard Worker 		ndef = 0;
273*03f9172cSAndroid Build Coastguard Worker 	else if (os_strcmp(cmd, "NDEF") == 0)
274*03f9172cSAndroid Build Coastguard Worker 		ndef = 1;
275*03f9172cSAndroid Build Coastguard Worker 	else
276*03f9172cSAndroid Build Coastguard Worker 		return -1;
277*03f9172cSAndroid Build Coastguard Worker 
278*03f9172cSAndroid Build Coastguard Worker 	buf = hostapd_wps_nfc_config_token(hapd, ndef);
279*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
280*03f9172cSAndroid Build Coastguard Worker 		return -1;
281*03f9172cSAndroid Build Coastguard Worker 
282*03f9172cSAndroid Build Coastguard Worker 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
283*03f9172cSAndroid Build Coastguard Worker 					 wpabuf_len(buf));
284*03f9172cSAndroid Build Coastguard Worker 	reply[res++] = '\n';
285*03f9172cSAndroid Build Coastguard Worker 	reply[res] = '\0';
286*03f9172cSAndroid Build Coastguard Worker 
287*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(buf);
288*03f9172cSAndroid Build Coastguard Worker 
289*03f9172cSAndroid Build Coastguard Worker 	return res;
290*03f9172cSAndroid Build Coastguard Worker }
291*03f9172cSAndroid Build Coastguard Worker 
292*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data * hapd,char * reply,size_t max_len,int ndef)293*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
294*03f9172cSAndroid Build Coastguard Worker 						char *reply, size_t max_len,
295*03f9172cSAndroid Build Coastguard Worker 						int ndef)
296*03f9172cSAndroid Build Coastguard Worker {
297*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *buf;
298*03f9172cSAndroid Build Coastguard Worker 	int res;
299*03f9172cSAndroid Build Coastguard Worker 
300*03f9172cSAndroid Build Coastguard Worker 	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
301*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
302*03f9172cSAndroid Build Coastguard Worker 		return -1;
303*03f9172cSAndroid Build Coastguard Worker 
304*03f9172cSAndroid Build Coastguard Worker 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
305*03f9172cSAndroid Build Coastguard Worker 					 wpabuf_len(buf));
306*03f9172cSAndroid Build Coastguard Worker 	reply[res++] = '\n';
307*03f9172cSAndroid Build Coastguard Worker 	reply[res] = '\0';
308*03f9172cSAndroid Build Coastguard Worker 
309*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(buf);
310*03f9172cSAndroid Build Coastguard Worker 
311*03f9172cSAndroid Build Coastguard Worker 	return res;
312*03f9172cSAndroid Build Coastguard Worker }
313*03f9172cSAndroid Build Coastguard Worker 
314*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data * hapd,char * cmd,char * reply,size_t max_len)315*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
316*03f9172cSAndroid Build Coastguard Worker 					    char *cmd, char *reply,
317*03f9172cSAndroid Build Coastguard Worker 					    size_t max_len)
318*03f9172cSAndroid Build Coastguard Worker {
319*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "WPS") == 0)
320*03f9172cSAndroid Build Coastguard Worker 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
321*03f9172cSAndroid Build Coastguard Worker 							    max_len, 0);
322*03f9172cSAndroid Build Coastguard Worker 
323*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "NDEF") == 0)
324*03f9172cSAndroid Build Coastguard Worker 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
325*03f9172cSAndroid Build Coastguard Worker 							    max_len, 1);
326*03f9172cSAndroid Build Coastguard Worker 
327*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "enable") == 0)
328*03f9172cSAndroid Build Coastguard Worker 		return hostapd_wps_nfc_token_enable(hapd);
329*03f9172cSAndroid Build Coastguard Worker 
330*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "disable") == 0) {
331*03f9172cSAndroid Build Coastguard Worker 		hostapd_wps_nfc_token_disable(hapd);
332*03f9172cSAndroid Build Coastguard Worker 		return 0;
333*03f9172cSAndroid Build Coastguard Worker 	}
334*03f9172cSAndroid Build Coastguard Worker 
335*03f9172cSAndroid Build Coastguard Worker 	return -1;
336*03f9172cSAndroid Build Coastguard Worker }
337*03f9172cSAndroid Build Coastguard Worker 
338*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data * hapd,char * cmd,char * reply,size_t max_len)339*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
340*03f9172cSAndroid Build Coastguard Worker 						   char *cmd, char *reply,
341*03f9172cSAndroid Build Coastguard Worker 						   size_t max_len)
342*03f9172cSAndroid Build Coastguard Worker {
343*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *buf;
344*03f9172cSAndroid Build Coastguard Worker 	int res;
345*03f9172cSAndroid Build Coastguard Worker 	char *pos;
346*03f9172cSAndroid Build Coastguard Worker 	int ndef;
347*03f9172cSAndroid Build Coastguard Worker 
348*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(cmd, ' ');
349*03f9172cSAndroid Build Coastguard Worker 	if (pos == NULL)
350*03f9172cSAndroid Build Coastguard Worker 		return -1;
351*03f9172cSAndroid Build Coastguard Worker 	*pos++ = '\0';
352*03f9172cSAndroid Build Coastguard Worker 
353*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "WPS") == 0)
354*03f9172cSAndroid Build Coastguard Worker 		ndef = 0;
355*03f9172cSAndroid Build Coastguard Worker 	else if (os_strcmp(cmd, "NDEF") == 0)
356*03f9172cSAndroid Build Coastguard Worker 		ndef = 1;
357*03f9172cSAndroid Build Coastguard Worker 	else
358*03f9172cSAndroid Build Coastguard Worker 		return -1;
359*03f9172cSAndroid Build Coastguard Worker 
360*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(pos, "WPS-CR") == 0)
361*03f9172cSAndroid Build Coastguard Worker 		buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
362*03f9172cSAndroid Build Coastguard Worker 	else
363*03f9172cSAndroid Build Coastguard Worker 		buf = NULL;
364*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
365*03f9172cSAndroid Build Coastguard Worker 		return -1;
366*03f9172cSAndroid Build Coastguard Worker 
367*03f9172cSAndroid Build Coastguard Worker 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
368*03f9172cSAndroid Build Coastguard Worker 					 wpabuf_len(buf));
369*03f9172cSAndroid Build Coastguard Worker 	reply[res++] = '\n';
370*03f9172cSAndroid Build Coastguard Worker 	reply[res] = '\0';
371*03f9172cSAndroid Build Coastguard Worker 
372*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(buf);
373*03f9172cSAndroid Build Coastguard Worker 
374*03f9172cSAndroid Build Coastguard Worker 	return res;
375*03f9172cSAndroid Build Coastguard Worker }
376*03f9172cSAndroid Build Coastguard Worker 
377*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data * hapd,char * cmd)378*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
379*03f9172cSAndroid Build Coastguard Worker 						  char *cmd)
380*03f9172cSAndroid Build Coastguard Worker {
381*03f9172cSAndroid Build Coastguard Worker 	size_t len;
382*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *req, *sel;
383*03f9172cSAndroid Build Coastguard Worker 	int ret;
384*03f9172cSAndroid Build Coastguard Worker 	char *pos, *role, *type, *pos2;
385*03f9172cSAndroid Build Coastguard Worker 
386*03f9172cSAndroid Build Coastguard Worker 	role = cmd;
387*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(role, ' ');
388*03f9172cSAndroid Build Coastguard Worker 	if (pos == NULL)
389*03f9172cSAndroid Build Coastguard Worker 		return -1;
390*03f9172cSAndroid Build Coastguard Worker 	*pos++ = '\0';
391*03f9172cSAndroid Build Coastguard Worker 
392*03f9172cSAndroid Build Coastguard Worker 	type = pos;
393*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(type, ' ');
394*03f9172cSAndroid Build Coastguard Worker 	if (pos == NULL)
395*03f9172cSAndroid Build Coastguard Worker 		return -1;
396*03f9172cSAndroid Build Coastguard Worker 	*pos++ = '\0';
397*03f9172cSAndroid Build Coastguard Worker 
398*03f9172cSAndroid Build Coastguard Worker 	pos2 = os_strchr(pos, ' ');
399*03f9172cSAndroid Build Coastguard Worker 	if (pos2 == NULL)
400*03f9172cSAndroid Build Coastguard Worker 		return -1;
401*03f9172cSAndroid Build Coastguard Worker 	*pos2++ = '\0';
402*03f9172cSAndroid Build Coastguard Worker 
403*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(pos);
404*03f9172cSAndroid Build Coastguard Worker 	if (len & 0x01)
405*03f9172cSAndroid Build Coastguard Worker 		return -1;
406*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
407*03f9172cSAndroid Build Coastguard Worker 
408*03f9172cSAndroid Build Coastguard Worker 	req = wpabuf_alloc(len);
409*03f9172cSAndroid Build Coastguard Worker 	if (req == NULL)
410*03f9172cSAndroid Build Coastguard Worker 		return -1;
411*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
412*03f9172cSAndroid Build Coastguard Worker 		wpabuf_free(req);
413*03f9172cSAndroid Build Coastguard Worker 		return -1;
414*03f9172cSAndroid Build Coastguard Worker 	}
415*03f9172cSAndroid Build Coastguard Worker 
416*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(pos2);
417*03f9172cSAndroid Build Coastguard Worker 	if (len & 0x01) {
418*03f9172cSAndroid Build Coastguard Worker 		wpabuf_free(req);
419*03f9172cSAndroid Build Coastguard Worker 		return -1;
420*03f9172cSAndroid Build Coastguard Worker 	}
421*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
422*03f9172cSAndroid Build Coastguard Worker 
423*03f9172cSAndroid Build Coastguard Worker 	sel = wpabuf_alloc(len);
424*03f9172cSAndroid Build Coastguard Worker 	if (sel == NULL) {
425*03f9172cSAndroid Build Coastguard Worker 		wpabuf_free(req);
426*03f9172cSAndroid Build Coastguard Worker 		return -1;
427*03f9172cSAndroid Build Coastguard Worker 	}
428*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
429*03f9172cSAndroid Build Coastguard Worker 		wpabuf_free(req);
430*03f9172cSAndroid Build Coastguard Worker 		wpabuf_free(sel);
431*03f9172cSAndroid Build Coastguard Worker 		return -1;
432*03f9172cSAndroid Build Coastguard Worker 	}
433*03f9172cSAndroid Build Coastguard Worker 
434*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
435*03f9172cSAndroid Build Coastguard Worker 		ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
436*03f9172cSAndroid Build Coastguard Worker 	} else {
437*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
438*03f9172cSAndroid Build Coastguard Worker 			   "reported: role=%s type=%s", role, type);
439*03f9172cSAndroid Build Coastguard Worker 		ret = -1;
440*03f9172cSAndroid Build Coastguard Worker 	}
441*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(req);
442*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(sel);
443*03f9172cSAndroid Build Coastguard Worker 
444*03f9172cSAndroid Build Coastguard Worker 	return ret;
445*03f9172cSAndroid Build Coastguard Worker }
446*03f9172cSAndroid Build Coastguard Worker 
447*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS_NFC */
448*03f9172cSAndroid Build Coastguard Worker 
449*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data * hapd,char * txt,char * buf,size_t buflen)450*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
451*03f9172cSAndroid Build Coastguard Worker 					 char *buf, size_t buflen)
452*03f9172cSAndroid Build Coastguard Worker {
453*03f9172cSAndroid Build Coastguard Worker 	int timeout = 300;
454*03f9172cSAndroid Build Coastguard Worker 	char *pos;
455*03f9172cSAndroid Build Coastguard Worker 	const char *pin_txt;
456*03f9172cSAndroid Build Coastguard Worker 
457*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(txt, ' ');
458*03f9172cSAndroid Build Coastguard Worker 	if (pos)
459*03f9172cSAndroid Build Coastguard Worker 		*pos++ = '\0';
460*03f9172cSAndroid Build Coastguard Worker 
461*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(txt, "disable") == 0) {
462*03f9172cSAndroid Build Coastguard Worker 		hostapd_wps_ap_pin_disable(hapd);
463*03f9172cSAndroid Build Coastguard Worker 		return os_snprintf(buf, buflen, "OK\n");
464*03f9172cSAndroid Build Coastguard Worker 	}
465*03f9172cSAndroid Build Coastguard Worker 
466*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(txt, "random") == 0) {
467*03f9172cSAndroid Build Coastguard Worker 		if (pos)
468*03f9172cSAndroid Build Coastguard Worker 			timeout = atoi(pos);
469*03f9172cSAndroid Build Coastguard Worker 		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
470*03f9172cSAndroid Build Coastguard Worker 		if (pin_txt == NULL)
471*03f9172cSAndroid Build Coastguard Worker 			return -1;
472*03f9172cSAndroid Build Coastguard Worker 		return os_snprintf(buf, buflen, "%s", pin_txt);
473*03f9172cSAndroid Build Coastguard Worker 	}
474*03f9172cSAndroid Build Coastguard Worker 
475*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(txt, "get") == 0) {
476*03f9172cSAndroid Build Coastguard Worker 		pin_txt = hostapd_wps_ap_pin_get(hapd);
477*03f9172cSAndroid Build Coastguard Worker 		if (pin_txt == NULL)
478*03f9172cSAndroid Build Coastguard Worker 			return -1;
479*03f9172cSAndroid Build Coastguard Worker 		return os_snprintf(buf, buflen, "%s", pin_txt);
480*03f9172cSAndroid Build Coastguard Worker 	}
481*03f9172cSAndroid Build Coastguard Worker 
482*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(txt, "set") == 0) {
483*03f9172cSAndroid Build Coastguard Worker 		char *pin;
484*03f9172cSAndroid Build Coastguard Worker 		if (pos == NULL)
485*03f9172cSAndroid Build Coastguard Worker 			return -1;
486*03f9172cSAndroid Build Coastguard Worker 		pin = pos;
487*03f9172cSAndroid Build Coastguard Worker 		pos = os_strchr(pos, ' ');
488*03f9172cSAndroid Build Coastguard Worker 		if (pos) {
489*03f9172cSAndroid Build Coastguard Worker 			*pos++ = '\0';
490*03f9172cSAndroid Build Coastguard Worker 			timeout = atoi(pos);
491*03f9172cSAndroid Build Coastguard Worker 		}
492*03f9172cSAndroid Build Coastguard Worker 		if (os_strlen(pin) > buflen)
493*03f9172cSAndroid Build Coastguard Worker 			return -1;
494*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
495*03f9172cSAndroid Build Coastguard Worker 			return -1;
496*03f9172cSAndroid Build Coastguard Worker 		return os_snprintf(buf, buflen, "%s", pin);
497*03f9172cSAndroid Build Coastguard Worker 	}
498*03f9172cSAndroid Build Coastguard Worker 
499*03f9172cSAndroid Build Coastguard Worker 	return -1;
500*03f9172cSAndroid Build Coastguard Worker }
501*03f9172cSAndroid Build Coastguard Worker 
502*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_wps_config(struct hostapd_data * hapd,char * txt)503*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
504*03f9172cSAndroid Build Coastguard Worker {
505*03f9172cSAndroid Build Coastguard Worker 	char *pos;
506*03f9172cSAndroid Build Coastguard Worker 	char *ssid, *auth, *encr = NULL, *key = NULL;
507*03f9172cSAndroid Build Coastguard Worker 
508*03f9172cSAndroid Build Coastguard Worker 	ssid = txt;
509*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(txt, ' ');
510*03f9172cSAndroid Build Coastguard Worker 	if (!pos)
511*03f9172cSAndroid Build Coastguard Worker 		return -1;
512*03f9172cSAndroid Build Coastguard Worker 	*pos++ = '\0';
513*03f9172cSAndroid Build Coastguard Worker 
514*03f9172cSAndroid Build Coastguard Worker 	auth = pos;
515*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
516*03f9172cSAndroid Build Coastguard Worker 	if (pos) {
517*03f9172cSAndroid Build Coastguard Worker 		*pos++ = '\0';
518*03f9172cSAndroid Build Coastguard Worker 		encr = pos;
519*03f9172cSAndroid Build Coastguard Worker 		pos = os_strchr(pos, ' ');
520*03f9172cSAndroid Build Coastguard Worker 		if (pos) {
521*03f9172cSAndroid Build Coastguard Worker 			*pos++ = '\0';
522*03f9172cSAndroid Build Coastguard Worker 			key = pos;
523*03f9172cSAndroid Build Coastguard Worker 		}
524*03f9172cSAndroid Build Coastguard Worker 	}
525*03f9172cSAndroid Build Coastguard Worker 
526*03f9172cSAndroid Build Coastguard Worker 	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
527*03f9172cSAndroid Build Coastguard Worker }
528*03f9172cSAndroid Build Coastguard Worker 
529*03f9172cSAndroid Build Coastguard Worker 
pbc_status_str(enum pbc_status status)530*03f9172cSAndroid Build Coastguard Worker static const char * pbc_status_str(enum pbc_status status)
531*03f9172cSAndroid Build Coastguard Worker {
532*03f9172cSAndroid Build Coastguard Worker 	switch (status) {
533*03f9172cSAndroid Build Coastguard Worker 	case WPS_PBC_STATUS_DISABLE:
534*03f9172cSAndroid Build Coastguard Worker 		return "Disabled";
535*03f9172cSAndroid Build Coastguard Worker 	case WPS_PBC_STATUS_ACTIVE:
536*03f9172cSAndroid Build Coastguard Worker 		return "Active";
537*03f9172cSAndroid Build Coastguard Worker 	case WPS_PBC_STATUS_TIMEOUT:
538*03f9172cSAndroid Build Coastguard Worker 		return "Timed-out";
539*03f9172cSAndroid Build Coastguard Worker 	case WPS_PBC_STATUS_OVERLAP:
540*03f9172cSAndroid Build Coastguard Worker 		return "Overlap";
541*03f9172cSAndroid Build Coastguard Worker 	default:
542*03f9172cSAndroid Build Coastguard Worker 		return "Unknown";
543*03f9172cSAndroid Build Coastguard Worker 	}
544*03f9172cSAndroid Build Coastguard Worker }
545*03f9172cSAndroid Build Coastguard Worker 
546*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_wps_get_status(struct hostapd_data * hapd,char * buf,size_t buflen)547*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
548*03f9172cSAndroid Build Coastguard Worker 					     char *buf, size_t buflen)
549*03f9172cSAndroid Build Coastguard Worker {
550*03f9172cSAndroid Build Coastguard Worker 	int ret;
551*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
552*03f9172cSAndroid Build Coastguard Worker 
553*03f9172cSAndroid Build Coastguard Worker 	pos = buf;
554*03f9172cSAndroid Build Coastguard Worker 	end = buf + buflen;
555*03f9172cSAndroid Build Coastguard Worker 
556*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
557*03f9172cSAndroid Build Coastguard Worker 			  pbc_status_str(hapd->wps_stats.pbc_status));
558*03f9172cSAndroid Build Coastguard Worker 
559*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(end - pos, ret))
560*03f9172cSAndroid Build Coastguard Worker 		return pos - buf;
561*03f9172cSAndroid Build Coastguard Worker 	pos += ret;
562*03f9172cSAndroid Build Coastguard Worker 
563*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
564*03f9172cSAndroid Build Coastguard Worker 			  (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
565*03f9172cSAndroid Build Coastguard Worker 			   "Success":
566*03f9172cSAndroid Build Coastguard Worker 			   (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
567*03f9172cSAndroid Build Coastguard Worker 			    "Failed" : "None")));
568*03f9172cSAndroid Build Coastguard Worker 
569*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(end - pos, ret))
570*03f9172cSAndroid Build Coastguard Worker 		return pos - buf;
571*03f9172cSAndroid Build Coastguard Worker 	pos += ret;
572*03f9172cSAndroid Build Coastguard Worker 
573*03f9172cSAndroid Build Coastguard Worker 	/* If status == Failure - Add possible Reasons */
574*03f9172cSAndroid Build Coastguard Worker 	if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
575*03f9172cSAndroid Build Coastguard Worker 	   hapd->wps_stats.failure_reason > 0) {
576*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos,
577*03f9172cSAndroid Build Coastguard Worker 				  "Failure Reason: %s\n",
578*03f9172cSAndroid Build Coastguard Worker 				  wps_ei_str(hapd->wps_stats.failure_reason));
579*03f9172cSAndroid Build Coastguard Worker 
580*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
581*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
582*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
583*03f9172cSAndroid Build Coastguard Worker 	}
584*03f9172cSAndroid Build Coastguard Worker 
585*03f9172cSAndroid Build Coastguard Worker 	if (hapd->wps_stats.status) {
586*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
587*03f9172cSAndroid Build Coastguard Worker 				  MAC2STR(hapd->wps_stats.peer_addr));
588*03f9172cSAndroid Build Coastguard Worker 
589*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
590*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
591*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
592*03f9172cSAndroid Build Coastguard Worker 	}
593*03f9172cSAndroid Build Coastguard Worker 
594*03f9172cSAndroid Build Coastguard Worker 	return pos - buf;
595*03f9172cSAndroid Build Coastguard Worker }
596*03f9172cSAndroid Build Coastguard Worker 
597*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS */
598*03f9172cSAndroid Build Coastguard Worker 
599*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HS20
600*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data * hapd,const char * cmd)601*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
602*03f9172cSAndroid Build Coastguard Worker 					     const char *cmd)
603*03f9172cSAndroid Build Coastguard Worker {
604*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
605*03f9172cSAndroid Build Coastguard Worker 	const char *url;
606*03f9172cSAndroid Build Coastguard Worker 
607*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
608*03f9172cSAndroid Build Coastguard Worker 		return -1;
609*03f9172cSAndroid Build Coastguard Worker 	url = cmd + 17;
610*03f9172cSAndroid Build Coastguard Worker 	if (*url == '\0') {
611*03f9172cSAndroid Build Coastguard Worker 		url = NULL;
612*03f9172cSAndroid Build Coastguard Worker 	} else {
613*03f9172cSAndroid Build Coastguard Worker 		if (*url != ' ')
614*03f9172cSAndroid Build Coastguard Worker 			return -1;
615*03f9172cSAndroid Build Coastguard Worker 		url++;
616*03f9172cSAndroid Build Coastguard Worker 		if (*url == '\0')
617*03f9172cSAndroid Build Coastguard Worker 			url = NULL;
618*03f9172cSAndroid Build Coastguard Worker 	}
619*03f9172cSAndroid Build Coastguard Worker 
620*03f9172cSAndroid Build Coastguard Worker 	return hs20_send_wnm_notification(hapd, addr, 1, url);
621*03f9172cSAndroid Build Coastguard Worker }
622*03f9172cSAndroid Build Coastguard Worker 
623*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data * hapd,const char * cmd)624*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
625*03f9172cSAndroid Build Coastguard Worker 					      const char *cmd)
626*03f9172cSAndroid Build Coastguard Worker {
627*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
628*03f9172cSAndroid Build Coastguard Worker 	int code, reauth_delay, ret;
629*03f9172cSAndroid Build Coastguard Worker 	const char *pos;
630*03f9172cSAndroid Build Coastguard Worker 	size_t url_len;
631*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *req;
632*03f9172cSAndroid Build Coastguard Worker 
633*03f9172cSAndroid Build Coastguard Worker 	/* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
634*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
635*03f9172cSAndroid Build Coastguard Worker 		return -1;
636*03f9172cSAndroid Build Coastguard Worker 
637*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(cmd, ' ');
638*03f9172cSAndroid Build Coastguard Worker 	if (pos == NULL)
639*03f9172cSAndroid Build Coastguard Worker 		return -1;
640*03f9172cSAndroid Build Coastguard Worker 	pos++;
641*03f9172cSAndroid Build Coastguard Worker 	code = atoi(pos);
642*03f9172cSAndroid Build Coastguard Worker 
643*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
644*03f9172cSAndroid Build Coastguard Worker 	if (pos == NULL)
645*03f9172cSAndroid Build Coastguard Worker 		return -1;
646*03f9172cSAndroid Build Coastguard Worker 	pos++;
647*03f9172cSAndroid Build Coastguard Worker 	reauth_delay = atoi(pos);
648*03f9172cSAndroid Build Coastguard Worker 
649*03f9172cSAndroid Build Coastguard Worker 	url_len = 0;
650*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
651*03f9172cSAndroid Build Coastguard Worker 	if (pos) {
652*03f9172cSAndroid Build Coastguard Worker 		pos++;
653*03f9172cSAndroid Build Coastguard Worker 		url_len = os_strlen(pos);
654*03f9172cSAndroid Build Coastguard Worker 	}
655*03f9172cSAndroid Build Coastguard Worker 
656*03f9172cSAndroid Build Coastguard Worker 	req = wpabuf_alloc(4 + url_len);
657*03f9172cSAndroid Build Coastguard Worker 	if (req == NULL)
658*03f9172cSAndroid Build Coastguard Worker 		return -1;
659*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_u8(req, code);
660*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_le16(req, reauth_delay);
661*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_u8(req, url_len);
662*03f9172cSAndroid Build Coastguard Worker 	if (pos)
663*03f9172cSAndroid Build Coastguard Worker 		wpabuf_put_data(req, pos, url_len);
664*03f9172cSAndroid Build Coastguard Worker 
665*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
666*03f9172cSAndroid Build Coastguard Worker 		   " to indicate imminent deauthentication (code=%d "
667*03f9172cSAndroid Build Coastguard Worker 		   "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
668*03f9172cSAndroid Build Coastguard Worker 	ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
669*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(req);
670*03f9172cSAndroid Build Coastguard Worker 	return ret;
671*03f9172cSAndroid Build Coastguard Worker }
672*03f9172cSAndroid Build Coastguard Worker 
673*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HS20 */
674*03f9172cSAndroid Build Coastguard Worker 
675*03f9172cSAndroid Build Coastguard Worker 
676*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_INTERWORKING
677*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data * hapd,const char * cmd)678*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
679*03f9172cSAndroid Build Coastguard Worker 					      const char *cmd)
680*03f9172cSAndroid Build Coastguard Worker {
681*03f9172cSAndroid Build Coastguard Worker 	u8 qos_map_set[16 + 2 * 21], count = 0;
682*03f9172cSAndroid Build Coastguard Worker 	const char *pos = cmd;
683*03f9172cSAndroid Build Coastguard Worker 	int val, ret;
684*03f9172cSAndroid Build Coastguard Worker 
685*03f9172cSAndroid Build Coastguard Worker 	for (;;) {
686*03f9172cSAndroid Build Coastguard Worker 		if (count == sizeof(qos_map_set)) {
687*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
688*03f9172cSAndroid Build Coastguard Worker 			return -1;
689*03f9172cSAndroid Build Coastguard Worker 		}
690*03f9172cSAndroid Build Coastguard Worker 
691*03f9172cSAndroid Build Coastguard Worker 		val = atoi(pos);
692*03f9172cSAndroid Build Coastguard Worker 		if (val < 0 || val > 255) {
693*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Invalid QoS Map Set");
694*03f9172cSAndroid Build Coastguard Worker 			return -1;
695*03f9172cSAndroid Build Coastguard Worker 		}
696*03f9172cSAndroid Build Coastguard Worker 
697*03f9172cSAndroid Build Coastguard Worker 		qos_map_set[count++] = val;
698*03f9172cSAndroid Build Coastguard Worker 		pos = os_strchr(pos, ',');
699*03f9172cSAndroid Build Coastguard Worker 		if (!pos)
700*03f9172cSAndroid Build Coastguard Worker 			break;
701*03f9172cSAndroid Build Coastguard Worker 		pos++;
702*03f9172cSAndroid Build Coastguard Worker 	}
703*03f9172cSAndroid Build Coastguard Worker 
704*03f9172cSAndroid Build Coastguard Worker 	if (count < 16 || count & 1) {
705*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Invalid QoS Map Set");
706*03f9172cSAndroid Build Coastguard Worker 		return -1;
707*03f9172cSAndroid Build Coastguard Worker 	}
708*03f9172cSAndroid Build Coastguard Worker 
709*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
710*03f9172cSAndroid Build Coastguard Worker 	if (ret) {
711*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
712*03f9172cSAndroid Build Coastguard Worker 		return -1;
713*03f9172cSAndroid Build Coastguard Worker 	}
714*03f9172cSAndroid Build Coastguard Worker 
715*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
716*03f9172cSAndroid Build Coastguard Worker 	hapd->conf->qos_map_set_len = count;
717*03f9172cSAndroid Build Coastguard Worker 
718*03f9172cSAndroid Build Coastguard Worker 	return 0;
719*03f9172cSAndroid Build Coastguard Worker }
720*03f9172cSAndroid Build Coastguard Worker 
721*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data * hapd,const char * cmd)722*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
723*03f9172cSAndroid Build Coastguard Worker 						const char *cmd)
724*03f9172cSAndroid Build Coastguard Worker {
725*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
726*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
727*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *buf;
728*03f9172cSAndroid Build Coastguard Worker 	u8 *qos_map_set = hapd->conf->qos_map_set;
729*03f9172cSAndroid Build Coastguard Worker 	u8 qos_map_set_len = hapd->conf->qos_map_set_len;
730*03f9172cSAndroid Build Coastguard Worker 	int ret;
731*03f9172cSAndroid Build Coastguard Worker 
732*03f9172cSAndroid Build Coastguard Worker 	if (!qos_map_set_len) {
733*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "QoS Map Set is not set");
734*03f9172cSAndroid Build Coastguard Worker 		return -1;
735*03f9172cSAndroid Build Coastguard Worker 	}
736*03f9172cSAndroid Build Coastguard Worker 
737*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
738*03f9172cSAndroid Build Coastguard Worker 		return -1;
739*03f9172cSAndroid Build Coastguard Worker 
740*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
741*03f9172cSAndroid Build Coastguard Worker 	if (sta == NULL) {
742*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
743*03f9172cSAndroid Build Coastguard Worker 			   "for QoS Map Configuration message",
744*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(addr));
745*03f9172cSAndroid Build Coastguard Worker 		return -1;
746*03f9172cSAndroid Build Coastguard Worker 	}
747*03f9172cSAndroid Build Coastguard Worker 
748*03f9172cSAndroid Build Coastguard Worker 	if (!sta->qos_map_enabled) {
749*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
750*03f9172cSAndroid Build Coastguard Worker 			   "support for QoS Map", MAC2STR(addr));
751*03f9172cSAndroid Build Coastguard Worker 		return -1;
752*03f9172cSAndroid Build Coastguard Worker 	}
753*03f9172cSAndroid Build Coastguard Worker 
754*03f9172cSAndroid Build Coastguard Worker 	buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
755*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
756*03f9172cSAndroid Build Coastguard Worker 		return -1;
757*03f9172cSAndroid Build Coastguard Worker 
758*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_u8(buf, WLAN_ACTION_QOS);
759*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
760*03f9172cSAndroid Build Coastguard Worker 
761*03f9172cSAndroid Build Coastguard Worker 	/* QoS Map Set Element */
762*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
763*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_u8(buf, qos_map_set_len);
764*03f9172cSAndroid Build Coastguard Worker 	wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
765*03f9172cSAndroid Build Coastguard Worker 
766*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
767*03f9172cSAndroid Build Coastguard Worker 				      wpabuf_head(buf), wpabuf_len(buf));
768*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(buf);
769*03f9172cSAndroid Build Coastguard Worker 
770*03f9172cSAndroid Build Coastguard Worker 	return ret;
771*03f9172cSAndroid Build Coastguard Worker }
772*03f9172cSAndroid Build Coastguard Worker 
773*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_INTERWORKING */
774*03f9172cSAndroid Build Coastguard Worker 
775*03f9172cSAndroid Build Coastguard Worker 
776*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WNM_AP
777*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data * hapd,const char * cmd)778*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd,
779*03f9172cSAndroid Build Coastguard Worker 					     const char *cmd)
780*03f9172cSAndroid Build Coastguard Worker {
781*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
782*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
783*03f9172cSAndroid Build Coastguard Worker 	const char *pos;
784*03f9172cSAndroid Build Coastguard Worker 	unsigned int auto_report, timeout;
785*03f9172cSAndroid Build Coastguard Worker 
786*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr)) {
787*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
788*03f9172cSAndroid Build Coastguard Worker 		return -1;
789*03f9172cSAndroid Build Coastguard Worker 	}
790*03f9172cSAndroid Build Coastguard Worker 
791*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
792*03f9172cSAndroid Build Coastguard Worker 	if (!sta) {
793*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "Station " MACSTR
794*03f9172cSAndroid Build Coastguard Worker 			   " not found for Collocated Interference Request",
795*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(addr));
796*03f9172cSAndroid Build Coastguard Worker 		return -1;
797*03f9172cSAndroid Build Coastguard Worker 	}
798*03f9172cSAndroid Build Coastguard Worker 
799*03f9172cSAndroid Build Coastguard Worker 	pos = cmd + 17;
800*03f9172cSAndroid Build Coastguard Worker 	if (*pos != ' ')
801*03f9172cSAndroid Build Coastguard Worker 		return -1;
802*03f9172cSAndroid Build Coastguard Worker 	pos++;
803*03f9172cSAndroid Build Coastguard Worker 	auto_report = atoi(pos);
804*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
805*03f9172cSAndroid Build Coastguard Worker 	if (!pos)
806*03f9172cSAndroid Build Coastguard Worker 		return -1;
807*03f9172cSAndroid Build Coastguard Worker 	pos++;
808*03f9172cSAndroid Build Coastguard Worker 	timeout = atoi(pos);
809*03f9172cSAndroid Build Coastguard Worker 
810*03f9172cSAndroid Build Coastguard Worker 	return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout);
811*03f9172cSAndroid Build Coastguard Worker }
812*03f9172cSAndroid Build Coastguard Worker 
813*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WNM_AP */
814*03f9172cSAndroid Build Coastguard Worker 
815*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data * hapd,char * buf,size_t buflen)816*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
817*03f9172cSAndroid Build Coastguard Worker 					   char *buf, size_t buflen)
818*03f9172cSAndroid Build Coastguard Worker {
819*03f9172cSAndroid Build Coastguard Worker 	int ret = 0;
820*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
821*03f9172cSAndroid Build Coastguard Worker 
822*03f9172cSAndroid Build Coastguard Worker 	pos = buf;
823*03f9172cSAndroid Build Coastguard Worker 	end = buf + buflen;
824*03f9172cSAndroid Build Coastguard Worker 
825*03f9172cSAndroid Build Coastguard Worker 	WPA_ASSERT(hapd->conf->wpa_key_mgmt);
826*03f9172cSAndroid Build Coastguard Worker 
827*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
828*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "WPA-PSK ");
829*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
830*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
831*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
832*03f9172cSAndroid Build Coastguard Worker 	}
833*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
834*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "WPA-EAP ");
835*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
836*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
837*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
838*03f9172cSAndroid Build Coastguard Worker 	}
839*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R_AP
840*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
841*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FT-PSK ");
842*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
843*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
844*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
845*03f9172cSAndroid Build Coastguard Worker 	}
846*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
847*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FT-EAP ");
848*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
849*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
850*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
851*03f9172cSAndroid Build Coastguard Worker 	}
852*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SHA384
853*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
854*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FT-EAP-SHA384 ");
855*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
856*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
857*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
858*03f9172cSAndroid Build Coastguard Worker 	}
859*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SHA384 */
860*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
861*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
862*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FT-SAE ");
863*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
864*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
865*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
866*03f9172cSAndroid Build Coastguard Worker 	}
867*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
868*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FT-SAE-EXT-KEY ");
869*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
870*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
871*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
872*03f9172cSAndroid Build Coastguard Worker 	}
873*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
874*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
875*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
876*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FT-FILS-SHA256 ");
877*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
878*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
879*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
880*03f9172cSAndroid Build Coastguard Worker 	}
881*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
882*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FT-FILS-SHA384 ");
883*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
884*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
885*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
886*03f9172cSAndroid Build Coastguard Worker 	}
887*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
888*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R_AP */
889*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
890*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
891*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
892*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
893*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
894*03f9172cSAndroid Build Coastguard Worker 	}
895*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
896*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
897*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
898*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
899*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
900*03f9172cSAndroid Build Coastguard Worker 	}
901*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
902*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
903*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "SAE ");
904*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
905*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
906*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
907*03f9172cSAndroid Build Coastguard Worker 	}
908*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
909*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "SAE-EXT-KEY ");
910*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
911*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
912*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
913*03f9172cSAndroid Build Coastguard Worker 	}
914*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
915*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
916*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
917*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
918*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
919*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
920*03f9172cSAndroid Build Coastguard Worker 	}
921*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt &
922*03f9172cSAndroid Build Coastguard Worker 	    WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
923*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos,
924*03f9172cSAndroid Build Coastguard Worker 				  "WPA-EAP-SUITE-B-192 ");
925*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
926*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
927*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
928*03f9172cSAndroid Build Coastguard Worker 	}
929*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
930*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
931*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FILS-SHA256 ");
932*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
933*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
934*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
935*03f9172cSAndroid Build Coastguard Worker 	}
936*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
937*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "FILS-SHA384 ");
938*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
939*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
940*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
941*03f9172cSAndroid Build Coastguard Worker 	}
942*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
943*03f9172cSAndroid Build Coastguard Worker 
944*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_OWE
945*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) {
946*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "OWE ");
947*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
948*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
949*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
950*03f9172cSAndroid Build Coastguard Worker 	}
951*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_OWE */
952*03f9172cSAndroid Build Coastguard Worker 
953*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
954*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
955*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "DPP ");
956*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
957*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
958*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
959*03f9172cSAndroid Build Coastguard Worker 	}
960*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
961*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SHA384
962*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
963*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA384 ");
964*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
965*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
966*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
967*03f9172cSAndroid Build Coastguard Worker 	}
968*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SHA384 */
969*03f9172cSAndroid Build Coastguard Worker 
970*03f9172cSAndroid Build Coastguard Worker 	if (pos > buf && *(pos - 1) == ' ') {
971*03f9172cSAndroid Build Coastguard Worker 		*(pos - 1) = '\0';
972*03f9172cSAndroid Build Coastguard Worker 		pos--;
973*03f9172cSAndroid Build Coastguard Worker 	}
974*03f9172cSAndroid Build Coastguard Worker 
975*03f9172cSAndroid Build Coastguard Worker 	return pos - buf;
976*03f9172cSAndroid Build Coastguard Worker }
977*03f9172cSAndroid Build Coastguard Worker 
978*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_get_config(struct hostapd_data * hapd,char * buf,size_t buflen)979*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
980*03f9172cSAndroid Build Coastguard Worker 					 char *buf, size_t buflen)
981*03f9172cSAndroid Build Coastguard Worker {
982*03f9172cSAndroid Build Coastguard Worker 	int ret;
983*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
984*03f9172cSAndroid Build Coastguard Worker 
985*03f9172cSAndroid Build Coastguard Worker 	pos = buf;
986*03f9172cSAndroid Build Coastguard Worker 	end = buf + buflen;
987*03f9172cSAndroid Build Coastguard Worker 
988*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
989*03f9172cSAndroid Build Coastguard Worker 			  "ssid=%s\n",
990*03f9172cSAndroid Build Coastguard Worker 			  MAC2STR(hapd->own_addr),
991*03f9172cSAndroid Build Coastguard Worker 			  wpa_ssid_txt(hapd->conf->ssid.ssid,
992*03f9172cSAndroid Build Coastguard Worker 				       hapd->conf->ssid.ssid_len));
993*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(end - pos, ret))
994*03f9172cSAndroid Build Coastguard Worker 		return pos - buf;
995*03f9172cSAndroid Build Coastguard Worker 	pos += ret;
996*03f9172cSAndroid Build Coastguard Worker 
997*03f9172cSAndroid Build Coastguard Worker 	if ((hapd->conf->config_id)) {
998*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "config_id=%s\n",
999*03f9172cSAndroid Build Coastguard Worker 				  hapd->conf->config_id);
1000*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1001*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1002*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1003*03f9172cSAndroid Build Coastguard Worker 	}
1004*03f9172cSAndroid Build Coastguard Worker 
1005*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS
1006*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
1007*03f9172cSAndroid Build Coastguard Worker 			  hapd->conf->wps_state == 0 ? "disabled" :
1008*03f9172cSAndroid Build Coastguard Worker 			  (hapd->conf->wps_state == 1 ? "not configured" :
1009*03f9172cSAndroid Build Coastguard Worker 			   "configured"));
1010*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(end - pos, ret))
1011*03f9172cSAndroid Build Coastguard Worker 		return pos - buf;
1012*03f9172cSAndroid Build Coastguard Worker 	pos += ret;
1013*03f9172cSAndroid Build Coastguard Worker 
1014*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wps_state && hapd->conf->wpa &&
1015*03f9172cSAndroid Build Coastguard Worker 	    hapd->conf->ssid.wpa_passphrase) {
1016*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
1017*03f9172cSAndroid Build Coastguard Worker 				  hapd->conf->ssid.wpa_passphrase);
1018*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1019*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1020*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1021*03f9172cSAndroid Build Coastguard Worker 	}
1022*03f9172cSAndroid Build Coastguard Worker 
1023*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wps_state && hapd->conf->wpa &&
1024*03f9172cSAndroid Build Coastguard Worker 	    hapd->conf->ssid.wpa_psk &&
1025*03f9172cSAndroid Build Coastguard Worker 	    hapd->conf->ssid.wpa_psk->group) {
1026*03f9172cSAndroid Build Coastguard Worker 		char hex[PMK_LEN * 2 + 1];
1027*03f9172cSAndroid Build Coastguard Worker 		wpa_snprintf_hex(hex, sizeof(hex),
1028*03f9172cSAndroid Build Coastguard Worker 				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
1029*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
1030*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1031*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1032*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1033*03f9172cSAndroid Build Coastguard Worker 	}
1034*03f9172cSAndroid Build Coastguard Worker 
1035*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->multi_ap) {
1036*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_ssid *ssid = &hapd->conf->multi_ap_backhaul_ssid;
1037*03f9172cSAndroid Build Coastguard Worker 
1038*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "multi_ap=%d\n",
1039*03f9172cSAndroid Build Coastguard Worker 				  hapd->conf->multi_ap);
1040*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1041*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1042*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1043*03f9172cSAndroid Build Coastguard Worker 
1044*03f9172cSAndroid Build Coastguard Worker 		if (ssid->ssid_len) {
1045*03f9172cSAndroid Build Coastguard Worker 			ret = os_snprintf(pos, end - pos,
1046*03f9172cSAndroid Build Coastguard Worker 					  "multi_ap_backhaul_ssid=%s\n",
1047*03f9172cSAndroid Build Coastguard Worker 					  wpa_ssid_txt(ssid->ssid,
1048*03f9172cSAndroid Build Coastguard Worker 						       ssid->ssid_len));
1049*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(end - pos, ret))
1050*03f9172cSAndroid Build Coastguard Worker 				return pos - buf;
1051*03f9172cSAndroid Build Coastguard Worker 			pos += ret;
1052*03f9172cSAndroid Build Coastguard Worker 		}
1053*03f9172cSAndroid Build Coastguard Worker 
1054*03f9172cSAndroid Build Coastguard Worker 		if (hapd->conf->wps_state && hapd->conf->wpa &&
1055*03f9172cSAndroid Build Coastguard Worker 			ssid->wpa_passphrase) {
1056*03f9172cSAndroid Build Coastguard Worker 			ret = os_snprintf(pos, end - pos,
1057*03f9172cSAndroid Build Coastguard Worker 					  "multi_ap_backhaul_wpa_passphrase=%s\n",
1058*03f9172cSAndroid Build Coastguard Worker 					  ssid->wpa_passphrase);
1059*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(end - pos, ret))
1060*03f9172cSAndroid Build Coastguard Worker 				return pos - buf;
1061*03f9172cSAndroid Build Coastguard Worker 			pos += ret;
1062*03f9172cSAndroid Build Coastguard Worker 		}
1063*03f9172cSAndroid Build Coastguard Worker 
1064*03f9172cSAndroid Build Coastguard Worker 		if (hapd->conf->wps_state && hapd->conf->wpa &&
1065*03f9172cSAndroid Build Coastguard Worker 		    ssid->wpa_psk &&
1066*03f9172cSAndroid Build Coastguard Worker 		    ssid->wpa_psk->group) {
1067*03f9172cSAndroid Build Coastguard Worker 			char hex[PMK_LEN * 2 + 1];
1068*03f9172cSAndroid Build Coastguard Worker 
1069*03f9172cSAndroid Build Coastguard Worker 			wpa_snprintf_hex(hex, sizeof(hex), ssid->wpa_psk->psk,
1070*03f9172cSAndroid Build Coastguard Worker 					 PMK_LEN);
1071*03f9172cSAndroid Build Coastguard Worker 			ret = os_snprintf(pos, end - pos,
1072*03f9172cSAndroid Build Coastguard Worker 					  "multi_ap_backhaul_wpa_psk=%s\n",
1073*03f9172cSAndroid Build Coastguard Worker 					  hex);
1074*03f9172cSAndroid Build Coastguard Worker 			forced_memzero(hex, sizeof(hex));
1075*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(end - pos, ret))
1076*03f9172cSAndroid Build Coastguard Worker 				return pos - buf;
1077*03f9172cSAndroid Build Coastguard Worker 			pos += ret;
1078*03f9172cSAndroid Build Coastguard Worker 		}
1079*03f9172cSAndroid Build Coastguard Worker 	}
1080*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS */
1081*03f9172cSAndroid Build Coastguard Worker 
1082*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa) {
1083*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
1084*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1085*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1086*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1087*03f9172cSAndroid Build Coastguard Worker 	}
1088*03f9172cSAndroid Build Coastguard Worker 
1089*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
1090*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "key_mgmt=");
1091*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1092*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1093*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1094*03f9172cSAndroid Build Coastguard Worker 
1095*03f9172cSAndroid Build Coastguard Worker 		pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
1096*03f9172cSAndroid Build Coastguard Worker 
1097*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "\n");
1098*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1099*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1100*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1101*03f9172cSAndroid Build Coastguard Worker 	}
1102*03f9172cSAndroid Build Coastguard Worker 
1103*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa) {
1104*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
1105*03f9172cSAndroid Build Coastguard Worker 				  wpa_cipher_txt(hapd->conf->wpa_group));
1106*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1107*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1108*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1109*03f9172cSAndroid Build Coastguard Worker 	}
1110*03f9172cSAndroid Build Coastguard Worker 
1111*03f9172cSAndroid Build Coastguard Worker 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
1112*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
1113*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1114*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1115*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1116*03f9172cSAndroid Build Coastguard Worker 
1117*03f9172cSAndroid Build Coastguard Worker 		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
1118*03f9172cSAndroid Build Coastguard Worker 					" ");
1119*03f9172cSAndroid Build Coastguard Worker 		if (ret < 0)
1120*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1121*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1122*03f9172cSAndroid Build Coastguard Worker 
1123*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "\n");
1124*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1125*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1126*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1127*03f9172cSAndroid Build Coastguard Worker 	}
1128*03f9172cSAndroid Build Coastguard Worker 
1129*03f9172cSAndroid Build Coastguard Worker 	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1130*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1131*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1132*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1133*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1134*03f9172cSAndroid Build Coastguard Worker 
1135*03f9172cSAndroid Build Coastguard Worker 		ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1136*03f9172cSAndroid Build Coastguard Worker 					" ");
1137*03f9172cSAndroid Build Coastguard Worker 		if (ret < 0)
1138*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1139*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1140*03f9172cSAndroid Build Coastguard Worker 
1141*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "\n");
1142*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1143*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1144*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1145*03f9172cSAndroid Build Coastguard Worker 	}
1146*03f9172cSAndroid Build Coastguard Worker 
1147*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->wpa && hapd->conf->wpa_deny_ptk0_rekey) {
1148*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "wpa_deny_ptk0_rekey=%d\n",
1149*03f9172cSAndroid Build Coastguard Worker 				  hapd->conf->wpa_deny_ptk0_rekey);
1150*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1151*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1152*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1153*03f9172cSAndroid Build Coastguard Worker 	}
1154*03f9172cSAndroid Build Coastguard Worker 
1155*03f9172cSAndroid Build Coastguard Worker 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->extended_key_id) {
1156*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "extended_key_id=%d\n",
1157*03f9172cSAndroid Build Coastguard Worker 				  hapd->conf->extended_key_id);
1158*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1159*03f9172cSAndroid Build Coastguard Worker 			return pos - buf;
1160*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1161*03f9172cSAndroid Build Coastguard Worker 	}
1162*03f9172cSAndroid Build Coastguard Worker 
1163*03f9172cSAndroid Build Coastguard Worker 	return pos - buf;
1164*03f9172cSAndroid Build Coastguard Worker }
1165*03f9172cSAndroid Build Coastguard Worker 
1166*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_set_band(struct hostapd_data * hapd,const char * bands)1167*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
1168*03f9172cSAndroid Build Coastguard Worker 				       const char *bands)
1169*03f9172cSAndroid Build Coastguard Worker {
1170*03f9172cSAndroid Build Coastguard Worker 	union wpa_event_data event;
1171*03f9172cSAndroid Build Coastguard Worker 	u32 setband_mask = WPA_SETBAND_AUTO;
1172*03f9172cSAndroid Build Coastguard Worker 
1173*03f9172cSAndroid Build Coastguard Worker 	/*
1174*03f9172cSAndroid Build Coastguard Worker 	 * For example:
1175*03f9172cSAndroid Build Coastguard Worker 	 *  SET setband 2G,6G
1176*03f9172cSAndroid Build Coastguard Worker 	 *  SET setband 5G
1177*03f9172cSAndroid Build Coastguard Worker 	 *  SET setband AUTO
1178*03f9172cSAndroid Build Coastguard Worker 	 */
1179*03f9172cSAndroid Build Coastguard Worker 	if (!os_strstr(bands, "AUTO")) {
1180*03f9172cSAndroid Build Coastguard Worker 		if (os_strstr(bands, "5G"))
1181*03f9172cSAndroid Build Coastguard Worker 			setband_mask |= WPA_SETBAND_5G;
1182*03f9172cSAndroid Build Coastguard Worker 		if (os_strstr(bands, "6G"))
1183*03f9172cSAndroid Build Coastguard Worker 			setband_mask |= WPA_SETBAND_6G;
1184*03f9172cSAndroid Build Coastguard Worker 		if (os_strstr(bands, "2G"))
1185*03f9172cSAndroid Build Coastguard Worker 			setband_mask |= WPA_SETBAND_2G;
1186*03f9172cSAndroid Build Coastguard Worker 		if (setband_mask == WPA_SETBAND_AUTO)
1187*03f9172cSAndroid Build Coastguard Worker 			return -1;
1188*03f9172cSAndroid Build Coastguard Worker 	}
1189*03f9172cSAndroid Build Coastguard Worker 
1190*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_drv_set_band(hapd, setband_mask) == 0) {
1191*03f9172cSAndroid Build Coastguard Worker 		os_memset(&event, 0, sizeof(event));
1192*03f9172cSAndroid Build Coastguard Worker 		event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
1193*03f9172cSAndroid Build Coastguard Worker 		event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
1194*03f9172cSAndroid Build Coastguard Worker 		wpa_supplicant_event(hapd, EVENT_CHANNEL_LIST_CHANGED, &event);
1195*03f9172cSAndroid Build Coastguard Worker 	}
1196*03f9172cSAndroid Build Coastguard Worker 
1197*03f9172cSAndroid Build Coastguard Worker 	return 0;
1198*03f9172cSAndroid Build Coastguard Worker }
1199*03f9172cSAndroid Build Coastguard Worker 
1200*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_set(struct hostapd_data * hapd,char * cmd)1201*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1202*03f9172cSAndroid Build Coastguard Worker {
1203*03f9172cSAndroid Build Coastguard Worker 	char *value;
1204*03f9172cSAndroid Build Coastguard Worker 	int ret = 0;
1205*03f9172cSAndroid Build Coastguard Worker 
1206*03f9172cSAndroid Build Coastguard Worker 	value = os_strchr(cmd, ' ');
1207*03f9172cSAndroid Build Coastguard Worker 	if (value == NULL)
1208*03f9172cSAndroid Build Coastguard Worker 		return -1;
1209*03f9172cSAndroid Build Coastguard Worker 	*value++ = '\0';
1210*03f9172cSAndroid Build Coastguard Worker 
1211*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1212*03f9172cSAndroid Build Coastguard Worker 	if (0) {
1213*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS_TESTING
1214*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1215*03f9172cSAndroid Build Coastguard Worker 		long int val;
1216*03f9172cSAndroid Build Coastguard Worker 		val = strtol(value, NULL, 0);
1217*03f9172cSAndroid Build Coastguard Worker 		if (val < 0 || val > 0xff) {
1218*03f9172cSAndroid Build Coastguard Worker 			ret = -1;
1219*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
1220*03f9172cSAndroid Build Coastguard Worker 				   "wps_version_number %ld", val);
1221*03f9172cSAndroid Build Coastguard Worker 		} else {
1222*03f9172cSAndroid Build Coastguard Worker 			wps_version_number = val;
1223*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1224*03f9172cSAndroid Build Coastguard Worker 				   "version %u.%u",
1225*03f9172cSAndroid Build Coastguard Worker 				   (wps_version_number & 0xf0) >> 4,
1226*03f9172cSAndroid Build Coastguard Worker 				   wps_version_number & 0x0f);
1227*03f9172cSAndroid Build Coastguard Worker 			hostapd_wps_update_ie(hapd);
1228*03f9172cSAndroid Build Coastguard Worker 		}
1229*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
1230*03f9172cSAndroid Build Coastguard Worker 		wps_testing_stub_cred = atoi(value);
1231*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
1232*03f9172cSAndroid Build Coastguard Worker 			   wps_testing_stub_cred);
1233*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1234*03f9172cSAndroid Build Coastguard Worker 		wps_corrupt_pkhash = atoi(value);
1235*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1236*03f9172cSAndroid Build Coastguard Worker 			   wps_corrupt_pkhash);
1237*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS_TESTING */
1238*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
1239*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1240*03f9172cSAndroid Build Coastguard Worker 		hapd->ext_mgmt_frame_handling = atoi(value);
1241*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
1242*03f9172cSAndroid Build Coastguard Worker 		hapd->ext_eapol_frame_io = atoi(value);
1243*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "force_backlog_bytes") == 0) {
1244*03f9172cSAndroid Build Coastguard Worker 		hapd->force_backlog_bytes = atoi(value);
1245*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
1246*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
1247*03f9172cSAndroid Build Coastguard Worker 		os_free(hapd->dpp_config_obj_override);
1248*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_config_obj_override = os_strdup(value);
1249*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
1250*03f9172cSAndroid Build Coastguard Worker 		os_free(hapd->dpp_discovery_override);
1251*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_discovery_override = os_strdup(value);
1252*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
1253*03f9172cSAndroid Build Coastguard Worker 		os_free(hapd->dpp_groups_override);
1254*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_groups_override = os_strdup(value);
1255*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd,
1256*03f9172cSAndroid Build Coastguard Worker 				 "dpp_ignore_netaccesskey_mismatch") == 0) {
1257*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_ignore_netaccesskey_mismatch = atoi(value);
1258*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
1259*03f9172cSAndroid Build Coastguard Worker 		dpp_test = atoi(value);
1260*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
1261*03f9172cSAndroid Build Coastguard Worker 		dpp_version_override = atoi(value);
1262*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
1263*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
1264*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_MBO
1265*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
1266*03f9172cSAndroid Build Coastguard Worker 		int val;
1267*03f9172cSAndroid Build Coastguard Worker 
1268*03f9172cSAndroid Build Coastguard Worker 		if (!hapd->conf->mbo_enabled)
1269*03f9172cSAndroid Build Coastguard Worker 			return -1;
1270*03f9172cSAndroid Build Coastguard Worker 
1271*03f9172cSAndroid Build Coastguard Worker 		val = atoi(value);
1272*03f9172cSAndroid Build Coastguard Worker 		if (val < 0 || val > MBO_ASSOC_DISALLOW_REASON_LOW_RSSI)
1273*03f9172cSAndroid Build Coastguard Worker 			return -1;
1274*03f9172cSAndroid Build Coastguard Worker 
1275*03f9172cSAndroid Build Coastguard Worker 		hapd->mbo_assoc_disallow = val;
1276*03f9172cSAndroid Build Coastguard Worker 		ieee802_11_update_beacons(hapd->iface);
1277*03f9172cSAndroid Build Coastguard Worker 
1278*03f9172cSAndroid Build Coastguard Worker 		/*
1279*03f9172cSAndroid Build Coastguard Worker 		 * TODO: Need to configure drivers that do AP MLME offload with
1280*03f9172cSAndroid Build Coastguard Worker 		 * disallowing station logic.
1281*03f9172cSAndroid Build Coastguard Worker 		 */
1282*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_MBO */
1283*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
1284*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
1285*03f9172cSAndroid Build Coastguard Worker 		os_free(hapd->dpp_configurator_params);
1286*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_configurator_params = os_strdup(value);
1287*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP2
1288*03f9172cSAndroid Build Coastguard Worker 		dpp_controller_set_params(hapd->iface->interfaces->dpp, value);
1289*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP2 */
1290*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
1291*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_init_max_tries = atoi(value);
1292*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
1293*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_init_retry_time = atoi(value);
1294*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
1295*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_resp_wait_time = atoi(value);
1296*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
1297*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_resp_max_tries = atoi(value);
1298*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
1299*03f9172cSAndroid Build Coastguard Worker 		hapd->dpp_resp_retry_time = atoi(value);
1300*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
1301*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcasecmp(cmd, "setband") == 0) {
1302*03f9172cSAndroid Build Coastguard Worker 		ret = hostapd_ctrl_iface_set_band(hapd, value);
1303*03f9172cSAndroid Build Coastguard Worker 	} else {
1304*03f9172cSAndroid Build Coastguard Worker 		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1305*03f9172cSAndroid Build Coastguard Worker 		if (ret)
1306*03f9172cSAndroid Build Coastguard Worker 			return ret;
1307*03f9172cSAndroid Build Coastguard Worker 
1308*03f9172cSAndroid Build Coastguard Worker 		if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1309*03f9172cSAndroid Build Coastguard Worker 			hostapd_disassoc_deny_mac(hapd);
1310*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
1311*03f9172cSAndroid Build Coastguard Worker 			hostapd_disassoc_accept_mac(hapd);
1312*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcasecmp(cmd, "ssid") == 0) {
1313*03f9172cSAndroid Build Coastguard Worker 			hostapd_neighbor_sync_own_report(hapd);
1314*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
1315*03f9172cSAndroid Build Coastguard Worker 			   os_strncmp(cmd, "wmm_ac_", 7) == 0) {
1316*03f9172cSAndroid Build Coastguard Worker 			hapd->parameter_set_count++;
1317*03f9172cSAndroid Build Coastguard Worker 			if (ieee802_11_update_beacons(hapd->iface))
1318*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_DEBUG,
1319*03f9172cSAndroid Build Coastguard Worker 					   "Failed to update beacons with WMM parameters");
1320*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcmp(cmd, "wpa_passphrase") == 0 ||
1321*03f9172cSAndroid Build Coastguard Worker 			   os_strcmp(cmd, "sae_password") == 0 ||
1322*03f9172cSAndroid Build Coastguard Worker 			   os_strcmp(cmd, "sae_pwe") == 0) {
1323*03f9172cSAndroid Build Coastguard Worker 			if (hapd->started)
1324*03f9172cSAndroid Build Coastguard Worker 				hostapd_setup_sae_pt(hapd->conf);
1325*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcasecmp(cmd, "transition_disable") == 0) {
1326*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_transition_disable(hapd->wpa_auth,
1327*03f9172cSAndroid Build Coastguard Worker 							hapd->conf->transition_disable);
1328*03f9172cSAndroid Build Coastguard Worker 		}
1329*03f9172cSAndroid Build Coastguard Worker 
1330*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
1331*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(cmd, "ft_rsnxe_used") == 0)
1332*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth,
1333*03f9172cSAndroid Build Coastguard Worker 						   hapd->conf->ft_rsnxe_used);
1334*03f9172cSAndroid Build Coastguard Worker 		else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0)
1335*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_ocv_override_freq(
1336*03f9172cSAndroid Build Coastguard Worker 				hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3,
1337*03f9172cSAndroid Build Coastguard Worker 				atoi(value));
1338*03f9172cSAndroid Build Coastguard Worker 		else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0)
1339*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_ocv_override_freq(
1340*03f9172cSAndroid Build Coastguard Worker 				hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1,
1341*03f9172cSAndroid Build Coastguard Worker 				atoi(value));
1342*03f9172cSAndroid Build Coastguard Worker 		else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0)
1343*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_ocv_override_freq(
1344*03f9172cSAndroid Build Coastguard Worker 				hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC,
1345*03f9172cSAndroid Build Coastguard Worker 				atoi(value));
1346*03f9172cSAndroid Build Coastguard Worker 		else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0)
1347*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_ocv_override_freq(
1348*03f9172cSAndroid Build Coastguard Worker 				hapd->wpa_auth,
1349*03f9172cSAndroid Build Coastguard Worker 				WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value));
1350*03f9172cSAndroid Build Coastguard Worker 		else if (os_strcasecmp(cmd, "skip_send_eapol") == 0)
1351*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_skip_send_eapol(hapd->wpa_auth, atoi(value));
1352*03f9172cSAndroid Build Coastguard Worker 		else if (os_strcasecmp(cmd, "enable_eapol_large_timeout") == 0)
1353*03f9172cSAndroid Build Coastguard Worker 			wpa_auth_set_enable_eapol_large_timeout(hapd->wpa_auth, atoi(value));
1354*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
1355*03f9172cSAndroid Build Coastguard Worker 	}
1356*03f9172cSAndroid Build Coastguard Worker 
1357*03f9172cSAndroid Build Coastguard Worker 	return ret;
1358*03f9172cSAndroid Build Coastguard Worker }
1359*03f9172cSAndroid Build Coastguard Worker 
1360*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_get(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)1361*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1362*03f9172cSAndroid Build Coastguard Worker 				  char *buf, size_t buflen)
1363*03f9172cSAndroid Build Coastguard Worker {
1364*03f9172cSAndroid Build Coastguard Worker 	int res;
1365*03f9172cSAndroid Build Coastguard Worker 
1366*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1367*03f9172cSAndroid Build Coastguard Worker 
1368*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "version") == 0) {
1369*03f9172cSAndroid Build Coastguard Worker 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1370*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(buflen, res))
1371*03f9172cSAndroid Build Coastguard Worker 			return -1;
1372*03f9172cSAndroid Build Coastguard Worker 		return res;
1373*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(cmd, "tls_library") == 0) {
1374*03f9172cSAndroid Build Coastguard Worker 		res = tls_get_library_version(buf, buflen);
1375*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(buflen, res))
1376*03f9172cSAndroid Build Coastguard Worker 			return -1;
1377*03f9172cSAndroid Build Coastguard Worker 		return res;
1378*03f9172cSAndroid Build Coastguard Worker 	}
1379*03f9172cSAndroid Build Coastguard Worker 
1380*03f9172cSAndroid Build Coastguard Worker 	return -1;
1381*03f9172cSAndroid Build Coastguard Worker }
1382*03f9172cSAndroid Build Coastguard Worker 
1383*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_enable(struct hostapd_iface * iface)1384*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1385*03f9172cSAndroid Build Coastguard Worker {
1386*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_enable_iface(iface) < 0) {
1387*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Enabling of interface failed");
1388*03f9172cSAndroid Build Coastguard Worker 		return -1;
1389*03f9172cSAndroid Build Coastguard Worker 	}
1390*03f9172cSAndroid Build Coastguard Worker 	return 0;
1391*03f9172cSAndroid Build Coastguard Worker }
1392*03f9172cSAndroid Build Coastguard Worker 
1393*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_reload(struct hostapd_iface * iface)1394*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1395*03f9172cSAndroid Build Coastguard Worker {
1396*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_reload_iface(iface) < 0) {
1397*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Reloading of interface failed");
1398*03f9172cSAndroid Build Coastguard Worker 		return -1;
1399*03f9172cSAndroid Build Coastguard Worker 	}
1400*03f9172cSAndroid Build Coastguard Worker 	return 0;
1401*03f9172cSAndroid Build Coastguard Worker }
1402*03f9172cSAndroid Build Coastguard Worker 
1403*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_reload_bss(struct hostapd_data * bss)1404*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_reload_bss(struct hostapd_data *bss)
1405*03f9172cSAndroid Build Coastguard Worker {
1406*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_reload_bss_only(bss) < 0) {
1407*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Reloading of BSS failed");
1408*03f9172cSAndroid Build Coastguard Worker 		return -1;
1409*03f9172cSAndroid Build Coastguard Worker 	}
1410*03f9172cSAndroid Build Coastguard Worker 	return 0;
1411*03f9172cSAndroid Build Coastguard Worker }
1412*03f9172cSAndroid Build Coastguard Worker 
1413*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_disable(struct hostapd_iface * iface)1414*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1415*03f9172cSAndroid Build Coastguard Worker {
1416*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_disable_iface(iface) < 0) {
1417*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Disabling of interface failed");
1418*03f9172cSAndroid Build Coastguard Worker 		return -1;
1419*03f9172cSAndroid Build Coastguard Worker 	}
1420*03f9172cSAndroid Build Coastguard Worker 	return 0;
1421*03f9172cSAndroid Build Coastguard Worker }
1422*03f9172cSAndroid Build Coastguard Worker 
1423*03f9172cSAndroid Build Coastguard Worker 
1424*03f9172cSAndroid Build Coastguard Worker static int
hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data * hapd,struct sta_info * sta,void * ctx)1425*03f9172cSAndroid Build Coastguard Worker hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd,
1426*03f9172cSAndroid Build Coastguard Worker 					      struct sta_info *sta, void *ctx)
1427*03f9172cSAndroid Build Coastguard Worker {
1428*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_wpa_psk *psk;
1429*03f9172cSAndroid Build Coastguard Worker 	const u8 *pmk;
1430*03f9172cSAndroid Build Coastguard Worker 	int pmk_len;
1431*03f9172cSAndroid Build Coastguard Worker 	int pmk_match;
1432*03f9172cSAndroid Build Coastguard Worker 	int sta_match;
1433*03f9172cSAndroid Build Coastguard Worker 	int bss_match;
1434*03f9172cSAndroid Build Coastguard Worker 	int reason;
1435*03f9172cSAndroid Build Coastguard Worker 
1436*03f9172cSAndroid Build Coastguard Worker 	pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
1437*03f9172cSAndroid Build Coastguard Worker 
1438*03f9172cSAndroid Build Coastguard Worker 	for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) {
1439*03f9172cSAndroid Build Coastguard Worker 		pmk_match = PMK_LEN == pmk_len &&
1440*03f9172cSAndroid Build Coastguard Worker 			os_memcmp(psk->psk, pmk, pmk_len) == 0;
1441*03f9172cSAndroid Build Coastguard Worker 		sta_match = psk->group == 0 &&
1442*03f9172cSAndroid Build Coastguard Worker 			ether_addr_equal(sta->addr, psk->addr);
1443*03f9172cSAndroid Build Coastguard Worker 		bss_match = psk->group == 1;
1444*03f9172cSAndroid Build Coastguard Worker 
1445*03f9172cSAndroid Build Coastguard Worker 		if (pmk_match && (sta_match || bss_match))
1446*03f9172cSAndroid Build Coastguard Worker 			return 0;
1447*03f9172cSAndroid Build Coastguard Worker 	}
1448*03f9172cSAndroid Build Coastguard Worker 
1449*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO, "STA " MACSTR
1450*03f9172cSAndroid Build Coastguard Worker 		   " PSK/passphrase no longer valid - disconnect",
1451*03f9172cSAndroid Build Coastguard Worker 		   MAC2STR(sta->addr));
1452*03f9172cSAndroid Build Coastguard Worker 	reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1453*03f9172cSAndroid Build Coastguard Worker 	hostapd_drv_sta_deauth(hapd, sta->addr, reason);
1454*03f9172cSAndroid Build Coastguard Worker 	ap_sta_deauthenticate(hapd, sta, reason);
1455*03f9172cSAndroid Build Coastguard Worker 
1456*03f9172cSAndroid Build Coastguard Worker 	return 0;
1457*03f9172cSAndroid Build Coastguard Worker }
1458*03f9172cSAndroid Build Coastguard Worker 
1459*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data * hapd)1460*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd)
1461*03f9172cSAndroid Build Coastguard Worker {
1462*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_bss_config *conf = hapd->conf;
1463*03f9172cSAndroid Build Coastguard Worker 	int err;
1464*03f9172cSAndroid Build Coastguard Worker 
1465*03f9172cSAndroid Build Coastguard Worker 	hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
1466*03f9172cSAndroid Build Coastguard Worker 
1467*03f9172cSAndroid Build Coastguard Worker 	err = hostapd_setup_wpa_psk(conf);
1468*03f9172cSAndroid Build Coastguard Worker 	if (err < 0) {
1469*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d",
1470*03f9172cSAndroid Build Coastguard Worker 			   err);
1471*03f9172cSAndroid Build Coastguard Worker 		return -1;
1472*03f9172cSAndroid Build Coastguard Worker 	}
1473*03f9172cSAndroid Build Coastguard Worker 
1474*03f9172cSAndroid Build Coastguard Worker 	ap_for_each_sta(hapd, hostapd_ctrl_iface_kick_mismatch_psk_sta_iter,
1475*03f9172cSAndroid Build Coastguard Worker 			NULL);
1476*03f9172cSAndroid Build Coastguard Worker 
1477*03f9172cSAndroid Build Coastguard Worker 	return 0;
1478*03f9172cSAndroid Build Coastguard Worker }
1479*03f9172cSAndroid Build Coastguard Worker 
1480*03f9172cSAndroid Build Coastguard Worker 
1481*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R_AP
1482*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_get_rxkhs(struct hostapd_data * hapd,char * buf,size_t buflen)1483*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_get_rxkhs(struct hostapd_data *hapd,
1484*03f9172cSAndroid Build Coastguard Worker 					char *buf, size_t buflen)
1485*03f9172cSAndroid Build Coastguard Worker {
1486*03f9172cSAndroid Build Coastguard Worker 	int ret, start_pos;
1487*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
1488*03f9172cSAndroid Build Coastguard Worker 	struct ft_remote_r0kh *r0kh;
1489*03f9172cSAndroid Build Coastguard Worker 	struct ft_remote_r1kh *r1kh;
1490*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_bss_config *conf = hapd->conf;
1491*03f9172cSAndroid Build Coastguard Worker 
1492*03f9172cSAndroid Build Coastguard Worker 	pos = buf;
1493*03f9172cSAndroid Build Coastguard Worker 	end = buf + buflen;
1494*03f9172cSAndroid Build Coastguard Worker 
1495*03f9172cSAndroid Build Coastguard Worker 	for (r0kh = conf->r0kh_list; r0kh; r0kh=r0kh->next) {
1496*03f9172cSAndroid Build Coastguard Worker 		start_pos = pos - buf;
1497*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "r0kh=" MACSTR " ",
1498*03f9172cSAndroid Build Coastguard Worker 				  MAC2STR(r0kh->addr));
1499*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1500*03f9172cSAndroid Build Coastguard Worker 			return start_pos;
1501*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1502*03f9172cSAndroid Build Coastguard Worker 		if (r0kh->id_len + 1 >= (size_t) (end - pos))
1503*03f9172cSAndroid Build Coastguard Worker 			return start_pos;
1504*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(pos, r0kh->id, r0kh->id_len);
1505*03f9172cSAndroid Build Coastguard Worker 		pos += r0kh->id_len;
1506*03f9172cSAndroid Build Coastguard Worker 		*pos++ = ' ';
1507*03f9172cSAndroid Build Coastguard Worker 		pos += wpa_snprintf_hex(pos, end - pos, r0kh->key,
1508*03f9172cSAndroid Build Coastguard Worker 					sizeof(r0kh->key));
1509*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "\n");
1510*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1511*03f9172cSAndroid Build Coastguard Worker 			return start_pos;
1512*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1513*03f9172cSAndroid Build Coastguard Worker 	}
1514*03f9172cSAndroid Build Coastguard Worker 
1515*03f9172cSAndroid Build Coastguard Worker 	for (r1kh = conf->r1kh_list; r1kh; r1kh=r1kh->next) {
1516*03f9172cSAndroid Build Coastguard Worker 		start_pos = pos - buf;
1517*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "r1kh=" MACSTR " " MACSTR " ",
1518*03f9172cSAndroid Build Coastguard Worker 			MAC2STR(r1kh->addr), MAC2STR(r1kh->id));
1519*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1520*03f9172cSAndroid Build Coastguard Worker 			return start_pos;
1521*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1522*03f9172cSAndroid Build Coastguard Worker 		pos += wpa_snprintf_hex(pos, end - pos, r1kh->key,
1523*03f9172cSAndroid Build Coastguard Worker 					sizeof(r1kh->key));
1524*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "\n");
1525*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
1526*03f9172cSAndroid Build Coastguard Worker 			return start_pos;
1527*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
1528*03f9172cSAndroid Build Coastguard Worker 	}
1529*03f9172cSAndroid Build Coastguard Worker 
1530*03f9172cSAndroid Build Coastguard Worker 	return pos - buf;
1531*03f9172cSAndroid Build Coastguard Worker }
1532*03f9172cSAndroid Build Coastguard Worker 
1533*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_reload_rxkhs(struct hostapd_data * hapd)1534*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_reload_rxkhs(struct hostapd_data *hapd)
1535*03f9172cSAndroid Build Coastguard Worker {
1536*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_bss_config *conf = hapd->conf;
1537*03f9172cSAndroid Build Coastguard Worker 	int err;
1538*03f9172cSAndroid Build Coastguard Worker 
1539*03f9172cSAndroid Build Coastguard Worker 	hostapd_config_clear_rxkhs(conf);
1540*03f9172cSAndroid Build Coastguard Worker 
1541*03f9172cSAndroid Build Coastguard Worker 	err = hostapd_config_read_rxkh_file(conf, conf->rxkh_file);
1542*03f9172cSAndroid Build Coastguard Worker 	if (err < 0) {
1543*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Reloading RxKHs failed: %d",
1544*03f9172cSAndroid Build Coastguard Worker 			   err);
1545*03f9172cSAndroid Build Coastguard Worker 		return -1;
1546*03f9172cSAndroid Build Coastguard Worker 	}
1547*03f9172cSAndroid Build Coastguard Worker 
1548*03f9172cSAndroid Build Coastguard Worker 	return 0;
1549*03f9172cSAndroid Build Coastguard Worker }
1550*03f9172cSAndroid Build Coastguard Worker 
1551*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R_AP */
1552*03f9172cSAndroid Build Coastguard Worker 
1553*03f9172cSAndroid Build Coastguard Worker 
1554*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
1555*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_radar(struct hostapd_data * hapd,char * cmd)1556*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1557*03f9172cSAndroid Build Coastguard Worker {
1558*03f9172cSAndroid Build Coastguard Worker 	union wpa_event_data data;
1559*03f9172cSAndroid Build Coastguard Worker 	char *pos, *param;
1560*03f9172cSAndroid Build Coastguard Worker 	enum wpa_event_type event;
1561*03f9172cSAndroid Build Coastguard Worker 
1562*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1563*03f9172cSAndroid Build Coastguard Worker 
1564*03f9172cSAndroid Build Coastguard Worker 	os_memset(&data, 0, sizeof(data));
1565*03f9172cSAndroid Build Coastguard Worker 
1566*03f9172cSAndroid Build Coastguard Worker 	param = os_strchr(cmd, ' ');
1567*03f9172cSAndroid Build Coastguard Worker 	if (param == NULL)
1568*03f9172cSAndroid Build Coastguard Worker 		return -1;
1569*03f9172cSAndroid Build Coastguard Worker 	*param++ = '\0';
1570*03f9172cSAndroid Build Coastguard Worker 
1571*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "DETECTED") == 0)
1572*03f9172cSAndroid Build Coastguard Worker 		event = EVENT_DFS_RADAR_DETECTED;
1573*03f9172cSAndroid Build Coastguard Worker 	else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1574*03f9172cSAndroid Build Coastguard Worker 		event = EVENT_DFS_CAC_FINISHED;
1575*03f9172cSAndroid Build Coastguard Worker 	else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1576*03f9172cSAndroid Build Coastguard Worker 		event = EVENT_DFS_CAC_ABORTED;
1577*03f9172cSAndroid Build Coastguard Worker 	else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1578*03f9172cSAndroid Build Coastguard Worker 		event = EVENT_DFS_NOP_FINISHED;
1579*03f9172cSAndroid Build Coastguard Worker 	else {
1580*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1581*03f9172cSAndroid Build Coastguard Worker 			   cmd);
1582*03f9172cSAndroid Build Coastguard Worker 		return -1;
1583*03f9172cSAndroid Build Coastguard Worker 	}
1584*03f9172cSAndroid Build Coastguard Worker 
1585*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(param, "freq=");
1586*03f9172cSAndroid Build Coastguard Worker 	if (pos)
1587*03f9172cSAndroid Build Coastguard Worker 		data.dfs_event.freq = atoi(pos + 5);
1588*03f9172cSAndroid Build Coastguard Worker 
1589*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(param, "ht_enabled=1");
1590*03f9172cSAndroid Build Coastguard Worker 	if (pos)
1591*03f9172cSAndroid Build Coastguard Worker 		data.dfs_event.ht_enabled = 1;
1592*03f9172cSAndroid Build Coastguard Worker 
1593*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(param, "chan_offset=");
1594*03f9172cSAndroid Build Coastguard Worker 	if (pos)
1595*03f9172cSAndroid Build Coastguard Worker 		data.dfs_event.chan_offset = atoi(pos + 12);
1596*03f9172cSAndroid Build Coastguard Worker 
1597*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(param, "chan_width=");
1598*03f9172cSAndroid Build Coastguard Worker 	if (pos)
1599*03f9172cSAndroid Build Coastguard Worker 		data.dfs_event.chan_width = atoi(pos + 11);
1600*03f9172cSAndroid Build Coastguard Worker 
1601*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(param, "cf1=");
1602*03f9172cSAndroid Build Coastguard Worker 	if (pos)
1603*03f9172cSAndroid Build Coastguard Worker 		data.dfs_event.cf1 = atoi(pos + 4);
1604*03f9172cSAndroid Build Coastguard Worker 
1605*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(param, "cf2=");
1606*03f9172cSAndroid Build Coastguard Worker 	if (pos)
1607*03f9172cSAndroid Build Coastguard Worker 		data.dfs_event.cf2 = atoi(pos + 4);
1608*03f9172cSAndroid Build Coastguard Worker 
1609*03f9172cSAndroid Build Coastguard Worker 	wpa_supplicant_event(hapd, event, &data);
1610*03f9172cSAndroid Build Coastguard Worker 
1611*03f9172cSAndroid Build Coastguard Worker 	return 0;
1612*03f9172cSAndroid Build Coastguard Worker }
1613*03f9172cSAndroid Build Coastguard Worker 
1614*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_mgmt_tx(struct hostapd_data * hapd,char * cmd)1615*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1616*03f9172cSAndroid Build Coastguard Worker {
1617*03f9172cSAndroid Build Coastguard Worker 	size_t len;
1618*03f9172cSAndroid Build Coastguard Worker 	u8 *buf;
1619*03f9172cSAndroid Build Coastguard Worker 	int res;
1620*03f9172cSAndroid Build Coastguard Worker 
1621*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1622*03f9172cSAndroid Build Coastguard Worker 
1623*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(cmd);
1624*03f9172cSAndroid Build Coastguard Worker 	if (len & 1)
1625*03f9172cSAndroid Build Coastguard Worker 		return -1;
1626*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
1627*03f9172cSAndroid Build Coastguard Worker 
1628*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
1629*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
1630*03f9172cSAndroid Build Coastguard Worker 		return -1;
1631*03f9172cSAndroid Build Coastguard Worker 
1632*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(cmd, buf, len) < 0) {
1633*03f9172cSAndroid Build Coastguard Worker 		os_free(buf);
1634*03f9172cSAndroid Build Coastguard Worker 		return -1;
1635*03f9172cSAndroid Build Coastguard Worker 	}
1636*03f9172cSAndroid Build Coastguard Worker 
1637*03f9172cSAndroid Build Coastguard Worker 	res = hostapd_drv_send_mlme(hapd, buf, len, 0, NULL, 0, 0);
1638*03f9172cSAndroid Build Coastguard Worker 	os_free(buf);
1639*03f9172cSAndroid Build Coastguard Worker 	return res;
1640*03f9172cSAndroid Build Coastguard Worker }
1641*03f9172cSAndroid Build Coastguard Worker 
1642*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data * hapd,char * cmd)1643*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data *hapd,
1644*03f9172cSAndroid Build Coastguard Worker 						     char *cmd)
1645*03f9172cSAndroid Build Coastguard Worker {
1646*03f9172cSAndroid Build Coastguard Worker 	char *pos, *param;
1647*03f9172cSAndroid Build Coastguard Worker 	size_t len;
1648*03f9172cSAndroid Build Coastguard Worker 	u8 *buf;
1649*03f9172cSAndroid Build Coastguard Worker 	int stype = 0, ok = 0;
1650*03f9172cSAndroid Build Coastguard Worker 	union wpa_event_data event;
1651*03f9172cSAndroid Build Coastguard Worker 
1652*03f9172cSAndroid Build Coastguard Worker 	if (!hapd->ext_mgmt_frame_handling)
1653*03f9172cSAndroid Build Coastguard Worker 		return -1;
1654*03f9172cSAndroid Build Coastguard Worker 
1655*03f9172cSAndroid Build Coastguard Worker 	/* stype=<val> ok=<0/1> buf=<frame hexdump> */
1656*03f9172cSAndroid Build Coastguard Worker 
1657*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "External MGMT TX status process: %s", cmd);
1658*03f9172cSAndroid Build Coastguard Worker 
1659*03f9172cSAndroid Build Coastguard Worker 	pos = cmd;
1660*03f9172cSAndroid Build Coastguard Worker 	param = os_strstr(pos, "stype=");
1661*03f9172cSAndroid Build Coastguard Worker 	if (param) {
1662*03f9172cSAndroid Build Coastguard Worker 		param += 6;
1663*03f9172cSAndroid Build Coastguard Worker 		stype = atoi(param);
1664*03f9172cSAndroid Build Coastguard Worker 	}
1665*03f9172cSAndroid Build Coastguard Worker 
1666*03f9172cSAndroid Build Coastguard Worker 	param = os_strstr(pos, " ok=");
1667*03f9172cSAndroid Build Coastguard Worker 	if (param) {
1668*03f9172cSAndroid Build Coastguard Worker 		param += 4;
1669*03f9172cSAndroid Build Coastguard Worker 		ok = atoi(param);
1670*03f9172cSAndroid Build Coastguard Worker 	}
1671*03f9172cSAndroid Build Coastguard Worker 
1672*03f9172cSAndroid Build Coastguard Worker 	param = os_strstr(pos, " buf=");
1673*03f9172cSAndroid Build Coastguard Worker 	if (!param)
1674*03f9172cSAndroid Build Coastguard Worker 		return -1;
1675*03f9172cSAndroid Build Coastguard Worker 	param += 5;
1676*03f9172cSAndroid Build Coastguard Worker 
1677*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(param);
1678*03f9172cSAndroid Build Coastguard Worker 	if (len & 1)
1679*03f9172cSAndroid Build Coastguard Worker 		return -1;
1680*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
1681*03f9172cSAndroid Build Coastguard Worker 
1682*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
1683*03f9172cSAndroid Build Coastguard Worker 	if (!buf || hexstr2bin(param, buf, len) < 0) {
1684*03f9172cSAndroid Build Coastguard Worker 		os_free(buf);
1685*03f9172cSAndroid Build Coastguard Worker 		return -1;
1686*03f9172cSAndroid Build Coastguard Worker 	}
1687*03f9172cSAndroid Build Coastguard Worker 
1688*03f9172cSAndroid Build Coastguard Worker 	os_memset(&event, 0, sizeof(event));
1689*03f9172cSAndroid Build Coastguard Worker 	event.tx_status.type = WLAN_FC_TYPE_MGMT;
1690*03f9172cSAndroid Build Coastguard Worker 	event.tx_status.data = buf;
1691*03f9172cSAndroid Build Coastguard Worker 	event.tx_status.data_len = len;
1692*03f9172cSAndroid Build Coastguard Worker 	event.tx_status.stype = stype;
1693*03f9172cSAndroid Build Coastguard Worker 	event.tx_status.ack = ok;
1694*03f9172cSAndroid Build Coastguard Worker 	hapd->ext_mgmt_frame_handling = 0;
1695*03f9172cSAndroid Build Coastguard Worker 	wpa_supplicant_event(hapd, EVENT_TX_STATUS, &event);
1696*03f9172cSAndroid Build Coastguard Worker 	hapd->ext_mgmt_frame_handling = 1;
1697*03f9172cSAndroid Build Coastguard Worker 
1698*03f9172cSAndroid Build Coastguard Worker 	os_free(buf);
1699*03f9172cSAndroid Build Coastguard Worker 
1700*03f9172cSAndroid Build Coastguard Worker 	return 0;
1701*03f9172cSAndroid Build Coastguard Worker }
1702*03f9172cSAndroid Build Coastguard Worker 
1703*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data * hapd,char * cmd)1704*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd,
1705*03f9172cSAndroid Build Coastguard Worker 					      char *cmd)
1706*03f9172cSAndroid Build Coastguard Worker {
1707*03f9172cSAndroid Build Coastguard Worker 	char *pos, *param;
1708*03f9172cSAndroid Build Coastguard Worker 	size_t len;
1709*03f9172cSAndroid Build Coastguard Worker 	u8 *buf;
1710*03f9172cSAndroid Build Coastguard Worker 	int freq = 0, datarate = 0, ssi_signal = 0;
1711*03f9172cSAndroid Build Coastguard Worker 	union wpa_event_data event;
1712*03f9172cSAndroid Build Coastguard Worker 
1713*03f9172cSAndroid Build Coastguard Worker 	if (!hapd->ext_mgmt_frame_handling)
1714*03f9172cSAndroid Build Coastguard Worker 		return -1;
1715*03f9172cSAndroid Build Coastguard Worker 
1716*03f9172cSAndroid Build Coastguard Worker 	/* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
1717*03f9172cSAndroid Build Coastguard Worker 
1718*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
1719*03f9172cSAndroid Build Coastguard Worker 
1720*03f9172cSAndroid Build Coastguard Worker 	pos = cmd;
1721*03f9172cSAndroid Build Coastguard Worker 	param = os_strstr(pos, "freq=");
1722*03f9172cSAndroid Build Coastguard Worker 	if (param) {
1723*03f9172cSAndroid Build Coastguard Worker 		param += 5;
1724*03f9172cSAndroid Build Coastguard Worker 		freq = atoi(param);
1725*03f9172cSAndroid Build Coastguard Worker 	}
1726*03f9172cSAndroid Build Coastguard Worker 
1727*03f9172cSAndroid Build Coastguard Worker 	param = os_strstr(pos, " datarate=");
1728*03f9172cSAndroid Build Coastguard Worker 	if (param) {
1729*03f9172cSAndroid Build Coastguard Worker 		param += 10;
1730*03f9172cSAndroid Build Coastguard Worker 		datarate = atoi(param);
1731*03f9172cSAndroid Build Coastguard Worker 	}
1732*03f9172cSAndroid Build Coastguard Worker 
1733*03f9172cSAndroid Build Coastguard Worker 	param = os_strstr(pos, " ssi_signal=");
1734*03f9172cSAndroid Build Coastguard Worker 	if (param) {
1735*03f9172cSAndroid Build Coastguard Worker 		param += 12;
1736*03f9172cSAndroid Build Coastguard Worker 		ssi_signal = atoi(param);
1737*03f9172cSAndroid Build Coastguard Worker 	}
1738*03f9172cSAndroid Build Coastguard Worker 
1739*03f9172cSAndroid Build Coastguard Worker 	param = os_strstr(pos, " frame=");
1740*03f9172cSAndroid Build Coastguard Worker 	if (param == NULL)
1741*03f9172cSAndroid Build Coastguard Worker 		return -1;
1742*03f9172cSAndroid Build Coastguard Worker 	param += 7;
1743*03f9172cSAndroid Build Coastguard Worker 
1744*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(param);
1745*03f9172cSAndroid Build Coastguard Worker 	if (len & 1)
1746*03f9172cSAndroid Build Coastguard Worker 		return -1;
1747*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
1748*03f9172cSAndroid Build Coastguard Worker 
1749*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
1750*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
1751*03f9172cSAndroid Build Coastguard Worker 		return -1;
1752*03f9172cSAndroid Build Coastguard Worker 
1753*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(param, buf, len) < 0) {
1754*03f9172cSAndroid Build Coastguard Worker 		os_free(buf);
1755*03f9172cSAndroid Build Coastguard Worker 		return -1;
1756*03f9172cSAndroid Build Coastguard Worker 	}
1757*03f9172cSAndroid Build Coastguard Worker 
1758*03f9172cSAndroid Build Coastguard Worker 	os_memset(&event, 0, sizeof(event));
1759*03f9172cSAndroid Build Coastguard Worker 	event.rx_mgmt.freq = freq;
1760*03f9172cSAndroid Build Coastguard Worker 	event.rx_mgmt.frame = buf;
1761*03f9172cSAndroid Build Coastguard Worker 	event.rx_mgmt.frame_len = len;
1762*03f9172cSAndroid Build Coastguard Worker 	event.rx_mgmt.ssi_signal = ssi_signal;
1763*03f9172cSAndroid Build Coastguard Worker 	event.rx_mgmt.datarate = datarate;
1764*03f9172cSAndroid Build Coastguard Worker 	hapd->ext_mgmt_frame_handling = 0;
1765*03f9172cSAndroid Build Coastguard Worker 	wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event);
1766*03f9172cSAndroid Build Coastguard Worker 	hapd->ext_mgmt_frame_handling = 1;
1767*03f9172cSAndroid Build Coastguard Worker 
1768*03f9172cSAndroid Build Coastguard Worker 	os_free(buf);
1769*03f9172cSAndroid Build Coastguard Worker 
1770*03f9172cSAndroid Build Coastguard Worker 	return 0;
1771*03f9172cSAndroid Build Coastguard Worker }
1772*03f9172cSAndroid Build Coastguard Worker 
1773*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_eapol_rx(struct hostapd_data * hapd,char * cmd)1774*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1775*03f9172cSAndroid Build Coastguard Worker {
1776*03f9172cSAndroid Build Coastguard Worker 	char *pos;
1777*03f9172cSAndroid Build Coastguard Worker 	u8 src[ETH_ALEN], *buf;
1778*03f9172cSAndroid Build Coastguard Worker 	int used;
1779*03f9172cSAndroid Build Coastguard Worker 	size_t len;
1780*03f9172cSAndroid Build Coastguard Worker 
1781*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1782*03f9172cSAndroid Build Coastguard Worker 
1783*03f9172cSAndroid Build Coastguard Worker 	pos = cmd;
1784*03f9172cSAndroid Build Coastguard Worker 	used = hwaddr_aton2(pos, src);
1785*03f9172cSAndroid Build Coastguard Worker 	if (used < 0)
1786*03f9172cSAndroid Build Coastguard Worker 		return -1;
1787*03f9172cSAndroid Build Coastguard Worker 	pos += used;
1788*03f9172cSAndroid Build Coastguard Worker 	while (*pos == ' ')
1789*03f9172cSAndroid Build Coastguard Worker 		pos++;
1790*03f9172cSAndroid Build Coastguard Worker 
1791*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(pos);
1792*03f9172cSAndroid Build Coastguard Worker 	if (len & 1)
1793*03f9172cSAndroid Build Coastguard Worker 		return -1;
1794*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
1795*03f9172cSAndroid Build Coastguard Worker 
1796*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
1797*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
1798*03f9172cSAndroid Build Coastguard Worker 		return -1;
1799*03f9172cSAndroid Build Coastguard Worker 
1800*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(pos, buf, len) < 0) {
1801*03f9172cSAndroid Build Coastguard Worker 		os_free(buf);
1802*03f9172cSAndroid Build Coastguard Worker 		return -1;
1803*03f9172cSAndroid Build Coastguard Worker 	}
1804*03f9172cSAndroid Build Coastguard Worker 
1805*03f9172cSAndroid Build Coastguard Worker 	ieee802_1x_receive(hapd, src, buf, len, FRAME_ENCRYPTION_UNKNOWN);
1806*03f9172cSAndroid Build Coastguard Worker 	os_free(buf);
1807*03f9172cSAndroid Build Coastguard Worker 
1808*03f9172cSAndroid Build Coastguard Worker 	return 0;
1809*03f9172cSAndroid Build Coastguard Worker }
1810*03f9172cSAndroid Build Coastguard Worker 
1811*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_eapol_tx(struct hostapd_data * hapd,char * cmd)1812*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_eapol_tx(struct hostapd_data *hapd, char *cmd)
1813*03f9172cSAndroid Build Coastguard Worker {
1814*03f9172cSAndroid Build Coastguard Worker 	char *pos, *pos2;
1815*03f9172cSAndroid Build Coastguard Worker 	u8 dst[ETH_ALEN], *buf;
1816*03f9172cSAndroid Build Coastguard Worker 	int used, ret;
1817*03f9172cSAndroid Build Coastguard Worker 	size_t len;
1818*03f9172cSAndroid Build Coastguard Worker 	unsigned int prev;
1819*03f9172cSAndroid Build Coastguard Worker 	int encrypt = 0;
1820*03f9172cSAndroid Build Coastguard Worker 
1821*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
1822*03f9172cSAndroid Build Coastguard Worker 
1823*03f9172cSAndroid Build Coastguard Worker 	pos = cmd;
1824*03f9172cSAndroid Build Coastguard Worker 	used = hwaddr_aton2(pos, dst);
1825*03f9172cSAndroid Build Coastguard Worker 	if (used < 0)
1826*03f9172cSAndroid Build Coastguard Worker 		return -1;
1827*03f9172cSAndroid Build Coastguard Worker 	pos += used;
1828*03f9172cSAndroid Build Coastguard Worker 	while (*pos == ' ')
1829*03f9172cSAndroid Build Coastguard Worker 		pos++;
1830*03f9172cSAndroid Build Coastguard Worker 
1831*03f9172cSAndroid Build Coastguard Worker 	pos2 = os_strchr(pos, ' ');
1832*03f9172cSAndroid Build Coastguard Worker 	if (pos2) {
1833*03f9172cSAndroid Build Coastguard Worker 		len = pos2 - pos;
1834*03f9172cSAndroid Build Coastguard Worker 		encrypt = os_strstr(pos2, "encrypt=1") != NULL;
1835*03f9172cSAndroid Build Coastguard Worker 	} else {
1836*03f9172cSAndroid Build Coastguard Worker 		len = os_strlen(pos);
1837*03f9172cSAndroid Build Coastguard Worker 	}
1838*03f9172cSAndroid Build Coastguard Worker 	if (len & 1)
1839*03f9172cSAndroid Build Coastguard Worker 		return -1;
1840*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
1841*03f9172cSAndroid Build Coastguard Worker 
1842*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
1843*03f9172cSAndroid Build Coastguard Worker 	if (!buf || hexstr2bin(pos, buf, len) < 0) {
1844*03f9172cSAndroid Build Coastguard Worker 		os_free(buf);
1845*03f9172cSAndroid Build Coastguard Worker 		return -1;
1846*03f9172cSAndroid Build Coastguard Worker 	}
1847*03f9172cSAndroid Build Coastguard Worker 
1848*03f9172cSAndroid Build Coastguard Worker 	prev = hapd->ext_eapol_frame_io;
1849*03f9172cSAndroid Build Coastguard Worker 	hapd->ext_eapol_frame_io = 0;
1850*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_wpa_auth_send_eapol(hapd, dst, buf, len, encrypt);
1851*03f9172cSAndroid Build Coastguard Worker 	hapd->ext_eapol_frame_io = prev;
1852*03f9172cSAndroid Build Coastguard Worker 	os_free(buf);
1853*03f9172cSAndroid Build Coastguard Worker 
1854*03f9172cSAndroid Build Coastguard Worker 	return ret;
1855*03f9172cSAndroid Build Coastguard Worker }
1856*03f9172cSAndroid Build Coastguard Worker 
1857*03f9172cSAndroid Build Coastguard Worker 
ipv4_hdr_checksum(const void * buf,size_t len)1858*03f9172cSAndroid Build Coastguard Worker static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1859*03f9172cSAndroid Build Coastguard Worker {
1860*03f9172cSAndroid Build Coastguard Worker 	size_t i;
1861*03f9172cSAndroid Build Coastguard Worker 	u32 sum = 0;
1862*03f9172cSAndroid Build Coastguard Worker 	const u16 *pos = buf;
1863*03f9172cSAndroid Build Coastguard Worker 
1864*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < len / 2; i++)
1865*03f9172cSAndroid Build Coastguard Worker 		sum += *pos++;
1866*03f9172cSAndroid Build Coastguard Worker 
1867*03f9172cSAndroid Build Coastguard Worker 	while (sum >> 16)
1868*03f9172cSAndroid Build Coastguard Worker 		sum = (sum & 0xffff) + (sum >> 16);
1869*03f9172cSAndroid Build Coastguard Worker 
1870*03f9172cSAndroid Build Coastguard Worker 	return sum ^ 0xffff;
1871*03f9172cSAndroid Build Coastguard Worker }
1872*03f9172cSAndroid Build Coastguard Worker 
1873*03f9172cSAndroid Build Coastguard Worker 
1874*03f9172cSAndroid Build Coastguard Worker #define HWSIM_PACKETLEN 1500
1875*03f9172cSAndroid Build Coastguard Worker #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1876*03f9172cSAndroid Build Coastguard Worker 
hostapd_data_test_rx(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)1877*03f9172cSAndroid Build Coastguard Worker static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1878*03f9172cSAndroid Build Coastguard Worker 				 size_t len)
1879*03f9172cSAndroid Build Coastguard Worker {
1880*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd = ctx;
1881*03f9172cSAndroid Build Coastguard Worker 	const struct ether_header *eth;
1882*03f9172cSAndroid Build Coastguard Worker 	struct ip ip;
1883*03f9172cSAndroid Build Coastguard Worker 	const u8 *pos;
1884*03f9172cSAndroid Build Coastguard Worker 	unsigned int i;
1885*03f9172cSAndroid Build Coastguard Worker 	char extra[30];
1886*03f9172cSAndroid Build Coastguard Worker 
1887*03f9172cSAndroid Build Coastguard Worker 	if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
1888*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
1889*03f9172cSAndroid Build Coastguard Worker 			   "test data: RX - ignore unexpected length %d",
1890*03f9172cSAndroid Build Coastguard Worker 			   (int) len);
1891*03f9172cSAndroid Build Coastguard Worker 		return;
1892*03f9172cSAndroid Build Coastguard Worker 	}
1893*03f9172cSAndroid Build Coastguard Worker 
1894*03f9172cSAndroid Build Coastguard Worker 	eth = (const struct ether_header *) buf;
1895*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(&ip, eth + 1, sizeof(ip));
1896*03f9172cSAndroid Build Coastguard Worker 	pos = &buf[sizeof(*eth) + sizeof(ip)];
1897*03f9172cSAndroid Build Coastguard Worker 
1898*03f9172cSAndroid Build Coastguard Worker 	if (ip.ip_hl != 5 || ip.ip_v != 4 ||
1899*03f9172cSAndroid Build Coastguard Worker 	    ntohs(ip.ip_len) > HWSIM_IP_LEN) {
1900*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
1901*03f9172cSAndroid Build Coastguard Worker 			   "test data: RX - ignore unexpected IP header");
1902*03f9172cSAndroid Build Coastguard Worker 		return;
1903*03f9172cSAndroid Build Coastguard Worker 	}
1904*03f9172cSAndroid Build Coastguard Worker 
1905*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
1906*03f9172cSAndroid Build Coastguard Worker 		if (*pos != (u8) i) {
1907*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG,
1908*03f9172cSAndroid Build Coastguard Worker 				   "test data: RX - ignore mismatching payload");
1909*03f9172cSAndroid Build Coastguard Worker 			return;
1910*03f9172cSAndroid Build Coastguard Worker 		}
1911*03f9172cSAndroid Build Coastguard Worker 		pos++;
1912*03f9172cSAndroid Build Coastguard Worker 	}
1913*03f9172cSAndroid Build Coastguard Worker 
1914*03f9172cSAndroid Build Coastguard Worker 	extra[0] = '\0';
1915*03f9172cSAndroid Build Coastguard Worker 	if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
1916*03f9172cSAndroid Build Coastguard Worker 		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
1917*03f9172cSAndroid Build Coastguard Worker 	wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
1918*03f9172cSAndroid Build Coastguard Worker 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
1919*03f9172cSAndroid Build Coastguard Worker }
1920*03f9172cSAndroid Build Coastguard Worker 
1921*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_data_test_config(struct hostapd_data * hapd,char * cmd)1922*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1923*03f9172cSAndroid Build Coastguard Worker 					       char *cmd)
1924*03f9172cSAndroid Build Coastguard Worker {
1925*03f9172cSAndroid Build Coastguard Worker 	int enabled = atoi(cmd);
1926*03f9172cSAndroid Build Coastguard Worker 	char *pos;
1927*03f9172cSAndroid Build Coastguard Worker 	const char *ifname;
1928*03f9172cSAndroid Build Coastguard Worker 	const u8 *addr = hapd->own_addr;
1929*03f9172cSAndroid Build Coastguard Worker 
1930*03f9172cSAndroid Build Coastguard Worker 	if (!enabled) {
1931*03f9172cSAndroid Build Coastguard Worker 		if (hapd->l2_test) {
1932*03f9172cSAndroid Build Coastguard Worker 			l2_packet_deinit(hapd->l2_test);
1933*03f9172cSAndroid Build Coastguard Worker 			hapd->l2_test = NULL;
1934*03f9172cSAndroid Build Coastguard Worker 			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1935*03f9172cSAndroid Build Coastguard Worker 				"test data: Disabled");
1936*03f9172cSAndroid Build Coastguard Worker 		}
1937*03f9172cSAndroid Build Coastguard Worker 		return 0;
1938*03f9172cSAndroid Build Coastguard Worker 	}
1939*03f9172cSAndroid Build Coastguard Worker 
1940*03f9172cSAndroid Build Coastguard Worker 	if (hapd->l2_test)
1941*03f9172cSAndroid Build Coastguard Worker 		return 0;
1942*03f9172cSAndroid Build Coastguard Worker 
1943*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(cmd, " ifname=");
1944*03f9172cSAndroid Build Coastguard Worker 	if (pos)
1945*03f9172cSAndroid Build Coastguard Worker 		ifname = pos + 8;
1946*03f9172cSAndroid Build Coastguard Worker 	else
1947*03f9172cSAndroid Build Coastguard Worker 		ifname = hapd->conf->iface;
1948*03f9172cSAndroid Build Coastguard Worker 
1949*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211BE
1950*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->mld_ap)
1951*03f9172cSAndroid Build Coastguard Worker 		addr = hapd->mld->mld_addr;
1952*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211BE */
1953*03f9172cSAndroid Build Coastguard Worker 	hapd->l2_test = l2_packet_init(ifname, addr,
1954*03f9172cSAndroid Build Coastguard Worker 					ETHERTYPE_IP, hostapd_data_test_rx,
1955*03f9172cSAndroid Build Coastguard Worker 					hapd, 1);
1956*03f9172cSAndroid Build Coastguard Worker 	if (hapd->l2_test == NULL)
1957*03f9172cSAndroid Build Coastguard Worker 		return -1;
1958*03f9172cSAndroid Build Coastguard Worker 
1959*03f9172cSAndroid Build Coastguard Worker 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1960*03f9172cSAndroid Build Coastguard Worker 
1961*03f9172cSAndroid Build Coastguard Worker 	return 0;
1962*03f9172cSAndroid Build Coastguard Worker }
1963*03f9172cSAndroid Build Coastguard Worker 
1964*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_data_test_tx(struct hostapd_data * hapd,char * cmd)1965*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1966*03f9172cSAndroid Build Coastguard Worker {
1967*03f9172cSAndroid Build Coastguard Worker 	u8 dst[ETH_ALEN], src[ETH_ALEN];
1968*03f9172cSAndroid Build Coastguard Worker 	char *pos, *pos2;
1969*03f9172cSAndroid Build Coastguard Worker 	int used;
1970*03f9172cSAndroid Build Coastguard Worker 	long int val;
1971*03f9172cSAndroid Build Coastguard Worker 	u8 tos;
1972*03f9172cSAndroid Build Coastguard Worker 	u8 buf[2 + HWSIM_PACKETLEN];
1973*03f9172cSAndroid Build Coastguard Worker 	struct ether_header *eth;
1974*03f9172cSAndroid Build Coastguard Worker 	struct ip *ip;
1975*03f9172cSAndroid Build Coastguard Worker 	u8 *dpos;
1976*03f9172cSAndroid Build Coastguard Worker 	unsigned int i;
1977*03f9172cSAndroid Build Coastguard Worker 	size_t send_len = HWSIM_IP_LEN;
1978*03f9172cSAndroid Build Coastguard Worker 
1979*03f9172cSAndroid Build Coastguard Worker 	if (hapd->l2_test == NULL)
1980*03f9172cSAndroid Build Coastguard Worker 		return -1;
1981*03f9172cSAndroid Build Coastguard Worker 
1982*03f9172cSAndroid Build Coastguard Worker 	/* format: <dst> <src> <tos> [len=<length>] */
1983*03f9172cSAndroid Build Coastguard Worker 
1984*03f9172cSAndroid Build Coastguard Worker 	pos = cmd;
1985*03f9172cSAndroid Build Coastguard Worker 	used = hwaddr_aton2(pos, dst);
1986*03f9172cSAndroid Build Coastguard Worker 	if (used < 0)
1987*03f9172cSAndroid Build Coastguard Worker 		return -1;
1988*03f9172cSAndroid Build Coastguard Worker 	pos += used;
1989*03f9172cSAndroid Build Coastguard Worker 	while (*pos == ' ')
1990*03f9172cSAndroid Build Coastguard Worker 		pos++;
1991*03f9172cSAndroid Build Coastguard Worker 	used = hwaddr_aton2(pos, src);
1992*03f9172cSAndroid Build Coastguard Worker 	if (used < 0)
1993*03f9172cSAndroid Build Coastguard Worker 		return -1;
1994*03f9172cSAndroid Build Coastguard Worker 	pos += used;
1995*03f9172cSAndroid Build Coastguard Worker 
1996*03f9172cSAndroid Build Coastguard Worker 	val = strtol(pos, &pos2, 0);
1997*03f9172cSAndroid Build Coastguard Worker 	if (val < 0 || val > 0xff)
1998*03f9172cSAndroid Build Coastguard Worker 		return -1;
1999*03f9172cSAndroid Build Coastguard Worker 	tos = val;
2000*03f9172cSAndroid Build Coastguard Worker 
2001*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(pos2, " len=");
2002*03f9172cSAndroid Build Coastguard Worker 	if (pos) {
2003*03f9172cSAndroid Build Coastguard Worker 		i = atoi(pos + 5);
2004*03f9172cSAndroid Build Coastguard Worker 		if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
2005*03f9172cSAndroid Build Coastguard Worker 			return -1;
2006*03f9172cSAndroid Build Coastguard Worker 		send_len = i;
2007*03f9172cSAndroid Build Coastguard Worker 	}
2008*03f9172cSAndroid Build Coastguard Worker 
2009*03f9172cSAndroid Build Coastguard Worker 	eth = (struct ether_header *) &buf[2];
2010*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
2011*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
2012*03f9172cSAndroid Build Coastguard Worker 	eth->ether_type = htons(ETHERTYPE_IP);
2013*03f9172cSAndroid Build Coastguard Worker 	ip = (struct ip *) (eth + 1);
2014*03f9172cSAndroid Build Coastguard Worker 	os_memset(ip, 0, sizeof(*ip));
2015*03f9172cSAndroid Build Coastguard Worker 	ip->ip_hl = 5;
2016*03f9172cSAndroid Build Coastguard Worker 	ip->ip_v = 4;
2017*03f9172cSAndroid Build Coastguard Worker 	ip->ip_ttl = 64;
2018*03f9172cSAndroid Build Coastguard Worker 	ip->ip_tos = tos;
2019*03f9172cSAndroid Build Coastguard Worker 	ip->ip_len = htons(send_len);
2020*03f9172cSAndroid Build Coastguard Worker 	ip->ip_p = 1;
2021*03f9172cSAndroid Build Coastguard Worker 	ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
2022*03f9172cSAndroid Build Coastguard Worker 	ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
2023*03f9172cSAndroid Build Coastguard Worker 	ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
2024*03f9172cSAndroid Build Coastguard Worker 	dpos = (u8 *) (ip + 1);
2025*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < send_len - sizeof(*ip); i++)
2026*03f9172cSAndroid Build Coastguard Worker 		*dpos++ = i;
2027*03f9172cSAndroid Build Coastguard Worker 
2028*03f9172cSAndroid Build Coastguard Worker 	if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
2029*03f9172cSAndroid Build Coastguard Worker 			   sizeof(struct ether_header) + send_len) < 0)
2030*03f9172cSAndroid Build Coastguard Worker 		return -1;
2031*03f9172cSAndroid Build Coastguard Worker 
2032*03f9172cSAndroid Build Coastguard Worker 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
2033*03f9172cSAndroid Build Coastguard Worker 		" src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
2034*03f9172cSAndroid Build Coastguard Worker 
2035*03f9172cSAndroid Build Coastguard Worker 	return 0;
2036*03f9172cSAndroid Build Coastguard Worker }
2037*03f9172cSAndroid Build Coastguard Worker 
2038*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_data_test_frame(struct hostapd_data * hapd,char * cmd)2039*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
2040*03f9172cSAndroid Build Coastguard Worker 					      char *cmd)
2041*03f9172cSAndroid Build Coastguard Worker {
2042*03f9172cSAndroid Build Coastguard Worker 	u8 *buf;
2043*03f9172cSAndroid Build Coastguard Worker 	struct ether_header *eth;
2044*03f9172cSAndroid Build Coastguard Worker 	struct l2_packet_data *l2 = NULL;
2045*03f9172cSAndroid Build Coastguard Worker 	size_t len;
2046*03f9172cSAndroid Build Coastguard Worker 	u16 ethertype;
2047*03f9172cSAndroid Build Coastguard Worker 	int res = -1;
2048*03f9172cSAndroid Build Coastguard Worker 	const char *ifname = hapd->conf->iface;
2049*03f9172cSAndroid Build Coastguard Worker 
2050*03f9172cSAndroid Build Coastguard Worker 	if (os_strncmp(cmd, "ifname=", 7) == 0) {
2051*03f9172cSAndroid Build Coastguard Worker 		cmd += 7;
2052*03f9172cSAndroid Build Coastguard Worker 		ifname = cmd;
2053*03f9172cSAndroid Build Coastguard Worker 		cmd = os_strchr(cmd, ' ');
2054*03f9172cSAndroid Build Coastguard Worker 		if (cmd == NULL)
2055*03f9172cSAndroid Build Coastguard Worker 			return -1;
2056*03f9172cSAndroid Build Coastguard Worker 		*cmd++ = '\0';
2057*03f9172cSAndroid Build Coastguard Worker 	}
2058*03f9172cSAndroid Build Coastguard Worker 
2059*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(cmd);
2060*03f9172cSAndroid Build Coastguard Worker 	if (len & 1 || len < ETH_HLEN * 2)
2061*03f9172cSAndroid Build Coastguard Worker 		return -1;
2062*03f9172cSAndroid Build Coastguard Worker 	len /= 2;
2063*03f9172cSAndroid Build Coastguard Worker 
2064*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
2065*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
2066*03f9172cSAndroid Build Coastguard Worker 		return -1;
2067*03f9172cSAndroid Build Coastguard Worker 
2068*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(cmd, buf, len) < 0)
2069*03f9172cSAndroid Build Coastguard Worker 		goto done;
2070*03f9172cSAndroid Build Coastguard Worker 
2071*03f9172cSAndroid Build Coastguard Worker 	eth = (struct ether_header *) buf;
2072*03f9172cSAndroid Build Coastguard Worker 	ethertype = ntohs(eth->ether_type);
2073*03f9172cSAndroid Build Coastguard Worker 
2074*03f9172cSAndroid Build Coastguard Worker 	l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
2075*03f9172cSAndroid Build Coastguard Worker 			    hostapd_data_test_rx, hapd, 1);
2076*03f9172cSAndroid Build Coastguard Worker 	if (l2 == NULL)
2077*03f9172cSAndroid Build Coastguard Worker 		goto done;
2078*03f9172cSAndroid Build Coastguard Worker 
2079*03f9172cSAndroid Build Coastguard Worker 	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
2080*03f9172cSAndroid Build Coastguard Worker 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
2081*03f9172cSAndroid Build Coastguard Worker done:
2082*03f9172cSAndroid Build Coastguard Worker 	if (l2)
2083*03f9172cSAndroid Build Coastguard Worker 		l2_packet_deinit(l2);
2084*03f9172cSAndroid Build Coastguard Worker 	os_free(buf);
2085*03f9172cSAndroid Build Coastguard Worker 
2086*03f9172cSAndroid Build Coastguard Worker 	return res < 0 ? -1 : 0;
2087*03f9172cSAndroid Build Coastguard Worker }
2088*03f9172cSAndroid Build Coastguard Worker 
2089*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_reset_pn(struct hostapd_data * hapd,const char * cmd)2090*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
2091*03f9172cSAndroid Build Coastguard Worker {
2092*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
2093*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
2094*03f9172cSAndroid Build Coastguard Worker 	u8 zero[WPA_TK_MAX_LEN];
2095*03f9172cSAndroid Build Coastguard Worker 
2096*03f9172cSAndroid Build Coastguard Worker 	os_memset(zero, 0, sizeof(zero));
2097*03f9172cSAndroid Build Coastguard Worker 
2098*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
2099*03f9172cSAndroid Build Coastguard Worker 		return -1;
2100*03f9172cSAndroid Build Coastguard Worker 
2101*03f9172cSAndroid Build Coastguard Worker 	if (is_broadcast_ether_addr(addr) && os_strstr(cmd, " BIGTK")) {
2102*03f9172cSAndroid Build Coastguard Worker 		if (hapd->last_bigtk_alg == WPA_ALG_NONE)
2103*03f9172cSAndroid Build Coastguard Worker 			return -1;
2104*03f9172cSAndroid Build Coastguard Worker 
2105*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "TESTING: Reset BIPN for BIGTK");
2106*03f9172cSAndroid Build Coastguard Worker 
2107*03f9172cSAndroid Build Coastguard Worker 		/* First, use a zero key to avoid any possible duplicate key
2108*03f9172cSAndroid Build Coastguard Worker 		 * avoidance in the driver. */
2109*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2110*03f9172cSAndroid Build Coastguard Worker 					hapd->last_bigtk_alg,
2111*03f9172cSAndroid Build Coastguard Worker 					broadcast_ether_addr,
2112*03f9172cSAndroid Build Coastguard Worker 					hapd->last_bigtk_key_idx, 0, 1, NULL, 0,
2113*03f9172cSAndroid Build Coastguard Worker 					zero, hapd->last_bigtk_len,
2114*03f9172cSAndroid Build Coastguard Worker 					KEY_FLAG_GROUP_TX_DEFAULT) < 0)
2115*03f9172cSAndroid Build Coastguard Worker 			return -1;
2116*03f9172cSAndroid Build Coastguard Worker 
2117*03f9172cSAndroid Build Coastguard Worker 		/* Set the previously configured key to reset its TSC */
2118*03f9172cSAndroid Build Coastguard Worker 		return hostapd_drv_set_key(hapd->conf->iface, hapd,
2119*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_bigtk_alg,
2120*03f9172cSAndroid Build Coastguard Worker 					   broadcast_ether_addr,
2121*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_bigtk_key_idx, 0, 1, NULL,
2122*03f9172cSAndroid Build Coastguard Worker 					   0, hapd->last_bigtk,
2123*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_bigtk_len,
2124*03f9172cSAndroid Build Coastguard Worker 					   KEY_FLAG_GROUP_TX_DEFAULT);
2125*03f9172cSAndroid Build Coastguard Worker 	}
2126*03f9172cSAndroid Build Coastguard Worker 
2127*03f9172cSAndroid Build Coastguard Worker 	if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
2128*03f9172cSAndroid Build Coastguard Worker 		if (hapd->last_igtk_alg == WPA_ALG_NONE)
2129*03f9172cSAndroid Build Coastguard Worker 			return -1;
2130*03f9172cSAndroid Build Coastguard Worker 
2131*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "TESTING: Reset IPN for IGTK");
2132*03f9172cSAndroid Build Coastguard Worker 
2133*03f9172cSAndroid Build Coastguard Worker 		/* First, use a zero key to avoid any possible duplicate key
2134*03f9172cSAndroid Build Coastguard Worker 		 * avoidance in the driver. */
2135*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2136*03f9172cSAndroid Build Coastguard Worker 					hapd->last_igtk_alg,
2137*03f9172cSAndroid Build Coastguard Worker 					broadcast_ether_addr,
2138*03f9172cSAndroid Build Coastguard Worker 					hapd->last_igtk_key_idx, 0, 1, NULL, 0,
2139*03f9172cSAndroid Build Coastguard Worker 					zero, hapd->last_igtk_len,
2140*03f9172cSAndroid Build Coastguard Worker 					KEY_FLAG_GROUP_TX_DEFAULT) < 0)
2141*03f9172cSAndroid Build Coastguard Worker 			return -1;
2142*03f9172cSAndroid Build Coastguard Worker 
2143*03f9172cSAndroid Build Coastguard Worker 		/* Set the previously configured key to reset its TSC */
2144*03f9172cSAndroid Build Coastguard Worker 		return hostapd_drv_set_key(hapd->conf->iface, hapd,
2145*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_igtk_alg,
2146*03f9172cSAndroid Build Coastguard Worker 					   broadcast_ether_addr,
2147*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_igtk_key_idx, 0, 1, NULL,
2148*03f9172cSAndroid Build Coastguard Worker 					   0, hapd->last_igtk,
2149*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_igtk_len,
2150*03f9172cSAndroid Build Coastguard Worker 					   KEY_FLAG_GROUP_TX_DEFAULT);
2151*03f9172cSAndroid Build Coastguard Worker 	}
2152*03f9172cSAndroid Build Coastguard Worker 
2153*03f9172cSAndroid Build Coastguard Worker 	if (is_broadcast_ether_addr(addr)) {
2154*03f9172cSAndroid Build Coastguard Worker 		if (hapd->last_gtk_alg == WPA_ALG_NONE)
2155*03f9172cSAndroid Build Coastguard Worker 			return -1;
2156*03f9172cSAndroid Build Coastguard Worker 
2157*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "TESTING: Reset PN for GTK");
2158*03f9172cSAndroid Build Coastguard Worker 
2159*03f9172cSAndroid Build Coastguard Worker 		/* First, use a zero key to avoid any possible duplicate key
2160*03f9172cSAndroid Build Coastguard Worker 		 * avoidance in the driver. */
2161*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2162*03f9172cSAndroid Build Coastguard Worker 					hapd->last_gtk_alg,
2163*03f9172cSAndroid Build Coastguard Worker 					broadcast_ether_addr,
2164*03f9172cSAndroid Build Coastguard Worker 					hapd->last_gtk_key_idx, 0, 1, NULL, 0,
2165*03f9172cSAndroid Build Coastguard Worker 					zero, hapd->last_gtk_len,
2166*03f9172cSAndroid Build Coastguard Worker 					KEY_FLAG_GROUP_TX_DEFAULT) < 0)
2167*03f9172cSAndroid Build Coastguard Worker 			return -1;
2168*03f9172cSAndroid Build Coastguard Worker 
2169*03f9172cSAndroid Build Coastguard Worker 		/* Set the previously configured key to reset its TSC */
2170*03f9172cSAndroid Build Coastguard Worker 		return hostapd_drv_set_key(hapd->conf->iface, hapd,
2171*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_gtk_alg,
2172*03f9172cSAndroid Build Coastguard Worker 					   broadcast_ether_addr,
2173*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_gtk_key_idx, 0, 1, NULL,
2174*03f9172cSAndroid Build Coastguard Worker 					   0, hapd->last_gtk,
2175*03f9172cSAndroid Build Coastguard Worker 					   hapd->last_gtk_len,
2176*03f9172cSAndroid Build Coastguard Worker 					   KEY_FLAG_GROUP_TX_DEFAULT);
2177*03f9172cSAndroid Build Coastguard Worker 	}
2178*03f9172cSAndroid Build Coastguard Worker 
2179*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
2180*03f9172cSAndroid Build Coastguard Worker 	if (!sta)
2181*03f9172cSAndroid Build Coastguard Worker 		return -1;
2182*03f9172cSAndroid Build Coastguard Worker 
2183*03f9172cSAndroid Build Coastguard Worker 	if (sta->last_tk_alg == WPA_ALG_NONE)
2184*03f9172cSAndroid Build Coastguard Worker 		return -1;
2185*03f9172cSAndroid Build Coastguard Worker 
2186*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO, "TESTING: Reset PN for " MACSTR,
2187*03f9172cSAndroid Build Coastguard Worker 		   MAC2STR(sta->addr));
2188*03f9172cSAndroid Build Coastguard Worker 
2189*03f9172cSAndroid Build Coastguard Worker 	/* First, use a zero key to avoid any possible duplicate key avoidance
2190*03f9172cSAndroid Build Coastguard Worker 	 * in the driver. */
2191*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2192*03f9172cSAndroid Build Coastguard Worker 				sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
2193*03f9172cSAndroid Build Coastguard Worker 				zero, sta->last_tk_len,
2194*03f9172cSAndroid Build Coastguard Worker 				KEY_FLAG_PAIRWISE_RX_TX) < 0)
2195*03f9172cSAndroid Build Coastguard Worker 		return -1;
2196*03f9172cSAndroid Build Coastguard Worker 
2197*03f9172cSAndroid Build Coastguard Worker 	/* Set the previously configured key to reset its TSC/RSC */
2198*03f9172cSAndroid Build Coastguard Worker 	return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2199*03f9172cSAndroid Build Coastguard Worker 				   sta->addr, sta->last_tk_key_idx, 0, 1, NULL,
2200*03f9172cSAndroid Build Coastguard Worker 				   0, sta->last_tk, sta->last_tk_len,
2201*03f9172cSAndroid Build Coastguard Worker 				   KEY_FLAG_PAIRWISE_RX_TX);
2202*03f9172cSAndroid Build Coastguard Worker }
2203*03f9172cSAndroid Build Coastguard Worker 
2204*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_set_key(struct hostapd_data * hapd,const char * cmd)2205*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
2206*03f9172cSAndroid Build Coastguard Worker {
2207*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
2208*03f9172cSAndroid Build Coastguard Worker 	const char *pos = cmd;
2209*03f9172cSAndroid Build Coastguard Worker 	enum wpa_alg alg;
2210*03f9172cSAndroid Build Coastguard Worker 	enum key_flag key_flag;
2211*03f9172cSAndroid Build Coastguard Worker 	int idx, set_tx;
2212*03f9172cSAndroid Build Coastguard Worker 	u8 seq[6], key[WPA_TK_MAX_LEN];
2213*03f9172cSAndroid Build Coastguard Worker 	size_t key_len;
2214*03f9172cSAndroid Build Coastguard Worker 
2215*03f9172cSAndroid Build Coastguard Worker 	/* parameters: alg addr idx set_tx seq key key_flag */
2216*03f9172cSAndroid Build Coastguard Worker 
2217*03f9172cSAndroid Build Coastguard Worker 	alg = atoi(pos);
2218*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
2219*03f9172cSAndroid Build Coastguard Worker 	if (!pos)
2220*03f9172cSAndroid Build Coastguard Worker 		return -1;
2221*03f9172cSAndroid Build Coastguard Worker 	pos++;
2222*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(pos, addr))
2223*03f9172cSAndroid Build Coastguard Worker 		return -1;
2224*03f9172cSAndroid Build Coastguard Worker 	pos += 17;
2225*03f9172cSAndroid Build Coastguard Worker 	if (*pos != ' ')
2226*03f9172cSAndroid Build Coastguard Worker 		return -1;
2227*03f9172cSAndroid Build Coastguard Worker 	pos++;
2228*03f9172cSAndroid Build Coastguard Worker 	idx = atoi(pos);
2229*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
2230*03f9172cSAndroid Build Coastguard Worker 	if (!pos)
2231*03f9172cSAndroid Build Coastguard Worker 		return -1;
2232*03f9172cSAndroid Build Coastguard Worker 	pos++;
2233*03f9172cSAndroid Build Coastguard Worker 	set_tx = atoi(pos);
2234*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
2235*03f9172cSAndroid Build Coastguard Worker 	if (!pos)
2236*03f9172cSAndroid Build Coastguard Worker 		return -1;
2237*03f9172cSAndroid Build Coastguard Worker 	pos++;
2238*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(pos, seq, sizeof(seq)) < 0)
2239*03f9172cSAndroid Build Coastguard Worker 		return -1;
2240*03f9172cSAndroid Build Coastguard Worker 	pos += 2 * 6;
2241*03f9172cSAndroid Build Coastguard Worker 	if (*pos != ' ')
2242*03f9172cSAndroid Build Coastguard Worker 		return -1;
2243*03f9172cSAndroid Build Coastguard Worker 	pos++;
2244*03f9172cSAndroid Build Coastguard Worker 	if (!os_strchr(pos, ' '))
2245*03f9172cSAndroid Build Coastguard Worker 		return -1;
2246*03f9172cSAndroid Build Coastguard Worker 	key_len = (os_strchr(pos, ' ') - pos) / 2;
2247*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(pos, key, key_len) < 0)
2248*03f9172cSAndroid Build Coastguard Worker 		return -1;
2249*03f9172cSAndroid Build Coastguard Worker 	pos += 2 * key_len;
2250*03f9172cSAndroid Build Coastguard Worker 	if (*pos != ' ')
2251*03f9172cSAndroid Build Coastguard Worker 		return -1;
2252*03f9172cSAndroid Build Coastguard Worker 
2253*03f9172cSAndroid Build Coastguard Worker 	pos++;
2254*03f9172cSAndroid Build Coastguard Worker 	key_flag = atoi(pos);
2255*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
2256*03f9172cSAndroid Build Coastguard Worker 	if (pos)
2257*03f9172cSAndroid Build Coastguard Worker 		return -1;
2258*03f9172cSAndroid Build Coastguard Worker 
2259*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO, "TESTING: Set key");
2260*03f9172cSAndroid Build Coastguard Worker 	return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx, 0,
2261*03f9172cSAndroid Build Coastguard Worker 				   set_tx, seq, 6, key, key_len, key_flag);
2262*03f9172cSAndroid Build Coastguard Worker }
2263*03f9172cSAndroid Build Coastguard Worker 
2264*03f9172cSAndroid Build Coastguard Worker 
restore_tk(void * ctx1,void * ctx2)2265*03f9172cSAndroid Build Coastguard Worker static void restore_tk(void *ctx1, void *ctx2)
2266*03f9172cSAndroid Build Coastguard Worker {
2267*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd = ctx1;
2268*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta = ctx2;
2269*03f9172cSAndroid Build Coastguard Worker 
2270*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR,
2271*03f9172cSAndroid Build Coastguard Worker 		   MAC2STR(sta->addr));
2272*03f9172cSAndroid Build Coastguard Worker 	/* This does not really restore the TSC properly, so this will result
2273*03f9172cSAndroid Build Coastguard Worker 	 * in replay protection issues for now since there is no clean way of
2274*03f9172cSAndroid Build Coastguard Worker 	 * preventing encryption of a single EAPOL frame. */
2275*03f9172cSAndroid Build Coastguard Worker 	hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2276*03f9172cSAndroid Build Coastguard Worker 			    sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
2277*03f9172cSAndroid Build Coastguard Worker 			    sta->last_tk, sta->last_tk_len,
2278*03f9172cSAndroid Build Coastguard Worker 			    KEY_FLAG_PAIRWISE_RX_TX);
2279*03f9172cSAndroid Build Coastguard Worker }
2280*03f9172cSAndroid Build Coastguard Worker 
2281*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_resend_m1(struct hostapd_data * hapd,const char * cmd)2282*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
2283*03f9172cSAndroid Build Coastguard Worker {
2284*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
2285*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
2286*03f9172cSAndroid Build Coastguard Worker 	int plain = os_strstr(cmd, "plaintext") != NULL;
2287*03f9172cSAndroid Build Coastguard Worker 
2288*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
2289*03f9172cSAndroid Build Coastguard Worker 		return -1;
2290*03f9172cSAndroid Build Coastguard Worker 
2291*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
2292*03f9172cSAndroid Build Coastguard Worker 	if (!sta || !sta->wpa_sm)
2293*03f9172cSAndroid Build Coastguard Worker 		return -1;
2294*03f9172cSAndroid Build Coastguard Worker 
2295*03f9172cSAndroid Build Coastguard Worker 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2296*03f9172cSAndroid Build Coastguard Worker 		plain = 0; /* no need for special processing */
2297*03f9172cSAndroid Build Coastguard Worker 	if (plain) {
2298*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2299*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(sta->addr));
2300*03f9172cSAndroid Build Coastguard Worker 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2301*03f9172cSAndroid Build Coastguard Worker 				    sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
2302*03f9172cSAndroid Build Coastguard Worker 				    0, NULL, 0, KEY_FLAG_PAIRWISE);
2303*03f9172cSAndroid Build Coastguard Worker 	}
2304*03f9172cSAndroid Build Coastguard Worker 
2305*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
2306*03f9172cSAndroid Build Coastguard Worker 	return wpa_auth_resend_m1(sta->wpa_sm,
2307*03f9172cSAndroid Build Coastguard Worker 				  os_strstr(cmd, "change-anonce") != NULL,
2308*03f9172cSAndroid Build Coastguard Worker 				  plain ? restore_tk : NULL, hapd, sta);
2309*03f9172cSAndroid Build Coastguard Worker }
2310*03f9172cSAndroid Build Coastguard Worker 
2311*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_resend_m3(struct hostapd_data * hapd,const char * cmd)2312*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
2313*03f9172cSAndroid Build Coastguard Worker {
2314*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
2315*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
2316*03f9172cSAndroid Build Coastguard Worker 	int plain = os_strstr(cmd, "plaintext") != NULL;
2317*03f9172cSAndroid Build Coastguard Worker 
2318*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
2319*03f9172cSAndroid Build Coastguard Worker 		return -1;
2320*03f9172cSAndroid Build Coastguard Worker 
2321*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
2322*03f9172cSAndroid Build Coastguard Worker 	if (!sta || !sta->wpa_sm)
2323*03f9172cSAndroid Build Coastguard Worker 		return -1;
2324*03f9172cSAndroid Build Coastguard Worker 
2325*03f9172cSAndroid Build Coastguard Worker 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2326*03f9172cSAndroid Build Coastguard Worker 		plain = 0; /* no need for special processing */
2327*03f9172cSAndroid Build Coastguard Worker 	if (plain) {
2328*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2329*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(sta->addr));
2330*03f9172cSAndroid Build Coastguard Worker 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2331*03f9172cSAndroid Build Coastguard Worker 				    sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
2332*03f9172cSAndroid Build Coastguard Worker 				    0, NULL, 0, KEY_FLAG_PAIRWISE);
2333*03f9172cSAndroid Build Coastguard Worker 	}
2334*03f9172cSAndroid Build Coastguard Worker 
2335*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
2336*03f9172cSAndroid Build Coastguard Worker 	return wpa_auth_resend_m3(sta->wpa_sm,
2337*03f9172cSAndroid Build Coastguard Worker 				  plain ? restore_tk : NULL, hapd, sta);
2338*03f9172cSAndroid Build Coastguard Worker }
2339*03f9172cSAndroid Build Coastguard Worker 
2340*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_resend_group_m1(struct hostapd_data * hapd,const char * cmd)2341*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
2342*03f9172cSAndroid Build Coastguard Worker 					const char *cmd)
2343*03f9172cSAndroid Build Coastguard Worker {
2344*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
2345*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
2346*03f9172cSAndroid Build Coastguard Worker 	int plain = os_strstr(cmd, "plaintext") != NULL;
2347*03f9172cSAndroid Build Coastguard Worker 
2348*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
2349*03f9172cSAndroid Build Coastguard Worker 		return -1;
2350*03f9172cSAndroid Build Coastguard Worker 
2351*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
2352*03f9172cSAndroid Build Coastguard Worker 	if (!sta || !sta->wpa_sm)
2353*03f9172cSAndroid Build Coastguard Worker 		return -1;
2354*03f9172cSAndroid Build Coastguard Worker 
2355*03f9172cSAndroid Build Coastguard Worker 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2356*03f9172cSAndroid Build Coastguard Worker 		plain = 0; /* no need for special processing */
2357*03f9172cSAndroid Build Coastguard Worker 	if (plain) {
2358*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2359*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(sta->addr));
2360*03f9172cSAndroid Build Coastguard Worker 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2361*03f9172cSAndroid Build Coastguard Worker 				    sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
2362*03f9172cSAndroid Build Coastguard Worker 				    0, NULL, 0, KEY_FLAG_PAIRWISE);
2363*03f9172cSAndroid Build Coastguard Worker 	}
2364*03f9172cSAndroid Build Coastguard Worker 
2365*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO,
2366*03f9172cSAndroid Build Coastguard Worker 		   "TESTING: Send group M1 for the same GTK and zero RSC to "
2367*03f9172cSAndroid Build Coastguard Worker 		   MACSTR, MAC2STR(sta->addr));
2368*03f9172cSAndroid Build Coastguard Worker 	return wpa_auth_resend_group_m1(sta->wpa_sm,
2369*03f9172cSAndroid Build Coastguard Worker 					plain ? restore_tk : NULL, hapd, sta);
2370*03f9172cSAndroid Build Coastguard Worker }
2371*03f9172cSAndroid Build Coastguard Worker 
2372*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_rekey_ptk(struct hostapd_data * hapd,const char * cmd)2373*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_rekey_ptk(struct hostapd_data *hapd, const char *cmd)
2374*03f9172cSAndroid Build Coastguard Worker {
2375*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
2376*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
2377*03f9172cSAndroid Build Coastguard Worker 
2378*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
2379*03f9172cSAndroid Build Coastguard Worker 		return -1;
2380*03f9172cSAndroid Build Coastguard Worker 
2381*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
2382*03f9172cSAndroid Build Coastguard Worker 	if (!sta || !sta->wpa_sm)
2383*03f9172cSAndroid Build Coastguard Worker 		return -1;
2384*03f9172cSAndroid Build Coastguard Worker 
2385*03f9172cSAndroid Build Coastguard Worker 	return wpa_auth_rekey_ptk(hapd->wpa_auth, sta->wpa_sm);
2386*03f9172cSAndroid Build Coastguard Worker }
2387*03f9172cSAndroid Build Coastguard Worker 
2388*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_get_pmksa_pmk(struct hostapd_data * hapd,const u8 * addr,char * buf,size_t buflen)2389*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr,
2390*03f9172cSAndroid Build Coastguard Worker 				      char *buf, size_t buflen)
2391*03f9172cSAndroid Build Coastguard Worker {
2392*03f9172cSAndroid Build Coastguard Worker 	struct rsn_pmksa_cache_entry *pmksa;
2393*03f9172cSAndroid Build Coastguard Worker 
2394*03f9172cSAndroid Build Coastguard Worker 	pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, addr, NULL);
2395*03f9172cSAndroid Build Coastguard Worker 	if (!pmksa)
2396*03f9172cSAndroid Build Coastguard Worker 		return -1;
2397*03f9172cSAndroid Build Coastguard Worker 
2398*03f9172cSAndroid Build Coastguard Worker 	return wpa_snprintf_hex(buf, buflen, pmksa->pmk, pmksa->pmk_len);
2399*03f9172cSAndroid Build Coastguard Worker }
2400*03f9172cSAndroid Build Coastguard Worker 
2401*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_get_pmk(struct hostapd_data * hapd,const char * cmd,char * buf,size_t buflen)2402*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
2403*03f9172cSAndroid Build Coastguard Worker 				char *buf, size_t buflen)
2404*03f9172cSAndroid Build Coastguard Worker {
2405*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
2406*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
2407*03f9172cSAndroid Build Coastguard Worker 	const u8 *pmk;
2408*03f9172cSAndroid Build Coastguard Worker 	int pmk_len;
2409*03f9172cSAndroid Build Coastguard Worker 
2410*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
2411*03f9172cSAndroid Build Coastguard Worker 		return -1;
2412*03f9172cSAndroid Build Coastguard Worker 
2413*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
2414*03f9172cSAndroid Build Coastguard Worker 	if (!sta || !sta->wpa_sm) {
2415*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR,
2416*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(addr));
2417*03f9172cSAndroid Build Coastguard Worker 		return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
2418*03f9172cSAndroid Build Coastguard Worker 	}
2419*03f9172cSAndroid Build Coastguard Worker 	pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
2420*03f9172cSAndroid Build Coastguard Worker 	if (!pmk || !pmk_len) {
2421*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR,
2422*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(addr));
2423*03f9172cSAndroid Build Coastguard Worker 		return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
2424*03f9172cSAndroid Build Coastguard Worker 	}
2425*03f9172cSAndroid Build Coastguard Worker 
2426*03f9172cSAndroid Build Coastguard Worker 	return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
2427*03f9172cSAndroid Build Coastguard Worker }
2428*03f9172cSAndroid Build Coastguard Worker 
2429*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_register_frame(struct hostapd_data * hapd,const char * cmd)2430*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
2431*03f9172cSAndroid Build Coastguard Worker 				       const char *cmd)
2432*03f9172cSAndroid Build Coastguard Worker {
2433*03f9172cSAndroid Build Coastguard Worker 	u16 type;
2434*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
2435*03f9172cSAndroid Build Coastguard Worker 	u8 match[10];
2436*03f9172cSAndroid Build Coastguard Worker 	size_t match_len;
2437*03f9172cSAndroid Build Coastguard Worker 	bool multicast = false;
2438*03f9172cSAndroid Build Coastguard Worker 
2439*03f9172cSAndroid Build Coastguard Worker 	type = strtol(cmd, &pos, 16);
2440*03f9172cSAndroid Build Coastguard Worker 	if (*pos != ' ')
2441*03f9172cSAndroid Build Coastguard Worker 		return -1;
2442*03f9172cSAndroid Build Coastguard Worker 	pos++;
2443*03f9172cSAndroid Build Coastguard Worker 	end = os_strchr(pos, ' ');
2444*03f9172cSAndroid Build Coastguard Worker 	if (end) {
2445*03f9172cSAndroid Build Coastguard Worker 		match_len = end - pos;
2446*03f9172cSAndroid Build Coastguard Worker 		multicast = os_strstr(end, "multicast") != NULL;
2447*03f9172cSAndroid Build Coastguard Worker 	} else {
2448*03f9172cSAndroid Build Coastguard Worker 		match_len = os_strlen(pos) / 2;
2449*03f9172cSAndroid Build Coastguard Worker 	}
2450*03f9172cSAndroid Build Coastguard Worker 	if (hexstr2bin(pos, match, match_len))
2451*03f9172cSAndroid Build Coastguard Worker 		return -1;
2452*03f9172cSAndroid Build Coastguard Worker 
2453*03f9172cSAndroid Build Coastguard Worker 	return hostapd_drv_register_frame(hapd, type, match, match_len,
2454*03f9172cSAndroid Build Coastguard Worker 					  multicast);
2455*03f9172cSAndroid Build Coastguard Worker }
2456*03f9172cSAndroid Build Coastguard Worker 
2457*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
2458*03f9172cSAndroid Build Coastguard Worker 
2459*03f9172cSAndroid Build Coastguard Worker 
2460*03f9172cSAndroid Build Coastguard Worker #ifdef NEED_AP_MLME
2461*03f9172cSAndroid Build Coastguard Worker 
2462*03f9172cSAndroid Build Coastguard Worker static bool
hostapd_ctrl_is_freq_in_cmode(struct hostapd_hw_modes * mode,struct hostapd_multi_hw_info * current_hw_info,int freq)2463*03f9172cSAndroid Build Coastguard Worker hostapd_ctrl_is_freq_in_cmode(struct hostapd_hw_modes *mode,
2464*03f9172cSAndroid Build Coastguard Worker 			      struct hostapd_multi_hw_info *current_hw_info,
2465*03f9172cSAndroid Build Coastguard Worker 			      int freq)
2466*03f9172cSAndroid Build Coastguard Worker {
2467*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_channel_data *chan;
2468*03f9172cSAndroid Build Coastguard Worker 	int i;
2469*03f9172cSAndroid Build Coastguard Worker 
2470*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < mode->num_channels; i++) {
2471*03f9172cSAndroid Build Coastguard Worker 		chan = &mode->channels[i];
2472*03f9172cSAndroid Build Coastguard Worker 
2473*03f9172cSAndroid Build Coastguard Worker 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
2474*03f9172cSAndroid Build Coastguard Worker 			continue;
2475*03f9172cSAndroid Build Coastguard Worker 
2476*03f9172cSAndroid Build Coastguard Worker 		if (!chan_in_current_hw_info(current_hw_info, chan))
2477*03f9172cSAndroid Build Coastguard Worker 			continue;
2478*03f9172cSAndroid Build Coastguard Worker 
2479*03f9172cSAndroid Build Coastguard Worker 		if (chan->freq == freq)
2480*03f9172cSAndroid Build Coastguard Worker 			return true;
2481*03f9172cSAndroid Build Coastguard Worker 	}
2482*03f9172cSAndroid Build Coastguard Worker 	return false;
2483*03f9172cSAndroid Build Coastguard Worker }
2484*03f9172cSAndroid Build Coastguard Worker 
2485*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_check_freq_params(struct hostapd_freq_params * params,u16 punct_bitmap)2486*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
2487*03f9172cSAndroid Build Coastguard Worker 					  u16 punct_bitmap)
2488*03f9172cSAndroid Build Coastguard Worker {
2489*03f9172cSAndroid Build Coastguard Worker 	u32 start_freq;
2490*03f9172cSAndroid Build Coastguard Worker 
2491*03f9172cSAndroid Build Coastguard Worker 	if (is_6ghz_freq(params->freq)) {
2492*03f9172cSAndroid Build Coastguard Worker 		const int bw_idx[] = { 20, 40, 80, 160, 320 };
2493*03f9172cSAndroid Build Coastguard Worker 		int idx, bw;
2494*03f9172cSAndroid Build Coastguard Worker 
2495*03f9172cSAndroid Build Coastguard Worker 		/* The 6 GHz band requires HE to be enabled. */
2496*03f9172cSAndroid Build Coastguard Worker 		params->he_enabled = 1;
2497*03f9172cSAndroid Build Coastguard Worker 
2498*03f9172cSAndroid Build Coastguard Worker 		if (params->center_freq1) {
2499*03f9172cSAndroid Build Coastguard Worker 			if (params->freq == 5935)
2500*03f9172cSAndroid Build Coastguard Worker 				idx = (params->center_freq1 - 5925) / 5;
2501*03f9172cSAndroid Build Coastguard Worker 			else
2502*03f9172cSAndroid Build Coastguard Worker 				idx = (params->center_freq1 - 5950) / 5;
2503*03f9172cSAndroid Build Coastguard Worker 
2504*03f9172cSAndroid Build Coastguard Worker 			bw = center_idx_to_bw_6ghz(idx);
2505*03f9172cSAndroid Build Coastguard Worker 			if (bw < 0 || bw > (int) ARRAY_SIZE(bw_idx) ||
2506*03f9172cSAndroid Build Coastguard Worker 			    bw_idx[bw] != params->bandwidth)
2507*03f9172cSAndroid Build Coastguard Worker 				return -1;
2508*03f9172cSAndroid Build Coastguard Worker 		}
2509*03f9172cSAndroid Build Coastguard Worker 	} else { /* Non-6 GHz channel */
2510*03f9172cSAndroid Build Coastguard Worker 		/* An EHT STA is also an HE STA as defined in
2511*03f9172cSAndroid Build Coastguard Worker 		 * IEEE P802.11be/D5.0, 4.3.16a. */
2512*03f9172cSAndroid Build Coastguard Worker 		if (params->he_enabled || params->eht_enabled) {
2513*03f9172cSAndroid Build Coastguard Worker 			params->he_enabled = 1;
2514*03f9172cSAndroid Build Coastguard Worker 			/* An HE STA is also a VHT STA if operating in the 5 GHz
2515*03f9172cSAndroid Build Coastguard Worker 			 * band and an HE STA is also an HT STA in the 2.4 GHz
2516*03f9172cSAndroid Build Coastguard Worker 			 * band as defined in IEEE Std 802.11ax-2021, 4.3.15a.
2517*03f9172cSAndroid Build Coastguard Worker 			 * A VHT STA is an HT STA as defined in IEEE
2518*03f9172cSAndroid Build Coastguard Worker 			 * Std 802.11, 4.3.15. */
2519*03f9172cSAndroid Build Coastguard Worker 			if (IS_5GHZ(params->freq))
2520*03f9172cSAndroid Build Coastguard Worker 				params->vht_enabled = 1;
2521*03f9172cSAndroid Build Coastguard Worker 
2522*03f9172cSAndroid Build Coastguard Worker 			params->ht_enabled = 1;
2523*03f9172cSAndroid Build Coastguard Worker 		}
2524*03f9172cSAndroid Build Coastguard Worker 	}
2525*03f9172cSAndroid Build Coastguard Worker 
2526*03f9172cSAndroid Build Coastguard Worker 	switch (params->bandwidth) {
2527*03f9172cSAndroid Build Coastguard Worker 	case 0:
2528*03f9172cSAndroid Build Coastguard Worker 		/* bandwidth not specified: use 20 MHz by default */
2529*03f9172cSAndroid Build Coastguard Worker 		/* fall-through */
2530*03f9172cSAndroid Build Coastguard Worker 	case 20:
2531*03f9172cSAndroid Build Coastguard Worker 		if (params->center_freq1 &&
2532*03f9172cSAndroid Build Coastguard Worker 		    params->center_freq1 != params->freq)
2533*03f9172cSAndroid Build Coastguard Worker 			return -1;
2534*03f9172cSAndroid Build Coastguard Worker 
2535*03f9172cSAndroid Build Coastguard Worker 		if (params->center_freq2 || params->sec_channel_offset)
2536*03f9172cSAndroid Build Coastguard Worker 			return -1;
2537*03f9172cSAndroid Build Coastguard Worker 
2538*03f9172cSAndroid Build Coastguard Worker 		if (punct_bitmap)
2539*03f9172cSAndroid Build Coastguard Worker 			return -1;
2540*03f9172cSAndroid Build Coastguard Worker 		break;
2541*03f9172cSAndroid Build Coastguard Worker 	case 40:
2542*03f9172cSAndroid Build Coastguard Worker 		if (params->center_freq2 || !params->sec_channel_offset)
2543*03f9172cSAndroid Build Coastguard Worker 			return -1;
2544*03f9172cSAndroid Build Coastguard Worker 
2545*03f9172cSAndroid Build Coastguard Worker 		if (punct_bitmap)
2546*03f9172cSAndroid Build Coastguard Worker 			return -1;
2547*03f9172cSAndroid Build Coastguard Worker 
2548*03f9172cSAndroid Build Coastguard Worker 		if (!params->center_freq1)
2549*03f9172cSAndroid Build Coastguard Worker 			break;
2550*03f9172cSAndroid Build Coastguard Worker 		switch (params->sec_channel_offset) {
2551*03f9172cSAndroid Build Coastguard Worker 		case 1:
2552*03f9172cSAndroid Build Coastguard Worker 			if (params->freq + 10 != params->center_freq1)
2553*03f9172cSAndroid Build Coastguard Worker 				return -1;
2554*03f9172cSAndroid Build Coastguard Worker 			break;
2555*03f9172cSAndroid Build Coastguard Worker 		case -1:
2556*03f9172cSAndroid Build Coastguard Worker 			if (params->freq - 10 != params->center_freq1)
2557*03f9172cSAndroid Build Coastguard Worker 				return -1;
2558*03f9172cSAndroid Build Coastguard Worker 			break;
2559*03f9172cSAndroid Build Coastguard Worker 		default:
2560*03f9172cSAndroid Build Coastguard Worker 			return -1;
2561*03f9172cSAndroid Build Coastguard Worker 		}
2562*03f9172cSAndroid Build Coastguard Worker 		break;
2563*03f9172cSAndroid Build Coastguard Worker 	case 80:
2564*03f9172cSAndroid Build Coastguard Worker 		if (!params->center_freq1 || !params->sec_channel_offset)
2565*03f9172cSAndroid Build Coastguard Worker 			return 1;
2566*03f9172cSAndroid Build Coastguard Worker 
2567*03f9172cSAndroid Build Coastguard Worker 		switch (params->sec_channel_offset) {
2568*03f9172cSAndroid Build Coastguard Worker 		case 1:
2569*03f9172cSAndroid Build Coastguard Worker 			if (params->freq - 10 != params->center_freq1 &&
2570*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 30 != params->center_freq1)
2571*03f9172cSAndroid Build Coastguard Worker 				return 1;
2572*03f9172cSAndroid Build Coastguard Worker 			break;
2573*03f9172cSAndroid Build Coastguard Worker 		case -1:
2574*03f9172cSAndroid Build Coastguard Worker 			if (params->freq + 10 != params->center_freq1 &&
2575*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 30 != params->center_freq1)
2576*03f9172cSAndroid Build Coastguard Worker 				return -1;
2577*03f9172cSAndroid Build Coastguard Worker 			break;
2578*03f9172cSAndroid Build Coastguard Worker 		default:
2579*03f9172cSAndroid Build Coastguard Worker 			return -1;
2580*03f9172cSAndroid Build Coastguard Worker 		}
2581*03f9172cSAndroid Build Coastguard Worker 
2582*03f9172cSAndroid Build Coastguard Worker 		if (params->center_freq2 && punct_bitmap)
2583*03f9172cSAndroid Build Coastguard Worker 			return -1;
2584*03f9172cSAndroid Build Coastguard Worker 
2585*03f9172cSAndroid Build Coastguard Worker 		/* Adjacent and overlapped are not allowed for 80+80 */
2586*03f9172cSAndroid Build Coastguard Worker 		if (params->center_freq2 &&
2587*03f9172cSAndroid Build Coastguard Worker 		    params->center_freq1 - params->center_freq2 <= 80 &&
2588*03f9172cSAndroid Build Coastguard Worker 		    params->center_freq2 - params->center_freq1 <= 80)
2589*03f9172cSAndroid Build Coastguard Worker 			return 1;
2590*03f9172cSAndroid Build Coastguard Worker 		break;
2591*03f9172cSAndroid Build Coastguard Worker 	case 160:
2592*03f9172cSAndroid Build Coastguard Worker 		if (!params->center_freq1 || params->center_freq2 ||
2593*03f9172cSAndroid Build Coastguard Worker 		    !params->sec_channel_offset)
2594*03f9172cSAndroid Build Coastguard Worker 			return -1;
2595*03f9172cSAndroid Build Coastguard Worker 
2596*03f9172cSAndroid Build Coastguard Worker 		switch (params->sec_channel_offset) {
2597*03f9172cSAndroid Build Coastguard Worker 		case 1:
2598*03f9172cSAndroid Build Coastguard Worker 			if (params->freq + 70 != params->center_freq1 &&
2599*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 30 != params->center_freq1 &&
2600*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 10 != params->center_freq1 &&
2601*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 50 != params->center_freq1)
2602*03f9172cSAndroid Build Coastguard Worker 				return -1;
2603*03f9172cSAndroid Build Coastguard Worker 			break;
2604*03f9172cSAndroid Build Coastguard Worker 		case -1:
2605*03f9172cSAndroid Build Coastguard Worker 			if (params->freq + 50 != params->center_freq1 &&
2606*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 10 != params->center_freq1 &&
2607*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 30 != params->center_freq1 &&
2608*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 70 != params->center_freq1)
2609*03f9172cSAndroid Build Coastguard Worker 				return -1;
2610*03f9172cSAndroid Build Coastguard Worker 			break;
2611*03f9172cSAndroid Build Coastguard Worker 		default:
2612*03f9172cSAndroid Build Coastguard Worker 			return -1;
2613*03f9172cSAndroid Build Coastguard Worker 		}
2614*03f9172cSAndroid Build Coastguard Worker 		break;
2615*03f9172cSAndroid Build Coastguard Worker 	case 320:
2616*03f9172cSAndroid Build Coastguard Worker 		if (!params->center_freq1 || params->center_freq2 ||
2617*03f9172cSAndroid Build Coastguard Worker 		    !params->sec_channel_offset)
2618*03f9172cSAndroid Build Coastguard Worker 			return -1;
2619*03f9172cSAndroid Build Coastguard Worker 
2620*03f9172cSAndroid Build Coastguard Worker 		switch (params->sec_channel_offset) {
2621*03f9172cSAndroid Build Coastguard Worker 		case 1:
2622*03f9172cSAndroid Build Coastguard Worker 			if (params->freq + 150 != params->center_freq1 &&
2623*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 110 != params->center_freq1 &&
2624*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 70 != params->center_freq1 &&
2625*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 30 != params->center_freq1 &&
2626*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 10 != params->center_freq1 &&
2627*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 50 != params->center_freq1 &&
2628*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 90 != params->center_freq1 &&
2629*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 130 != params->center_freq1)
2630*03f9172cSAndroid Build Coastguard Worker 				return -1;
2631*03f9172cSAndroid Build Coastguard Worker 			break;
2632*03f9172cSAndroid Build Coastguard Worker 		case -1:
2633*03f9172cSAndroid Build Coastguard Worker 			if (params->freq + 130 != params->center_freq1 &&
2634*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 90 != params->center_freq1 &&
2635*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 50 != params->center_freq1 &&
2636*03f9172cSAndroid Build Coastguard Worker 			    params->freq + 10 != params->center_freq1 &&
2637*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 30 != params->center_freq1 &&
2638*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 70 != params->center_freq1 &&
2639*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 110 != params->center_freq1 &&
2640*03f9172cSAndroid Build Coastguard Worker 			    params->freq - 150 != params->center_freq1)
2641*03f9172cSAndroid Build Coastguard Worker 				return -1;
2642*03f9172cSAndroid Build Coastguard Worker 			break;
2643*03f9172cSAndroid Build Coastguard Worker 		}
2644*03f9172cSAndroid Build Coastguard Worker 		break;
2645*03f9172cSAndroid Build Coastguard Worker 	default:
2646*03f9172cSAndroid Build Coastguard Worker 		return -1;
2647*03f9172cSAndroid Build Coastguard Worker 	}
2648*03f9172cSAndroid Build Coastguard Worker 
2649*03f9172cSAndroid Build Coastguard Worker 	if (!punct_bitmap)
2650*03f9172cSAndroid Build Coastguard Worker 		return 0;
2651*03f9172cSAndroid Build Coastguard Worker 
2652*03f9172cSAndroid Build Coastguard Worker 	if (!params->eht_enabled) {
2653*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
2654*03f9172cSAndroid Build Coastguard Worker 			   "Preamble puncturing supported only in EHT");
2655*03f9172cSAndroid Build Coastguard Worker 		return -1;
2656*03f9172cSAndroid Build Coastguard Worker 	}
2657*03f9172cSAndroid Build Coastguard Worker 
2658*03f9172cSAndroid Build Coastguard Worker 	if (params->freq >= 2412 && params->freq <= 2484) {
2659*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
2660*03f9172cSAndroid Build Coastguard Worker 			   "Preamble puncturing is not supported in 2.4 GHz");
2661*03f9172cSAndroid Build Coastguard Worker 		return -1;
2662*03f9172cSAndroid Build Coastguard Worker 	}
2663*03f9172cSAndroid Build Coastguard Worker 
2664*03f9172cSAndroid Build Coastguard Worker 	start_freq = params->center_freq1 - (params->bandwidth / 2);
2665*03f9172cSAndroid Build Coastguard Worker 	if (!is_punct_bitmap_valid(params->bandwidth,
2666*03f9172cSAndroid Build Coastguard Worker 				   (params->freq - start_freq) / 20,
2667*03f9172cSAndroid Build Coastguard Worker 				   punct_bitmap)) {
2668*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Invalid preamble puncturing bitmap");
2669*03f9172cSAndroid Build Coastguard Worker 		return -1;
2670*03f9172cSAndroid Build Coastguard Worker 	}
2671*03f9172cSAndroid Build Coastguard Worker 
2672*03f9172cSAndroid Build Coastguard Worker 	return 0;
2673*03f9172cSAndroid Build Coastguard Worker }
2674*03f9172cSAndroid Build Coastguard Worker #endif /* NEED_AP_MLME */
2675*03f9172cSAndroid Build Coastguard Worker 
2676*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_chan_switch(struct hostapd_iface * iface,char * pos)2677*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
2678*03f9172cSAndroid Build Coastguard Worker 					  char *pos)
2679*03f9172cSAndroid Build Coastguard Worker {
2680*03f9172cSAndroid Build Coastguard Worker #ifdef NEED_AP_MLME
2681*03f9172cSAndroid Build Coastguard Worker 	struct csa_settings settings;
2682*03f9172cSAndroid Build Coastguard Worker 	int ret;
2683*03f9172cSAndroid Build Coastguard Worker 	int dfs_range = 0;
2684*03f9172cSAndroid Build Coastguard Worker 	unsigned int i;
2685*03f9172cSAndroid Build Coastguard Worker 	int bandwidth;
2686*03f9172cSAndroid Build Coastguard Worker 	u8 chan;
2687*03f9172cSAndroid Build Coastguard Worker 	unsigned int num_err = 0;
2688*03f9172cSAndroid Build Coastguard Worker 	int err = 0;
2689*03f9172cSAndroid Build Coastguard Worker 
2690*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_parse_csa_settings(pos, &settings);
2691*03f9172cSAndroid Build Coastguard Worker 	if (ret)
2692*03f9172cSAndroid Build Coastguard Worker 		return ret;
2693*03f9172cSAndroid Build Coastguard Worker 
2694*03f9172cSAndroid Build Coastguard Worker 	settings.link_id = -1;
2695*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211BE
2696*03f9172cSAndroid Build Coastguard Worker 	if (iface->num_bss && iface->bss[0]->conf->mld_ap)
2697*03f9172cSAndroid Build Coastguard Worker 		settings.link_id = iface->bss[0]->mld_link_id;
2698*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211BE */
2699*03f9172cSAndroid Build Coastguard Worker 
2700*03f9172cSAndroid Build Coastguard Worker 	if (iface->num_hw_features > 1 &&
2701*03f9172cSAndroid Build Coastguard Worker 	    !hostapd_ctrl_is_freq_in_cmode(iface->current_mode,
2702*03f9172cSAndroid Build Coastguard Worker 					   iface->current_hw_info,
2703*03f9172cSAndroid Build Coastguard Worker 					   settings.freq_params.freq)) {
2704*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
2705*03f9172cSAndroid Build Coastguard Worker 			   "chanswitch: Invalid frequency settings provided for multi band phy");
2706*03f9172cSAndroid Build Coastguard Worker 		return -1;
2707*03f9172cSAndroid Build Coastguard Worker 	}
2708*03f9172cSAndroid Build Coastguard Worker 
2709*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_ctrl_check_freq_params(&settings.freq_params,
2710*03f9172cSAndroid Build Coastguard Worker 					     settings.punct_bitmap);
2711*03f9172cSAndroid Build Coastguard Worker 	if (ret) {
2712*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
2713*03f9172cSAndroid Build Coastguard Worker 			   "chanswitch: invalid frequency settings provided");
2714*03f9172cSAndroid Build Coastguard Worker 		return ret;
2715*03f9172cSAndroid Build Coastguard Worker 	}
2716*03f9172cSAndroid Build Coastguard Worker 
2717*03f9172cSAndroid Build Coastguard Worker 	switch (settings.freq_params.bandwidth) {
2718*03f9172cSAndroid Build Coastguard Worker 	case 40:
2719*03f9172cSAndroid Build Coastguard Worker 		bandwidth = CHAN_WIDTH_40;
2720*03f9172cSAndroid Build Coastguard Worker 		break;
2721*03f9172cSAndroid Build Coastguard Worker 	case 80:
2722*03f9172cSAndroid Build Coastguard Worker 		if (settings.freq_params.center_freq2)
2723*03f9172cSAndroid Build Coastguard Worker 			bandwidth = CHAN_WIDTH_80P80;
2724*03f9172cSAndroid Build Coastguard Worker 		else
2725*03f9172cSAndroid Build Coastguard Worker 			bandwidth = CHAN_WIDTH_80;
2726*03f9172cSAndroid Build Coastguard Worker 		break;
2727*03f9172cSAndroid Build Coastguard Worker 	case 160:
2728*03f9172cSAndroid Build Coastguard Worker 		bandwidth = CHAN_WIDTH_160;
2729*03f9172cSAndroid Build Coastguard Worker 		break;
2730*03f9172cSAndroid Build Coastguard Worker 	case 320:
2731*03f9172cSAndroid Build Coastguard Worker 		bandwidth = CHAN_WIDTH_320;
2732*03f9172cSAndroid Build Coastguard Worker 		break;
2733*03f9172cSAndroid Build Coastguard Worker 	default:
2734*03f9172cSAndroid Build Coastguard Worker 		bandwidth = CHAN_WIDTH_20;
2735*03f9172cSAndroid Build Coastguard Worker 		break;
2736*03f9172cSAndroid Build Coastguard Worker 	}
2737*03f9172cSAndroid Build Coastguard Worker 
2738*03f9172cSAndroid Build Coastguard Worker 	if (settings.freq_params.center_freq1)
2739*03f9172cSAndroid Build Coastguard Worker 		dfs_range += hostapd_is_dfs_overlap(
2740*03f9172cSAndroid Build Coastguard Worker 			iface, bandwidth, settings.freq_params.center_freq1);
2741*03f9172cSAndroid Build Coastguard Worker 	else
2742*03f9172cSAndroid Build Coastguard Worker 		dfs_range += hostapd_is_dfs_overlap(
2743*03f9172cSAndroid Build Coastguard Worker 			iface, bandwidth, settings.freq_params.freq);
2744*03f9172cSAndroid Build Coastguard Worker 
2745*03f9172cSAndroid Build Coastguard Worker 	if (settings.freq_params.center_freq2)
2746*03f9172cSAndroid Build Coastguard Worker 		dfs_range += hostapd_is_dfs_overlap(
2747*03f9172cSAndroid Build Coastguard Worker 			iface, bandwidth, settings.freq_params.center_freq2);
2748*03f9172cSAndroid Build Coastguard Worker 
2749*03f9172cSAndroid Build Coastguard Worker 	if (dfs_range) {
2750*03f9172cSAndroid Build Coastguard Worker 		ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan);
2751*03f9172cSAndroid Build Coastguard Worker 		if (ret == NUM_HOSTAPD_MODES) {
2752*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
2753*03f9172cSAndroid Build Coastguard Worker 				   "Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)",
2754*03f9172cSAndroid Build Coastguard Worker 				   settings.freq_params.freq,
2755*03f9172cSAndroid Build Coastguard Worker 				   settings.freq_params.sec_channel_offset,
2756*03f9172cSAndroid Build Coastguard Worker 				   settings.freq_params.bandwidth);
2757*03f9172cSAndroid Build Coastguard Worker 			return -1;
2758*03f9172cSAndroid Build Coastguard Worker 		}
2759*03f9172cSAndroid Build Coastguard Worker 
2760*03f9172cSAndroid Build Coastguard Worker 		settings.freq_params.channel = chan;
2761*03f9172cSAndroid Build Coastguard Worker 
2762*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
2763*03f9172cSAndroid Build Coastguard Worker 			   "DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)",
2764*03f9172cSAndroid Build Coastguard Worker 			   settings.freq_params.channel,
2765*03f9172cSAndroid Build Coastguard Worker 			   settings.freq_params.freq,
2766*03f9172cSAndroid Build Coastguard Worker 			   settings.freq_params.sec_channel_offset,
2767*03f9172cSAndroid Build Coastguard Worker 			   settings.freq_params.bandwidth,
2768*03f9172cSAndroid Build Coastguard Worker 			   settings.freq_params.center_freq1);
2769*03f9172cSAndroid Build Coastguard Worker 
2770*03f9172cSAndroid Build Coastguard Worker 		/* Perform CAC and switch channel */
2771*03f9172cSAndroid Build Coastguard Worker 		iface->is_ch_switch_dfs = true;
2772*03f9172cSAndroid Build Coastguard Worker 		hostapd_switch_channel_fallback(iface, &settings.freq_params);
2773*03f9172cSAndroid Build Coastguard Worker 		return 0;
2774*03f9172cSAndroid Build Coastguard Worker 	}
2775*03f9172cSAndroid Build Coastguard Worker 
2776*03f9172cSAndroid Build Coastguard Worker 	if (iface->cac_started) {
2777*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
2778*03f9172cSAndroid Build Coastguard Worker 			   "CAC is in progress - switching channel without CSA");
2779*03f9172cSAndroid Build Coastguard Worker 		return hostapd_force_channel_switch(iface, &settings);
2780*03f9172cSAndroid Build Coastguard Worker 	}
2781*03f9172cSAndroid Build Coastguard Worker 
2782*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < iface->num_bss; i++) {
2783*03f9172cSAndroid Build Coastguard Worker 
2784*03f9172cSAndroid Build Coastguard Worker 		/* Save CHAN_SWITCH VHT, HE, and EHT config */
2785*03f9172cSAndroid Build Coastguard Worker 		hostapd_chan_switch_config(iface->bss[i],
2786*03f9172cSAndroid Build Coastguard Worker 					   &settings.freq_params);
2787*03f9172cSAndroid Build Coastguard Worker 
2788*03f9172cSAndroid Build Coastguard Worker 		err = hostapd_switch_channel(iface->bss[i], &settings);
2789*03f9172cSAndroid Build Coastguard Worker 		if (err) {
2790*03f9172cSAndroid Build Coastguard Worker 			ret = err;
2791*03f9172cSAndroid Build Coastguard Worker 			num_err++;
2792*03f9172cSAndroid Build Coastguard Worker 		}
2793*03f9172cSAndroid Build Coastguard Worker 	}
2794*03f9172cSAndroid Build Coastguard Worker 
2795*03f9172cSAndroid Build Coastguard Worker 	return (iface->num_bss == num_err) ? ret : 0;
2796*03f9172cSAndroid Build Coastguard Worker #else /* NEED_AP_MLME */
2797*03f9172cSAndroid Build Coastguard Worker 	return -1;
2798*03f9172cSAndroid Build Coastguard Worker #endif /* NEED_AP_MLME */
2799*03f9172cSAndroid Build Coastguard Worker }
2800*03f9172cSAndroid Build Coastguard Worker 
2801*03f9172cSAndroid Build Coastguard Worker 
2802*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211AX
hostapd_ctrl_iface_color_change(struct hostapd_iface * iface,const char * pos)2803*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_color_change(struct hostapd_iface *iface,
2804*03f9172cSAndroid Build Coastguard Worker 					   const char *pos)
2805*03f9172cSAndroid Build Coastguard Worker {
2806*03f9172cSAndroid Build Coastguard Worker #ifdef NEED_AP_MLME
2807*03f9172cSAndroid Build Coastguard Worker 	struct cca_settings settings;
2808*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd = iface->bss[0];
2809*03f9172cSAndroid Build Coastguard Worker 	int ret, color;
2810*03f9172cSAndroid Build Coastguard Worker 	unsigned int i;
2811*03f9172cSAndroid Build Coastguard Worker 	char *end;
2812*03f9172cSAndroid Build Coastguard Worker 
2813*03f9172cSAndroid Build Coastguard Worker 	os_memset(&settings, 0, sizeof(settings));
2814*03f9172cSAndroid Build Coastguard Worker 
2815*03f9172cSAndroid Build Coastguard Worker 	color = strtol(pos, &end, 10);
2816*03f9172cSAndroid Build Coastguard Worker 	if (pos == end || color < 0 || color > 63) {
2817*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "color_change: Invalid color provided");
2818*03f9172cSAndroid Build Coastguard Worker 		return -1;
2819*03f9172cSAndroid Build Coastguard Worker 	}
2820*03f9172cSAndroid Build Coastguard Worker 
2821*03f9172cSAndroid Build Coastguard Worker 	/* Color value is expected to be [1-63]. If 0 comes, assumption is this
2822*03f9172cSAndroid Build Coastguard Worker 	 * is to disable the color. In this case no need to do CCA, just
2823*03f9172cSAndroid Build Coastguard Worker 	 * changing Beacon frames is sufficient. */
2824*03f9172cSAndroid Build Coastguard Worker 	if (color == 0) {
2825*03f9172cSAndroid Build Coastguard Worker 		if (iface->conf->he_op.he_bss_color_disabled) {
2826*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
2827*03f9172cSAndroid Build Coastguard Worker 				   "color_change: Color is already disabled");
2828*03f9172cSAndroid Build Coastguard Worker 			return -1;
2829*03f9172cSAndroid Build Coastguard Worker 		}
2830*03f9172cSAndroid Build Coastguard Worker 
2831*03f9172cSAndroid Build Coastguard Worker 		iface->conf->he_op.he_bss_color_disabled = 1;
2832*03f9172cSAndroid Build Coastguard Worker 
2833*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; i < iface->num_bss; i++)
2834*03f9172cSAndroid Build Coastguard Worker 			ieee802_11_set_beacon(iface->bss[i]);
2835*03f9172cSAndroid Build Coastguard Worker 
2836*03f9172cSAndroid Build Coastguard Worker 		return 0;
2837*03f9172cSAndroid Build Coastguard Worker 	}
2838*03f9172cSAndroid Build Coastguard Worker 
2839*03f9172cSAndroid Build Coastguard Worker 	if (color == iface->conf->he_op.he_bss_color) {
2840*03f9172cSAndroid Build Coastguard Worker 		if (!iface->conf->he_op.he_bss_color_disabled) {
2841*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
2842*03f9172cSAndroid Build Coastguard Worker 				   "color_change: Provided color is already set");
2843*03f9172cSAndroid Build Coastguard Worker 			return -1;
2844*03f9172cSAndroid Build Coastguard Worker 		}
2845*03f9172cSAndroid Build Coastguard Worker 
2846*03f9172cSAndroid Build Coastguard Worker 		iface->conf->he_op.he_bss_color_disabled = 0;
2847*03f9172cSAndroid Build Coastguard Worker 
2848*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; i < iface->num_bss; i++)
2849*03f9172cSAndroid Build Coastguard Worker 			ieee802_11_set_beacon(iface->bss[i]);
2850*03f9172cSAndroid Build Coastguard Worker 
2851*03f9172cSAndroid Build Coastguard Worker 		return 0;
2852*03f9172cSAndroid Build Coastguard Worker 	}
2853*03f9172cSAndroid Build Coastguard Worker 
2854*03f9172cSAndroid Build Coastguard Worker 	if (hapd->cca_in_progress) {
2855*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
2856*03f9172cSAndroid Build Coastguard Worker 			   "color_change: CCA is already in progress");
2857*03f9172cSAndroid Build Coastguard Worker 		return -1;
2858*03f9172cSAndroid Build Coastguard Worker 	}
2859*03f9172cSAndroid Build Coastguard Worker 
2860*03f9172cSAndroid Build Coastguard Worker 	iface->conf->he_op.he_bss_color_disabled = 0;
2861*03f9172cSAndroid Build Coastguard Worker 
2862*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < iface->num_bss; i++) {
2863*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_data *bss = iface->bss[i];
2864*03f9172cSAndroid Build Coastguard Worker 
2865*03f9172cSAndroid Build Coastguard Worker 		hostapd_cleanup_cca_params(bss);
2866*03f9172cSAndroid Build Coastguard Worker 
2867*03f9172cSAndroid Build Coastguard Worker 		bss->cca_color = color;
2868*03f9172cSAndroid Build Coastguard Worker 		bss->cca_count = 10;
2869*03f9172cSAndroid Build Coastguard Worker 
2870*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_fill_cca_settings(bss, &settings)) {
2871*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG,
2872*03f9172cSAndroid Build Coastguard Worker 				   "color_change: Filling CCA settings failed for color: %d\n",
2873*03f9172cSAndroid Build Coastguard Worker 				   color);
2874*03f9172cSAndroid Build Coastguard Worker 			hostapd_cleanup_cca_params(bss);
2875*03f9172cSAndroid Build Coastguard Worker 			continue;
2876*03f9172cSAndroid Build Coastguard Worker 		}
2877*03f9172cSAndroid Build Coastguard Worker 
2878*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "Setting user selected color: %d", color);
2879*03f9172cSAndroid Build Coastguard Worker 		ret = hostapd_drv_switch_color(bss, &settings);
2880*03f9172cSAndroid Build Coastguard Worker 		if (ret)
2881*03f9172cSAndroid Build Coastguard Worker 			hostapd_cleanup_cca_params(bss);
2882*03f9172cSAndroid Build Coastguard Worker 
2883*03f9172cSAndroid Build Coastguard Worker 		free_beacon_data(&settings.beacon_cca);
2884*03f9172cSAndroid Build Coastguard Worker 		free_beacon_data(&settings.beacon_after);
2885*03f9172cSAndroid Build Coastguard Worker 	}
2886*03f9172cSAndroid Build Coastguard Worker 
2887*03f9172cSAndroid Build Coastguard Worker 	return 0;
2888*03f9172cSAndroid Build Coastguard Worker #else /* NEED_AP_MLME */
2889*03f9172cSAndroid Build Coastguard Worker 	return -1;
2890*03f9172cSAndroid Build Coastguard Worker #endif /* NEED_AP_MLME */
2891*03f9172cSAndroid Build Coastguard Worker }
2892*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211AX */
2893*03f9172cSAndroid Build Coastguard Worker 
2894*03f9172cSAndroid Build Coastguard Worker 
hostapd_maxnss(struct hostapd_data * hapd,struct sta_info * sta)2895*03f9172cSAndroid Build Coastguard Worker static u8 hostapd_maxnss(struct hostapd_data *hapd, struct sta_info *sta)
2896*03f9172cSAndroid Build Coastguard Worker {
2897*03f9172cSAndroid Build Coastguard Worker 	u8 *mcs_set = NULL;
2898*03f9172cSAndroid Build Coastguard Worker 	u16 mcs_map;
2899*03f9172cSAndroid Build Coastguard Worker 	u8 ht_rx_nss = 0;
2900*03f9172cSAndroid Build Coastguard Worker 	u8 vht_rx_nss = 1;
2901*03f9172cSAndroid Build Coastguard Worker 	u8 mcs;
2902*03f9172cSAndroid Build Coastguard Worker 	bool ht_supported = false;
2903*03f9172cSAndroid Build Coastguard Worker 	bool vht_supported = false;
2904*03f9172cSAndroid Build Coastguard Worker 	int i;
2905*03f9172cSAndroid Build Coastguard Worker 
2906*03f9172cSAndroid Build Coastguard Worker 	if (sta->ht_capabilities && (sta->flags & WLAN_STA_HT)) {
2907*03f9172cSAndroid Build Coastguard Worker 		mcs_set = sta->ht_capabilities->supported_mcs_set;
2908*03f9172cSAndroid Build Coastguard Worker 		ht_supported = true;
2909*03f9172cSAndroid Build Coastguard Worker 	}
2910*03f9172cSAndroid Build Coastguard Worker 
2911*03f9172cSAndroid Build Coastguard Worker 	if (sta->vht_capabilities && (sta->flags & WLAN_STA_VHT)) {
2912*03f9172cSAndroid Build Coastguard Worker 		mcs_map = le_to_host16(
2913*03f9172cSAndroid Build Coastguard Worker 			sta->vht_capabilities->vht_supported_mcs_set.rx_map);
2914*03f9172cSAndroid Build Coastguard Worker 		vht_supported = true;
2915*03f9172cSAndroid Build Coastguard Worker 	}
2916*03f9172cSAndroid Build Coastguard Worker 
2917*03f9172cSAndroid Build Coastguard Worker 	if (ht_supported && mcs_set) {
2918*03f9172cSAndroid Build Coastguard Worker 		if (mcs_set[0])
2919*03f9172cSAndroid Build Coastguard Worker 			ht_rx_nss++;
2920*03f9172cSAndroid Build Coastguard Worker 		if (mcs_set[1])
2921*03f9172cSAndroid Build Coastguard Worker 			ht_rx_nss++;
2922*03f9172cSAndroid Build Coastguard Worker 		if (mcs_set[2])
2923*03f9172cSAndroid Build Coastguard Worker 			ht_rx_nss++;
2924*03f9172cSAndroid Build Coastguard Worker 		if (mcs_set[3])
2925*03f9172cSAndroid Build Coastguard Worker 			ht_rx_nss++;
2926*03f9172cSAndroid Build Coastguard Worker 	}
2927*03f9172cSAndroid Build Coastguard Worker 	if (vht_supported) {
2928*03f9172cSAndroid Build Coastguard Worker 		for (i = 7; i >= 0; i--) {
2929*03f9172cSAndroid Build Coastguard Worker 			mcs = (mcs_map >> (2 * i)) & 0x03;
2930*03f9172cSAndroid Build Coastguard Worker 			if (mcs != 0x03) {
2931*03f9172cSAndroid Build Coastguard Worker 				vht_rx_nss = i + 1;
2932*03f9172cSAndroid Build Coastguard Worker 				break;
2933*03f9172cSAndroid Build Coastguard Worker 			}
2934*03f9172cSAndroid Build Coastguard Worker 		}
2935*03f9172cSAndroid Build Coastguard Worker 	}
2936*03f9172cSAndroid Build Coastguard Worker 
2937*03f9172cSAndroid Build Coastguard Worker 	return ht_rx_nss > vht_rx_nss ? ht_rx_nss : vht_rx_nss;
2938*03f9172cSAndroid Build Coastguard Worker }
2939*03f9172cSAndroid Build Coastguard Worker 
2940*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_notify_cw_htaction(struct hostapd_data * hapd,const u8 * addr,u8 width)2941*03f9172cSAndroid Build Coastguard Worker static char hostapd_ctrl_iface_notify_cw_htaction(struct hostapd_data *hapd,
2942*03f9172cSAndroid Build Coastguard Worker 						  const u8 *addr, u8 width)
2943*03f9172cSAndroid Build Coastguard Worker {
2944*03f9172cSAndroid Build Coastguard Worker 	u8 buf[3];
2945*03f9172cSAndroid Build Coastguard Worker 	char ret;
2946*03f9172cSAndroid Build Coastguard Worker 
2947*03f9172cSAndroid Build Coastguard Worker 	width = width >= 1 ? 1 : 0;
2948*03f9172cSAndroid Build Coastguard Worker 
2949*03f9172cSAndroid Build Coastguard Worker 	buf[0] = WLAN_ACTION_HT;
2950*03f9172cSAndroid Build Coastguard Worker 	buf[1] = WLAN_HT_ACTION_NOTIFY_CHANWIDTH;
2951*03f9172cSAndroid Build Coastguard Worker 	buf[2] = width;
2952*03f9172cSAndroid Build Coastguard Worker 
2953*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
2954*03f9172cSAndroid Build Coastguard Worker 				      buf, sizeof(buf));
2955*03f9172cSAndroid Build Coastguard Worker 	if (ret)
2956*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
2957*03f9172cSAndroid Build Coastguard Worker 			   "Failed to send Notify Channel Width frame to "
2958*03f9172cSAndroid Build Coastguard Worker 			   MACSTR, MAC2STR(addr));
2959*03f9172cSAndroid Build Coastguard Worker 
2960*03f9172cSAndroid Build Coastguard Worker 	return ret;
2961*03f9172cSAndroid Build Coastguard Worker }
2962*03f9172cSAndroid Build Coastguard Worker 
2963*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_notify_cw_vhtaction(struct hostapd_data * hapd,const u8 * addr,u8 width)2964*03f9172cSAndroid Build Coastguard Worker static char hostapd_ctrl_iface_notify_cw_vhtaction(struct hostapd_data *hapd,
2965*03f9172cSAndroid Build Coastguard Worker 						   const u8 *addr, u8 width)
2966*03f9172cSAndroid Build Coastguard Worker {
2967*03f9172cSAndroid Build Coastguard Worker 	u8 buf[3];
2968*03f9172cSAndroid Build Coastguard Worker 	char ret;
2969*03f9172cSAndroid Build Coastguard Worker 
2970*03f9172cSAndroid Build Coastguard Worker 	buf[0] = WLAN_ACTION_VHT;
2971*03f9172cSAndroid Build Coastguard Worker 	buf[1] = WLAN_VHT_ACTION_OPMODE_NOTIF;
2972*03f9172cSAndroid Build Coastguard Worker 	buf[2] = width;
2973*03f9172cSAndroid Build Coastguard Worker 
2974*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
2975*03f9172cSAndroid Build Coastguard Worker 				      buf, sizeof(buf));
2976*03f9172cSAndroid Build Coastguard Worker 	if (ret)
2977*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
2978*03f9172cSAndroid Build Coastguard Worker 			   "Failed to send Opeating Mode Notification frame to "
2979*03f9172cSAndroid Build Coastguard Worker 			   MACSTR, MAC2STR(addr));
2980*03f9172cSAndroid Build Coastguard Worker 
2981*03f9172cSAndroid Build Coastguard Worker 	return ret;
2982*03f9172cSAndroid Build Coastguard Worker }
2983*03f9172cSAndroid Build Coastguard Worker 
2984*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_notify_cw_change(struct hostapd_data * hapd,const char * cmd)2985*03f9172cSAndroid Build Coastguard Worker static char hostapd_ctrl_iface_notify_cw_change(struct hostapd_data *hapd,
2986*03f9172cSAndroid Build Coastguard Worker 						const char *cmd)
2987*03f9172cSAndroid Build Coastguard Worker {
2988*03f9172cSAndroid Build Coastguard Worker 	u8 cw, operating_mode = 0, nss;
2989*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
2990*03f9172cSAndroid Build Coastguard Worker 	enum hostapd_hw_mode hw_mode;
2991*03f9172cSAndroid Build Coastguard Worker 
2992*03f9172cSAndroid Build Coastguard Worker 	if (is_6ghz_freq(hapd->iface->freq)) {
2993*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "20/40 BSS coex not supported in 6 GHz");
2994*03f9172cSAndroid Build Coastguard Worker 		return -1;
2995*03f9172cSAndroid Build Coastguard Worker 	}
2996*03f9172cSAndroid Build Coastguard Worker 
2997*03f9172cSAndroid Build Coastguard Worker 	cw = atoi(cmd);
2998*03f9172cSAndroid Build Coastguard Worker 	hw_mode = hapd->iface->current_mode->mode;
2999*03f9172cSAndroid Build Coastguard Worker 	if ((hw_mode == HOSTAPD_MODE_IEEE80211G ||
3000*03f9172cSAndroid Build Coastguard Worker 	     hw_mode == HOSTAPD_MODE_IEEE80211B) &&
3001*03f9172cSAndroid Build Coastguard Worker 	    !(cw == 0 || cw == 1)) {
3002*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3003*03f9172cSAndroid Build Coastguard Worker 			   "Channel width should be either 20 MHz or 40 MHz for 2.4 GHz band");
3004*03f9172cSAndroid Build Coastguard Worker 		return -1;
3005*03f9172cSAndroid Build Coastguard Worker 	}
3006*03f9172cSAndroid Build Coastguard Worker 
3007*03f9172cSAndroid Build Coastguard Worker 	switch (cw) {
3008*03f9172cSAndroid Build Coastguard Worker 	case 0:
3009*03f9172cSAndroid Build Coastguard Worker 		operating_mode = 0;
3010*03f9172cSAndroid Build Coastguard Worker 		break;
3011*03f9172cSAndroid Build Coastguard Worker 	case 1:
3012*03f9172cSAndroid Build Coastguard Worker 		operating_mode = VHT_OPMODE_CHANNEL_40MHZ;
3013*03f9172cSAndroid Build Coastguard Worker 		break;
3014*03f9172cSAndroid Build Coastguard Worker 	case 2:
3015*03f9172cSAndroid Build Coastguard Worker 		operating_mode = VHT_OPMODE_CHANNEL_80MHZ;
3016*03f9172cSAndroid Build Coastguard Worker 		break;
3017*03f9172cSAndroid Build Coastguard Worker 	case 3:
3018*03f9172cSAndroid Build Coastguard Worker 		operating_mode = VHT_OPMODE_CHANNEL_160MHZ;
3019*03f9172cSAndroid Build Coastguard Worker 		break;
3020*03f9172cSAndroid Build Coastguard Worker 	default:
3021*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Channel width should be between 0 to 3");
3022*03f9172cSAndroid Build Coastguard Worker 		return -1;
3023*03f9172cSAndroid Build Coastguard Worker 	}
3024*03f9172cSAndroid Build Coastguard Worker 
3025*03f9172cSAndroid Build Coastguard Worker 	for (sta = hapd->sta_list; sta; sta = sta->next) {
3026*03f9172cSAndroid Build Coastguard Worker 		if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) {
3027*03f9172cSAndroid Build Coastguard Worker 			nss = hostapd_maxnss(hapd, sta) - 1;
3028*03f9172cSAndroid Build Coastguard Worker 			hostapd_ctrl_iface_notify_cw_vhtaction(hapd, sta->addr,
3029*03f9172cSAndroid Build Coastguard Worker 							       operating_mode |
3030*03f9172cSAndroid Build Coastguard Worker 							       (u8) (nss << 4));
3031*03f9172cSAndroid Build Coastguard Worker 			continue;
3032*03f9172cSAndroid Build Coastguard Worker 		}
3033*03f9172cSAndroid Build Coastguard Worker 
3034*03f9172cSAndroid Build Coastguard Worker 		if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) ==
3035*03f9172cSAndroid Build Coastguard Worker 		    WLAN_STA_HT && sta->ht_capabilities)
3036*03f9172cSAndroid Build Coastguard Worker 			hostapd_ctrl_iface_notify_cw_htaction(hapd, sta->addr,
3037*03f9172cSAndroid Build Coastguard Worker 							      cw);
3038*03f9172cSAndroid Build Coastguard Worker 	}
3039*03f9172cSAndroid Build Coastguard Worker 
3040*03f9172cSAndroid Build Coastguard Worker 	return 0;
3041*03f9172cSAndroid Build Coastguard Worker }
3042*03f9172cSAndroid Build Coastguard Worker 
3043*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_mib(struct hostapd_data * hapd,char * reply,int reply_size,const char * param)3044*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
3045*03f9172cSAndroid Build Coastguard Worker 				  int reply_size, const char *param)
3046*03f9172cSAndroid Build Coastguard Worker {
3047*03f9172cSAndroid Build Coastguard Worker #ifdef RADIUS_SERVER
3048*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(param, "radius_server") == 0) {
3049*03f9172cSAndroid Build Coastguard Worker 		return radius_server_get_mib(hapd->radius_srv, reply,
3050*03f9172cSAndroid Build Coastguard Worker 					     reply_size);
3051*03f9172cSAndroid Build Coastguard Worker 	}
3052*03f9172cSAndroid Build Coastguard Worker #endif /* RADIUS_SERVER */
3053*03f9172cSAndroid Build Coastguard Worker 	return -1;
3054*03f9172cSAndroid Build Coastguard Worker }
3055*03f9172cSAndroid Build Coastguard Worker 
3056*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_vendor(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3057*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
3058*03f9172cSAndroid Build Coastguard Worker 				     char *buf, size_t buflen)
3059*03f9172cSAndroid Build Coastguard Worker {
3060*03f9172cSAndroid Build Coastguard Worker 	int ret;
3061*03f9172cSAndroid Build Coastguard Worker 	char *pos, *temp = NULL;
3062*03f9172cSAndroid Build Coastguard Worker 	u8 *data = NULL;
3063*03f9172cSAndroid Build Coastguard Worker 	unsigned int vendor_id, subcmd;
3064*03f9172cSAndroid Build Coastguard Worker 	enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
3065*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *reply;
3066*03f9172cSAndroid Build Coastguard Worker 	size_t data_len = 0;
3067*03f9172cSAndroid Build Coastguard Worker 
3068*03f9172cSAndroid Build Coastguard Worker 	/**
3069*03f9172cSAndroid Build Coastguard Worker 	 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
3070*03f9172cSAndroid Build Coastguard Worker 	 * [nested=<0|1>]
3071*03f9172cSAndroid Build Coastguard Worker 	 */
3072*03f9172cSAndroid Build Coastguard Worker 	vendor_id = strtoul(cmd, &pos, 16);
3073*03f9172cSAndroid Build Coastguard Worker 	if (!isblank((unsigned char) *pos))
3074*03f9172cSAndroid Build Coastguard Worker 		return -EINVAL;
3075*03f9172cSAndroid Build Coastguard Worker 
3076*03f9172cSAndroid Build Coastguard Worker 	subcmd = strtoul(pos, &pos, 10);
3077*03f9172cSAndroid Build Coastguard Worker 
3078*03f9172cSAndroid Build Coastguard Worker 	if (*pos != '\0') {
3079*03f9172cSAndroid Build Coastguard Worker 		if (!isblank((unsigned char) *pos++))
3080*03f9172cSAndroid Build Coastguard Worker 			return -EINVAL;
3081*03f9172cSAndroid Build Coastguard Worker 
3082*03f9172cSAndroid Build Coastguard Worker 		temp = os_strchr(pos, ' ');
3083*03f9172cSAndroid Build Coastguard Worker 		data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
3084*03f9172cSAndroid Build Coastguard Worker 	}
3085*03f9172cSAndroid Build Coastguard Worker 
3086*03f9172cSAndroid Build Coastguard Worker 	if (data_len) {
3087*03f9172cSAndroid Build Coastguard Worker 		data_len /= 2;
3088*03f9172cSAndroid Build Coastguard Worker 		data = os_malloc(data_len);
3089*03f9172cSAndroid Build Coastguard Worker 		if (!data)
3090*03f9172cSAndroid Build Coastguard Worker 			return -ENOBUFS;
3091*03f9172cSAndroid Build Coastguard Worker 
3092*03f9172cSAndroid Build Coastguard Worker 		if (hexstr2bin(pos, data, data_len)) {
3093*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG,
3094*03f9172cSAndroid Build Coastguard Worker 				   "Vendor command: wrong parameter format");
3095*03f9172cSAndroid Build Coastguard Worker 			os_free(data);
3096*03f9172cSAndroid Build Coastguard Worker 			return -EINVAL;
3097*03f9172cSAndroid Build Coastguard Worker 		}
3098*03f9172cSAndroid Build Coastguard Worker 	}
3099*03f9172cSAndroid Build Coastguard Worker 
3100*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(cmd, "nested=");
3101*03f9172cSAndroid Build Coastguard Worker 	if (pos)
3102*03f9172cSAndroid Build Coastguard Worker 		nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
3103*03f9172cSAndroid Build Coastguard Worker 			NESTED_ATTR_NOT_USED;
3104*03f9172cSAndroid Build Coastguard Worker 
3105*03f9172cSAndroid Build Coastguard Worker 	reply = wpabuf_alloc((buflen - 1) / 2);
3106*03f9172cSAndroid Build Coastguard Worker 	if (!reply) {
3107*03f9172cSAndroid Build Coastguard Worker 		os_free(data);
3108*03f9172cSAndroid Build Coastguard Worker 		return -ENOBUFS;
3109*03f9172cSAndroid Build Coastguard Worker 	}
3110*03f9172cSAndroid Build Coastguard Worker 
3111*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
3112*03f9172cSAndroid Build Coastguard Worker 				     nested_attr_flag, reply);
3113*03f9172cSAndroid Build Coastguard Worker 
3114*03f9172cSAndroid Build Coastguard Worker 	if (ret == 0)
3115*03f9172cSAndroid Build Coastguard Worker 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
3116*03f9172cSAndroid Build Coastguard Worker 				       wpabuf_len(reply));
3117*03f9172cSAndroid Build Coastguard Worker 
3118*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(reply);
3119*03f9172cSAndroid Build Coastguard Worker 	os_free(data);
3120*03f9172cSAndroid Build Coastguard Worker 
3121*03f9172cSAndroid Build Coastguard Worker 	return ret;
3122*03f9172cSAndroid Build Coastguard Worker }
3123*03f9172cSAndroid Build Coastguard Worker 
3124*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_eapol_reauth(struct hostapd_data * hapd,const char * cmd)3125*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
3126*03f9172cSAndroid Build Coastguard Worker 					   const char *cmd)
3127*03f9172cSAndroid Build Coastguard Worker {
3128*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
3129*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
3130*03f9172cSAndroid Build Coastguard Worker 
3131*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
3132*03f9172cSAndroid Build Coastguard Worker 		return -1;
3133*03f9172cSAndroid Build Coastguard Worker 
3134*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
3135*03f9172cSAndroid Build Coastguard Worker 	if (!sta || !sta->eapol_sm)
3136*03f9172cSAndroid Build Coastguard Worker 		return -1;
3137*03f9172cSAndroid Build Coastguard Worker 
3138*03f9172cSAndroid Build Coastguard Worker 	eapol_auth_reauthenticate(sta->eapol_sm);
3139*03f9172cSAndroid Build Coastguard Worker 	return 0;
3140*03f9172cSAndroid Build Coastguard Worker }
3141*03f9172cSAndroid Build Coastguard Worker 
3142*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_eapol_set(struct hostapd_data * hapd,char * cmd)3143*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
3144*03f9172cSAndroid Build Coastguard Worker {
3145*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
3146*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
3147*03f9172cSAndroid Build Coastguard Worker 	char *pos = cmd, *param;
3148*03f9172cSAndroid Build Coastguard Worker 
3149*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(pos, addr) || pos[17] != ' ')
3150*03f9172cSAndroid Build Coastguard Worker 		return -1;
3151*03f9172cSAndroid Build Coastguard Worker 	pos += 18;
3152*03f9172cSAndroid Build Coastguard Worker 	param = pos;
3153*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(pos, ' ');
3154*03f9172cSAndroid Build Coastguard Worker 	if (!pos)
3155*03f9172cSAndroid Build Coastguard Worker 		return -1;
3156*03f9172cSAndroid Build Coastguard Worker 	*pos++ = '\0';
3157*03f9172cSAndroid Build Coastguard Worker 
3158*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
3159*03f9172cSAndroid Build Coastguard Worker 	if (!sta || !sta->eapol_sm)
3160*03f9172cSAndroid Build Coastguard Worker 		return -1;
3161*03f9172cSAndroid Build Coastguard Worker 
3162*03f9172cSAndroid Build Coastguard Worker 	return eapol_auth_set_conf(sta->eapol_sm, param, pos);
3163*03f9172cSAndroid Build Coastguard Worker }
3164*03f9172cSAndroid Build Coastguard Worker 
3165*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_log_level(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3166*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
3167*03f9172cSAndroid Build Coastguard Worker 					char *buf, size_t buflen)
3168*03f9172cSAndroid Build Coastguard Worker {
3169*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end, *stamp;
3170*03f9172cSAndroid Build Coastguard Worker 	int ret;
3171*03f9172cSAndroid Build Coastguard Worker 
3172*03f9172cSAndroid Build Coastguard Worker 	/* cmd: "LOG_LEVEL [<level>]" */
3173*03f9172cSAndroid Build Coastguard Worker 	if (*cmd == '\0') {
3174*03f9172cSAndroid Build Coastguard Worker 		pos = buf;
3175*03f9172cSAndroid Build Coastguard Worker 		end = buf + buflen;
3176*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
3177*03f9172cSAndroid Build Coastguard Worker 				  "Timestamp: %d\n",
3178*03f9172cSAndroid Build Coastguard Worker 				  debug_level_str(wpa_debug_level),
3179*03f9172cSAndroid Build Coastguard Worker 				  wpa_debug_timestamp);
3180*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
3181*03f9172cSAndroid Build Coastguard Worker 			ret = 0;
3182*03f9172cSAndroid Build Coastguard Worker 
3183*03f9172cSAndroid Build Coastguard Worker 		return ret;
3184*03f9172cSAndroid Build Coastguard Worker 	}
3185*03f9172cSAndroid Build Coastguard Worker 
3186*03f9172cSAndroid Build Coastguard Worker 	while (*cmd == ' ')
3187*03f9172cSAndroid Build Coastguard Worker 		cmd++;
3188*03f9172cSAndroid Build Coastguard Worker 
3189*03f9172cSAndroid Build Coastguard Worker 	stamp = os_strchr(cmd, ' ');
3190*03f9172cSAndroid Build Coastguard Worker 	if (stamp) {
3191*03f9172cSAndroid Build Coastguard Worker 		*stamp++ = '\0';
3192*03f9172cSAndroid Build Coastguard Worker 		while (*stamp == ' ') {
3193*03f9172cSAndroid Build Coastguard Worker 			stamp++;
3194*03f9172cSAndroid Build Coastguard Worker 		}
3195*03f9172cSAndroid Build Coastguard Worker 	}
3196*03f9172cSAndroid Build Coastguard Worker 
3197*03f9172cSAndroid Build Coastguard Worker 	if (os_strlen(cmd)) {
3198*03f9172cSAndroid Build Coastguard Worker 		int level = str_to_debug_level(cmd);
3199*03f9172cSAndroid Build Coastguard Worker 		if (level < 0)
3200*03f9172cSAndroid Build Coastguard Worker 			return -1;
3201*03f9172cSAndroid Build Coastguard Worker 		wpa_debug_level = level;
3202*03f9172cSAndroid Build Coastguard Worker 	}
3203*03f9172cSAndroid Build Coastguard Worker 
3204*03f9172cSAndroid Build Coastguard Worker 	if (stamp && os_strlen(stamp))
3205*03f9172cSAndroid Build Coastguard Worker 		wpa_debug_timestamp = atoi(stamp);
3206*03f9172cSAndroid Build Coastguard Worker 
3207*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(buf, "OK\n", 3);
3208*03f9172cSAndroid Build Coastguard Worker 	return 3;
3209*03f9172cSAndroid Build Coastguard Worker }
3210*03f9172cSAndroid Build Coastguard Worker 
3211*03f9172cSAndroid Build Coastguard Worker 
3212*03f9172cSAndroid Build Coastguard Worker #ifdef NEED_AP_MLME
hostapd_ctrl_iface_track_sta_list(struct hostapd_data * hapd,char * buf,size_t buflen)3213*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
3214*03f9172cSAndroid Build Coastguard Worker 					     char *buf, size_t buflen)
3215*03f9172cSAndroid Build Coastguard Worker {
3216*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_iface *iface = hapd->iface;
3217*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
3218*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_sta_info *info;
3219*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime now;
3220*03f9172cSAndroid Build Coastguard Worker 
3221*03f9172cSAndroid Build Coastguard Worker 	if (!iface->num_sta_seen)
3222*03f9172cSAndroid Build Coastguard Worker 		return 0;
3223*03f9172cSAndroid Build Coastguard Worker 
3224*03f9172cSAndroid Build Coastguard Worker 	sta_track_expire(iface, 0);
3225*03f9172cSAndroid Build Coastguard Worker 
3226*03f9172cSAndroid Build Coastguard Worker 	pos = buf;
3227*03f9172cSAndroid Build Coastguard Worker 	end = buf + buflen;
3228*03f9172cSAndroid Build Coastguard Worker 
3229*03f9172cSAndroid Build Coastguard Worker 	os_get_reltime(&now);
3230*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_reverse(info, &iface->sta_seen,
3231*03f9172cSAndroid Build Coastguard Worker 				 struct hostapd_sta_info, list) {
3232*03f9172cSAndroid Build Coastguard Worker 		struct os_reltime age;
3233*03f9172cSAndroid Build Coastguard Worker 		int ret;
3234*03f9172cSAndroid Build Coastguard Worker 
3235*03f9172cSAndroid Build Coastguard Worker 		os_reltime_sub(&now, &info->last_seen, &age);
3236*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n",
3237*03f9172cSAndroid Build Coastguard Worker 				  MAC2STR(info->addr), (unsigned int) age.sec,
3238*03f9172cSAndroid Build Coastguard Worker 				  info->ssi_signal);
3239*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(end - pos, ret))
3240*03f9172cSAndroid Build Coastguard Worker 			break;
3241*03f9172cSAndroid Build Coastguard Worker 		pos += ret;
3242*03f9172cSAndroid Build Coastguard Worker 	}
3243*03f9172cSAndroid Build Coastguard Worker 
3244*03f9172cSAndroid Build Coastguard Worker 	return pos - buf;
3245*03f9172cSAndroid Build Coastguard Worker }
3246*03f9172cSAndroid Build Coastguard Worker #endif /* NEED_AP_MLME */
3247*03f9172cSAndroid Build Coastguard Worker 
3248*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_req_lci(struct hostapd_data * hapd,const char * cmd)3249*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd,
3250*03f9172cSAndroid Build Coastguard Worker 				      const char *cmd)
3251*03f9172cSAndroid Build Coastguard Worker {
3252*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
3253*03f9172cSAndroid Build Coastguard Worker 
3254*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr)) {
3255*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address");
3256*03f9172cSAndroid Build Coastguard Worker 		return -1;
3257*03f9172cSAndroid Build Coastguard Worker 	}
3258*03f9172cSAndroid Build Coastguard Worker 
3259*03f9172cSAndroid Build Coastguard Worker 	return hostapd_send_lci_req(hapd, addr);
3260*03f9172cSAndroid Build Coastguard Worker }
3261*03f9172cSAndroid Build Coastguard Worker 
3262*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_req_range(struct hostapd_data * hapd,char * cmd)3263*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd)
3264*03f9172cSAndroid Build Coastguard Worker {
3265*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
3266*03f9172cSAndroid Build Coastguard Worker 	char *token, *context = NULL;
3267*03f9172cSAndroid Build Coastguard Worker 	int random_interval, min_ap;
3268*03f9172cSAndroid Build Coastguard Worker 	u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS];
3269*03f9172cSAndroid Build Coastguard Worker 	unsigned int n_responders;
3270*03f9172cSAndroid Build Coastguard Worker 
3271*03f9172cSAndroid Build Coastguard Worker 	token = str_token(cmd, " ", &context);
3272*03f9172cSAndroid Build Coastguard Worker 	if (!token || hwaddr_aton(token, addr)) {
3273*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3274*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: REQ_RANGE - Bad destination address");
3275*03f9172cSAndroid Build Coastguard Worker 		return -1;
3276*03f9172cSAndroid Build Coastguard Worker 	}
3277*03f9172cSAndroid Build Coastguard Worker 
3278*03f9172cSAndroid Build Coastguard Worker 	token = str_token(cmd, " ", &context);
3279*03f9172cSAndroid Build Coastguard Worker 	if (!token)
3280*03f9172cSAndroid Build Coastguard Worker 		return -1;
3281*03f9172cSAndroid Build Coastguard Worker 
3282*03f9172cSAndroid Build Coastguard Worker 	random_interval = atoi(token);
3283*03f9172cSAndroid Build Coastguard Worker 	if (random_interval < 0 || random_interval > 0xffff)
3284*03f9172cSAndroid Build Coastguard Worker 		return -1;
3285*03f9172cSAndroid Build Coastguard Worker 
3286*03f9172cSAndroid Build Coastguard Worker 	token = str_token(cmd, " ", &context);
3287*03f9172cSAndroid Build Coastguard Worker 	if (!token)
3288*03f9172cSAndroid Build Coastguard Worker 		return -1;
3289*03f9172cSAndroid Build Coastguard Worker 
3290*03f9172cSAndroid Build Coastguard Worker 	min_ap = atoi(token);
3291*03f9172cSAndroid Build Coastguard Worker 	if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP)
3292*03f9172cSAndroid Build Coastguard Worker 		return -1;
3293*03f9172cSAndroid Build Coastguard Worker 
3294*03f9172cSAndroid Build Coastguard Worker 	n_responders = 0;
3295*03f9172cSAndroid Build Coastguard Worker 	while ((token = str_token(cmd, " ", &context))) {
3296*03f9172cSAndroid Build Coastguard Worker 		if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) {
3297*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO,
3298*03f9172cSAndroid Build Coastguard Worker 				   "CTRL: REQ_RANGE: Too many responders");
3299*03f9172cSAndroid Build Coastguard Worker 			return -1;
3300*03f9172cSAndroid Build Coastguard Worker 		}
3301*03f9172cSAndroid Build Coastguard Worker 
3302*03f9172cSAndroid Build Coastguard Worker 		if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) {
3303*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO,
3304*03f9172cSAndroid Build Coastguard Worker 				   "CTRL: REQ_RANGE: Bad responder address");
3305*03f9172cSAndroid Build Coastguard Worker 			return -1;
3306*03f9172cSAndroid Build Coastguard Worker 		}
3307*03f9172cSAndroid Build Coastguard Worker 
3308*03f9172cSAndroid Build Coastguard Worker 		n_responders++;
3309*03f9172cSAndroid Build Coastguard Worker 	}
3310*03f9172cSAndroid Build Coastguard Worker 
3311*03f9172cSAndroid Build Coastguard Worker 	if (!n_responders) {
3312*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3313*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: REQ_RANGE - No FTM responder address");
3314*03f9172cSAndroid Build Coastguard Worker 		return -1;
3315*03f9172cSAndroid Build Coastguard Worker 	}
3316*03f9172cSAndroid Build Coastguard Worker 
3317*03f9172cSAndroid Build Coastguard Worker 	return hostapd_send_range_req(hapd, addr, random_interval, min_ap,
3318*03f9172cSAndroid Build Coastguard Worker 				      responders, n_responders);
3319*03f9172cSAndroid Build Coastguard Worker }
3320*03f9172cSAndroid Build Coastguard Worker 
3321*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_req_beacon(struct hostapd_data * hapd,const char * cmd,char * reply,size_t reply_size)3322*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
3323*03f9172cSAndroid Build Coastguard Worker 					 const char *cmd, char *reply,
3324*03f9172cSAndroid Build Coastguard Worker 					 size_t reply_size)
3325*03f9172cSAndroid Build Coastguard Worker {
3326*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
3327*03f9172cSAndroid Build Coastguard Worker 	const char *pos;
3328*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *req;
3329*03f9172cSAndroid Build Coastguard Worker 	int ret;
3330*03f9172cSAndroid Build Coastguard Worker 	u8 req_mode = 0;
3331*03f9172cSAndroid Build Coastguard Worker 
3332*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr))
3333*03f9172cSAndroid Build Coastguard Worker 		return -1;
3334*03f9172cSAndroid Build Coastguard Worker 	pos = os_strchr(cmd, ' ');
3335*03f9172cSAndroid Build Coastguard Worker 	if (!pos)
3336*03f9172cSAndroid Build Coastguard Worker 		return -1;
3337*03f9172cSAndroid Build Coastguard Worker 	pos++;
3338*03f9172cSAndroid Build Coastguard Worker 	if (os_strncmp(pos, "req_mode=", 9) == 0) {
3339*03f9172cSAndroid Build Coastguard Worker 		int val = hex2byte(pos + 9);
3340*03f9172cSAndroid Build Coastguard Worker 
3341*03f9172cSAndroid Build Coastguard Worker 		if (val < 0)
3342*03f9172cSAndroid Build Coastguard Worker 			return -1;
3343*03f9172cSAndroid Build Coastguard Worker 		req_mode = val;
3344*03f9172cSAndroid Build Coastguard Worker 		pos += 11;
3345*03f9172cSAndroid Build Coastguard Worker 		pos = os_strchr(pos, ' ');
3346*03f9172cSAndroid Build Coastguard Worker 		if (!pos)
3347*03f9172cSAndroid Build Coastguard Worker 			return -1;
3348*03f9172cSAndroid Build Coastguard Worker 		pos++;
3349*03f9172cSAndroid Build Coastguard Worker 	}
3350*03f9172cSAndroid Build Coastguard Worker 	req = wpabuf_parse_bin(pos);
3351*03f9172cSAndroid Build Coastguard Worker 	if (!req)
3352*03f9172cSAndroid Build Coastguard Worker 		return -1;
3353*03f9172cSAndroid Build Coastguard Worker 
3354*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_send_beacon_req(hapd, addr, req_mode, req);
3355*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(req);
3356*03f9172cSAndroid Build Coastguard Worker 	if (ret >= 0)
3357*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(reply, reply_size, "%d", ret);
3358*03f9172cSAndroid Build Coastguard Worker 	return ret;
3359*03f9172cSAndroid Build Coastguard Worker }
3360*03f9172cSAndroid Build Coastguard Worker 
3361*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_req_link_measurement(struct hostapd_data * hapd,const char * cmd,char * reply,size_t reply_size)3362*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_req_link_measurement(struct hostapd_data *hapd,
3363*03f9172cSAndroid Build Coastguard Worker 						   const char *cmd, char *reply,
3364*03f9172cSAndroid Build Coastguard Worker 						   size_t reply_size)
3365*03f9172cSAndroid Build Coastguard Worker {
3366*03f9172cSAndroid Build Coastguard Worker 	u8 addr[ETH_ALEN];
3367*03f9172cSAndroid Build Coastguard Worker 	int ret;
3368*03f9172cSAndroid Build Coastguard Worker 
3369*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(cmd, addr)) {
3370*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3371*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: REQ_LINK_MEASUREMENT: Invalid MAC address");
3372*03f9172cSAndroid Build Coastguard Worker 		return -1;
3373*03f9172cSAndroid Build Coastguard Worker 	}
3374*03f9172cSAndroid Build Coastguard Worker 
3375*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_send_link_measurement_req(hapd, addr);
3376*03f9172cSAndroid Build Coastguard Worker 	if (ret >= 0)
3377*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(reply, reply_size, "%d", ret);
3378*03f9172cSAndroid Build Coastguard Worker 	return ret;
3379*03f9172cSAndroid Build Coastguard Worker }
3380*03f9172cSAndroid Build Coastguard Worker 
3381*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_show_neighbor(struct hostapd_data * hapd,char * buf,size_t buflen)3382*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
3383*03f9172cSAndroid Build Coastguard Worker 					    char *buf, size_t buflen)
3384*03f9172cSAndroid Build Coastguard Worker {
3385*03f9172cSAndroid Build Coastguard Worker 	if (!(hapd->conf->radio_measurements[0] &
3386*03f9172cSAndroid Build Coastguard Worker 	      WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
3387*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3388*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: SHOW_NEIGHBOR: Neighbor report is not enabled");
3389*03f9172cSAndroid Build Coastguard Worker 		return -1;
3390*03f9172cSAndroid Build Coastguard Worker 	}
3391*03f9172cSAndroid Build Coastguard Worker 
3392*03f9172cSAndroid Build Coastguard Worker 	return hostapd_neighbor_show(hapd, buf, buflen);
3393*03f9172cSAndroid Build Coastguard Worker }
3394*03f9172cSAndroid Build Coastguard Worker 
3395*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_set_neighbor(struct hostapd_data * hapd,char * buf)3396*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
3397*03f9172cSAndroid Build Coastguard Worker {
3398*03f9172cSAndroid Build Coastguard Worker 	struct wpa_ssid_value ssid;
3399*03f9172cSAndroid Build Coastguard Worker 	u8 bssid[ETH_ALEN];
3400*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *nr, *lci = NULL, *civic = NULL;
3401*03f9172cSAndroid Build Coastguard Worker 	int stationary = 0;
3402*03f9172cSAndroid Build Coastguard Worker 	int bss_parameters = 0;
3403*03f9172cSAndroid Build Coastguard Worker 	char *tmp;
3404*03f9172cSAndroid Build Coastguard Worker 	int ret = -1;
3405*03f9172cSAndroid Build Coastguard Worker 
3406*03f9172cSAndroid Build Coastguard Worker 	if (!(hapd->conf->radio_measurements[0] &
3407*03f9172cSAndroid Build Coastguard Worker 	      WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
3408*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3409*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
3410*03f9172cSAndroid Build Coastguard Worker 		return -1;
3411*03f9172cSAndroid Build Coastguard Worker 	}
3412*03f9172cSAndroid Build Coastguard Worker 
3413*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(buf, bssid)) {
3414*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
3415*03f9172cSAndroid Build Coastguard Worker 		return -1;
3416*03f9172cSAndroid Build Coastguard Worker 	}
3417*03f9172cSAndroid Build Coastguard Worker 
3418*03f9172cSAndroid Build Coastguard Worker 	tmp = os_strstr(buf, "ssid=");
3419*03f9172cSAndroid Build Coastguard Worker 	if (!tmp || ssid_parse(tmp + 5, &ssid)) {
3420*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3421*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: SET_NEIGHBOR: Bad or missing SSID");
3422*03f9172cSAndroid Build Coastguard Worker 		return -1;
3423*03f9172cSAndroid Build Coastguard Worker 	}
3424*03f9172cSAndroid Build Coastguard Worker 	buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
3425*03f9172cSAndroid Build Coastguard Worker 	if (!buf)
3426*03f9172cSAndroid Build Coastguard Worker 		return -1;
3427*03f9172cSAndroid Build Coastguard Worker 
3428*03f9172cSAndroid Build Coastguard Worker 	tmp = os_strstr(buf, "nr=");
3429*03f9172cSAndroid Build Coastguard Worker 	if (!tmp) {
3430*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3431*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
3432*03f9172cSAndroid Build Coastguard Worker 		return -1;
3433*03f9172cSAndroid Build Coastguard Worker 	}
3434*03f9172cSAndroid Build Coastguard Worker 
3435*03f9172cSAndroid Build Coastguard Worker 	buf = os_strchr(tmp, ' ');
3436*03f9172cSAndroid Build Coastguard Worker 	if (buf)
3437*03f9172cSAndroid Build Coastguard Worker 		*buf++ = '\0';
3438*03f9172cSAndroid Build Coastguard Worker 
3439*03f9172cSAndroid Build Coastguard Worker 	nr = wpabuf_parse_bin(tmp + 3);
3440*03f9172cSAndroid Build Coastguard Worker 	if (!nr) {
3441*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3442*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
3443*03f9172cSAndroid Build Coastguard Worker 		return -1;
3444*03f9172cSAndroid Build Coastguard Worker 	}
3445*03f9172cSAndroid Build Coastguard Worker 
3446*03f9172cSAndroid Build Coastguard Worker 	if (!buf)
3447*03f9172cSAndroid Build Coastguard Worker 		goto set;
3448*03f9172cSAndroid Build Coastguard Worker 
3449*03f9172cSAndroid Build Coastguard Worker 	tmp = os_strstr(buf, "lci=");
3450*03f9172cSAndroid Build Coastguard Worker 	if (tmp) {
3451*03f9172cSAndroid Build Coastguard Worker 		buf = os_strchr(tmp, ' ');
3452*03f9172cSAndroid Build Coastguard Worker 		if (buf)
3453*03f9172cSAndroid Build Coastguard Worker 			*buf++ = '\0';
3454*03f9172cSAndroid Build Coastguard Worker 		lci = wpabuf_parse_bin(tmp + 4);
3455*03f9172cSAndroid Build Coastguard Worker 		if (!lci) {
3456*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
3457*03f9172cSAndroid Build Coastguard Worker 				   "CTRL: SET_NEIGHBOR: Bad LCI subelement");
3458*03f9172cSAndroid Build Coastguard Worker 			goto fail;
3459*03f9172cSAndroid Build Coastguard Worker 		}
3460*03f9172cSAndroid Build Coastguard Worker 	}
3461*03f9172cSAndroid Build Coastguard Worker 
3462*03f9172cSAndroid Build Coastguard Worker 	if (!buf)
3463*03f9172cSAndroid Build Coastguard Worker 		goto set;
3464*03f9172cSAndroid Build Coastguard Worker 
3465*03f9172cSAndroid Build Coastguard Worker 	tmp = os_strstr(buf, "civic=");
3466*03f9172cSAndroid Build Coastguard Worker 	if (tmp) {
3467*03f9172cSAndroid Build Coastguard Worker 		buf = os_strchr(tmp, ' ');
3468*03f9172cSAndroid Build Coastguard Worker 		if (buf)
3469*03f9172cSAndroid Build Coastguard Worker 			*buf++ = '\0';
3470*03f9172cSAndroid Build Coastguard Worker 		civic = wpabuf_parse_bin(tmp + 6);
3471*03f9172cSAndroid Build Coastguard Worker 		if (!civic) {
3472*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
3473*03f9172cSAndroid Build Coastguard Worker 				   "CTRL: SET_NEIGHBOR: Bad civic subelement");
3474*03f9172cSAndroid Build Coastguard Worker 			goto fail;
3475*03f9172cSAndroid Build Coastguard Worker 		}
3476*03f9172cSAndroid Build Coastguard Worker 	}
3477*03f9172cSAndroid Build Coastguard Worker 
3478*03f9172cSAndroid Build Coastguard Worker 	if (!buf)
3479*03f9172cSAndroid Build Coastguard Worker 		goto set;
3480*03f9172cSAndroid Build Coastguard Worker 
3481*03f9172cSAndroid Build Coastguard Worker 	if (os_strstr(buf, "stat"))
3482*03f9172cSAndroid Build Coastguard Worker 		stationary = 1;
3483*03f9172cSAndroid Build Coastguard Worker 
3484*03f9172cSAndroid Build Coastguard Worker 	tmp = os_strstr(buf, "bss_parameter=");
3485*03f9172cSAndroid Build Coastguard Worker 	if (tmp) {
3486*03f9172cSAndroid Build Coastguard Worker 		bss_parameters = atoi(tmp + 14);
3487*03f9172cSAndroid Build Coastguard Worker 		if (bss_parameters < 0 || bss_parameters > 0xff) {
3488*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
3489*03f9172cSAndroid Build Coastguard Worker 				   "CTRL: SET_NEIGHBOR: Bad bss_parameters subelement");
3490*03f9172cSAndroid Build Coastguard Worker 			goto fail;
3491*03f9172cSAndroid Build Coastguard Worker 		}
3492*03f9172cSAndroid Build Coastguard Worker 	}
3493*03f9172cSAndroid Build Coastguard Worker 
3494*03f9172cSAndroid Build Coastguard Worker set:
3495*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic,
3496*03f9172cSAndroid Build Coastguard Worker 				   stationary, bss_parameters);
3497*03f9172cSAndroid Build Coastguard Worker 
3498*03f9172cSAndroid Build Coastguard Worker fail:
3499*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(nr);
3500*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(lci);
3501*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(civic);
3502*03f9172cSAndroid Build Coastguard Worker 
3503*03f9172cSAndroid Build Coastguard Worker 	return ret;
3504*03f9172cSAndroid Build Coastguard Worker }
3505*03f9172cSAndroid Build Coastguard Worker 
3506*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_remove_neighbor(struct hostapd_data * hapd,char * buf)3507*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
3508*03f9172cSAndroid Build Coastguard Worker 					      char *buf)
3509*03f9172cSAndroid Build Coastguard Worker {
3510*03f9172cSAndroid Build Coastguard Worker 	struct wpa_ssid_value ssid;
3511*03f9172cSAndroid Build Coastguard Worker 	struct wpa_ssid_value *ssidp = NULL;
3512*03f9172cSAndroid Build Coastguard Worker 	u8 bssid[ETH_ALEN];
3513*03f9172cSAndroid Build Coastguard Worker 	char *tmp;
3514*03f9172cSAndroid Build Coastguard Worker 
3515*03f9172cSAndroid Build Coastguard Worker 	if (hwaddr_aton(buf, bssid)) {
3516*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
3517*03f9172cSAndroid Build Coastguard Worker 		return -1;
3518*03f9172cSAndroid Build Coastguard Worker 	}
3519*03f9172cSAndroid Build Coastguard Worker 
3520*03f9172cSAndroid Build Coastguard Worker 	tmp = os_strstr(buf, "ssid=");
3521*03f9172cSAndroid Build Coastguard Worker 	if (tmp) {
3522*03f9172cSAndroid Build Coastguard Worker 		ssidp = &ssid;
3523*03f9172cSAndroid Build Coastguard Worker 		if (ssid_parse(tmp + 5, &ssid)) {
3524*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
3525*03f9172cSAndroid Build Coastguard Worker 				   "CTRL: REMOVE_NEIGHBOR: Bad SSID");
3526*03f9172cSAndroid Build Coastguard Worker 			return -1;
3527*03f9172cSAndroid Build Coastguard Worker 		}
3528*03f9172cSAndroid Build Coastguard Worker 	}
3529*03f9172cSAndroid Build Coastguard Worker 
3530*03f9172cSAndroid Build Coastguard Worker 	return hostapd_neighbor_remove(hapd, bssid, ssidp);
3531*03f9172cSAndroid Build Coastguard Worker }
3532*03f9172cSAndroid Build Coastguard Worker 
3533*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_driver_flags(struct hostapd_iface * iface,char * buf,size_t buflen)3534*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
3535*03f9172cSAndroid Build Coastguard Worker 				     size_t buflen)
3536*03f9172cSAndroid Build Coastguard Worker {
3537*03f9172cSAndroid Build Coastguard Worker 	int ret, i;
3538*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
3539*03f9172cSAndroid Build Coastguard Worker 
3540*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(buf, buflen, "%016llX:\n",
3541*03f9172cSAndroid Build Coastguard Worker 			  (long long unsigned) iface->drv_flags);
3542*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(buflen, ret))
3543*03f9172cSAndroid Build Coastguard Worker 		return -1;
3544*03f9172cSAndroid Build Coastguard Worker 
3545*03f9172cSAndroid Build Coastguard Worker 	pos = buf + ret;
3546*03f9172cSAndroid Build Coastguard Worker 	end = buf + buflen;
3547*03f9172cSAndroid Build Coastguard Worker 
3548*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < 64; i++) {
3549*03f9172cSAndroid Build Coastguard Worker 		if (iface->drv_flags & (1LLU << i)) {
3550*03f9172cSAndroid Build Coastguard Worker 			ret = os_snprintf(pos, end - pos, "%s\n",
3551*03f9172cSAndroid Build Coastguard Worker 					  driver_flag_to_string(1LLU << i));
3552*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(end - pos, ret))
3553*03f9172cSAndroid Build Coastguard Worker 				return -1;
3554*03f9172cSAndroid Build Coastguard Worker 			pos += ret;
3555*03f9172cSAndroid Build Coastguard Worker 		}
3556*03f9172cSAndroid Build Coastguard Worker 	}
3557*03f9172cSAndroid Build Coastguard Worker 
3558*03f9172cSAndroid Build Coastguard Worker 	return pos - buf;
3559*03f9172cSAndroid Build Coastguard Worker }
3560*03f9172cSAndroid Build Coastguard Worker 
3561*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_driver_flags2(struct hostapd_iface * iface,char * buf,size_t buflen)3562*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf,
3563*03f9172cSAndroid Build Coastguard Worker 				      size_t buflen)
3564*03f9172cSAndroid Build Coastguard Worker {
3565*03f9172cSAndroid Build Coastguard Worker 	int ret, i;
3566*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
3567*03f9172cSAndroid Build Coastguard Worker 
3568*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(buf, buflen, "%016llX:\n",
3569*03f9172cSAndroid Build Coastguard Worker 			  (long long unsigned) iface->drv_flags2);
3570*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(buflen, ret))
3571*03f9172cSAndroid Build Coastguard Worker 		return -1;
3572*03f9172cSAndroid Build Coastguard Worker 
3573*03f9172cSAndroid Build Coastguard Worker 	pos = buf + ret;
3574*03f9172cSAndroid Build Coastguard Worker 	end = buf + buflen;
3575*03f9172cSAndroid Build Coastguard Worker 
3576*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < 64; i++) {
3577*03f9172cSAndroid Build Coastguard Worker 		if (iface->drv_flags2 & (1LLU << i)) {
3578*03f9172cSAndroid Build Coastguard Worker 			ret = os_snprintf(pos, end - pos, "%s\n",
3579*03f9172cSAndroid Build Coastguard Worker 					  driver_flag2_to_string(1LLU << i));
3580*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(end - pos, ret))
3581*03f9172cSAndroid Build Coastguard Worker 				return -1;
3582*03f9172cSAndroid Build Coastguard Worker 			pos += ret;
3583*03f9172cSAndroid Build Coastguard Worker 		}
3584*03f9172cSAndroid Build Coastguard Worker 	}
3585*03f9172cSAndroid Build Coastguard Worker 
3586*03f9172cSAndroid Build Coastguard Worker 	return pos - buf;
3587*03f9172cSAndroid Build Coastguard Worker }
3588*03f9172cSAndroid Build Coastguard Worker 
3589*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_get_capability(struct hostapd_data * hapd,const char * field,char * buf,size_t buflen)3590*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd,
3591*03f9172cSAndroid Build Coastguard Worker 					     const char *field, char *buf,
3592*03f9172cSAndroid Build Coastguard Worker 					     size_t buflen)
3593*03f9172cSAndroid Build Coastguard Worker {
3594*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
3595*03f9172cSAndroid Build Coastguard Worker 
3596*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
3597*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(field, "dpp") == 0) {
3598*03f9172cSAndroid Build Coastguard Worker 		int res;
3599*03f9172cSAndroid Build Coastguard Worker 
3600*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP3
3601*03f9172cSAndroid Build Coastguard Worker 		res = os_snprintf(buf, buflen, "DPP=3");
3602*03f9172cSAndroid Build Coastguard Worker #elif defined(CONFIG_DPP2)
3603*03f9172cSAndroid Build Coastguard Worker 		res = os_snprintf(buf, buflen, "DPP=2");
3604*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_DPP2 */
3605*03f9172cSAndroid Build Coastguard Worker 		res = os_snprintf(buf, buflen, "DPP=1");
3606*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP2 */
3607*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(buflen, res))
3608*03f9172cSAndroid Build Coastguard Worker 			return -1;
3609*03f9172cSAndroid Build Coastguard Worker 		return res;
3610*03f9172cSAndroid Build Coastguard Worker 	}
3611*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
3612*03f9172cSAndroid Build Coastguard Worker 
3613*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3614*03f9172cSAndroid Build Coastguard Worker 		   field);
3615*03f9172cSAndroid Build Coastguard Worker 
3616*03f9172cSAndroid Build Coastguard Worker 	return -1;
3617*03f9172cSAndroid Build Coastguard Worker }
3618*03f9172cSAndroid Build Coastguard Worker 
3619*03f9172cSAndroid Build Coastguard Worker 
3620*03f9172cSAndroid Build Coastguard Worker #ifdef ANDROID
hostapd_ctrl_iface_driver_cmd(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3621*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_driver_cmd(struct hostapd_data *hapd, char *cmd,
3622*03f9172cSAndroid Build Coastguard Worker 					 char *buf, size_t buflen)
3623*03f9172cSAndroid Build Coastguard Worker {
3624*03f9172cSAndroid Build Coastguard Worker 	int ret;
3625*03f9172cSAndroid Build Coastguard Worker 
3626*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_drv_driver_cmd(hapd, cmd, buf, buflen);
3627*03f9172cSAndroid Build Coastguard Worker 	if (ret == 0) {
3628*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(buf, buflen, "%s\n", "OK");
3629*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(buflen, ret))
3630*03f9172cSAndroid Build Coastguard Worker 			ret = -1;
3631*03f9172cSAndroid Build Coastguard Worker 	}
3632*03f9172cSAndroid Build Coastguard Worker 	return ret;
3633*03f9172cSAndroid Build Coastguard Worker }
3634*03f9172cSAndroid Build Coastguard Worker #endif /* ANDROID */
3635*03f9172cSAndroid Build Coastguard Worker 
3636*03f9172cSAndroid Build Coastguard Worker 
3637*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211BE
3638*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_enable_mld(struct hostapd_iface * iface)3639*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_enable_mld(struct hostapd_iface *iface)
3640*03f9172cSAndroid Build Coastguard Worker {
3641*03f9172cSAndroid Build Coastguard Worker 	unsigned int i;
3642*03f9172cSAndroid Build Coastguard Worker 
3643*03f9172cSAndroid Build Coastguard Worker 	if (!iface || !iface->bss[0]->conf->mld_ap) {
3644*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3645*03f9172cSAndroid Build Coastguard Worker 			   "Trying to enable AP MLD on an interface that is not affiliated with an AP MLD");
3646*03f9172cSAndroid Build Coastguard Worker 		return -1;
3647*03f9172cSAndroid Build Coastguard Worker 	}
3648*03f9172cSAndroid Build Coastguard Worker 
3649*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < iface->interfaces->count; ++i) {
3650*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
3651*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_data *h_hapd = h_iface->bss[0];
3652*03f9172cSAndroid Build Coastguard Worker 
3653*03f9172cSAndroid Build Coastguard Worker 		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
3654*03f9172cSAndroid Build Coastguard Worker 			continue;
3655*03f9172cSAndroid Build Coastguard Worker 
3656*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_enable_iface(h_iface)) {
3657*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Enabling of AP MLD failed");
3658*03f9172cSAndroid Build Coastguard Worker 			return -1;
3659*03f9172cSAndroid Build Coastguard Worker 		}
3660*03f9172cSAndroid Build Coastguard Worker 	}
3661*03f9172cSAndroid Build Coastguard Worker 	return 0;
3662*03f9172cSAndroid Build Coastguard Worker }
3663*03f9172cSAndroid Build Coastguard Worker 
3664*03f9172cSAndroid Build Coastguard Worker 
hostapd_disable_iface_bss(struct hostapd_iface * iface)3665*03f9172cSAndroid Build Coastguard Worker static void hostapd_disable_iface_bss(struct hostapd_iface *iface)
3666*03f9172cSAndroid Build Coastguard Worker {
3667*03f9172cSAndroid Build Coastguard Worker 	unsigned int i;
3668*03f9172cSAndroid Build Coastguard Worker 
3669*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < iface->num_bss; i++)
3670*03f9172cSAndroid Build Coastguard Worker 		hostapd_bss_deinit_no_free(iface->bss[i]);
3671*03f9172cSAndroid Build Coastguard Worker }
3672*03f9172cSAndroid Build Coastguard Worker 
3673*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_disable_mld(struct hostapd_iface * iface)3674*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
3675*03f9172cSAndroid Build Coastguard Worker {
3676*03f9172cSAndroid Build Coastguard Worker 	unsigned int i;
3677*03f9172cSAndroid Build Coastguard Worker 
3678*03f9172cSAndroid Build Coastguard Worker 	if (!iface || !iface->bss[0]->conf->mld_ap) {
3679*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
3680*03f9172cSAndroid Build Coastguard Worker 			   "Trying to disable AP MLD on an interface that is not affiliated with an AP MLD.");
3681*03f9172cSAndroid Build Coastguard Worker 		return -1;
3682*03f9172cSAndroid Build Coastguard Worker 	}
3683*03f9172cSAndroid Build Coastguard Worker 
3684*03f9172cSAndroid Build Coastguard Worker 	/* First, disable BSSs before stopping beaconing and doing driver
3685*03f9172cSAndroid Build Coastguard Worker 	 * deinit so that the broadcast Deauthentication frames go out. */
3686*03f9172cSAndroid Build Coastguard Worker 
3687*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < iface->interfaces->count; ++i) {
3688*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
3689*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_data *h_hapd = h_iface->bss[0];
3690*03f9172cSAndroid Build Coastguard Worker 
3691*03f9172cSAndroid Build Coastguard Worker 		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
3692*03f9172cSAndroid Build Coastguard Worker 			continue;
3693*03f9172cSAndroid Build Coastguard Worker 
3694*03f9172cSAndroid Build Coastguard Worker 		hostapd_disable_iface_bss(iface);
3695*03f9172cSAndroid Build Coastguard Worker 	}
3696*03f9172cSAndroid Build Coastguard Worker 
3697*03f9172cSAndroid Build Coastguard Worker 	/* Then, fully disable interfaces */
3698*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < iface->interfaces->count; ++i) {
3699*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
3700*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_data *h_hapd = h_iface->bss[0];
3701*03f9172cSAndroid Build Coastguard Worker 
3702*03f9172cSAndroid Build Coastguard Worker 		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
3703*03f9172cSAndroid Build Coastguard Worker 			continue;
3704*03f9172cSAndroid Build Coastguard Worker 
3705*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_disable_iface(h_iface)) {
3706*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
3707*03f9172cSAndroid Build Coastguard Worker 			return -1;
3708*03f9172cSAndroid Build Coastguard Worker 		}
3709*03f9172cSAndroid Build Coastguard Worker 	}
3710*03f9172cSAndroid Build Coastguard Worker 
3711*03f9172cSAndroid Build Coastguard Worker 	return 0;
3712*03f9172cSAndroid Build Coastguard Worker }
3713*03f9172cSAndroid Build Coastguard Worker 
3714*03f9172cSAndroid Build Coastguard Worker 
3715*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
hostapd_ctrl_iface_link_remove(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3716*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_link_remove(struct hostapd_data *hapd, char *cmd,
3717*03f9172cSAndroid Build Coastguard Worker 					  char *buf, size_t buflen)
3718*03f9172cSAndroid Build Coastguard Worker {
3719*03f9172cSAndroid Build Coastguard Worker 	int ret;
3720*03f9172cSAndroid Build Coastguard Worker 	u32 count = atoi(cmd);
3721*03f9172cSAndroid Build Coastguard Worker 
3722*03f9172cSAndroid Build Coastguard Worker 	if (!count)
3723*03f9172cSAndroid Build Coastguard Worker 		count = 1;
3724*03f9172cSAndroid Build Coastguard Worker 
3725*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_link_remove(hapd, count);
3726*03f9172cSAndroid Build Coastguard Worker 	if (ret == 0) {
3727*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(buf, buflen, "%s\n", "OK");
3728*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(buflen, ret))
3729*03f9172cSAndroid Build Coastguard Worker 			ret = -1;
3730*03f9172cSAndroid Build Coastguard Worker 		else
3731*03f9172cSAndroid Build Coastguard Worker 			ret = 0;
3732*03f9172cSAndroid Build Coastguard Worker 	}
3733*03f9172cSAndroid Build Coastguard Worker 
3734*03f9172cSAndroid Build Coastguard Worker 	return ret;
3735*03f9172cSAndroid Build Coastguard Worker }
3736*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
3737*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211BE */
3738*03f9172cSAndroid Build Coastguard Worker 
3739*03f9172cSAndroid Build Coastguard Worker 
3740*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_NAN_USD
3741*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_nan_publish(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3742*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
3743*03f9172cSAndroid Build Coastguard Worker 				    char *buf, size_t buflen)
3744*03f9172cSAndroid Build Coastguard Worker {
3745*03f9172cSAndroid Build Coastguard Worker 	char *token, *context = NULL;
3746*03f9172cSAndroid Build Coastguard Worker 	int publish_id;
3747*03f9172cSAndroid Build Coastguard Worker 	struct nan_publish_params params;
3748*03f9172cSAndroid Build Coastguard Worker 	const char *service_name = NULL;
3749*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *ssi = NULL;
3750*03f9172cSAndroid Build Coastguard Worker 	int ret = -1;
3751*03f9172cSAndroid Build Coastguard Worker 	enum nan_service_protocol_type srv_proto_type = 0;
3752*03f9172cSAndroid Build Coastguard Worker 	bool p2p = false;
3753*03f9172cSAndroid Build Coastguard Worker 
3754*03f9172cSAndroid Build Coastguard Worker 	os_memset(&params, 0, sizeof(params));
3755*03f9172cSAndroid Build Coastguard Worker 	/* USD shall use both solicited and unsolicited transmissions */
3756*03f9172cSAndroid Build Coastguard Worker 	params.unsolicited = true;
3757*03f9172cSAndroid Build Coastguard Worker 	params.solicited = true;
3758*03f9172cSAndroid Build Coastguard Worker 	/* USD shall require FSD without GAS */
3759*03f9172cSAndroid Build Coastguard Worker 	params.fsd = true;
3760*03f9172cSAndroid Build Coastguard Worker 
3761*03f9172cSAndroid Build Coastguard Worker 	while ((token = str_token(cmd, " ", &context))) {
3762*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "service_name=", 13) == 0) {
3763*03f9172cSAndroid Build Coastguard Worker 			service_name = token + 13;
3764*03f9172cSAndroid Build Coastguard Worker 			continue;
3765*03f9172cSAndroid Build Coastguard Worker 		}
3766*03f9172cSAndroid Build Coastguard Worker 
3767*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "ttl=", 4) == 0) {
3768*03f9172cSAndroid Build Coastguard Worker 			params.ttl = atoi(token + 4);
3769*03f9172cSAndroid Build Coastguard Worker 			continue;
3770*03f9172cSAndroid Build Coastguard Worker 		}
3771*03f9172cSAndroid Build Coastguard Worker 
3772*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
3773*03f9172cSAndroid Build Coastguard Worker 			srv_proto_type = atoi(token + 15);
3774*03f9172cSAndroid Build Coastguard Worker 			continue;
3775*03f9172cSAndroid Build Coastguard Worker 		}
3776*03f9172cSAndroid Build Coastguard Worker 
3777*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "ssi=", 4) == 0) {
3778*03f9172cSAndroid Build Coastguard Worker 			if (ssi)
3779*03f9172cSAndroid Build Coastguard Worker 				goto fail;
3780*03f9172cSAndroid Build Coastguard Worker 			ssi = wpabuf_parse_bin(token + 4);
3781*03f9172cSAndroid Build Coastguard Worker 			if (!ssi)
3782*03f9172cSAndroid Build Coastguard Worker 				goto fail;
3783*03f9172cSAndroid Build Coastguard Worker 			continue;
3784*03f9172cSAndroid Build Coastguard Worker 		}
3785*03f9172cSAndroid Build Coastguard Worker 
3786*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(token, "p2p=1") == 0) {
3787*03f9172cSAndroid Build Coastguard Worker 			p2p = true;
3788*03f9172cSAndroid Build Coastguard Worker 			continue;
3789*03f9172cSAndroid Build Coastguard Worker 		}
3790*03f9172cSAndroid Build Coastguard Worker 
3791*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(token, "solicited=0") == 0) {
3792*03f9172cSAndroid Build Coastguard Worker 			params.solicited = false;
3793*03f9172cSAndroid Build Coastguard Worker 			continue;
3794*03f9172cSAndroid Build Coastguard Worker 		}
3795*03f9172cSAndroid Build Coastguard Worker 
3796*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(token, "unsolicited=0") == 0) {
3797*03f9172cSAndroid Build Coastguard Worker 			params.unsolicited = false;
3798*03f9172cSAndroid Build Coastguard Worker 			continue;
3799*03f9172cSAndroid Build Coastguard Worker 		}
3800*03f9172cSAndroid Build Coastguard Worker 
3801*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(token, "fsd=0") == 0) {
3802*03f9172cSAndroid Build Coastguard Worker 			params.fsd = false;
3803*03f9172cSAndroid Build Coastguard Worker 			continue;
3804*03f9172cSAndroid Build Coastguard Worker 		}
3805*03f9172cSAndroid Build Coastguard Worker 
3806*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
3807*03f9172cSAndroid Build Coastguard Worker 			   token);
3808*03f9172cSAndroid Build Coastguard Worker 		goto fail;
3809*03f9172cSAndroid Build Coastguard Worker 	}
3810*03f9172cSAndroid Build Coastguard Worker 
3811*03f9172cSAndroid Build Coastguard Worker 	publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
3812*03f9172cSAndroid Build Coastguard Worker 					     ssi, &params, p2p);
3813*03f9172cSAndroid Build Coastguard Worker 	if (publish_id > 0)
3814*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(buf, buflen, "%d", publish_id);
3815*03f9172cSAndroid Build Coastguard Worker fail:
3816*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(ssi);
3817*03f9172cSAndroid Build Coastguard Worker 	return ret;
3818*03f9172cSAndroid Build Coastguard Worker }
3819*03f9172cSAndroid Build Coastguard Worker 
3820*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_nan_cancel_publish(struct hostapd_data * hapd,char * cmd)3821*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_nan_cancel_publish(struct hostapd_data *hapd,
3822*03f9172cSAndroid Build Coastguard Worker 					   char *cmd)
3823*03f9172cSAndroid Build Coastguard Worker {
3824*03f9172cSAndroid Build Coastguard Worker 	char *token, *context = NULL;
3825*03f9172cSAndroid Build Coastguard Worker 	int publish_id = 0;
3826*03f9172cSAndroid Build Coastguard Worker 
3827*03f9172cSAndroid Build Coastguard Worker 	while ((token = str_token(cmd, " ", &context))) {
3828*03f9172cSAndroid Build Coastguard Worker 		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
3829*03f9172cSAndroid Build Coastguard Worker 			continue;
3830*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3831*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
3832*03f9172cSAndroid Build Coastguard Worker 			   token);
3833*03f9172cSAndroid Build Coastguard Worker 		return -1;
3834*03f9172cSAndroid Build Coastguard Worker 	}
3835*03f9172cSAndroid Build Coastguard Worker 
3836*03f9172cSAndroid Build Coastguard Worker 	if (publish_id <= 0) {
3837*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3838*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
3839*03f9172cSAndroid Build Coastguard Worker 		return -1;
3840*03f9172cSAndroid Build Coastguard Worker 	}
3841*03f9172cSAndroid Build Coastguard Worker 
3842*03f9172cSAndroid Build Coastguard Worker 	hostapd_nan_usd_cancel_publish(hapd, publish_id);
3843*03f9172cSAndroid Build Coastguard Worker 	return 0;
3844*03f9172cSAndroid Build Coastguard Worker }
3845*03f9172cSAndroid Build Coastguard Worker 
3846*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_nan_update_publish(struct hostapd_data * hapd,char * cmd)3847*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_nan_update_publish(struct hostapd_data *hapd,
3848*03f9172cSAndroid Build Coastguard Worker 					   char *cmd)
3849*03f9172cSAndroid Build Coastguard Worker {
3850*03f9172cSAndroid Build Coastguard Worker 	char *token, *context = NULL;
3851*03f9172cSAndroid Build Coastguard Worker 	int publish_id = 0;
3852*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *ssi = NULL;
3853*03f9172cSAndroid Build Coastguard Worker 	int ret = -1;
3854*03f9172cSAndroid Build Coastguard Worker 
3855*03f9172cSAndroid Build Coastguard Worker 	while ((token = str_token(cmd, " ", &context))) {
3856*03f9172cSAndroid Build Coastguard Worker 		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
3857*03f9172cSAndroid Build Coastguard Worker 			continue;
3858*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "ssi=", 4) == 0) {
3859*03f9172cSAndroid Build Coastguard Worker 			if (ssi)
3860*03f9172cSAndroid Build Coastguard Worker 				goto fail;
3861*03f9172cSAndroid Build Coastguard Worker 			ssi = wpabuf_parse_bin(token + 4);
3862*03f9172cSAndroid Build Coastguard Worker 			if (!ssi)
3863*03f9172cSAndroid Build Coastguard Worker 				goto fail;
3864*03f9172cSAndroid Build Coastguard Worker 			continue;
3865*03f9172cSAndroid Build Coastguard Worker 		}
3866*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3867*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
3868*03f9172cSAndroid Build Coastguard Worker 			   token);
3869*03f9172cSAndroid Build Coastguard Worker 		goto fail;
3870*03f9172cSAndroid Build Coastguard Worker 	}
3871*03f9172cSAndroid Build Coastguard Worker 
3872*03f9172cSAndroid Build Coastguard Worker 	if (publish_id <= 0) {
3873*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3874*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
3875*03f9172cSAndroid Build Coastguard Worker 		goto fail;
3876*03f9172cSAndroid Build Coastguard Worker 	}
3877*03f9172cSAndroid Build Coastguard Worker 
3878*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_nan_usd_update_publish(hapd, publish_id, ssi);
3879*03f9172cSAndroid Build Coastguard Worker fail:
3880*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(ssi);
3881*03f9172cSAndroid Build Coastguard Worker 	return ret;
3882*03f9172cSAndroid Build Coastguard Worker }
3883*03f9172cSAndroid Build Coastguard Worker 
3884*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_nan_subscribe(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3885*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
3886*03f9172cSAndroid Build Coastguard Worker 				      char *buf, size_t buflen)
3887*03f9172cSAndroid Build Coastguard Worker {
3888*03f9172cSAndroid Build Coastguard Worker 	char *token, *context = NULL;
3889*03f9172cSAndroid Build Coastguard Worker 	int subscribe_id;
3890*03f9172cSAndroid Build Coastguard Worker 	struct nan_subscribe_params params;
3891*03f9172cSAndroid Build Coastguard Worker 	const char *service_name = NULL;
3892*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *ssi = NULL;
3893*03f9172cSAndroid Build Coastguard Worker 	int ret = -1;
3894*03f9172cSAndroid Build Coastguard Worker 	enum nan_service_protocol_type srv_proto_type = 0;
3895*03f9172cSAndroid Build Coastguard Worker 	bool p2p = false;
3896*03f9172cSAndroid Build Coastguard Worker 
3897*03f9172cSAndroid Build Coastguard Worker 	os_memset(&params, 0, sizeof(params));
3898*03f9172cSAndroid Build Coastguard Worker 
3899*03f9172cSAndroid Build Coastguard Worker 	while ((token = str_token(cmd, " ", &context))) {
3900*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "service_name=", 13) == 0) {
3901*03f9172cSAndroid Build Coastguard Worker 			service_name = token + 13;
3902*03f9172cSAndroid Build Coastguard Worker 			continue;
3903*03f9172cSAndroid Build Coastguard Worker 		}
3904*03f9172cSAndroid Build Coastguard Worker 
3905*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(token, "active=1") == 0) {
3906*03f9172cSAndroid Build Coastguard Worker 			params.active = true;
3907*03f9172cSAndroid Build Coastguard Worker 			continue;
3908*03f9172cSAndroid Build Coastguard Worker 		}
3909*03f9172cSAndroid Build Coastguard Worker 
3910*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "ttl=", 4) == 0) {
3911*03f9172cSAndroid Build Coastguard Worker 			params.ttl = atoi(token + 4);
3912*03f9172cSAndroid Build Coastguard Worker 			continue;
3913*03f9172cSAndroid Build Coastguard Worker 		}
3914*03f9172cSAndroid Build Coastguard Worker 
3915*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
3916*03f9172cSAndroid Build Coastguard Worker 			srv_proto_type = atoi(token + 15);
3917*03f9172cSAndroid Build Coastguard Worker 			continue;
3918*03f9172cSAndroid Build Coastguard Worker 		}
3919*03f9172cSAndroid Build Coastguard Worker 
3920*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "ssi=", 4) == 0) {
3921*03f9172cSAndroid Build Coastguard Worker 			if (ssi)
3922*03f9172cSAndroid Build Coastguard Worker 				goto fail;
3923*03f9172cSAndroid Build Coastguard Worker 			ssi = wpabuf_parse_bin(token + 4);
3924*03f9172cSAndroid Build Coastguard Worker 			if (!ssi)
3925*03f9172cSAndroid Build Coastguard Worker 				goto fail;
3926*03f9172cSAndroid Build Coastguard Worker 			continue;
3927*03f9172cSAndroid Build Coastguard Worker 		}
3928*03f9172cSAndroid Build Coastguard Worker 
3929*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(token, "p2p=1") == 0) {
3930*03f9172cSAndroid Build Coastguard Worker 			p2p = true;
3931*03f9172cSAndroid Build Coastguard Worker 			continue;
3932*03f9172cSAndroid Build Coastguard Worker 		}
3933*03f9172cSAndroid Build Coastguard Worker 
3934*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3935*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
3936*03f9172cSAndroid Build Coastguard Worker 			   token);
3937*03f9172cSAndroid Build Coastguard Worker 		goto fail;
3938*03f9172cSAndroid Build Coastguard Worker 	}
3939*03f9172cSAndroid Build Coastguard Worker 
3940*03f9172cSAndroid Build Coastguard Worker 	subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
3941*03f9172cSAndroid Build Coastguard Worker 						 srv_proto_type, ssi,
3942*03f9172cSAndroid Build Coastguard Worker 						 &params, p2p);
3943*03f9172cSAndroid Build Coastguard Worker 	if (subscribe_id > 0)
3944*03f9172cSAndroid Build Coastguard Worker 		ret = os_snprintf(buf, buflen, "%d", subscribe_id);
3945*03f9172cSAndroid Build Coastguard Worker fail:
3946*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(ssi);
3947*03f9172cSAndroid Build Coastguard Worker 	return ret;
3948*03f9172cSAndroid Build Coastguard Worker }
3949*03f9172cSAndroid Build Coastguard Worker 
3950*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_nan_cancel_subscribe(struct hostapd_data * hapd,char * cmd)3951*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_nan_cancel_subscribe(struct hostapd_data *hapd,
3952*03f9172cSAndroid Build Coastguard Worker 					     char *cmd)
3953*03f9172cSAndroid Build Coastguard Worker {
3954*03f9172cSAndroid Build Coastguard Worker 	char *token, *context = NULL;
3955*03f9172cSAndroid Build Coastguard Worker 	int subscribe_id = 0;
3956*03f9172cSAndroid Build Coastguard Worker 
3957*03f9172cSAndroid Build Coastguard Worker 	while ((token = str_token(cmd, " ", &context))) {
3958*03f9172cSAndroid Build Coastguard Worker 		if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
3959*03f9172cSAndroid Build Coastguard Worker 			continue;
3960*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3961*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
3962*03f9172cSAndroid Build Coastguard Worker 			   token);
3963*03f9172cSAndroid Build Coastguard Worker 		return -1;
3964*03f9172cSAndroid Build Coastguard Worker 	}
3965*03f9172cSAndroid Build Coastguard Worker 
3966*03f9172cSAndroid Build Coastguard Worker 	if (subscribe_id <= 0) {
3967*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
3968*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
3969*03f9172cSAndroid Build Coastguard Worker 		return -1;
3970*03f9172cSAndroid Build Coastguard Worker 	}
3971*03f9172cSAndroid Build Coastguard Worker 
3972*03f9172cSAndroid Build Coastguard Worker 	hostapd_nan_usd_cancel_subscribe(hapd, subscribe_id);
3973*03f9172cSAndroid Build Coastguard Worker 	return 0;
3974*03f9172cSAndroid Build Coastguard Worker }
3975*03f9172cSAndroid Build Coastguard Worker 
3976*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_nan_transmit(struct hostapd_data * hapd,char * cmd)3977*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_nan_transmit(struct hostapd_data *hapd, char *cmd)
3978*03f9172cSAndroid Build Coastguard Worker {
3979*03f9172cSAndroid Build Coastguard Worker 	char *token, *context = NULL;
3980*03f9172cSAndroid Build Coastguard Worker 	int handle = 0;
3981*03f9172cSAndroid Build Coastguard Worker 	int req_instance_id = 0;
3982*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *ssi = NULL;
3983*03f9172cSAndroid Build Coastguard Worker 	u8 peer_addr[ETH_ALEN];
3984*03f9172cSAndroid Build Coastguard Worker 	int ret = -1;
3985*03f9172cSAndroid Build Coastguard Worker 
3986*03f9172cSAndroid Build Coastguard Worker 	os_memset(peer_addr, 0, ETH_ALEN);
3987*03f9172cSAndroid Build Coastguard Worker 
3988*03f9172cSAndroid Build Coastguard Worker 	while ((token = str_token(cmd, " ", &context))) {
3989*03f9172cSAndroid Build Coastguard Worker 		if (sscanf(token, "handle=%i", &handle) == 1)
3990*03f9172cSAndroid Build Coastguard Worker 			continue;
3991*03f9172cSAndroid Build Coastguard Worker 
3992*03f9172cSAndroid Build Coastguard Worker 		if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
3993*03f9172cSAndroid Build Coastguard Worker 			continue;
3994*03f9172cSAndroid Build Coastguard Worker 
3995*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "address=", 8) == 0) {
3996*03f9172cSAndroid Build Coastguard Worker 			if (hwaddr_aton(token + 8, peer_addr) < 0)
3997*03f9172cSAndroid Build Coastguard Worker 				return -1;
3998*03f9172cSAndroid Build Coastguard Worker 			continue;
3999*03f9172cSAndroid Build Coastguard Worker 		}
4000*03f9172cSAndroid Build Coastguard Worker 
4001*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(token, "ssi=", 4) == 0) {
4002*03f9172cSAndroid Build Coastguard Worker 			if (ssi)
4003*03f9172cSAndroid Build Coastguard Worker 				goto fail;
4004*03f9172cSAndroid Build Coastguard Worker 			ssi = wpabuf_parse_bin(token + 4);
4005*03f9172cSAndroid Build Coastguard Worker 			if (!ssi)
4006*03f9172cSAndroid Build Coastguard Worker 				goto fail;
4007*03f9172cSAndroid Build Coastguard Worker 			continue;
4008*03f9172cSAndroid Build Coastguard Worker 		}
4009*03f9172cSAndroid Build Coastguard Worker 
4010*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
4011*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid NAN_TRANSMIT parameter: %s",
4012*03f9172cSAndroid Build Coastguard Worker 			   token);
4013*03f9172cSAndroid Build Coastguard Worker 		goto fail;
4014*03f9172cSAndroid Build Coastguard Worker 	}
4015*03f9172cSAndroid Build Coastguard Worker 
4016*03f9172cSAndroid Build Coastguard Worker 	if (handle <= 0) {
4017*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
4018*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid or missing NAN_TRANSMIT handle");
4019*03f9172cSAndroid Build Coastguard Worker 		goto fail;
4020*03f9172cSAndroid Build Coastguard Worker 	}
4021*03f9172cSAndroid Build Coastguard Worker 
4022*03f9172cSAndroid Build Coastguard Worker 	if (is_zero_ether_addr(peer_addr)) {
4023*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
4024*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid or missing NAN_TRANSMIT address");
4025*03f9172cSAndroid Build Coastguard Worker 		goto fail;
4026*03f9172cSAndroid Build Coastguard Worker 	}
4027*03f9172cSAndroid Build Coastguard Worker 
4028*03f9172cSAndroid Build Coastguard Worker 	ret = hostapd_nan_usd_transmit(hapd, handle, ssi, NULL, peer_addr,
4029*03f9172cSAndroid Build Coastguard Worker 				    req_instance_id);
4030*03f9172cSAndroid Build Coastguard Worker fail:
4031*03f9172cSAndroid Build Coastguard Worker 	wpabuf_free(ssi);
4032*03f9172cSAndroid Build Coastguard Worker 	return ret;
4033*03f9172cSAndroid Build Coastguard Worker }
4034*03f9172cSAndroid Build Coastguard Worker 
4035*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NAN_USD */
4036*03f9172cSAndroid Build Coastguard Worker 
4037*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_receive_process(struct hostapd_data * hapd,char * buf,char * reply,int reply_size,struct sockaddr_storage * from,socklen_t fromlen)4038*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
4039*03f9172cSAndroid Build Coastguard Worker 					      char *buf, char *reply,
4040*03f9172cSAndroid Build Coastguard Worker 					      int reply_size,
4041*03f9172cSAndroid Build Coastguard Worker 					      struct sockaddr_storage *from,
4042*03f9172cSAndroid Build Coastguard Worker 					      socklen_t fromlen)
4043*03f9172cSAndroid Build Coastguard Worker {
4044*03f9172cSAndroid Build Coastguard Worker 	int reply_len, res;
4045*03f9172cSAndroid Build Coastguard Worker 
4046*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(reply, "OK\n", 3);
4047*03f9172cSAndroid Build Coastguard Worker 	reply_len = 3;
4048*03f9172cSAndroid Build Coastguard Worker 
4049*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(buf, "PING") == 0) {
4050*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "PONG\n", 5);
4051*03f9172cSAndroid Build Coastguard Worker 		reply_len = 5;
4052*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
4053*03f9172cSAndroid Build Coastguard Worker 		if (wpa_debug_reopen_file() < 0)
4054*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4055*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "CLOSE_LOG") == 0) {
4056*03f9172cSAndroid Build Coastguard Worker 		wpa_debug_stop_log();
4057*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
4058*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
4059*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "STATUS") == 0) {
4060*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_status(hapd, reply,
4061*03f9172cSAndroid Build Coastguard Worker 						      reply_size);
4062*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
4063*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_drv_status(hapd, reply, reply_size);
4064*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "MIB") == 0) {
4065*03f9172cSAndroid Build Coastguard Worker 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
4066*03f9172cSAndroid Build Coastguard Worker 		if (reply_len >= 0) {
4067*03f9172cSAndroid Build Coastguard Worker 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
4068*03f9172cSAndroid Build Coastguard Worker 					  reply_size - reply_len);
4069*03f9172cSAndroid Build Coastguard Worker 			if (res < 0)
4070*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4071*03f9172cSAndroid Build Coastguard Worker 			else
4072*03f9172cSAndroid Build Coastguard Worker 				reply_len += res;
4073*03f9172cSAndroid Build Coastguard Worker 		}
4074*03f9172cSAndroid Build Coastguard Worker 		if (reply_len >= 0) {
4075*03f9172cSAndroid Build Coastguard Worker 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
4076*03f9172cSAndroid Build Coastguard Worker 						 reply_size - reply_len);
4077*03f9172cSAndroid Build Coastguard Worker 			if (res < 0)
4078*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4079*03f9172cSAndroid Build Coastguard Worker 			else
4080*03f9172cSAndroid Build Coastguard Worker 				reply_len += res;
4081*03f9172cSAndroid Build Coastguard Worker 		}
4082*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_NO_RADIUS
4083*03f9172cSAndroid Build Coastguard Worker 		if (reply_len >= 0) {
4084*03f9172cSAndroid Build Coastguard Worker 			res = radius_client_get_mib(hapd->radius,
4085*03f9172cSAndroid Build Coastguard Worker 						    reply + reply_len,
4086*03f9172cSAndroid Build Coastguard Worker 						    reply_size - reply_len);
4087*03f9172cSAndroid Build Coastguard Worker 			if (res < 0)
4088*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4089*03f9172cSAndroid Build Coastguard Worker 			else
4090*03f9172cSAndroid Build Coastguard Worker 				reply_len += res;
4091*03f9172cSAndroid Build Coastguard Worker 		}
4092*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NO_RADIUS */
4093*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "MIB ", 4) == 0) {
4094*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
4095*03f9172cSAndroid Build Coastguard Worker 						   buf + 4);
4096*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
4097*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
4098*03f9172cSAndroid Build Coastguard Worker 							 reply_size);
4099*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
4100*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
4101*03f9172cSAndroid Build Coastguard Worker 						   reply_size);
4102*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
4103*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
4104*03f9172cSAndroid Build Coastguard Worker 							reply_size);
4105*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "ATTACH") == 0) {
4106*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL))
4107*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4108*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
4109*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen, buf + 7))
4110*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4111*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DETACH") == 0) {
4112*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
4113*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4114*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
4115*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_level(hapd, from, fromlen,
4116*03f9172cSAndroid Build Coastguard Worker 						    buf + 6))
4117*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4118*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
4119*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
4120*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4121*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
4122*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
4123*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4124*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
4125*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
4126*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4127*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TAXONOMY
4128*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) {
4129*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10,
4130*03f9172cSAndroid Build Coastguard Worker 							 reply, reply_size);
4131*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TAXONOMY */
4132*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
4133*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
4134*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4135*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
4136*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_stop_ap(hapd))
4137*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4138*03f9172cSAndroid Build Coastguard Worker #ifdef NEED_AP_MLME
4139*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
4140*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
4141*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4142*03f9172cSAndroid Build Coastguard Worker #endif /* NEED_AP_MLME */
4143*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS
4144*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
4145*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
4146*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4147*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
4148*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_wps_check_pin(
4149*03f9172cSAndroid Build Coastguard Worker 			hapd, buf + 14, reply, reply_size);
4150*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
4151*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_wps_button_pushed(hapd, NULL))
4152*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4153*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
4154*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_wps_cancel(hapd))
4155*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4156*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
4157*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
4158*03f9172cSAndroid Build Coastguard Worker 							  reply, reply_size);
4159*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
4160*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
4161*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4162*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
4163*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
4164*03f9172cSAndroid Build Coastguard Worker 							      reply_size);
4165*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS_NFC
4166*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
4167*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
4168*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4169*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
4170*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
4171*03f9172cSAndroid Build Coastguard Worker 			hapd, buf + 21, reply, reply_size);
4172*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
4173*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_wps_nfc_token(
4174*03f9172cSAndroid Build Coastguard Worker 			hapd, buf + 14, reply, reply_size);
4175*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
4176*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
4177*03f9172cSAndroid Build Coastguard Worker 			hapd, buf + 21, reply, reply_size);
4178*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
4179*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
4180*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4181*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS_NFC */
4182*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS */
4183*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_INTERWORKING
4184*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
4185*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
4186*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4187*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
4188*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
4189*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4190*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_INTERWORKING */
4191*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HS20
4192*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
4193*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
4194*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4195*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
4196*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
4197*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4198*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HS20 */
4199*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WNM_AP
4200*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
4201*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
4202*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4203*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
4204*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
4205*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4206*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
4207*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
4208*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4209*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) {
4210*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
4211*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4212*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WNM_AP */
4213*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
4214*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
4215*03f9172cSAndroid Build Coastguard Worker 							  reply_size);
4216*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
4217*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
4218*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4219*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
4220*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
4221*03f9172cSAndroid Build Coastguard Worker 						   reply_size);
4222*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "ENABLE") == 0) {
4223*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_enable(hapd->iface))
4224*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4225*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) {
4226*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_reload_wpa_psk(hapd))
4227*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4228*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R_AP
4229*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "GET_RXKHS") == 0) {
4230*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_get_rxkhs(hapd, reply,
4231*03f9172cSAndroid Build Coastguard Worker 							 reply_size);
4232*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "RELOAD_RXKHS") == 0) {
4233*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_reload_rxkhs(hapd))
4234*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4235*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R_AP */
4236*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "RELOAD_BSS") == 0) {
4237*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_reload_bss(hapd))
4238*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4239*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "RELOAD_CONFIG") == 0) {
4240*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_reload_config(hapd->iface))
4241*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4242*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "RELOAD") == 0) {
4243*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_reload(hapd->iface))
4244*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4245*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DISABLE") == 0) {
4246*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_disable(hapd->iface))
4247*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4248*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
4249*03f9172cSAndroid Build Coastguard Worker 		if (ieee802_11_set_beacon(hapd))
4250*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4251*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
4252*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
4253*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_radar(hapd, buf + 6))
4254*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4255*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
4256*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
4257*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4258*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "MGMT_TX_STATUS_PROCESS ", 23) == 0) {
4259*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_mgmt_tx_status_process(hapd,
4260*03f9172cSAndroid Build Coastguard Worker 							      buf + 23) < 0)
4261*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4262*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
4263*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0)
4264*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4265*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
4266*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
4267*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4268*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
4269*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_eapol_tx(hapd, buf + 9) < 0)
4270*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4271*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
4272*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
4273*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4274*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
4275*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
4276*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4277*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
4278*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
4279*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4280*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
4281*03f9172cSAndroid Build Coastguard Worker 		if (testing_set_fail_pattern(true, buf + 16) < 0)
4282*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4283*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
4284*03f9172cSAndroid Build Coastguard Worker 		reply_len = testing_get_fail_pattern(true, reply, reply_size);
4285*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
4286*03f9172cSAndroid Build Coastguard Worker 		if (testing_set_fail_pattern(false, buf + 10) < 0)
4287*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4288*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
4289*03f9172cSAndroid Build Coastguard Worker 		reply_len = testing_get_fail_pattern(false, reply, reply_size);
4290*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "RESET_PN ", 9) == 0) {
4291*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_reset_pn(hapd, buf + 9) < 0)
4292*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4293*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "SET_KEY ", 8) == 0) {
4294*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_set_key(hapd, buf + 8) < 0)
4295*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4296*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "RESEND_M1 ", 10) == 0) {
4297*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_resend_m1(hapd, buf + 10) < 0)
4298*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4299*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "RESEND_M3 ", 10) == 0) {
4300*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_resend_m3(hapd, buf + 10) < 0)
4301*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4302*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "RESEND_GROUP_M1 ", 16) == 0) {
4303*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_resend_group_m1(hapd, buf + 16) < 0)
4304*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4305*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REKEY_PTK ", 10) == 0) {
4306*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_rekey_ptk(hapd, buf + 10) < 0)
4307*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4308*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "REKEY_GTK") == 0) {
4309*03f9172cSAndroid Build Coastguard Worker 		if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0)
4310*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4311*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
4312*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
4313*03f9172cSAndroid Build Coastguard Worker 						 reply_size);
4314*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REGISTER_FRAME ", 15) == 0) {
4315*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_register_frame(hapd, buf + 16) < 0)
4316*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4317*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
4318*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
4319*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
4320*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4321*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211AX
4322*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "COLOR_CHANGE ", 13) == 0) {
4323*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_color_change(hapd->iface, buf + 13))
4324*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4325*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211AX */
4326*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NOTIFY_CW_CHANGE ", 17) == 0) {
4327*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_notify_cw_change(hapd, buf + 17))
4328*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4329*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
4330*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
4331*03f9172cSAndroid Build Coastguard Worker 						      reply_size);
4332*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
4333*03f9172cSAndroid Build Coastguard Worker 		ieee802_1x_erp_flush(hapd);
4334*03f9172cSAndroid Build Coastguard Worker #ifdef RADIUS_SERVER
4335*03f9172cSAndroid Build Coastguard Worker 		radius_server_erp_flush(hapd->radius_srv);
4336*03f9172cSAndroid Build Coastguard Worker #endif /* RADIUS_SERVER */
4337*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
4338*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
4339*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4340*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
4341*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
4342*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4343*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
4344*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_log_level(
4345*03f9172cSAndroid Build Coastguard Worker 			hapd, buf + 9, reply, reply_size);
4346*03f9172cSAndroid Build Coastguard Worker #ifdef NEED_AP_MLME
4347*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
4348*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_track_sta_list(
4349*03f9172cSAndroid Build Coastguard Worker 			hapd, reply, reply_size);
4350*03f9172cSAndroid Build Coastguard Worker #endif /* NEED_AP_MLME */
4351*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "PMKSA") == 0) {
4352*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
4353*03f9172cSAndroid Build Coastguard Worker 							  reply_size);
4354*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
4355*03f9172cSAndroid Build Coastguard Worker 		hostapd_ctrl_iface_pmksa_flush(hapd);
4356*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
4357*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_pmksa_add(hapd, buf + 10) < 0)
4358*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4359*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
4360*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
4361*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4362*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "SHOW_NEIGHBOR") == 0) {
4363*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_show_neighbor(hapd, reply,
4364*03f9172cSAndroid Build Coastguard Worker 							     reply_size);
4365*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
4366*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
4367*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4368*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) {
4369*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_req_lci(hapd, buf + 8))
4370*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4371*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
4372*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
4373*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4374*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
4375*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
4376*03f9172cSAndroid Build Coastguard Worker 							  reply, reply_size);
4377*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) {
4378*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_req_link_measurement(
4379*03f9172cSAndroid Build Coastguard Worker 			hapd, buf + 21, reply, reply_size);
4380*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
4381*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
4382*03f9172cSAndroid Build Coastguard Worker 						      reply_size);
4383*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
4384*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply,
4385*03f9172cSAndroid Build Coastguard Worker 						       reply_size);
4386*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
4387*03f9172cSAndroid Build Coastguard Worker 		eloop_terminate();
4388*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
4389*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
4390*03f9172cSAndroid Build Coastguard Worker 			if (hostapd_ctrl_iface_acl_add_mac(
4391*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->accept_mac,
4392*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->num_accept_mac, buf + 19) ||
4393*03f9172cSAndroid Build Coastguard Worker 			    hostapd_set_acl(hapd))
4394*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4395*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
4396*03f9172cSAndroid Build Coastguard Worker 			if (hostapd_ctrl_iface_acl_del_mac(
4397*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->accept_mac,
4398*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->num_accept_mac, buf + 19) ||
4399*03f9172cSAndroid Build Coastguard Worker 			    hostapd_set_acl(hapd) ||
4400*03f9172cSAndroid Build Coastguard Worker 			    hostapd_disassoc_accept_mac(hapd))
4401*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4402*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcmp(buf + 11, "SHOW") == 0) {
4403*03f9172cSAndroid Build Coastguard Worker 			reply_len = hostapd_ctrl_iface_acl_show_mac(
4404*03f9172cSAndroid Build Coastguard Worker 				hapd->conf->accept_mac,
4405*03f9172cSAndroid Build Coastguard Worker 				hapd->conf->num_accept_mac, reply, reply_size);
4406*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcmp(buf + 11, "CLEAR") == 0) {
4407*03f9172cSAndroid Build Coastguard Worker 			hostapd_ctrl_iface_acl_clear_list(
4408*03f9172cSAndroid Build Coastguard Worker 				&hapd->conf->accept_mac,
4409*03f9172cSAndroid Build Coastguard Worker 				&hapd->conf->num_accept_mac);
4410*03f9172cSAndroid Build Coastguard Worker 			if (hostapd_set_acl(hapd) ||
4411*03f9172cSAndroid Build Coastguard Worker 			    hostapd_disassoc_accept_mac(hapd))
4412*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4413*03f9172cSAndroid Build Coastguard Worker 		} else {
4414*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4415*03f9172cSAndroid Build Coastguard Worker 		}
4416*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
4417*03f9172cSAndroid Build Coastguard Worker 		if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
4418*03f9172cSAndroid Build Coastguard Worker 			if (hostapd_ctrl_iface_acl_add_mac(
4419*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->deny_mac,
4420*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->num_deny_mac, buf + 17) ||
4421*03f9172cSAndroid Build Coastguard Worker 			    hostapd_set_acl(hapd) ||
4422*03f9172cSAndroid Build Coastguard Worker 			    hostapd_disassoc_deny_mac(hapd))
4423*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4424*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
4425*03f9172cSAndroid Build Coastguard Worker 			if (hostapd_ctrl_iface_acl_del_mac(
4426*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->deny_mac,
4427*03f9172cSAndroid Build Coastguard Worker 				    &hapd->conf->num_deny_mac, buf + 17) ||
4428*03f9172cSAndroid Build Coastguard Worker 			    hostapd_set_acl(hapd))
4429*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4430*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcmp(buf + 9, "SHOW") == 0) {
4431*03f9172cSAndroid Build Coastguard Worker 			reply_len = hostapd_ctrl_iface_acl_show_mac(
4432*03f9172cSAndroid Build Coastguard Worker 				hapd->conf->deny_mac,
4433*03f9172cSAndroid Build Coastguard Worker 				hapd->conf->num_deny_mac, reply, reply_size);
4434*03f9172cSAndroid Build Coastguard Worker 		} else if (os_strcmp(buf + 9, "CLEAR") == 0) {
4435*03f9172cSAndroid Build Coastguard Worker 			hostapd_ctrl_iface_acl_clear_list(
4436*03f9172cSAndroid Build Coastguard Worker 				&hapd->conf->deny_mac,
4437*03f9172cSAndroid Build Coastguard Worker 				&hapd->conf->num_deny_mac);
4438*03f9172cSAndroid Build Coastguard Worker 			if (hostapd_set_acl(hapd))
4439*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4440*03f9172cSAndroid Build Coastguard Worker 		} else {
4441*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4442*03f9172cSAndroid Build Coastguard Worker 		}
4443*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
4444*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
4445*03f9172cSAndroid Build Coastguard Worker 		res = hostapd_dpp_qr_code(hapd, buf + 12);
4446*03f9172cSAndroid Build Coastguard Worker 		if (res < 0) {
4447*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4448*03f9172cSAndroid Build Coastguard Worker 		} else {
4449*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%d", res);
4450*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4451*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4452*03f9172cSAndroid Build Coastguard Worker 		}
4453*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
4454*03f9172cSAndroid Build Coastguard Worker 		res = hostapd_dpp_nfc_uri(hapd, buf + 12);
4455*03f9172cSAndroid Build Coastguard Worker 		if (res < 0) {
4456*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4457*03f9172cSAndroid Build Coastguard Worker 		} else {
4458*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%d", res);
4459*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4460*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4461*03f9172cSAndroid Build Coastguard Worker 		}
4462*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
4463*03f9172cSAndroid Build Coastguard Worker 		res = hostapd_dpp_nfc_handover_req(hapd, buf + 20);
4464*03f9172cSAndroid Build Coastguard Worker 		if (res < 0) {
4465*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4466*03f9172cSAndroid Build Coastguard Worker 		} else {
4467*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%d", res);
4468*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4469*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4470*03f9172cSAndroid Build Coastguard Worker 		}
4471*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
4472*03f9172cSAndroid Build Coastguard Worker 		res = hostapd_dpp_nfc_handover_sel(hapd, buf + 20);
4473*03f9172cSAndroid Build Coastguard Worker 		if (res < 0) {
4474*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4475*03f9172cSAndroid Build Coastguard Worker 		} else {
4476*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%d", res);
4477*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4478*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4479*03f9172cSAndroid Build Coastguard Worker 		}
4480*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
4481*03f9172cSAndroid Build Coastguard Worker 		res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
4482*03f9172cSAndroid Build Coastguard Worker 		if (res < 0) {
4483*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4484*03f9172cSAndroid Build Coastguard Worker 		} else {
4485*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%d", res);
4486*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4487*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4488*03f9172cSAndroid Build Coastguard Worker 		}
4489*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
4490*03f9172cSAndroid Build Coastguard Worker 		if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp,
4491*03f9172cSAndroid Build Coastguard Worker 					 buf + 21) < 0)
4492*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4493*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
4494*03f9172cSAndroid Build Coastguard Worker 		const char *uri;
4495*03f9172cSAndroid Build Coastguard Worker 
4496*03f9172cSAndroid Build Coastguard Worker 		uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp,
4497*03f9172cSAndroid Build Coastguard Worker 					    atoi(buf + 22));
4498*03f9172cSAndroid Build Coastguard Worker 		if (!uri) {
4499*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4500*03f9172cSAndroid Build Coastguard Worker 		} else {
4501*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%s", uri);
4502*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4503*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4504*03f9172cSAndroid Build Coastguard Worker 		}
4505*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
4506*03f9172cSAndroid Build Coastguard Worker 		reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
4507*03f9172cSAndroid Build Coastguard Worker 					       atoi(buf + 19),
4508*03f9172cSAndroid Build Coastguard Worker 			reply, reply_size);
4509*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
4510*03f9172cSAndroid Build Coastguard Worker 		if (dpp_bootstrap_set(hapd->iface->interfaces->dpp,
4511*03f9172cSAndroid Build Coastguard Worker 				      atoi(buf + 18),
4512*03f9172cSAndroid Build Coastguard Worker 				      os_strchr(buf + 18, ' ')) < 0)
4513*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4514*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
4515*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
4516*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4517*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
4518*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_listen(hapd, buf + 11) < 0)
4519*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4520*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
4521*03f9172cSAndroid Build Coastguard Worker 		hostapd_dpp_stop(hapd);
4522*03f9172cSAndroid Build Coastguard Worker 		hostapd_dpp_listen_stop(hapd);
4523*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
4524*03f9172cSAndroid Build Coastguard Worker 		res = dpp_configurator_add(hapd->iface->interfaces->dpp,
4525*03f9172cSAndroid Build Coastguard Worker 					   buf + 20);
4526*03f9172cSAndroid Build Coastguard Worker 		if (res < 0) {
4527*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4528*03f9172cSAndroid Build Coastguard Worker 		} else {
4529*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%d", res);
4530*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4531*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4532*03f9172cSAndroid Build Coastguard Worker 		}
4533*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) {
4534*03f9172cSAndroid Build Coastguard Worker 		if (dpp_configurator_set(hapd->iface->interfaces->dpp,
4535*03f9172cSAndroid Build Coastguard Worker 					 buf + 20) < 0)
4536*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4537*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
4538*03f9172cSAndroid Build Coastguard Worker 		if (dpp_configurator_remove(hapd->iface->interfaces->dpp,
4539*03f9172cSAndroid Build Coastguard Worker 					    buf + 24) < 0)
4540*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4541*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
4542*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0)
4543*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4544*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
4545*03f9172cSAndroid Build Coastguard Worker 		reply_len = dpp_configurator_get_key_id(
4546*03f9172cSAndroid Build Coastguard Worker 			hapd->iface->interfaces->dpp,
4547*03f9172cSAndroid Build Coastguard Worker 			atoi(buf + 25),
4548*03f9172cSAndroid Build Coastguard Worker 			reply, reply_size);
4549*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
4550*03f9172cSAndroid Build Coastguard Worker 		res = hostapd_dpp_pkex_add(hapd, buf + 12);
4551*03f9172cSAndroid Build Coastguard Worker 		if (res < 0) {
4552*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4553*03f9172cSAndroid Build Coastguard Worker 		} else {
4554*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "%d", res);
4555*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(reply_size, reply_len))
4556*03f9172cSAndroid Build Coastguard Worker 				reply_len = -1;
4557*03f9172cSAndroid Build Coastguard Worker 		}
4558*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
4559*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0)
4560*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4561*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP2
4562*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
4563*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_controller_start(hapd, buf + 20) < 0)
4564*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4565*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
4566*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_controller_start(hapd, NULL) < 0)
4567*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4568*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
4569*03f9172cSAndroid Build Coastguard Worker 		dpp_controller_stop(hapd->iface->interfaces->dpp);
4570*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
4571*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_chirp(hapd, buf + 9) < 0)
4572*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4573*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
4574*03f9172cSAndroid Build Coastguard Worker 		hostapd_dpp_chirp_stop(hapd);
4575*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_RELAY_ADD_CONTROLLER ", 25) == 0) {
4576*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_add_controller(hapd, buf + 25) < 0)
4577*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4578*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_RELAY_REMOVE_CONTROLLER ", 28) == 0) {
4579*03f9172cSAndroid Build Coastguard Worker 		hostapd_dpp_remove_controller(hapd, buf + 28);
4580*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP2 */
4581*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP3
4582*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) {
4583*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_push_button(hapd, NULL) < 0)
4584*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4585*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) {
4586*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_dpp_push_button(hapd, buf + 15) < 0)
4587*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4588*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP3 */
4589*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
4590*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_NAN_USD
4591*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
4592*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_nan_publish(hapd, buf + 12, reply,
4593*03f9172cSAndroid Build Coastguard Worker 						     reply_size);
4594*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
4595*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_nan_cancel_publish(hapd, buf + 19) < 0)
4596*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4597*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
4598*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_nan_update_publish(hapd, buf + 19) < 0)
4599*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4600*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
4601*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_nan_subscribe(hapd, buf + 14, reply,
4602*03f9172cSAndroid Build Coastguard Worker 						       reply_size);
4603*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
4604*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_nan_cancel_subscribe(hapd, buf + 21) < 0)
4605*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4606*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
4607*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_nan_transmit(hapd, buf + 13) < 0)
4608*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4609*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NAN_USD */
4610*03f9172cSAndroid Build Coastguard Worker #ifdef RADIUS_SERVER
4611*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
4612*03f9172cSAndroid Build Coastguard Worker 		if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0)
4613*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4614*03f9172cSAndroid Build Coastguard Worker #endif /* RADIUS_SERVER */
4615*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
4616*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_get_capability(
4617*03f9172cSAndroid Build Coastguard Worker 			hapd, buf + 15, reply, reply_size);
4618*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_PASN
4619*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
4620*03f9172cSAndroid Build Coastguard Worker 		reply_len = ptksa_cache_list(hapd->ptksa, reply, reply_size);
4621*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_PASN */
4622*03f9172cSAndroid Build Coastguard Worker #ifdef ANDROID
4623*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
4624*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_ctrl_iface_driver_cmd(hapd, buf + 7, reply,
4625*03f9172cSAndroid Build Coastguard Worker 							  reply_size);
4626*03f9172cSAndroid Build Coastguard Worker #endif /* ANDROID */
4627*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211BE
4628*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "ENABLE_MLD") == 0) {
4629*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_enable_mld(hapd->iface))
4630*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4631*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DISABLE_MLD") == 0) {
4632*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_disable_mld(hapd->iface))
4633*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4634*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
4635*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "LINK_REMOVE ", 12) == 0) {
4636*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_link_remove(hapd, buf + 12,
4637*03f9172cSAndroid Build Coastguard Worker 						   reply, reply_size))
4638*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4639*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
4640*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211BE */
4641*03f9172cSAndroid Build Coastguard Worker 	} else {
4642*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
4643*03f9172cSAndroid Build Coastguard Worker 		reply_len = 16;
4644*03f9172cSAndroid Build Coastguard Worker 	}
4645*03f9172cSAndroid Build Coastguard Worker 
4646*03f9172cSAndroid Build Coastguard Worker 	if (reply_len < 0) {
4647*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "FAIL\n", 5);
4648*03f9172cSAndroid Build Coastguard Worker 		reply_len = 5;
4649*03f9172cSAndroid Build Coastguard Worker 	}
4650*03f9172cSAndroid Build Coastguard Worker 
4651*03f9172cSAndroid Build Coastguard Worker 	return reply_len;
4652*03f9172cSAndroid Build Coastguard Worker }
4653*03f9172cSAndroid Build Coastguard Worker 
4654*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)4655*03f9172cSAndroid Build Coastguard Worker static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
4656*03f9172cSAndroid Build Coastguard Worker 				       void *sock_ctx)
4657*03f9172cSAndroid Build Coastguard Worker {
4658*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd = eloop_ctx;
4659*03f9172cSAndroid Build Coastguard Worker 	char buf[4096];
4660*03f9172cSAndroid Build Coastguard Worker 	int res;
4661*03f9172cSAndroid Build Coastguard Worker 	struct sockaddr_storage from;
4662*03f9172cSAndroid Build Coastguard Worker 	socklen_t fromlen = sizeof(from);
4663*03f9172cSAndroid Build Coastguard Worker 	char *reply, *pos = buf;
4664*03f9172cSAndroid Build Coastguard Worker 	const int reply_size = 4096;
4665*03f9172cSAndroid Build Coastguard Worker 	int reply_len;
4666*03f9172cSAndroid Build Coastguard Worker 	int level = MSG_DEBUG;
4667*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
4668*03f9172cSAndroid Build Coastguard Worker 	unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
4669*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
4670*03f9172cSAndroid Build Coastguard Worker 
4671*03f9172cSAndroid Build Coastguard Worker 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
4672*03f9172cSAndroid Build Coastguard Worker 		       (struct sockaddr *) &from, &fromlen);
4673*03f9172cSAndroid Build Coastguard Worker 	if (res < 0) {
4674*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
4675*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
4676*03f9172cSAndroid Build Coastguard Worker 		return;
4677*03f9172cSAndroid Build Coastguard Worker 	}
4678*03f9172cSAndroid Build Coastguard Worker 	buf[res] = '\0';
4679*03f9172cSAndroid Build Coastguard Worker 
4680*03f9172cSAndroid Build Coastguard Worker 	reply = os_malloc(reply_size);
4681*03f9172cSAndroid Build Coastguard Worker 	if (reply == NULL) {
4682*03f9172cSAndroid Build Coastguard Worker 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
4683*03f9172cSAndroid Build Coastguard Worker 			   fromlen) < 0) {
4684*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
4685*03f9172cSAndroid Build Coastguard Worker 				   strerror(errno));
4686*03f9172cSAndroid Build Coastguard Worker 		}
4687*03f9172cSAndroid Build Coastguard Worker 		return;
4688*03f9172cSAndroid Build Coastguard Worker 	}
4689*03f9172cSAndroid Build Coastguard Worker 
4690*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
4691*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
4692*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "COOKIE=", 7);
4693*03f9172cSAndroid Build Coastguard Worker 		wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
4694*03f9172cSAndroid Build Coastguard Worker 				 hapd->ctrl_iface_cookie,
4695*03f9172cSAndroid Build Coastguard Worker 				 CTRL_IFACE_COOKIE_LEN);
4696*03f9172cSAndroid Build Coastguard Worker 		reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
4697*03f9172cSAndroid Build Coastguard Worker 		goto done;
4698*03f9172cSAndroid Build Coastguard Worker 	}
4699*03f9172cSAndroid Build Coastguard Worker 
4700*03f9172cSAndroid Build Coastguard Worker 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
4701*03f9172cSAndroid Build Coastguard Worker 	    hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
4702*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
4703*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: No cookie in the request - drop request");
4704*03f9172cSAndroid Build Coastguard Worker 		os_free(reply);
4705*03f9172cSAndroid Build Coastguard Worker 		return;
4706*03f9172cSAndroid Build Coastguard Worker 	}
4707*03f9172cSAndroid Build Coastguard Worker 
4708*03f9172cSAndroid Build Coastguard Worker 	if (os_memcmp(hapd->ctrl_iface_cookie, lcookie,
4709*03f9172cSAndroid Build Coastguard Worker 		      CTRL_IFACE_COOKIE_LEN) != 0) {
4710*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
4711*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid cookie in the request - drop request");
4712*03f9172cSAndroid Build Coastguard Worker 		os_free(reply);
4713*03f9172cSAndroid Build Coastguard Worker 		return;
4714*03f9172cSAndroid Build Coastguard Worker 	}
4715*03f9172cSAndroid Build Coastguard Worker 
4716*03f9172cSAndroid Build Coastguard Worker 	pos = buf + 7 + 2 * CTRL_IFACE_COOKIE_LEN;
4717*03f9172cSAndroid Build Coastguard Worker 	while (*pos == ' ')
4718*03f9172cSAndroid Build Coastguard Worker 		pos++;
4719*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
4720*03f9172cSAndroid Build Coastguard Worker 
4721*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(pos, "PING") == 0)
4722*03f9172cSAndroid Build Coastguard Worker 		level = MSG_EXCESSIVE;
4723*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
4724*03f9172cSAndroid Build Coastguard Worker 
4725*03f9172cSAndroid Build Coastguard Worker 	reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
4726*03f9172cSAndroid Build Coastguard Worker 						       reply, reply_size,
4727*03f9172cSAndroid Build Coastguard Worker 						       &from, fromlen);
4728*03f9172cSAndroid Build Coastguard Worker 
4729*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
4730*03f9172cSAndroid Build Coastguard Worker done:
4731*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
4732*03f9172cSAndroid Build Coastguard Worker 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
4733*03f9172cSAndroid Build Coastguard Worker 		   fromlen) < 0) {
4734*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
4735*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
4736*03f9172cSAndroid Build Coastguard Worker 	}
4737*03f9172cSAndroid Build Coastguard Worker 	os_free(reply);
4738*03f9172cSAndroid Build Coastguard Worker }
4739*03f9172cSAndroid Build Coastguard Worker 
4740*03f9172cSAndroid Build Coastguard Worker 
4741*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211BE
4742*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
4743*03f9172cSAndroid Build Coastguard Worker 
hostapd_mld_ctrl_iface_receive_process(struct hostapd_mld * mld,char * buf,char * reply,size_t reply_size,struct sockaddr_storage * from,socklen_t fromlen)4744*03f9172cSAndroid Build Coastguard Worker static int hostapd_mld_ctrl_iface_receive_process(struct hostapd_mld *mld,
4745*03f9172cSAndroid Build Coastguard Worker 						  char *buf, char *reply,
4746*03f9172cSAndroid Build Coastguard Worker 						  size_t reply_size,
4747*03f9172cSAndroid Build Coastguard Worker 						  struct sockaddr_storage *from,
4748*03f9172cSAndroid Build Coastguard Worker 						  socklen_t fromlen)
4749*03f9172cSAndroid Build Coastguard Worker {
4750*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *link_hapd, *link_itr;
4751*03f9172cSAndroid Build Coastguard Worker 	int reply_len = -1, link_id = -1;
4752*03f9172cSAndroid Build Coastguard Worker 	char *cmd;
4753*03f9172cSAndroid Build Coastguard Worker 	bool found = false;
4754*03f9172cSAndroid Build Coastguard Worker 
4755*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(reply, "OK\n", 3);
4756*03f9172cSAndroid Build Coastguard Worker 	reply_len = 3;
4757*03f9172cSAndroid Build Coastguard Worker 
4758*03f9172cSAndroid Build Coastguard Worker 	cmd = buf;
4759*03f9172cSAndroid Build Coastguard Worker 
4760*03f9172cSAndroid Build Coastguard Worker 	/* Check whether the link ID is provided in the command */
4761*03f9172cSAndroid Build Coastguard Worker 	if (os_strncmp(cmd, "LINKID ", 7) == 0) {
4762*03f9172cSAndroid Build Coastguard Worker 		cmd += 7;
4763*03f9172cSAndroid Build Coastguard Worker 		link_id = atoi(cmd);
4764*03f9172cSAndroid Build Coastguard Worker 		if (link_id < 0 || link_id >= 15) {
4765*03f9172cSAndroid Build Coastguard Worker 			os_memcpy(reply, "INVALID LINK ID\n", 16);
4766*03f9172cSAndroid Build Coastguard Worker 			reply_len = 16;
4767*03f9172cSAndroid Build Coastguard Worker 			goto out;
4768*03f9172cSAndroid Build Coastguard Worker 		}
4769*03f9172cSAndroid Build Coastguard Worker 
4770*03f9172cSAndroid Build Coastguard Worker 		cmd = os_strchr(cmd, ' ');
4771*03f9172cSAndroid Build Coastguard Worker 		if (!cmd)
4772*03f9172cSAndroid Build Coastguard Worker 			goto out;
4773*03f9172cSAndroid Build Coastguard Worker 		cmd++;
4774*03f9172cSAndroid Build Coastguard Worker 	}
4775*03f9172cSAndroid Build Coastguard Worker 	if (link_id >= 0) {
4776*03f9172cSAndroid Build Coastguard Worker 		link_hapd = mld->fbss;
4777*03f9172cSAndroid Build Coastguard Worker 		if (!link_hapd) {
4778*03f9172cSAndroid Build Coastguard Worker 			os_memcpy(reply, "NO LINKS ACTIVE\n", 16);
4779*03f9172cSAndroid Build Coastguard Worker 			reply_len = 16;
4780*03f9172cSAndroid Build Coastguard Worker 			goto out;
4781*03f9172cSAndroid Build Coastguard Worker 		}
4782*03f9172cSAndroid Build Coastguard Worker 
4783*03f9172cSAndroid Build Coastguard Worker 		for_each_mld_link(link_itr, link_hapd) {
4784*03f9172cSAndroid Build Coastguard Worker 			if (link_itr->mld_link_id == link_id) {
4785*03f9172cSAndroid Build Coastguard Worker 				found = true;
4786*03f9172cSAndroid Build Coastguard Worker 				break;
4787*03f9172cSAndroid Build Coastguard Worker 			}
4788*03f9172cSAndroid Build Coastguard Worker 		}
4789*03f9172cSAndroid Build Coastguard Worker 
4790*03f9172cSAndroid Build Coastguard Worker 		if (!found)
4791*03f9172cSAndroid Build Coastguard Worker 			goto out;
4792*03f9172cSAndroid Build Coastguard Worker 
4793*03f9172cSAndroid Build Coastguard Worker 		link_hapd = link_itr;
4794*03f9172cSAndroid Build Coastguard Worker 	} else {
4795*03f9172cSAndroid Build Coastguard Worker 		link_hapd = mld->fbss;
4796*03f9172cSAndroid Build Coastguard Worker 	}
4797*03f9172cSAndroid Build Coastguard Worker 
4798*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(cmd, "PING") == 0) {
4799*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "PONG\n", 5);
4800*03f9172cSAndroid Build Coastguard Worker 		reply_len = 5;
4801*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(cmd, "ATTACH") == 0) {
4802*03f9172cSAndroid Build Coastguard Worker 		if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, NULL))
4803*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4804*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(cmd, "ATTACH ", 7) == 0) {
4805*03f9172cSAndroid Build Coastguard Worker 		if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, cmd + 7))
4806*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4807*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(cmd, "DETACH") == 0) {
4808*03f9172cSAndroid Build Coastguard Worker 		if (ctrl_iface_detach(&mld->ctrl_dst, from, fromlen))
4809*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4810*03f9172cSAndroid Build Coastguard Worker 	} else {
4811*03f9172cSAndroid Build Coastguard Worker 		if (link_id == -1)
4812*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG,
4813*03f9172cSAndroid Build Coastguard Worker 				   "Link ID not provided, using the first link BSS (if available)");
4814*03f9172cSAndroid Build Coastguard Worker 
4815*03f9172cSAndroid Build Coastguard Worker 		if (!link_hapd)
4816*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
4817*03f9172cSAndroid Build Coastguard Worker 		else
4818*03f9172cSAndroid Build Coastguard Worker 			reply_len =
4819*03f9172cSAndroid Build Coastguard Worker 				hostapd_ctrl_iface_receive_process(
4820*03f9172cSAndroid Build Coastguard Worker 					link_hapd, cmd, reply, reply_size,
4821*03f9172cSAndroid Build Coastguard Worker 					from, fromlen);
4822*03f9172cSAndroid Build Coastguard Worker 	}
4823*03f9172cSAndroid Build Coastguard Worker 
4824*03f9172cSAndroid Build Coastguard Worker out:
4825*03f9172cSAndroid Build Coastguard Worker 	if (reply_len < 0) {
4826*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "FAIL\n", 5);
4827*03f9172cSAndroid Build Coastguard Worker 		reply_len = 5;
4828*03f9172cSAndroid Build Coastguard Worker 	}
4829*03f9172cSAndroid Build Coastguard Worker 
4830*03f9172cSAndroid Build Coastguard Worker 	return reply_len;
4831*03f9172cSAndroid Build Coastguard Worker }
4832*03f9172cSAndroid Build Coastguard Worker 
4833*03f9172cSAndroid Build Coastguard Worker 
hostapd_mld_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)4834*03f9172cSAndroid Build Coastguard Worker static void hostapd_mld_ctrl_iface_receive(int sock, void *eloop_ctx,
4835*03f9172cSAndroid Build Coastguard Worker 					   void *sock_ctx)
4836*03f9172cSAndroid Build Coastguard Worker {
4837*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_mld *mld = eloop_ctx;
4838*03f9172cSAndroid Build Coastguard Worker 	char buf[4096];
4839*03f9172cSAndroid Build Coastguard Worker 	int res;
4840*03f9172cSAndroid Build Coastguard Worker 	struct sockaddr_storage from;
4841*03f9172cSAndroid Build Coastguard Worker 	socklen_t fromlen = sizeof(from);
4842*03f9172cSAndroid Build Coastguard Worker 	char *reply, *pos = buf;
4843*03f9172cSAndroid Build Coastguard Worker 	const size_t reply_size = 4096;
4844*03f9172cSAndroid Build Coastguard Worker 	int reply_len;
4845*03f9172cSAndroid Build Coastguard Worker 	int level = MSG_DEBUG;
4846*03f9172cSAndroid Build Coastguard Worker 
4847*03f9172cSAndroid Build Coastguard Worker 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
4848*03f9172cSAndroid Build Coastguard Worker 		       (struct sockaddr *) &from, &fromlen);
4849*03f9172cSAndroid Build Coastguard Worker 	if (res < 0) {
4850*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "recvfrom(mld ctrl_iface): %s",
4851*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
4852*03f9172cSAndroid Build Coastguard Worker 		return;
4853*03f9172cSAndroid Build Coastguard Worker 	}
4854*03f9172cSAndroid Build Coastguard Worker 	buf[res] = '\0';
4855*03f9172cSAndroid Build Coastguard Worker 
4856*03f9172cSAndroid Build Coastguard Worker 	reply = os_malloc(reply_size);
4857*03f9172cSAndroid Build Coastguard Worker 	if (!reply) {
4858*03f9172cSAndroid Build Coastguard Worker 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
4859*03f9172cSAndroid Build Coastguard Worker 			   fromlen) < 0) {
4860*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
4861*03f9172cSAndroid Build Coastguard Worker 				   strerror(errno));
4862*03f9172cSAndroid Build Coastguard Worker 		}
4863*03f9172cSAndroid Build Coastguard Worker 		return;
4864*03f9172cSAndroid Build Coastguard Worker 	}
4865*03f9172cSAndroid Build Coastguard Worker 
4866*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(pos, "PING") == 0)
4867*03f9172cSAndroid Build Coastguard Worker 		level = MSG_EXCESSIVE;
4868*03f9172cSAndroid Build Coastguard Worker 
4869*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump_ascii(level, "RX MLD ctrl_iface", pos, res);
4870*03f9172cSAndroid Build Coastguard Worker 
4871*03f9172cSAndroid Build Coastguard Worker 	reply_len = hostapd_mld_ctrl_iface_receive_process(mld, pos,
4872*03f9172cSAndroid Build Coastguard Worker 							   reply, reply_size,
4873*03f9172cSAndroid Build Coastguard Worker 							   &from, fromlen);
4874*03f9172cSAndroid Build Coastguard Worker 
4875*03f9172cSAndroid Build Coastguard Worker 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
4876*03f9172cSAndroid Build Coastguard Worker 		   fromlen) < 0) {
4877*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
4878*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
4879*03f9172cSAndroid Build Coastguard Worker 	}
4880*03f9172cSAndroid Build Coastguard Worker 	os_free(reply);
4881*03f9172cSAndroid Build Coastguard Worker }
4882*03f9172cSAndroid Build Coastguard Worker 
4883*03f9172cSAndroid Build Coastguard Worker 
hostapd_mld_ctrl_iface_path(struct hostapd_mld * mld)4884*03f9172cSAndroid Build Coastguard Worker static char * hostapd_mld_ctrl_iface_path(struct hostapd_mld *mld)
4885*03f9172cSAndroid Build Coastguard Worker {
4886*03f9172cSAndroid Build Coastguard Worker 	size_t len;
4887*03f9172cSAndroid Build Coastguard Worker 	char *buf;
4888*03f9172cSAndroid Build Coastguard Worker 	int ret;
4889*03f9172cSAndroid Build Coastguard Worker 
4890*03f9172cSAndroid Build Coastguard Worker 	if (!mld->ctrl_interface)
4891*03f9172cSAndroid Build Coastguard Worker 		return NULL;
4892*03f9172cSAndroid Build Coastguard Worker 
4893*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(mld->ctrl_interface) + os_strlen(mld->name) + 2;
4894*03f9172cSAndroid Build Coastguard Worker 
4895*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
4896*03f9172cSAndroid Build Coastguard Worker 	if (!buf)
4897*03f9172cSAndroid Build Coastguard Worker 		return NULL;
4898*03f9172cSAndroid Build Coastguard Worker 
4899*03f9172cSAndroid Build Coastguard Worker 	ret = os_snprintf(buf, len, "%s/%s", mld->ctrl_interface, mld->name);
4900*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(len, ret)) {
4901*03f9172cSAndroid Build Coastguard Worker 		os_free(buf);
4902*03f9172cSAndroid Build Coastguard Worker 		return NULL;
4903*03f9172cSAndroid Build Coastguard Worker 	}
4904*03f9172cSAndroid Build Coastguard Worker 
4905*03f9172cSAndroid Build Coastguard Worker 	return buf;
4906*03f9172cSAndroid Build Coastguard Worker }
4907*03f9172cSAndroid Build Coastguard Worker 
4908*03f9172cSAndroid Build Coastguard Worker #endif /* !CONFIG_CTRL_IFACE_UDP */
4909*03f9172cSAndroid Build Coastguard Worker 
4910*03f9172cSAndroid Build Coastguard Worker 
hostapd_mld_ctrl_iface_init(struct hostapd_mld * mld)4911*03f9172cSAndroid Build Coastguard Worker int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld)
4912*03f9172cSAndroid Build Coastguard Worker {
4913*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
4914*03f9172cSAndroid Build Coastguard Worker 	struct sockaddr_un addr;
4915*03f9172cSAndroid Build Coastguard Worker 	int s = -1;
4916*03f9172cSAndroid Build Coastguard Worker 	char *fname = NULL;
4917*03f9172cSAndroid Build Coastguard Worker 
4918*03f9172cSAndroid Build Coastguard Worker 	if (!mld)
4919*03f9172cSAndroid Build Coastguard Worker 		return -1;
4920*03f9172cSAndroid Build Coastguard Worker 
4921*03f9172cSAndroid Build Coastguard Worker 	if (mld->ctrl_sock > -1) {
4922*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "MLD %s ctrl_iface already exists!",
4923*03f9172cSAndroid Build Coastguard Worker 			   mld->name);
4924*03f9172cSAndroid Build Coastguard Worker 		return 0;
4925*03f9172cSAndroid Build Coastguard Worker 	}
4926*03f9172cSAndroid Build Coastguard Worker 
4927*03f9172cSAndroid Build Coastguard Worker 	dl_list_init(&mld->ctrl_dst);
4928*03f9172cSAndroid Build Coastguard Worker 
4929*03f9172cSAndroid Build Coastguard Worker 	if (!mld->ctrl_interface)
4930*03f9172cSAndroid Build Coastguard Worker 		return 0;
4931*03f9172cSAndroid Build Coastguard Worker 
4932*03f9172cSAndroid Build Coastguard Worker 	if (mkdir(mld->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
4933*03f9172cSAndroid Build Coastguard Worker 		if (errno == EEXIST) {
4934*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG,
4935*03f9172cSAndroid Build Coastguard Worker 				   "Using existing control interface directory.");
4936*03f9172cSAndroid Build Coastguard Worker 		} else {
4937*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
4938*03f9172cSAndroid Build Coastguard Worker 				   strerror(errno));
4939*03f9172cSAndroid Build Coastguard Worker 			goto fail;
4940*03f9172cSAndroid Build Coastguard Worker 		}
4941*03f9172cSAndroid Build Coastguard Worker 	}
4942*03f9172cSAndroid Build Coastguard Worker 
4943*03f9172cSAndroid Build Coastguard Worker 	if (os_strlen(mld->ctrl_interface) + 1 + os_strlen(mld->name) >=
4944*03f9172cSAndroid Build Coastguard Worker 	    sizeof(addr.sun_path))
4945*03f9172cSAndroid Build Coastguard Worker 		goto fail;
4946*03f9172cSAndroid Build Coastguard Worker 
4947*03f9172cSAndroid Build Coastguard Worker 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
4948*03f9172cSAndroid Build Coastguard Worker 	if (s < 0) {
4949*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
4950*03f9172cSAndroid Build Coastguard Worker 		goto fail;
4951*03f9172cSAndroid Build Coastguard Worker 	}
4952*03f9172cSAndroid Build Coastguard Worker 
4953*03f9172cSAndroid Build Coastguard Worker 	os_memset(&addr, 0, sizeof(addr));
4954*03f9172cSAndroid Build Coastguard Worker #ifdef __FreeBSD__
4955*03f9172cSAndroid Build Coastguard Worker 	addr.sun_len = sizeof(addr);
4956*03f9172cSAndroid Build Coastguard Worker #endif /* __FreeBSD__ */
4957*03f9172cSAndroid Build Coastguard Worker 	addr.sun_family = AF_UNIX;
4958*03f9172cSAndroid Build Coastguard Worker 
4959*03f9172cSAndroid Build Coastguard Worker 	fname = hostapd_mld_ctrl_iface_path(mld);
4960*03f9172cSAndroid Build Coastguard Worker 	if (!fname)
4961*03f9172cSAndroid Build Coastguard Worker 		goto fail;
4962*03f9172cSAndroid Build Coastguard Worker 
4963*03f9172cSAndroid Build Coastguard Worker 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
4964*03f9172cSAndroid Build Coastguard Worker 
4965*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "Setting up MLD %s ctrl_iface", mld->name);
4966*03f9172cSAndroid Build Coastguard Worker 
4967*03f9172cSAndroid Build Coastguard Worker 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
4968*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
4969*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
4970*03f9172cSAndroid Build Coastguard Worker 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
4971*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not allow connections - assuming it was left over from forced program termination");
4972*03f9172cSAndroid Build Coastguard Worker 			if (unlink(fname) < 0) {
4973*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
4974*03f9172cSAndroid Build Coastguard Worker 					   "Could not unlink existing ctrl_iface socket '%s': %s",
4975*03f9172cSAndroid Build Coastguard Worker 					   fname, strerror(errno));
4976*03f9172cSAndroid Build Coastguard Worker 				goto fail;
4977*03f9172cSAndroid Build Coastguard Worker 			}
4978*03f9172cSAndroid Build Coastguard Worker 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
4979*03f9172cSAndroid Build Coastguard Worker 			    0) {
4980*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
4981*03f9172cSAndroid Build Coastguard Worker 					   "hostapd-ctrl-iface: bind(PF_UNIX): %s",
4982*03f9172cSAndroid Build Coastguard Worker 					   strerror(errno));
4983*03f9172cSAndroid Build Coastguard Worker 				goto fail;
4984*03f9172cSAndroid Build Coastguard Worker 			}
4985*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG,
4986*03f9172cSAndroid Build Coastguard Worker 				   "Successfully replaced leftover ctrl_iface socket '%s'",
4987*03f9172cSAndroid Build Coastguard Worker 				   fname);
4988*03f9172cSAndroid Build Coastguard Worker 		} else {
4989*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO,
4990*03f9172cSAndroid Build Coastguard Worker 				   "ctrl_iface exists and seems to be in use - cannot override it");
4991*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO,
4992*03f9172cSAndroid Build Coastguard Worker 				   "Delete '%s' manually if it is not used anymore", fname);
4993*03f9172cSAndroid Build Coastguard Worker 			os_free(fname);
4994*03f9172cSAndroid Build Coastguard Worker 			fname = NULL;
4995*03f9172cSAndroid Build Coastguard Worker 			goto fail;
4996*03f9172cSAndroid Build Coastguard Worker 		}
4997*03f9172cSAndroid Build Coastguard Worker 	}
4998*03f9172cSAndroid Build Coastguard Worker 
4999*03f9172cSAndroid Build Coastguard Worker 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
5000*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
5001*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5002*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5003*03f9172cSAndroid Build Coastguard Worker 	}
5004*03f9172cSAndroid Build Coastguard Worker 	os_free(fname);
5005*03f9172cSAndroid Build Coastguard Worker 
5006*03f9172cSAndroid Build Coastguard Worker 	mld->ctrl_sock = s;
5007*03f9172cSAndroid Build Coastguard Worker 
5008*03f9172cSAndroid Build Coastguard Worker 	if (eloop_register_read_sock(s, hostapd_mld_ctrl_iface_receive, mld,
5009*03f9172cSAndroid Build Coastguard Worker 				     NULL) < 0)
5010*03f9172cSAndroid Build Coastguard Worker 		return -1;
5011*03f9172cSAndroid Build Coastguard Worker 
5012*03f9172cSAndroid Build Coastguard Worker 	return 0;
5013*03f9172cSAndroid Build Coastguard Worker 
5014*03f9172cSAndroid Build Coastguard Worker fail:
5015*03f9172cSAndroid Build Coastguard Worker 	if (s >= 0)
5016*03f9172cSAndroid Build Coastguard Worker 		close(s);
5017*03f9172cSAndroid Build Coastguard Worker 	if (fname) {
5018*03f9172cSAndroid Build Coastguard Worker 		unlink(fname);
5019*03f9172cSAndroid Build Coastguard Worker 		os_free(fname);
5020*03f9172cSAndroid Build Coastguard Worker 	}
5021*03f9172cSAndroid Build Coastguard Worker 	return -1;
5022*03f9172cSAndroid Build Coastguard Worker #endif /* !CONFIG_CTRL_IFACE_UDP */
5023*03f9172cSAndroid Build Coastguard Worker 	return 0;
5024*03f9172cSAndroid Build Coastguard Worker }
5025*03f9172cSAndroid Build Coastguard Worker 
5026*03f9172cSAndroid Build Coastguard Worker 
hostapd_mld_ctrl_iface_deinit(struct hostapd_mld * mld)5027*03f9172cSAndroid Build Coastguard Worker void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld)
5028*03f9172cSAndroid Build Coastguard Worker {
5029*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
5030*03f9172cSAndroid Build Coastguard Worker 	struct wpa_ctrl_dst *dst, *prev;
5031*03f9172cSAndroid Build Coastguard Worker 
5032*03f9172cSAndroid Build Coastguard Worker 	if (mld->ctrl_sock > -1) {
5033*03f9172cSAndroid Build Coastguard Worker 		char *fname;
5034*03f9172cSAndroid Build Coastguard Worker 
5035*03f9172cSAndroid Build Coastguard Worker 		eloop_unregister_read_sock(mld->ctrl_sock);
5036*03f9172cSAndroid Build Coastguard Worker 		close(mld->ctrl_sock);
5037*03f9172cSAndroid Build Coastguard Worker 		mld->ctrl_sock = -1;
5038*03f9172cSAndroid Build Coastguard Worker 
5039*03f9172cSAndroid Build Coastguard Worker 		fname = hostapd_mld_ctrl_iface_path(mld);
5040*03f9172cSAndroid Build Coastguard Worker 		if (fname) {
5041*03f9172cSAndroid Build Coastguard Worker 			unlink(fname);
5042*03f9172cSAndroid Build Coastguard Worker 			os_free(fname);
5043*03f9172cSAndroid Build Coastguard Worker 		}
5044*03f9172cSAndroid Build Coastguard Worker 
5045*03f9172cSAndroid Build Coastguard Worker 		if (mld->ctrl_interface &&
5046*03f9172cSAndroid Build Coastguard Worker 		    rmdir(mld->ctrl_interface) < 0) {
5047*03f9172cSAndroid Build Coastguard Worker 			if (errno == ENOTEMPTY) {
5048*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_DEBUG,
5049*03f9172cSAndroid Build Coastguard Worker 					   "MLD control interface directory not empty - leaving it behind");
5050*03f9172cSAndroid Build Coastguard Worker 			} else {
5051*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
5052*03f9172cSAndroid Build Coastguard Worker 					   "rmdir[ctrl_interface=%s]: %s",
5053*03f9172cSAndroid Build Coastguard Worker 					   mld->ctrl_interface,
5054*03f9172cSAndroid Build Coastguard Worker 					   strerror(errno));
5055*03f9172cSAndroid Build Coastguard Worker 			}
5056*03f9172cSAndroid Build Coastguard Worker 		}
5057*03f9172cSAndroid Build Coastguard Worker 	}
5058*03f9172cSAndroid Build Coastguard Worker 
5059*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_safe(dst, prev, &mld->ctrl_dst, struct wpa_ctrl_dst,
5060*03f9172cSAndroid Build Coastguard Worker 			      list)
5061*03f9172cSAndroid Build Coastguard Worker 		os_free(dst);
5062*03f9172cSAndroid Build Coastguard Worker #endif /* !CONFIG_CTRL_IFACE_UDP */
5063*03f9172cSAndroid Build Coastguard Worker 
5064*03f9172cSAndroid Build Coastguard Worker 	os_free(mld->ctrl_interface);
5065*03f9172cSAndroid Build Coastguard Worker }
5066*03f9172cSAndroid Build Coastguard Worker 
5067*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211BE */
5068*03f9172cSAndroid Build Coastguard Worker 
5069*03f9172cSAndroid Build Coastguard Worker 
5070*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
hostapd_ctrl_iface_path(struct hostapd_data * hapd)5071*03f9172cSAndroid Build Coastguard Worker static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
5072*03f9172cSAndroid Build Coastguard Worker {
5073*03f9172cSAndroid Build Coastguard Worker 	char *buf;
5074*03f9172cSAndroid Build Coastguard Worker 	size_t len;
5075*03f9172cSAndroid Build Coastguard Worker 	const char *ctrl_sock_iface;
5076*03f9172cSAndroid Build Coastguard Worker 
5077*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211BE
5078*03f9172cSAndroid Build Coastguard Worker 	ctrl_sock_iface = hapd->ctrl_sock_iface;
5079*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_IEEE80211BE */
5080*03f9172cSAndroid Build Coastguard Worker 	ctrl_sock_iface = hapd->conf->iface;
5081*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211BE */
5082*03f9172cSAndroid Build Coastguard Worker 
5083*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->ctrl_interface == NULL)
5084*03f9172cSAndroid Build Coastguard Worker 		return NULL;
5085*03f9172cSAndroid Build Coastguard Worker 
5086*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(hapd->conf->ctrl_interface) +
5087*03f9172cSAndroid Build Coastguard Worker 		os_strlen(ctrl_sock_iface) + 2;
5088*03f9172cSAndroid Build Coastguard Worker 
5089*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
5090*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
5091*03f9172cSAndroid Build Coastguard Worker 		return NULL;
5092*03f9172cSAndroid Build Coastguard Worker 
5093*03f9172cSAndroid Build Coastguard Worker 	os_snprintf(buf, len, "%s/%s",
5094*03f9172cSAndroid Build Coastguard Worker 		    hapd->conf->ctrl_interface, ctrl_sock_iface);
5095*03f9172cSAndroid Build Coastguard Worker 	buf[len - 1] = '\0';
5096*03f9172cSAndroid Build Coastguard Worker 	return buf;
5097*03f9172cSAndroid Build Coastguard Worker }
5098*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
5099*03f9172cSAndroid Build Coastguard Worker 
5100*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_msg_cb(void * ctx,int level,enum wpa_msg_type type,const char * txt,size_t len)5101*03f9172cSAndroid Build Coastguard Worker static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
5102*03f9172cSAndroid Build Coastguard Worker 				      enum wpa_msg_type type,
5103*03f9172cSAndroid Build Coastguard Worker 				      const char *txt, size_t len)
5104*03f9172cSAndroid Build Coastguard Worker {
5105*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd = ctx;
5106*03f9172cSAndroid Build Coastguard Worker 	if (hapd == NULL)
5107*03f9172cSAndroid Build Coastguard Worker 		return;
5108*03f9172cSAndroid Build Coastguard Worker 	hostapd_ctrl_iface_send(hapd, level, type, txt, len);
5109*03f9172cSAndroid Build Coastguard Worker }
5110*03f9172cSAndroid Build Coastguard Worker 
5111*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_init(struct hostapd_data * hapd)5112*03f9172cSAndroid Build Coastguard Worker int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
5113*03f9172cSAndroid Build Coastguard Worker {
5114*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
5115*03f9172cSAndroid Build Coastguard Worker 	int port = HOSTAPD_CTRL_IFACE_PORT;
5116*03f9172cSAndroid Build Coastguard Worker 	char p[32] = { 0 };
5117*03f9172cSAndroid Build Coastguard Worker 	char port_str[40], *tmp;
5118*03f9172cSAndroid Build Coastguard Worker 	char *pos;
5119*03f9172cSAndroid Build Coastguard Worker 	struct addrinfo hints = { 0 }, *res, *saveres;
5120*03f9172cSAndroid Build Coastguard Worker 	int n;
5121*03f9172cSAndroid Build Coastguard Worker 
5122*03f9172cSAndroid Build Coastguard Worker 	if (hapd->ctrl_sock > -1) {
5123*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
5124*03f9172cSAndroid Build Coastguard Worker 		return 0;
5125*03f9172cSAndroid Build Coastguard Worker 	}
5126*03f9172cSAndroid Build Coastguard Worker 
5127*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->ctrl_interface == NULL)
5128*03f9172cSAndroid Build Coastguard Worker 		return 0;
5129*03f9172cSAndroid Build Coastguard Worker 
5130*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
5131*03f9172cSAndroid Build Coastguard Worker 	if (pos) {
5132*03f9172cSAndroid Build Coastguard Worker 		pos += 4;
5133*03f9172cSAndroid Build Coastguard Worker 		port = atoi(pos);
5134*03f9172cSAndroid Build Coastguard Worker 		if (port <= 0) {
5135*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
5136*03f9172cSAndroid Build Coastguard Worker 			goto fail;
5137*03f9172cSAndroid Build Coastguard Worker 		}
5138*03f9172cSAndroid Build Coastguard Worker 	}
5139*03f9172cSAndroid Build Coastguard Worker 
5140*03f9172cSAndroid Build Coastguard Worker 	dl_list_init(&hapd->ctrl_dst);
5141*03f9172cSAndroid Build Coastguard Worker 	hapd->ctrl_sock = -1;
5142*03f9172cSAndroid Build Coastguard Worker 	os_get_random(hapd->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
5143*03f9172cSAndroid Build Coastguard Worker 
5144*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
5145*03f9172cSAndroid Build Coastguard Worker 	hints.ai_flags = AI_PASSIVE;
5146*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
5147*03f9172cSAndroid Build Coastguard Worker 
5148*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
5149*03f9172cSAndroid Build Coastguard Worker 	hints.ai_family = AF_INET6;
5150*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
5151*03f9172cSAndroid Build Coastguard Worker 	hints.ai_family = AF_INET;
5152*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
5153*03f9172cSAndroid Build Coastguard Worker 	hints.ai_socktype = SOCK_DGRAM;
5154*03f9172cSAndroid Build Coastguard Worker 
5155*03f9172cSAndroid Build Coastguard Worker try_again:
5156*03f9172cSAndroid Build Coastguard Worker 	os_snprintf(p, sizeof(p), "%d", port);
5157*03f9172cSAndroid Build Coastguard Worker 	n = getaddrinfo(NULL, p, &hints, &res);
5158*03f9172cSAndroid Build Coastguard Worker 	if (n) {
5159*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
5160*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5161*03f9172cSAndroid Build Coastguard Worker 	}
5162*03f9172cSAndroid Build Coastguard Worker 
5163*03f9172cSAndroid Build Coastguard Worker 	saveres = res;
5164*03f9172cSAndroid Build Coastguard Worker 	hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
5165*03f9172cSAndroid Build Coastguard Worker 				 res->ai_protocol);
5166*03f9172cSAndroid Build Coastguard Worker 	if (hapd->ctrl_sock < 0) {
5167*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
5168*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5169*03f9172cSAndroid Build Coastguard Worker 	}
5170*03f9172cSAndroid Build Coastguard Worker 
5171*03f9172cSAndroid Build Coastguard Worker 	if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
5172*03f9172cSAndroid Build Coastguard Worker 		port--;
5173*03f9172cSAndroid Build Coastguard Worker 		if ((HOSTAPD_CTRL_IFACE_PORT - port) <
5174*03f9172cSAndroid Build Coastguard Worker 		    HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
5175*03f9172cSAndroid Build Coastguard Worker 			goto try_again;
5176*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
5177*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5178*03f9172cSAndroid Build Coastguard Worker 	}
5179*03f9172cSAndroid Build Coastguard Worker 
5180*03f9172cSAndroid Build Coastguard Worker 	freeaddrinfo(saveres);
5181*03f9172cSAndroid Build Coastguard Worker 
5182*03f9172cSAndroid Build Coastguard Worker 	os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
5183*03f9172cSAndroid Build Coastguard Worker 	tmp = os_strdup(port_str);
5184*03f9172cSAndroid Build Coastguard Worker 	if (tmp) {
5185*03f9172cSAndroid Build Coastguard Worker 		os_free(hapd->conf->ctrl_interface);
5186*03f9172cSAndroid Build Coastguard Worker 		hapd->conf->ctrl_interface = tmp;
5187*03f9172cSAndroid Build Coastguard Worker 	}
5188*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
5189*03f9172cSAndroid Build Coastguard Worker 
5190*03f9172cSAndroid Build Coastguard Worker 	if (eloop_register_read_sock(hapd->ctrl_sock,
5191*03f9172cSAndroid Build Coastguard Worker 				     hostapd_ctrl_iface_receive, hapd, NULL) <
5192*03f9172cSAndroid Build Coastguard Worker 	    0) {
5193*03f9172cSAndroid Build Coastguard Worker 		hostapd_ctrl_iface_deinit(hapd);
5194*03f9172cSAndroid Build Coastguard Worker 		return -1;
5195*03f9172cSAndroid Build Coastguard Worker 	}
5196*03f9172cSAndroid Build Coastguard Worker 
5197*03f9172cSAndroid Build Coastguard Worker 	hapd->msg_ctx = hapd;
5198*03f9172cSAndroid Build Coastguard Worker 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
5199*03f9172cSAndroid Build Coastguard Worker 
5200*03f9172cSAndroid Build Coastguard Worker 	return 0;
5201*03f9172cSAndroid Build Coastguard Worker 
5202*03f9172cSAndroid Build Coastguard Worker fail:
5203*03f9172cSAndroid Build Coastguard Worker 	if (hapd->ctrl_sock >= 0)
5204*03f9172cSAndroid Build Coastguard Worker 		close(hapd->ctrl_sock);
5205*03f9172cSAndroid Build Coastguard Worker 	return -1;
5206*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_CTRL_IFACE_UDP */
5207*03f9172cSAndroid Build Coastguard Worker 	struct sockaddr_un addr;
5208*03f9172cSAndroid Build Coastguard Worker 	int s = -1;
5209*03f9172cSAndroid Build Coastguard Worker 	char *fname = NULL;
5210*03f9172cSAndroid Build Coastguard Worker 	size_t iflen;
5211*03f9172cSAndroid Build Coastguard Worker 
5212*03f9172cSAndroid Build Coastguard Worker 	if (hapd->ctrl_sock > -1) {
5213*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
5214*03f9172cSAndroid Build Coastguard Worker 		return 0;
5215*03f9172cSAndroid Build Coastguard Worker 	}
5216*03f9172cSAndroid Build Coastguard Worker 
5217*03f9172cSAndroid Build Coastguard Worker 	dl_list_init(&hapd->ctrl_dst);
5218*03f9172cSAndroid Build Coastguard Worker 
5219*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->ctrl_interface == NULL)
5220*03f9172cSAndroid Build Coastguard Worker 		return 0;
5221*03f9172cSAndroid Build Coastguard Worker 
5222*03f9172cSAndroid Build Coastguard Worker 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
5223*03f9172cSAndroid Build Coastguard Worker 		if (errno == EEXIST) {
5224*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "Using existing control "
5225*03f9172cSAndroid Build Coastguard Worker 				   "interface directory.");
5226*03f9172cSAndroid Build Coastguard Worker 		} else {
5227*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
5228*03f9172cSAndroid Build Coastguard Worker 				   strerror(errno));
5229*03f9172cSAndroid Build Coastguard Worker 			goto fail;
5230*03f9172cSAndroid Build Coastguard Worker 		}
5231*03f9172cSAndroid Build Coastguard Worker 	}
5232*03f9172cSAndroid Build Coastguard Worker 
5233*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->ctrl_interface_gid_set &&
5234*03f9172cSAndroid Build Coastguard Worker 	    lchown(hapd->conf->ctrl_interface, -1,
5235*03f9172cSAndroid Build Coastguard Worker 		   hapd->conf->ctrl_interface_gid) < 0) {
5236*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
5237*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5238*03f9172cSAndroid Build Coastguard Worker 		return -1;
5239*03f9172cSAndroid Build Coastguard Worker 	}
5240*03f9172cSAndroid Build Coastguard Worker 
5241*03f9172cSAndroid Build Coastguard Worker 	if (!hapd->conf->ctrl_interface_gid_set &&
5242*03f9172cSAndroid Build Coastguard Worker 	    hapd->iface->interfaces->ctrl_iface_group &&
5243*03f9172cSAndroid Build Coastguard Worker 	    lchown(hapd->conf->ctrl_interface, -1,
5244*03f9172cSAndroid Build Coastguard Worker 		   hapd->iface->interfaces->ctrl_iface_group) < 0) {
5245*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
5246*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5247*03f9172cSAndroid Build Coastguard Worker 		return -1;
5248*03f9172cSAndroid Build Coastguard Worker 	}
5249*03f9172cSAndroid Build Coastguard Worker 
5250*03f9172cSAndroid Build Coastguard Worker #ifdef ANDROID
5251*03f9172cSAndroid Build Coastguard Worker 	/*
5252*03f9172cSAndroid Build Coastguard Worker 	 * Android is using umask 0077 which would leave the control interface
5253*03f9172cSAndroid Build Coastguard Worker 	 * directory without group access. This breaks things since Wi-Fi
5254*03f9172cSAndroid Build Coastguard Worker 	 * framework assumes that this directory can be accessed by other
5255*03f9172cSAndroid Build Coastguard Worker 	 * applications in the wifi group. Fix this by adding group access even
5256*03f9172cSAndroid Build Coastguard Worker 	 * if umask value would prevent this.
5257*03f9172cSAndroid Build Coastguard Worker 	 */
5258*03f9172cSAndroid Build Coastguard Worker 	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
5259*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
5260*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5261*03f9172cSAndroid Build Coastguard Worker 		/* Try to continue anyway */
5262*03f9172cSAndroid Build Coastguard Worker 	}
5263*03f9172cSAndroid Build Coastguard Worker #endif /* ANDROID */
5264*03f9172cSAndroid Build Coastguard Worker 
5265*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211BE
5266*03f9172cSAndroid Build Coastguard Worker 	iflen = os_strlen(hapd->ctrl_sock_iface);
5267*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_IEEE80211BE */
5268*03f9172cSAndroid Build Coastguard Worker 	iflen = os_strlen(hapd->conf->iface);
5269*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211BE */
5270*03f9172cSAndroid Build Coastguard Worker 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
5271*03f9172cSAndroid Build Coastguard Worker 	    iflen >= sizeof(addr.sun_path))
5272*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5273*03f9172cSAndroid Build Coastguard Worker 
5274*03f9172cSAndroid Build Coastguard Worker 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
5275*03f9172cSAndroid Build Coastguard Worker 	if (s < 0) {
5276*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
5277*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5278*03f9172cSAndroid Build Coastguard Worker 	}
5279*03f9172cSAndroid Build Coastguard Worker 
5280*03f9172cSAndroid Build Coastguard Worker 	os_memset(&addr, 0, sizeof(addr));
5281*03f9172cSAndroid Build Coastguard Worker #ifdef __FreeBSD__
5282*03f9172cSAndroid Build Coastguard Worker 	addr.sun_len = sizeof(addr);
5283*03f9172cSAndroid Build Coastguard Worker #endif /* __FreeBSD__ */
5284*03f9172cSAndroid Build Coastguard Worker 	addr.sun_family = AF_UNIX;
5285*03f9172cSAndroid Build Coastguard Worker 	fname = hostapd_ctrl_iface_path(hapd);
5286*03f9172cSAndroid Build Coastguard Worker 	if (fname == NULL)
5287*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5288*03f9172cSAndroid Build Coastguard Worker 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
5289*03f9172cSAndroid Build Coastguard Worker 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
5290*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
5291*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5292*03f9172cSAndroid Build Coastguard Worker 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
5293*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
5294*03f9172cSAndroid Build Coastguard Worker 				   " allow connections - assuming it was left"
5295*03f9172cSAndroid Build Coastguard Worker 				   "over from forced program termination");
5296*03f9172cSAndroid Build Coastguard Worker 			if (unlink(fname) < 0) {
5297*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
5298*03f9172cSAndroid Build Coastguard Worker 					   "Could not unlink existing ctrl_iface socket '%s': %s",
5299*03f9172cSAndroid Build Coastguard Worker 					   fname, strerror(errno));
5300*03f9172cSAndroid Build Coastguard Worker 				goto fail;
5301*03f9172cSAndroid Build Coastguard Worker 			}
5302*03f9172cSAndroid Build Coastguard Worker 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
5303*03f9172cSAndroid Build Coastguard Worker 			    0) {
5304*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
5305*03f9172cSAndroid Build Coastguard Worker 					   "hostapd-ctrl-iface: bind(PF_UNIX): %s",
5306*03f9172cSAndroid Build Coastguard Worker 					   strerror(errno));
5307*03f9172cSAndroid Build Coastguard Worker 				goto fail;
5308*03f9172cSAndroid Build Coastguard Worker 			}
5309*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
5310*03f9172cSAndroid Build Coastguard Worker 				   "ctrl_iface socket '%s'", fname);
5311*03f9172cSAndroid Build Coastguard Worker 		} else {
5312*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
5313*03f9172cSAndroid Build Coastguard Worker 				   "be in use - cannot override it");
5314*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
5315*03f9172cSAndroid Build Coastguard Worker 				   "not used anymore", fname);
5316*03f9172cSAndroid Build Coastguard Worker 			os_free(fname);
5317*03f9172cSAndroid Build Coastguard Worker 			fname = NULL;
5318*03f9172cSAndroid Build Coastguard Worker 			goto fail;
5319*03f9172cSAndroid Build Coastguard Worker 		}
5320*03f9172cSAndroid Build Coastguard Worker 	}
5321*03f9172cSAndroid Build Coastguard Worker 
5322*03f9172cSAndroid Build Coastguard Worker 	if (hapd->conf->ctrl_interface_gid_set &&
5323*03f9172cSAndroid Build Coastguard Worker 	    lchown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
5324*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
5325*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5326*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5327*03f9172cSAndroid Build Coastguard Worker 	}
5328*03f9172cSAndroid Build Coastguard Worker 
5329*03f9172cSAndroid Build Coastguard Worker 	if (!hapd->conf->ctrl_interface_gid_set &&
5330*03f9172cSAndroid Build Coastguard Worker 	    hapd->iface->interfaces->ctrl_iface_group &&
5331*03f9172cSAndroid Build Coastguard Worker 	    lchown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
5332*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
5333*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5334*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5335*03f9172cSAndroid Build Coastguard Worker 	}
5336*03f9172cSAndroid Build Coastguard Worker 
5337*03f9172cSAndroid Build Coastguard Worker 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
5338*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
5339*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5340*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5341*03f9172cSAndroid Build Coastguard Worker 	}
5342*03f9172cSAndroid Build Coastguard Worker 	os_free(fname);
5343*03f9172cSAndroid Build Coastguard Worker 
5344*03f9172cSAndroid Build Coastguard Worker 	hapd->ctrl_sock = s;
5345*03f9172cSAndroid Build Coastguard Worker 	if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
5346*03f9172cSAndroid Build Coastguard Worker 				     NULL) < 0) {
5347*03f9172cSAndroid Build Coastguard Worker 		hostapd_ctrl_iface_deinit(hapd);
5348*03f9172cSAndroid Build Coastguard Worker 		return -1;
5349*03f9172cSAndroid Build Coastguard Worker 	}
5350*03f9172cSAndroid Build Coastguard Worker 	hapd->msg_ctx = hapd;
5351*03f9172cSAndroid Build Coastguard Worker 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
5352*03f9172cSAndroid Build Coastguard Worker 
5353*03f9172cSAndroid Build Coastguard Worker 	return 0;
5354*03f9172cSAndroid Build Coastguard Worker 
5355*03f9172cSAndroid Build Coastguard Worker fail:
5356*03f9172cSAndroid Build Coastguard Worker 	if (s >= 0)
5357*03f9172cSAndroid Build Coastguard Worker 		close(s);
5358*03f9172cSAndroid Build Coastguard Worker 	if (fname) {
5359*03f9172cSAndroid Build Coastguard Worker 		unlink(fname);
5360*03f9172cSAndroid Build Coastguard Worker 		os_free(fname);
5361*03f9172cSAndroid Build Coastguard Worker 	}
5362*03f9172cSAndroid Build Coastguard Worker 	return -1;
5363*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
5364*03f9172cSAndroid Build Coastguard Worker }
5365*03f9172cSAndroid Build Coastguard Worker 
5366*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_deinit(struct hostapd_data * hapd)5367*03f9172cSAndroid Build Coastguard Worker void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
5368*03f9172cSAndroid Build Coastguard Worker {
5369*03f9172cSAndroid Build Coastguard Worker 	struct wpa_ctrl_dst *dst, *prev;
5370*03f9172cSAndroid Build Coastguard Worker 
5371*03f9172cSAndroid Build Coastguard Worker 	if (hapd->ctrl_sock > -1) {
5372*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
5373*03f9172cSAndroid Build Coastguard Worker 		char *fname;
5374*03f9172cSAndroid Build Coastguard Worker #endif /* !CONFIG_CTRL_IFACE_UDP */
5375*03f9172cSAndroid Build Coastguard Worker 
5376*03f9172cSAndroid Build Coastguard Worker 		eloop_unregister_read_sock(hapd->ctrl_sock);
5377*03f9172cSAndroid Build Coastguard Worker 		close(hapd->ctrl_sock);
5378*03f9172cSAndroid Build Coastguard Worker 		hapd->ctrl_sock = -1;
5379*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
5380*03f9172cSAndroid Build Coastguard Worker 		fname = hostapd_ctrl_iface_path(hapd);
5381*03f9172cSAndroid Build Coastguard Worker 		if (fname)
5382*03f9172cSAndroid Build Coastguard Worker 			unlink(fname);
5383*03f9172cSAndroid Build Coastguard Worker 		os_free(fname);
5384*03f9172cSAndroid Build Coastguard Worker 
5385*03f9172cSAndroid Build Coastguard Worker 		if (hapd->conf->ctrl_interface &&
5386*03f9172cSAndroid Build Coastguard Worker 		    rmdir(hapd->conf->ctrl_interface) < 0) {
5387*03f9172cSAndroid Build Coastguard Worker 			if (errno == ENOTEMPTY) {
5388*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_DEBUG, "Control interface "
5389*03f9172cSAndroid Build Coastguard Worker 					   "directory not empty - leaving it "
5390*03f9172cSAndroid Build Coastguard Worker 					   "behind");
5391*03f9172cSAndroid Build Coastguard Worker 			} else {
5392*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
5393*03f9172cSAndroid Build Coastguard Worker 					   "rmdir[ctrl_interface=%s]: %s",
5394*03f9172cSAndroid Build Coastguard Worker 					   hapd->conf->ctrl_interface,
5395*03f9172cSAndroid Build Coastguard Worker 					   strerror(errno));
5396*03f9172cSAndroid Build Coastguard Worker 			}
5397*03f9172cSAndroid Build Coastguard Worker 		}
5398*03f9172cSAndroid Build Coastguard Worker #endif /* !CONFIG_CTRL_IFACE_UDP */
5399*03f9172cSAndroid Build Coastguard Worker 	}
5400*03f9172cSAndroid Build Coastguard Worker 
5401*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
5402*03f9172cSAndroid Build Coastguard Worker 			      list)
5403*03f9172cSAndroid Build Coastguard Worker 		os_free(dst);
5404*03f9172cSAndroid Build Coastguard Worker 
5405*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
5406*03f9172cSAndroid Build Coastguard Worker 	l2_packet_deinit(hapd->l2_test);
5407*03f9172cSAndroid Build Coastguard Worker 	hapd->l2_test = NULL;
5408*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
5409*03f9172cSAndroid Build Coastguard Worker }
5410*03f9172cSAndroid Build Coastguard Worker 
5411*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_add(struct hapd_interfaces * interfaces,char * buf)5412*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
5413*03f9172cSAndroid Build Coastguard Worker 				  char *buf)
5414*03f9172cSAndroid Build Coastguard Worker {
5415*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_add_iface(interfaces, buf) < 0) {
5416*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
5417*03f9172cSAndroid Build Coastguard Worker 		return -1;
5418*03f9172cSAndroid Build Coastguard Worker 	}
5419*03f9172cSAndroid Build Coastguard Worker 	return 0;
5420*03f9172cSAndroid Build Coastguard Worker }
5421*03f9172cSAndroid Build Coastguard Worker 
5422*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_remove(struct hapd_interfaces * interfaces,char * buf)5423*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
5424*03f9172cSAndroid Build Coastguard Worker 				     char *buf)
5425*03f9172cSAndroid Build Coastguard Worker {
5426*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_remove_iface(interfaces, buf) < 0) {
5427*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
5428*03f9172cSAndroid Build Coastguard Worker 		return -1;
5429*03f9172cSAndroid Build Coastguard Worker 	}
5430*03f9172cSAndroid Build Coastguard Worker 	return 0;
5431*03f9172cSAndroid Build Coastguard Worker }
5432*03f9172cSAndroid Build Coastguard Worker 
5433*03f9172cSAndroid Build Coastguard Worker 
hostapd_global_ctrl_iface_attach(struct hapd_interfaces * interfaces,struct sockaddr_storage * from,socklen_t fromlen,char * input)5434*03f9172cSAndroid Build Coastguard Worker static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
5435*03f9172cSAndroid Build Coastguard Worker 					    struct sockaddr_storage *from,
5436*03f9172cSAndroid Build Coastguard Worker 					    socklen_t fromlen, char *input)
5437*03f9172cSAndroid Build Coastguard Worker {
5438*03f9172cSAndroid Build Coastguard Worker 	return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen,
5439*03f9172cSAndroid Build Coastguard Worker 				 input);
5440*03f9172cSAndroid Build Coastguard Worker }
5441*03f9172cSAndroid Build Coastguard Worker 
5442*03f9172cSAndroid Build Coastguard Worker 
hostapd_global_ctrl_iface_detach(struct hapd_interfaces * interfaces,struct sockaddr_storage * from,socklen_t fromlen)5443*03f9172cSAndroid Build Coastguard Worker static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
5444*03f9172cSAndroid Build Coastguard Worker 					    struct sockaddr_storage *from,
5445*03f9172cSAndroid Build Coastguard Worker 					    socklen_t fromlen)
5446*03f9172cSAndroid Build Coastguard Worker {
5447*03f9172cSAndroid Build Coastguard Worker 	return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
5448*03f9172cSAndroid Build Coastguard Worker }
5449*03f9172cSAndroid Build Coastguard Worker 
5450*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_flush(struct hapd_interfaces * interfaces)5451*03f9172cSAndroid Build Coastguard Worker static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
5452*03f9172cSAndroid Build Coastguard Worker {
5453*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS_TESTING
5454*03f9172cSAndroid Build Coastguard Worker 	wps_version_number = 0x20;
5455*03f9172cSAndroid Build Coastguard Worker 	wps_testing_stub_cred = 0;
5456*03f9172cSAndroid Build Coastguard Worker 	wps_corrupt_pkhash = 0;
5457*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS_TESTING */
5458*03f9172cSAndroid Build Coastguard Worker 
5459*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
5460*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
5461*03f9172cSAndroid Build Coastguard Worker 	dpp_test = DPP_TEST_DISABLED;
5462*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP3
5463*03f9172cSAndroid Build Coastguard Worker 	dpp_version_override = 3;
5464*03f9172cSAndroid Build Coastguard Worker #elif defined(CONFIG_DPP2)
5465*03f9172cSAndroid Build Coastguard Worker 	dpp_version_override = 2;
5466*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_DPP2 */
5467*03f9172cSAndroid Build Coastguard Worker 	dpp_version_override = 1;
5468*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP2 */
5469*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
5470*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
5471*03f9172cSAndroid Build Coastguard Worker 
5472*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
5473*03f9172cSAndroid Build Coastguard Worker 	dpp_global_clear(interfaces->dpp);
5474*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP3
5475*03f9172cSAndroid Build Coastguard Worker 	interfaces->dpp_pb_bi = NULL;
5476*03f9172cSAndroid Build Coastguard Worker 	{
5477*03f9172cSAndroid Build Coastguard Worker 		int i;
5478*03f9172cSAndroid Build Coastguard Worker 
5479*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
5480*03f9172cSAndroid Build Coastguard Worker 			struct dpp_pb_info *info;
5481*03f9172cSAndroid Build Coastguard Worker 
5482*03f9172cSAndroid Build Coastguard Worker 			info = &interfaces->dpp_pb[i];
5483*03f9172cSAndroid Build Coastguard Worker 			info->rx_time.sec = 0;
5484*03f9172cSAndroid Build Coastguard Worker 			info->rx_time.usec = 0;
5485*03f9172cSAndroid Build Coastguard Worker 		}
5486*03f9172cSAndroid Build Coastguard Worker 	}
5487*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP3 */
5488*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
5489*03f9172cSAndroid Build Coastguard Worker }
5490*03f9172cSAndroid Build Coastguard Worker 
5491*03f9172cSAndroid Build Coastguard Worker 
5492*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FST
5493*03f9172cSAndroid Build Coastguard Worker 
5494*03f9172cSAndroid Build Coastguard Worker static int
hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces * interfaces,const char * cmd)5495*03f9172cSAndroid Build Coastguard Worker hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
5496*03f9172cSAndroid Build Coastguard Worker 				     const char *cmd)
5497*03f9172cSAndroid Build Coastguard Worker {
5498*03f9172cSAndroid Build Coastguard Worker 	char ifname[IFNAMSIZ + 1];
5499*03f9172cSAndroid Build Coastguard Worker 	struct fst_iface_cfg cfg;
5500*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd;
5501*03f9172cSAndroid Build Coastguard Worker 	struct fst_wpa_obj iface_obj;
5502*03f9172cSAndroid Build Coastguard Worker 
5503*03f9172cSAndroid Build Coastguard Worker 	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
5504*03f9172cSAndroid Build Coastguard Worker 		hapd = hostapd_get_iface(interfaces, ifname);
5505*03f9172cSAndroid Build Coastguard Worker 		if (hapd) {
5506*03f9172cSAndroid Build Coastguard Worker 			if (hapd->iface->fst) {
5507*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_INFO, "FST: Already attached");
5508*03f9172cSAndroid Build Coastguard Worker 				return -1;
5509*03f9172cSAndroid Build Coastguard Worker 			}
5510*03f9172cSAndroid Build Coastguard Worker 			fst_hostapd_fill_iface_obj(hapd, &iface_obj);
5511*03f9172cSAndroid Build Coastguard Worker 			hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
5512*03f9172cSAndroid Build Coastguard Worker 						      &iface_obj, &cfg);
5513*03f9172cSAndroid Build Coastguard Worker 			if (hapd->iface->fst)
5514*03f9172cSAndroid Build Coastguard Worker 				return 0;
5515*03f9172cSAndroid Build Coastguard Worker 		}
5516*03f9172cSAndroid Build Coastguard Worker 	}
5517*03f9172cSAndroid Build Coastguard Worker 
5518*03f9172cSAndroid Build Coastguard Worker 	return -EINVAL;
5519*03f9172cSAndroid Build Coastguard Worker }
5520*03f9172cSAndroid Build Coastguard Worker 
5521*03f9172cSAndroid Build Coastguard Worker 
5522*03f9172cSAndroid Build Coastguard Worker static int
hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces * interfaces,const char * cmd)5523*03f9172cSAndroid Build Coastguard Worker hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
5524*03f9172cSAndroid Build Coastguard Worker 				     const char *cmd)
5525*03f9172cSAndroid Build Coastguard Worker {
5526*03f9172cSAndroid Build Coastguard Worker 	char ifname[IFNAMSIZ + 1];
5527*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data * hapd;
5528*03f9172cSAndroid Build Coastguard Worker 
5529*03f9172cSAndroid Build Coastguard Worker 	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
5530*03f9172cSAndroid Build Coastguard Worker 		hapd = hostapd_get_iface(interfaces, ifname);
5531*03f9172cSAndroid Build Coastguard Worker 		if (hapd) {
5532*03f9172cSAndroid Build Coastguard Worker 			if (!fst_iface_detach(ifname)) {
5533*03f9172cSAndroid Build Coastguard Worker 				hapd->iface->fst = NULL;
5534*03f9172cSAndroid Build Coastguard Worker 				hapd->iface->fst_ies = NULL;
5535*03f9172cSAndroid Build Coastguard Worker 				return 0;
5536*03f9172cSAndroid Build Coastguard Worker 			}
5537*03f9172cSAndroid Build Coastguard Worker 		}
5538*03f9172cSAndroid Build Coastguard Worker 	}
5539*03f9172cSAndroid Build Coastguard Worker 
5540*03f9172cSAndroid Build Coastguard Worker 	return -EINVAL;
5541*03f9172cSAndroid Build Coastguard Worker }
5542*03f9172cSAndroid Build Coastguard Worker 
5543*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FST */
5544*03f9172cSAndroid Build Coastguard Worker 
5545*03f9172cSAndroid Build Coastguard Worker 
5546*03f9172cSAndroid Build Coastguard Worker static struct hostapd_data *
hostapd_interfaces_get_hapd(struct hapd_interfaces * interfaces,const char * ifname)5547*03f9172cSAndroid Build Coastguard Worker hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
5548*03f9172cSAndroid Build Coastguard Worker 			    const char *ifname)
5549*03f9172cSAndroid Build Coastguard Worker {
5550*03f9172cSAndroid Build Coastguard Worker 	size_t i, j;
5551*03f9172cSAndroid Build Coastguard Worker 
5552*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < interfaces->count; i++) {
5553*03f9172cSAndroid Build Coastguard Worker 		struct hostapd_iface *iface = interfaces->iface[i];
5554*03f9172cSAndroid Build Coastguard Worker 
5555*03f9172cSAndroid Build Coastguard Worker 		for (j = 0; j < iface->num_bss; j++) {
5556*03f9172cSAndroid Build Coastguard Worker 			struct hostapd_data *hapd;
5557*03f9172cSAndroid Build Coastguard Worker 
5558*03f9172cSAndroid Build Coastguard Worker 			hapd = iface->bss[j];
5559*03f9172cSAndroid Build Coastguard Worker 			if (os_strcmp(ifname, hapd->conf->iface) == 0)
5560*03f9172cSAndroid Build Coastguard Worker 				return hapd;
5561*03f9172cSAndroid Build Coastguard Worker 		}
5562*03f9172cSAndroid Build Coastguard Worker 	}
5563*03f9172cSAndroid Build Coastguard Worker 
5564*03f9172cSAndroid Build Coastguard Worker 	return NULL;
5565*03f9172cSAndroid Build Coastguard Worker }
5566*03f9172cSAndroid Build Coastguard Worker 
5567*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_dup_param(struct hostapd_data * src_hapd,struct hostapd_data * dst_hapd,const char * param)5568*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
5569*03f9172cSAndroid Build Coastguard Worker 					struct hostapd_data *dst_hapd,
5570*03f9172cSAndroid Build Coastguard Worker 					const char *param)
5571*03f9172cSAndroid Build Coastguard Worker {
5572*03f9172cSAndroid Build Coastguard Worker 	int res;
5573*03f9172cSAndroid Build Coastguard Worker 	char *value;
5574*03f9172cSAndroid Build Coastguard Worker 
5575*03f9172cSAndroid Build Coastguard Worker 	value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
5576*03f9172cSAndroid Build Coastguard Worker 	if (!value) {
5577*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR,
5578*03f9172cSAndroid Build Coastguard Worker 			   "DUP: cannot allocate buffer to stringify %s",
5579*03f9172cSAndroid Build Coastguard Worker 			   param);
5580*03f9172cSAndroid Build Coastguard Worker 		goto error_return;
5581*03f9172cSAndroid Build Coastguard Worker 	}
5582*03f9172cSAndroid Build Coastguard Worker 
5583*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(param, "wpa") == 0) {
5584*03f9172cSAndroid Build Coastguard Worker 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
5585*03f9172cSAndroid Build Coastguard Worker 			    src_hapd->conf->wpa);
5586*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
5587*03f9172cSAndroid Build Coastguard Worker 		   src_hapd->conf->wpa_key_mgmt) {
5588*03f9172cSAndroid Build Coastguard Worker 		res = hostapd_ctrl_iface_get_key_mgmt(
5589*03f9172cSAndroid Build Coastguard Worker 			src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
5590*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
5591*03f9172cSAndroid Build Coastguard Worker 			goto error_stringify;
5592*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(param, "wpa_pairwise") == 0 &&
5593*03f9172cSAndroid Build Coastguard Worker 		   src_hapd->conf->wpa_pairwise) {
5594*03f9172cSAndroid Build Coastguard Worker 		res = wpa_write_ciphers(value,
5595*03f9172cSAndroid Build Coastguard Worker 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
5596*03f9172cSAndroid Build Coastguard Worker 					src_hapd->conf->wpa_pairwise, " ");
5597*03f9172cSAndroid Build Coastguard Worker 		if (res < 0)
5598*03f9172cSAndroid Build Coastguard Worker 			goto error_stringify;
5599*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(param, "rsn_pairwise") == 0 &&
5600*03f9172cSAndroid Build Coastguard Worker 		   src_hapd->conf->rsn_pairwise) {
5601*03f9172cSAndroid Build Coastguard Worker 		res = wpa_write_ciphers(value,
5602*03f9172cSAndroid Build Coastguard Worker 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
5603*03f9172cSAndroid Build Coastguard Worker 					src_hapd->conf->rsn_pairwise, " ");
5604*03f9172cSAndroid Build Coastguard Worker 		if (res < 0)
5605*03f9172cSAndroid Build Coastguard Worker 			goto error_stringify;
5606*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(param, "wpa_passphrase") == 0 &&
5607*03f9172cSAndroid Build Coastguard Worker 		   src_hapd->conf->ssid.wpa_passphrase) {
5608*03f9172cSAndroid Build Coastguard Worker 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
5609*03f9172cSAndroid Build Coastguard Worker 			    src_hapd->conf->ssid.wpa_passphrase);
5610*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(param, "wpa_psk") == 0 &&
5611*03f9172cSAndroid Build Coastguard Worker 		   src_hapd->conf->ssid.wpa_psk_set) {
5612*03f9172cSAndroid Build Coastguard Worker 		wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
5613*03f9172cSAndroid Build Coastguard Worker 			src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
5614*03f9172cSAndroid Build Coastguard Worker 	} else {
5615*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
5616*03f9172cSAndroid Build Coastguard Worker 		goto error_return;
5617*03f9172cSAndroid Build Coastguard Worker 	}
5618*03f9172cSAndroid Build Coastguard Worker 
5619*03f9172cSAndroid Build Coastguard Worker 	res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
5620*03f9172cSAndroid Build Coastguard Worker 	os_free(value);
5621*03f9172cSAndroid Build Coastguard Worker 	return res;
5622*03f9172cSAndroid Build Coastguard Worker 
5623*03f9172cSAndroid Build Coastguard Worker error_stringify:
5624*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
5625*03f9172cSAndroid Build Coastguard Worker error_return:
5626*03f9172cSAndroid Build Coastguard Worker 	os_free(value);
5627*03f9172cSAndroid Build Coastguard Worker 	return -1;
5628*03f9172cSAndroid Build Coastguard Worker }
5629*03f9172cSAndroid Build Coastguard Worker 
5630*03f9172cSAndroid Build Coastguard Worker 
5631*03f9172cSAndroid Build Coastguard Worker static int
hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces * interfaces,const char * input,char * reply,int reply_size)5632*03f9172cSAndroid Build Coastguard Worker hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
5633*03f9172cSAndroid Build Coastguard Worker 				     const char *input,
5634*03f9172cSAndroid Build Coastguard Worker 				     char *reply, int reply_size)
5635*03f9172cSAndroid Build Coastguard Worker {
5636*03f9172cSAndroid Build Coastguard Worker 	size_t i, j;
5637*03f9172cSAndroid Build Coastguard Worker 	int res;
5638*03f9172cSAndroid Build Coastguard Worker 	char *pos, *end;
5639*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_iface *iface;
5640*03f9172cSAndroid Build Coastguard Worker 	int show_ctrl = 0;
5641*03f9172cSAndroid Build Coastguard Worker 
5642*03f9172cSAndroid Build Coastguard Worker 	if (input)
5643*03f9172cSAndroid Build Coastguard Worker 		show_ctrl = !!os_strstr(input, "ctrl");
5644*03f9172cSAndroid Build Coastguard Worker 
5645*03f9172cSAndroid Build Coastguard Worker 	pos = reply;
5646*03f9172cSAndroid Build Coastguard Worker 	end = reply + reply_size;
5647*03f9172cSAndroid Build Coastguard Worker 
5648*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < interfaces->count; i++) {
5649*03f9172cSAndroid Build Coastguard Worker 		iface = interfaces->iface[i];
5650*03f9172cSAndroid Build Coastguard Worker 
5651*03f9172cSAndroid Build Coastguard Worker 		for (j = 0; j < iface->num_bss; j++) {
5652*03f9172cSAndroid Build Coastguard Worker 			struct hostapd_bss_config *conf;
5653*03f9172cSAndroid Build Coastguard Worker 
5654*03f9172cSAndroid Build Coastguard Worker 			conf = iface->conf->bss[j];
5655*03f9172cSAndroid Build Coastguard Worker 			if (show_ctrl)
5656*03f9172cSAndroid Build Coastguard Worker 				res = os_snprintf(pos, end - pos,
5657*03f9172cSAndroid Build Coastguard Worker 						  "%s ctrl_iface=%s\n",
5658*03f9172cSAndroid Build Coastguard Worker 						  conf->iface,
5659*03f9172cSAndroid Build Coastguard Worker 						  conf->ctrl_interface ?
5660*03f9172cSAndroid Build Coastguard Worker 						  conf->ctrl_interface : "N/A");
5661*03f9172cSAndroid Build Coastguard Worker 			else
5662*03f9172cSAndroid Build Coastguard Worker 				res = os_snprintf(pos, end - pos, "%s\n",
5663*03f9172cSAndroid Build Coastguard Worker 						  conf->iface);
5664*03f9172cSAndroid Build Coastguard Worker 			if (os_snprintf_error(end - pos, res)) {
5665*03f9172cSAndroid Build Coastguard Worker 				*pos = '\0';
5666*03f9172cSAndroid Build Coastguard Worker 				return pos - reply;
5667*03f9172cSAndroid Build Coastguard Worker 			}
5668*03f9172cSAndroid Build Coastguard Worker 			pos += res;
5669*03f9172cSAndroid Build Coastguard Worker 		}
5670*03f9172cSAndroid Build Coastguard Worker 	}
5671*03f9172cSAndroid Build Coastguard Worker 
5672*03f9172cSAndroid Build Coastguard Worker 	return pos - reply;
5673*03f9172cSAndroid Build Coastguard Worker }
5674*03f9172cSAndroid Build Coastguard Worker 
5675*03f9172cSAndroid Build Coastguard Worker 
5676*03f9172cSAndroid Build Coastguard Worker static int
hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces * interfaces,char * cmd)5677*03f9172cSAndroid Build Coastguard Worker hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
5678*03f9172cSAndroid Build Coastguard Worker 				      char *cmd)
5679*03f9172cSAndroid Build Coastguard Worker {
5680*03f9172cSAndroid Build Coastguard Worker 	char *p_start = cmd, *p_end;
5681*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *src_hapd, *dst_hapd;
5682*03f9172cSAndroid Build Coastguard Worker 
5683*03f9172cSAndroid Build Coastguard Worker 	/* cmd: "<src ifname> <dst ifname> <variable name> */
5684*03f9172cSAndroid Build Coastguard Worker 
5685*03f9172cSAndroid Build Coastguard Worker 	p_end = os_strchr(p_start, ' ');
5686*03f9172cSAndroid Build Coastguard Worker 	if (!p_end) {
5687*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
5688*03f9172cSAndroid Build Coastguard Worker 			   cmd);
5689*03f9172cSAndroid Build Coastguard Worker 		return -1;
5690*03f9172cSAndroid Build Coastguard Worker 	}
5691*03f9172cSAndroid Build Coastguard Worker 
5692*03f9172cSAndroid Build Coastguard Worker 	*p_end = '\0';
5693*03f9172cSAndroid Build Coastguard Worker 	src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
5694*03f9172cSAndroid Build Coastguard Worker 	if (!src_hapd) {
5695*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
5696*03f9172cSAndroid Build Coastguard Worker 			   p_start);
5697*03f9172cSAndroid Build Coastguard Worker 		return -1;
5698*03f9172cSAndroid Build Coastguard Worker 	}
5699*03f9172cSAndroid Build Coastguard Worker 
5700*03f9172cSAndroid Build Coastguard Worker 	p_start = p_end + 1;
5701*03f9172cSAndroid Build Coastguard Worker 	p_end = os_strchr(p_start, ' ');
5702*03f9172cSAndroid Build Coastguard Worker 	if (!p_end) {
5703*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
5704*03f9172cSAndroid Build Coastguard Worker 			   cmd);
5705*03f9172cSAndroid Build Coastguard Worker 		return -1;
5706*03f9172cSAndroid Build Coastguard Worker 	}
5707*03f9172cSAndroid Build Coastguard Worker 
5708*03f9172cSAndroid Build Coastguard Worker 	*p_end = '\0';
5709*03f9172cSAndroid Build Coastguard Worker 	dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
5710*03f9172cSAndroid Build Coastguard Worker 	if (!dst_hapd) {
5711*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
5712*03f9172cSAndroid Build Coastguard Worker 			   p_start);
5713*03f9172cSAndroid Build Coastguard Worker 		return -1;
5714*03f9172cSAndroid Build Coastguard Worker 	}
5715*03f9172cSAndroid Build Coastguard Worker 
5716*03f9172cSAndroid Build Coastguard Worker 	p_start = p_end + 1;
5717*03f9172cSAndroid Build Coastguard Worker 	return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
5718*03f9172cSAndroid Build Coastguard Worker }
5719*03f9172cSAndroid Build Coastguard Worker 
5720*03f9172cSAndroid Build Coastguard Worker 
hostapd_global_ctrl_iface_ifname(struct hapd_interfaces * interfaces,const char * ifname,char * buf,char * reply,int reply_size,struct sockaddr_storage * from,socklen_t fromlen)5721*03f9172cSAndroid Build Coastguard Worker static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
5722*03f9172cSAndroid Build Coastguard Worker 					    const char *ifname,
5723*03f9172cSAndroid Build Coastguard Worker 					    char *buf, char *reply,
5724*03f9172cSAndroid Build Coastguard Worker 					    int reply_size,
5725*03f9172cSAndroid Build Coastguard Worker 					    struct sockaddr_storage *from,
5726*03f9172cSAndroid Build Coastguard Worker 					    socklen_t fromlen)
5727*03f9172cSAndroid Build Coastguard Worker {
5728*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd;
5729*03f9172cSAndroid Build Coastguard Worker 
5730*03f9172cSAndroid Build Coastguard Worker 	hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
5731*03f9172cSAndroid Build Coastguard Worker 	if (hapd == NULL) {
5732*03f9172cSAndroid Build Coastguard Worker 		int res;
5733*03f9172cSAndroid Build Coastguard Worker 
5734*03f9172cSAndroid Build Coastguard Worker 		res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
5735*03f9172cSAndroid Build Coastguard Worker 		if (os_snprintf_error(reply_size, res))
5736*03f9172cSAndroid Build Coastguard Worker 			return -1;
5737*03f9172cSAndroid Build Coastguard Worker 		return res;
5738*03f9172cSAndroid Build Coastguard Worker 	}
5739*03f9172cSAndroid Build Coastguard Worker 
5740*03f9172cSAndroid Build Coastguard Worker 	return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
5741*03f9172cSAndroid Build Coastguard Worker 						  from, fromlen);
5742*03f9172cSAndroid Build Coastguard Worker }
5743*03f9172cSAndroid Build Coastguard Worker 
5744*03f9172cSAndroid Build Coastguard Worker 
hostapd_global_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)5745*03f9172cSAndroid Build Coastguard Worker static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
5746*03f9172cSAndroid Build Coastguard Worker 					      void *sock_ctx)
5747*03f9172cSAndroid Build Coastguard Worker {
5748*03f9172cSAndroid Build Coastguard Worker 	struct hapd_interfaces *interfaces = eloop_ctx;
5749*03f9172cSAndroid Build Coastguard Worker 	char buffer[256], *buf = buffer;
5750*03f9172cSAndroid Build Coastguard Worker 	int res;
5751*03f9172cSAndroid Build Coastguard Worker 	struct sockaddr_storage from;
5752*03f9172cSAndroid Build Coastguard Worker 	socklen_t fromlen = sizeof(from);
5753*03f9172cSAndroid Build Coastguard Worker 	char *reply;
5754*03f9172cSAndroid Build Coastguard Worker 	int reply_len;
5755*03f9172cSAndroid Build Coastguard Worker 	const int reply_size = 4096;
5756*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
5757*03f9172cSAndroid Build Coastguard Worker 	unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
5758*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
5759*03f9172cSAndroid Build Coastguard Worker 
5760*03f9172cSAndroid Build Coastguard Worker 	res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
5761*03f9172cSAndroid Build Coastguard Worker 		       (struct sockaddr *) &from, &fromlen);
5762*03f9172cSAndroid Build Coastguard Worker 	if (res < 0) {
5763*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
5764*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5765*03f9172cSAndroid Build Coastguard Worker 		return;
5766*03f9172cSAndroid Build Coastguard Worker 	}
5767*03f9172cSAndroid Build Coastguard Worker 	buf[res] = '\0';
5768*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
5769*03f9172cSAndroid Build Coastguard Worker 
5770*03f9172cSAndroid Build Coastguard Worker 	reply = os_malloc(reply_size);
5771*03f9172cSAndroid Build Coastguard Worker 	if (reply == NULL) {
5772*03f9172cSAndroid Build Coastguard Worker 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
5773*03f9172cSAndroid Build Coastguard Worker 			   fromlen) < 0) {
5774*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
5775*03f9172cSAndroid Build Coastguard Worker 				   strerror(errno));
5776*03f9172cSAndroid Build Coastguard Worker 		}
5777*03f9172cSAndroid Build Coastguard Worker 		return;
5778*03f9172cSAndroid Build Coastguard Worker 	}
5779*03f9172cSAndroid Build Coastguard Worker 
5780*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(reply, "OK\n", 3);
5781*03f9172cSAndroid Build Coastguard Worker 	reply_len = 3;
5782*03f9172cSAndroid Build Coastguard Worker 
5783*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
5784*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
5785*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "COOKIE=", 7);
5786*03f9172cSAndroid Build Coastguard Worker 		wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
5787*03f9172cSAndroid Build Coastguard Worker 				 interfaces->ctrl_iface_cookie,
5788*03f9172cSAndroid Build Coastguard Worker 				 CTRL_IFACE_COOKIE_LEN);
5789*03f9172cSAndroid Build Coastguard Worker 		reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
5790*03f9172cSAndroid Build Coastguard Worker 		goto send_reply;
5791*03f9172cSAndroid Build Coastguard Worker 	}
5792*03f9172cSAndroid Build Coastguard Worker 
5793*03f9172cSAndroid Build Coastguard Worker 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
5794*03f9172cSAndroid Build Coastguard Worker 	    hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
5795*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
5796*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: No cookie in the request - drop request");
5797*03f9172cSAndroid Build Coastguard Worker 		os_free(reply);
5798*03f9172cSAndroid Build Coastguard Worker 		return;
5799*03f9172cSAndroid Build Coastguard Worker 	}
5800*03f9172cSAndroid Build Coastguard Worker 
5801*03f9172cSAndroid Build Coastguard Worker 	if (os_memcmp(interfaces->ctrl_iface_cookie, lcookie,
5802*03f9172cSAndroid Build Coastguard Worker 		      CTRL_IFACE_COOKIE_LEN) != 0) {
5803*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
5804*03f9172cSAndroid Build Coastguard Worker 			   "CTRL: Invalid cookie in the request - drop request");
5805*03f9172cSAndroid Build Coastguard Worker 		os_free(reply);
5806*03f9172cSAndroid Build Coastguard Worker 		return;
5807*03f9172cSAndroid Build Coastguard Worker 	}
5808*03f9172cSAndroid Build Coastguard Worker 
5809*03f9172cSAndroid Build Coastguard Worker 	buf += 7 + 2 * CTRL_IFACE_COOKIE_LEN;
5810*03f9172cSAndroid Build Coastguard Worker 	while (*buf == ' ')
5811*03f9172cSAndroid Build Coastguard Worker 		buf++;
5812*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
5813*03f9172cSAndroid Build Coastguard Worker 
5814*03f9172cSAndroid Build Coastguard Worker 	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
5815*03f9172cSAndroid Build Coastguard Worker 		char *pos = os_strchr(buf + 7, ' ');
5816*03f9172cSAndroid Build Coastguard Worker 
5817*03f9172cSAndroid Build Coastguard Worker 		if (pos) {
5818*03f9172cSAndroid Build Coastguard Worker 			*pos++ = '\0';
5819*03f9172cSAndroid Build Coastguard Worker 			reply_len = hostapd_global_ctrl_iface_ifname(
5820*03f9172cSAndroid Build Coastguard Worker 				interfaces, buf + 7, pos, reply, reply_size,
5821*03f9172cSAndroid Build Coastguard Worker 				&from, fromlen);
5822*03f9172cSAndroid Build Coastguard Worker 			goto send_reply;
5823*03f9172cSAndroid Build Coastguard Worker 		}
5824*03f9172cSAndroid Build Coastguard Worker 	}
5825*03f9172cSAndroid Build Coastguard Worker 
5826*03f9172cSAndroid Build Coastguard Worker 	if (os_strcmp(buf, "PING") == 0) {
5827*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "PONG\n", 5);
5828*03f9172cSAndroid Build Coastguard Worker 		reply_len = 5;
5829*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
5830*03f9172cSAndroid Build Coastguard Worker 		if (wpa_debug_reopen_file() < 0)
5831*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5832*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "FLUSH") == 0) {
5833*03f9172cSAndroid Build Coastguard Worker 		hostapd_ctrl_iface_flush(interfaces);
5834*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
5835*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
5836*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5837*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
5838*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
5839*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5840*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "ATTACH") == 0) {
5841*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
5842*03f9172cSAndroid Build Coastguard Worker 						     fromlen, NULL))
5843*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5844*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
5845*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
5846*03f9172cSAndroid Build Coastguard Worker 						     fromlen, buf + 7))
5847*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5848*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "DETACH") == 0) {
5849*03f9172cSAndroid Build Coastguard Worker 		if (hostapd_global_ctrl_iface_detach(interfaces, &from,
5850*03f9172cSAndroid Build Coastguard Worker 			fromlen))
5851*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5852*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_MODULE_TESTS
5853*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
5854*03f9172cSAndroid Build Coastguard Worker 		if (hapd_module_tests() < 0)
5855*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5856*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_MODULE_TESTS */
5857*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FST
5858*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
5859*03f9172cSAndroid Build Coastguard Worker 		if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
5860*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "OK\n");
5861*03f9172cSAndroid Build Coastguard Worker 		else
5862*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5863*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
5864*03f9172cSAndroid Build Coastguard Worker 		if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
5865*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "OK\n");
5866*03f9172cSAndroid Build Coastguard Worker 		else
5867*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5868*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
5869*03f9172cSAndroid Build Coastguard Worker 		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
5870*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FST */
5871*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
5872*03f9172cSAndroid Build Coastguard Worker 		if (!hostapd_global_ctrl_iface_dup_network(interfaces,
5873*03f9172cSAndroid Build Coastguard Worker 							   buf + 12))
5874*03f9172cSAndroid Build Coastguard Worker 			reply_len = os_snprintf(reply, reply_size, "OK\n");
5875*03f9172cSAndroid Build Coastguard Worker 		else
5876*03f9172cSAndroid Build Coastguard Worker 			reply_len = -1;
5877*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
5878*03f9172cSAndroid Build Coastguard Worker 		reply_len = hostapd_global_ctrl_iface_interfaces(
5879*03f9172cSAndroid Build Coastguard Worker 			interfaces, buf + 10, reply, reply_size);
5880*03f9172cSAndroid Build Coastguard Worker 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
5881*03f9172cSAndroid Build Coastguard Worker 		eloop_terminate();
5882*03f9172cSAndroid Build Coastguard Worker 	} else {
5883*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
5884*03f9172cSAndroid Build Coastguard Worker 			   "ignored");
5885*03f9172cSAndroid Build Coastguard Worker 		reply_len = -1;
5886*03f9172cSAndroid Build Coastguard Worker 	}
5887*03f9172cSAndroid Build Coastguard Worker 
5888*03f9172cSAndroid Build Coastguard Worker send_reply:
5889*03f9172cSAndroid Build Coastguard Worker 	if (reply_len < 0) {
5890*03f9172cSAndroid Build Coastguard Worker 		os_memcpy(reply, "FAIL\n", 5);
5891*03f9172cSAndroid Build Coastguard Worker 		reply_len = 5;
5892*03f9172cSAndroid Build Coastguard Worker 	}
5893*03f9172cSAndroid Build Coastguard Worker 
5894*03f9172cSAndroid Build Coastguard Worker 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
5895*03f9172cSAndroid Build Coastguard Worker 		   fromlen) < 0) {
5896*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
5897*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
5898*03f9172cSAndroid Build Coastguard Worker 	}
5899*03f9172cSAndroid Build Coastguard Worker 	os_free(reply);
5900*03f9172cSAndroid Build Coastguard Worker }
5901*03f9172cSAndroid Build Coastguard Worker 
5902*03f9172cSAndroid Build Coastguard Worker 
5903*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
hostapd_global_ctrl_iface_path(struct hapd_interfaces * interface)5904*03f9172cSAndroid Build Coastguard Worker static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
5905*03f9172cSAndroid Build Coastguard Worker {
5906*03f9172cSAndroid Build Coastguard Worker 	char *buf;
5907*03f9172cSAndroid Build Coastguard Worker 	size_t len;
5908*03f9172cSAndroid Build Coastguard Worker 
5909*03f9172cSAndroid Build Coastguard Worker 	if (interface->global_iface_path == NULL)
5910*03f9172cSAndroid Build Coastguard Worker 		return NULL;
5911*03f9172cSAndroid Build Coastguard Worker 
5912*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(interface->global_iface_path) +
5913*03f9172cSAndroid Build Coastguard Worker 		os_strlen(interface->global_iface_name) + 2;
5914*03f9172cSAndroid Build Coastguard Worker 	buf = os_malloc(len);
5915*03f9172cSAndroid Build Coastguard Worker 	if (buf == NULL)
5916*03f9172cSAndroid Build Coastguard Worker 		return NULL;
5917*03f9172cSAndroid Build Coastguard Worker 
5918*03f9172cSAndroid Build Coastguard Worker 	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
5919*03f9172cSAndroid Build Coastguard Worker 		    interface->global_iface_name);
5920*03f9172cSAndroid Build Coastguard Worker 	buf[len - 1] = '\0';
5921*03f9172cSAndroid Build Coastguard Worker 	return buf;
5922*03f9172cSAndroid Build Coastguard Worker }
5923*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
5924*03f9172cSAndroid Build Coastguard Worker 
5925*03f9172cSAndroid Build Coastguard Worker 
hostapd_global_ctrl_iface_init(struct hapd_interfaces * interface)5926*03f9172cSAndroid Build Coastguard Worker int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
5927*03f9172cSAndroid Build Coastguard Worker {
5928*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP
5929*03f9172cSAndroid Build Coastguard Worker 	int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
5930*03f9172cSAndroid Build Coastguard Worker 	char p[32] = { 0 };
5931*03f9172cSAndroid Build Coastguard Worker 	char *pos;
5932*03f9172cSAndroid Build Coastguard Worker 	struct addrinfo hints = { 0 }, *res, *saveres;
5933*03f9172cSAndroid Build Coastguard Worker 	int n;
5934*03f9172cSAndroid Build Coastguard Worker 
5935*03f9172cSAndroid Build Coastguard Worker 	if (interface->global_ctrl_sock > -1) {
5936*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
5937*03f9172cSAndroid Build Coastguard Worker 		return 0;
5938*03f9172cSAndroid Build Coastguard Worker 	}
5939*03f9172cSAndroid Build Coastguard Worker 
5940*03f9172cSAndroid Build Coastguard Worker 	if (interface->global_iface_path == NULL)
5941*03f9172cSAndroid Build Coastguard Worker 		return 0;
5942*03f9172cSAndroid Build Coastguard Worker 
5943*03f9172cSAndroid Build Coastguard Worker 	pos = os_strstr(interface->global_iface_path, "udp:");
5944*03f9172cSAndroid Build Coastguard Worker 	if (pos) {
5945*03f9172cSAndroid Build Coastguard Worker 		pos += 4;
5946*03f9172cSAndroid Build Coastguard Worker 		port = atoi(pos);
5947*03f9172cSAndroid Build Coastguard Worker 		if (port <= 0) {
5948*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
5949*03f9172cSAndroid Build Coastguard Worker 			goto fail;
5950*03f9172cSAndroid Build Coastguard Worker 		}
5951*03f9172cSAndroid Build Coastguard Worker 	}
5952*03f9172cSAndroid Build Coastguard Worker 
5953*03f9172cSAndroid Build Coastguard Worker 	os_get_random(interface->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
5954*03f9172cSAndroid Build Coastguard Worker 
5955*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
5956*03f9172cSAndroid Build Coastguard Worker 	hints.ai_flags = AI_PASSIVE;
5957*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
5958*03f9172cSAndroid Build Coastguard Worker 
5959*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
5960*03f9172cSAndroid Build Coastguard Worker 	hints.ai_family = AF_INET6;
5961*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
5962*03f9172cSAndroid Build Coastguard Worker 	hints.ai_family = AF_INET;
5963*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
5964*03f9172cSAndroid Build Coastguard Worker 	hints.ai_socktype = SOCK_DGRAM;
5965*03f9172cSAndroid Build Coastguard Worker 
5966*03f9172cSAndroid Build Coastguard Worker try_again:
5967*03f9172cSAndroid Build Coastguard Worker 	os_snprintf(p, sizeof(p), "%d", port);
5968*03f9172cSAndroid Build Coastguard Worker 	n = getaddrinfo(NULL, p, &hints, &res);
5969*03f9172cSAndroid Build Coastguard Worker 	if (n) {
5970*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
5971*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5972*03f9172cSAndroid Build Coastguard Worker 	}
5973*03f9172cSAndroid Build Coastguard Worker 
5974*03f9172cSAndroid Build Coastguard Worker 	saveres = res;
5975*03f9172cSAndroid Build Coastguard Worker 	interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
5976*03f9172cSAndroid Build Coastguard Worker 					     res->ai_protocol);
5977*03f9172cSAndroid Build Coastguard Worker 	if (interface->global_ctrl_sock < 0) {
5978*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
5979*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5980*03f9172cSAndroid Build Coastguard Worker 	}
5981*03f9172cSAndroid Build Coastguard Worker 
5982*03f9172cSAndroid Build Coastguard Worker 	if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
5983*03f9172cSAndroid Build Coastguard Worker 	    0) {
5984*03f9172cSAndroid Build Coastguard Worker 		port++;
5985*03f9172cSAndroid Build Coastguard Worker 		if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
5986*03f9172cSAndroid Build Coastguard Worker 		    HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
5987*03f9172cSAndroid Build Coastguard Worker 			goto try_again;
5988*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
5989*03f9172cSAndroid Build Coastguard Worker 		goto fail;
5990*03f9172cSAndroid Build Coastguard Worker 	}
5991*03f9172cSAndroid Build Coastguard Worker 
5992*03f9172cSAndroid Build Coastguard Worker 	freeaddrinfo(saveres);
5993*03f9172cSAndroid Build Coastguard Worker 
5994*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
5995*03f9172cSAndroid Build Coastguard Worker 
5996*03f9172cSAndroid Build Coastguard Worker 	if (eloop_register_read_sock(interface->global_ctrl_sock,
5997*03f9172cSAndroid Build Coastguard Worker 				     hostapd_global_ctrl_iface_receive,
5998*03f9172cSAndroid Build Coastguard Worker 				     interface, NULL) < 0) {
5999*03f9172cSAndroid Build Coastguard Worker 		hostapd_global_ctrl_iface_deinit(interface);
6000*03f9172cSAndroid Build Coastguard Worker 		return -1;
6001*03f9172cSAndroid Build Coastguard Worker 	}
6002*03f9172cSAndroid Build Coastguard Worker 
6003*03f9172cSAndroid Build Coastguard Worker 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
6004*03f9172cSAndroid Build Coastguard Worker 
6005*03f9172cSAndroid Build Coastguard Worker 	return 0;
6006*03f9172cSAndroid Build Coastguard Worker 
6007*03f9172cSAndroid Build Coastguard Worker fail:
6008*03f9172cSAndroid Build Coastguard Worker 	if (interface->global_ctrl_sock >= 0)
6009*03f9172cSAndroid Build Coastguard Worker 		close(interface->global_ctrl_sock);
6010*03f9172cSAndroid Build Coastguard Worker 	return -1;
6011*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_CTRL_IFACE_UDP */
6012*03f9172cSAndroid Build Coastguard Worker 	struct sockaddr_un addr;
6013*03f9172cSAndroid Build Coastguard Worker 	int s = -1;
6014*03f9172cSAndroid Build Coastguard Worker 	char *fname = NULL;
6015*03f9172cSAndroid Build Coastguard Worker 
6016*03f9172cSAndroid Build Coastguard Worker 	if (interface->global_iface_path == NULL) {
6017*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
6018*03f9172cSAndroid Build Coastguard Worker 		return 0;
6019*03f9172cSAndroid Build Coastguard Worker 	}
6020*03f9172cSAndroid Build Coastguard Worker 
6021*03f9172cSAndroid Build Coastguard Worker 	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
6022*03f9172cSAndroid Build Coastguard Worker 		if (errno == EEXIST) {
6023*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "Using existing control "
6024*03f9172cSAndroid Build Coastguard Worker 				   "interface directory.");
6025*03f9172cSAndroid Build Coastguard Worker 		} else {
6026*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
6027*03f9172cSAndroid Build Coastguard Worker 				   strerror(errno));
6028*03f9172cSAndroid Build Coastguard Worker 			goto fail;
6029*03f9172cSAndroid Build Coastguard Worker 		}
6030*03f9172cSAndroid Build Coastguard Worker 	} else if (interface->ctrl_iface_group &&
6031*03f9172cSAndroid Build Coastguard Worker 		   lchown(interface->global_iface_path, -1,
6032*03f9172cSAndroid Build Coastguard Worker 			  interface->ctrl_iface_group) < 0) {
6033*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
6034*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
6035*03f9172cSAndroid Build Coastguard Worker 		goto fail;
6036*03f9172cSAndroid Build Coastguard Worker 	}
6037*03f9172cSAndroid Build Coastguard Worker 
6038*03f9172cSAndroid Build Coastguard Worker 	if (os_strlen(interface->global_iface_path) + 1 +
6039*03f9172cSAndroid Build Coastguard Worker 	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
6040*03f9172cSAndroid Build Coastguard Worker 		goto fail;
6041*03f9172cSAndroid Build Coastguard Worker 
6042*03f9172cSAndroid Build Coastguard Worker 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
6043*03f9172cSAndroid Build Coastguard Worker 	if (s < 0) {
6044*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
6045*03f9172cSAndroid Build Coastguard Worker 		goto fail;
6046*03f9172cSAndroid Build Coastguard Worker 	}
6047*03f9172cSAndroid Build Coastguard Worker 
6048*03f9172cSAndroid Build Coastguard Worker 	os_memset(&addr, 0, sizeof(addr));
6049*03f9172cSAndroid Build Coastguard Worker #ifdef __FreeBSD__
6050*03f9172cSAndroid Build Coastguard Worker 	addr.sun_len = sizeof(addr);
6051*03f9172cSAndroid Build Coastguard Worker #endif /* __FreeBSD__ */
6052*03f9172cSAndroid Build Coastguard Worker 	addr.sun_family = AF_UNIX;
6053*03f9172cSAndroid Build Coastguard Worker 	fname = hostapd_global_ctrl_iface_path(interface);
6054*03f9172cSAndroid Build Coastguard Worker 	if (fname == NULL)
6055*03f9172cSAndroid Build Coastguard Worker 		goto fail;
6056*03f9172cSAndroid Build Coastguard Worker 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
6057*03f9172cSAndroid Build Coastguard Worker 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
6058*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
6059*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
6060*03f9172cSAndroid Build Coastguard Worker 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
6061*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
6062*03f9172cSAndroid Build Coastguard Worker 				   " allow connections - assuming it was left"
6063*03f9172cSAndroid Build Coastguard Worker 				   "over from forced program termination");
6064*03f9172cSAndroid Build Coastguard Worker 			if (unlink(fname) < 0) {
6065*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
6066*03f9172cSAndroid Build Coastguard Worker 					   "Could not unlink existing ctrl_iface socket '%s': %s",
6067*03f9172cSAndroid Build Coastguard Worker 					   fname, strerror(errno));
6068*03f9172cSAndroid Build Coastguard Worker 				goto fail;
6069*03f9172cSAndroid Build Coastguard Worker 			}
6070*03f9172cSAndroid Build Coastguard Worker 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
6071*03f9172cSAndroid Build Coastguard Worker 			    0) {
6072*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
6073*03f9172cSAndroid Build Coastguard Worker 					   strerror(errno));
6074*03f9172cSAndroid Build Coastguard Worker 				goto fail;
6075*03f9172cSAndroid Build Coastguard Worker 			}
6076*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
6077*03f9172cSAndroid Build Coastguard Worker 				   "ctrl_iface socket '%s'", fname);
6078*03f9172cSAndroid Build Coastguard Worker 		} else {
6079*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
6080*03f9172cSAndroid Build Coastguard Worker 				   "be in use - cannot override it");
6081*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
6082*03f9172cSAndroid Build Coastguard Worker 				   "not used anymore", fname);
6083*03f9172cSAndroid Build Coastguard Worker 			os_free(fname);
6084*03f9172cSAndroid Build Coastguard Worker 			fname = NULL;
6085*03f9172cSAndroid Build Coastguard Worker 			goto fail;
6086*03f9172cSAndroid Build Coastguard Worker 		}
6087*03f9172cSAndroid Build Coastguard Worker 	}
6088*03f9172cSAndroid Build Coastguard Worker 
6089*03f9172cSAndroid Build Coastguard Worker 	if (interface->ctrl_iface_group &&
6090*03f9172cSAndroid Build Coastguard Worker 	    lchown(fname, -1, interface->ctrl_iface_group) < 0) {
6091*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
6092*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
6093*03f9172cSAndroid Build Coastguard Worker 		goto fail;
6094*03f9172cSAndroid Build Coastguard Worker 	}
6095*03f9172cSAndroid Build Coastguard Worker 
6096*03f9172cSAndroid Build Coastguard Worker 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
6097*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
6098*03f9172cSAndroid Build Coastguard Worker 			   strerror(errno));
6099*03f9172cSAndroid Build Coastguard Worker 		goto fail;
6100*03f9172cSAndroid Build Coastguard Worker 	}
6101*03f9172cSAndroid Build Coastguard Worker 	os_free(fname);
6102*03f9172cSAndroid Build Coastguard Worker 
6103*03f9172cSAndroid Build Coastguard Worker 	interface->global_ctrl_sock = s;
6104*03f9172cSAndroid Build Coastguard Worker 	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
6105*03f9172cSAndroid Build Coastguard Worker 				 interface, NULL);
6106*03f9172cSAndroid Build Coastguard Worker 
6107*03f9172cSAndroid Build Coastguard Worker 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
6108*03f9172cSAndroid Build Coastguard Worker 
6109*03f9172cSAndroid Build Coastguard Worker 	return 0;
6110*03f9172cSAndroid Build Coastguard Worker 
6111*03f9172cSAndroid Build Coastguard Worker fail:
6112*03f9172cSAndroid Build Coastguard Worker 	if (s >= 0)
6113*03f9172cSAndroid Build Coastguard Worker 		close(s);
6114*03f9172cSAndroid Build Coastguard Worker 	if (fname) {
6115*03f9172cSAndroid Build Coastguard Worker 		unlink(fname);
6116*03f9172cSAndroid Build Coastguard Worker 		os_free(fname);
6117*03f9172cSAndroid Build Coastguard Worker 	}
6118*03f9172cSAndroid Build Coastguard Worker 	return -1;
6119*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
6120*03f9172cSAndroid Build Coastguard Worker }
6121*03f9172cSAndroid Build Coastguard Worker 
6122*03f9172cSAndroid Build Coastguard Worker 
hostapd_global_ctrl_iface_deinit(struct hapd_interfaces * interfaces)6123*03f9172cSAndroid Build Coastguard Worker void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
6124*03f9172cSAndroid Build Coastguard Worker {
6125*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
6126*03f9172cSAndroid Build Coastguard Worker 	char *fname = NULL;
6127*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
6128*03f9172cSAndroid Build Coastguard Worker 	struct wpa_ctrl_dst *dst, *prev;
6129*03f9172cSAndroid Build Coastguard Worker 
6130*03f9172cSAndroid Build Coastguard Worker 	if (interfaces->global_ctrl_sock > -1) {
6131*03f9172cSAndroid Build Coastguard Worker 		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
6132*03f9172cSAndroid Build Coastguard Worker 		close(interfaces->global_ctrl_sock);
6133*03f9172cSAndroid Build Coastguard Worker 		interfaces->global_ctrl_sock = -1;
6134*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_CTRL_IFACE_UDP
6135*03f9172cSAndroid Build Coastguard Worker 		fname = hostapd_global_ctrl_iface_path(interfaces);
6136*03f9172cSAndroid Build Coastguard Worker 		if (fname) {
6137*03f9172cSAndroid Build Coastguard Worker 			unlink(fname);
6138*03f9172cSAndroid Build Coastguard Worker 			os_free(fname);
6139*03f9172cSAndroid Build Coastguard Worker 		}
6140*03f9172cSAndroid Build Coastguard Worker 
6141*03f9172cSAndroid Build Coastguard Worker 		if (interfaces->global_iface_path &&
6142*03f9172cSAndroid Build Coastguard Worker 		    rmdir(interfaces->global_iface_path) < 0) {
6143*03f9172cSAndroid Build Coastguard Worker 			if (errno == ENOTEMPTY) {
6144*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_DEBUG, "Control interface "
6145*03f9172cSAndroid Build Coastguard Worker 					   "directory not empty - leaving it "
6146*03f9172cSAndroid Build Coastguard Worker 					   "behind");
6147*03f9172cSAndroid Build Coastguard Worker 			} else {
6148*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_ERROR,
6149*03f9172cSAndroid Build Coastguard Worker 					   "rmdir[ctrl_interface=%s]: %s",
6150*03f9172cSAndroid Build Coastguard Worker 					   interfaces->global_iface_path,
6151*03f9172cSAndroid Build Coastguard Worker 					   strerror(errno));
6152*03f9172cSAndroid Build Coastguard Worker 			}
6153*03f9172cSAndroid Build Coastguard Worker 		}
6154*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_CTRL_IFACE_UDP */
6155*03f9172cSAndroid Build Coastguard Worker 	}
6156*03f9172cSAndroid Build Coastguard Worker 
6157*03f9172cSAndroid Build Coastguard Worker 	os_free(interfaces->global_iface_path);
6158*03f9172cSAndroid Build Coastguard Worker 	interfaces->global_iface_path = NULL;
6159*03f9172cSAndroid Build Coastguard Worker 
6160*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
6161*03f9172cSAndroid Build Coastguard Worker 			      struct wpa_ctrl_dst, list)
6162*03f9172cSAndroid Build Coastguard Worker 		os_free(dst);
6163*03f9172cSAndroid Build Coastguard Worker }
6164*03f9172cSAndroid Build Coastguard Worker 
6165*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst * dst,const char * buf)6166*03f9172cSAndroid Build Coastguard Worker static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst,
6167*03f9172cSAndroid Build Coastguard Worker 					    const char *buf)
6168*03f9172cSAndroid Build Coastguard Worker {
6169*03f9172cSAndroid Build Coastguard Worker 	/* Enable Probe Request events based on explicit request.
6170*03f9172cSAndroid Build Coastguard Worker 	 * Other events are enabled by default.
6171*03f9172cSAndroid Build Coastguard Worker 	 */
6172*03f9172cSAndroid Build Coastguard Worker 	if (str_starts(buf, RX_PROBE_REQUEST))
6173*03f9172cSAndroid Build Coastguard Worker 		return !!(dst->events & WPA_EVENT_RX_PROBE_REQUEST);
6174*03f9172cSAndroid Build Coastguard Worker 	return 1;
6175*03f9172cSAndroid Build Coastguard Worker }
6176*03f9172cSAndroid Build Coastguard Worker 
6177*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_send_internal(int sock,struct dl_list * ctrl_dst,const char * ifname,int level,const char * buf,size_t len)6178*03f9172cSAndroid Build Coastguard Worker static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst,
6179*03f9172cSAndroid Build Coastguard Worker 					     const char *ifname, int level,
6180*03f9172cSAndroid Build Coastguard Worker 					     const char *buf, size_t len)
6181*03f9172cSAndroid Build Coastguard Worker {
6182*03f9172cSAndroid Build Coastguard Worker 	struct wpa_ctrl_dst *dst, *next;
6183*03f9172cSAndroid Build Coastguard Worker 	struct msghdr msg;
6184*03f9172cSAndroid Build Coastguard Worker 	int idx, res;
6185*03f9172cSAndroid Build Coastguard Worker 	struct iovec io[5];
6186*03f9172cSAndroid Build Coastguard Worker 	char levelstr[10];
6187*03f9172cSAndroid Build Coastguard Worker 
6188*03f9172cSAndroid Build Coastguard Worker 	if (sock < 0 || dl_list_empty(ctrl_dst))
6189*03f9172cSAndroid Build Coastguard Worker 		return;
6190*03f9172cSAndroid Build Coastguard Worker 
6191*03f9172cSAndroid Build Coastguard Worker 	res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
6192*03f9172cSAndroid Build Coastguard Worker 	if (os_snprintf_error(sizeof(levelstr), res))
6193*03f9172cSAndroid Build Coastguard Worker 		return;
6194*03f9172cSAndroid Build Coastguard Worker 	idx = 0;
6195*03f9172cSAndroid Build Coastguard Worker 	if (ifname) {
6196*03f9172cSAndroid Build Coastguard Worker 		io[idx].iov_base = "IFNAME=";
6197*03f9172cSAndroid Build Coastguard Worker 		io[idx].iov_len = 7;
6198*03f9172cSAndroid Build Coastguard Worker 		idx++;
6199*03f9172cSAndroid Build Coastguard Worker 		io[idx].iov_base = (char *) ifname;
6200*03f9172cSAndroid Build Coastguard Worker 		io[idx].iov_len = os_strlen(ifname);
6201*03f9172cSAndroid Build Coastguard Worker 		idx++;
6202*03f9172cSAndroid Build Coastguard Worker 		io[idx].iov_base = " ";
6203*03f9172cSAndroid Build Coastguard Worker 		io[idx].iov_len = 1;
6204*03f9172cSAndroid Build Coastguard Worker 		idx++;
6205*03f9172cSAndroid Build Coastguard Worker 	}
6206*03f9172cSAndroid Build Coastguard Worker 	io[idx].iov_base = levelstr;
6207*03f9172cSAndroid Build Coastguard Worker 	io[idx].iov_len = os_strlen(levelstr);
6208*03f9172cSAndroid Build Coastguard Worker 	idx++;
6209*03f9172cSAndroid Build Coastguard Worker 	io[idx].iov_base = (char *) buf;
6210*03f9172cSAndroid Build Coastguard Worker 	io[idx].iov_len = len;
6211*03f9172cSAndroid Build Coastguard Worker 	idx++;
6212*03f9172cSAndroid Build Coastguard Worker 	os_memset(&msg, 0, sizeof(msg));
6213*03f9172cSAndroid Build Coastguard Worker 	msg.msg_iov = io;
6214*03f9172cSAndroid Build Coastguard Worker 	msg.msg_iovlen = idx;
6215*03f9172cSAndroid Build Coastguard Worker 
6216*03f9172cSAndroid Build Coastguard Worker 	idx = 0;
6217*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
6218*03f9172cSAndroid Build Coastguard Worker 		if ((level >= dst->debug_level) &&
6219*03f9172cSAndroid Build Coastguard Worker 		     hostapd_ctrl_check_event_enabled(dst, buf)) {
6220*03f9172cSAndroid Build Coastguard Worker 			sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
6221*03f9172cSAndroid Build Coastguard Worker 				       &dst->addr, dst->addrlen);
6222*03f9172cSAndroid Build Coastguard Worker 			msg.msg_name = &dst->addr;
6223*03f9172cSAndroid Build Coastguard Worker 			msg.msg_namelen = dst->addrlen;
6224*03f9172cSAndroid Build Coastguard Worker 			if (sendmsg(sock, &msg, 0) < 0) {
6225*03f9172cSAndroid Build Coastguard Worker 				int _errno = errno;
6226*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
6227*03f9172cSAndroid Build Coastguard Worker 					   "%d - %s",
6228*03f9172cSAndroid Build Coastguard Worker 					   idx, errno, strerror(errno));
6229*03f9172cSAndroid Build Coastguard Worker 				dst->errors++;
6230*03f9172cSAndroid Build Coastguard Worker 				if (dst->errors > 10 || _errno == ENOENT) {
6231*03f9172cSAndroid Build Coastguard Worker 					ctrl_iface_detach(ctrl_dst,
6232*03f9172cSAndroid Build Coastguard Worker 							  &dst->addr,
6233*03f9172cSAndroid Build Coastguard Worker 							  dst->addrlen);
6234*03f9172cSAndroid Build Coastguard Worker 				}
6235*03f9172cSAndroid Build Coastguard Worker 			} else
6236*03f9172cSAndroid Build Coastguard Worker 				dst->errors = 0;
6237*03f9172cSAndroid Build Coastguard Worker 		}
6238*03f9172cSAndroid Build Coastguard Worker 		idx++;
6239*03f9172cSAndroid Build Coastguard Worker 	}
6240*03f9172cSAndroid Build Coastguard Worker }
6241*03f9172cSAndroid Build Coastguard Worker 
6242*03f9172cSAndroid Build Coastguard Worker 
hostapd_ctrl_iface_send(struct hostapd_data * hapd,int level,enum wpa_msg_type type,const char * buf,size_t len)6243*03f9172cSAndroid Build Coastguard Worker static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
6244*03f9172cSAndroid Build Coastguard Worker 				    enum wpa_msg_type type,
6245*03f9172cSAndroid Build Coastguard Worker 				    const char *buf, size_t len)
6246*03f9172cSAndroid Build Coastguard Worker {
6247*03f9172cSAndroid Build Coastguard Worker 	if (type != WPA_MSG_NO_GLOBAL) {
6248*03f9172cSAndroid Build Coastguard Worker 		hostapd_ctrl_iface_send_internal(
6249*03f9172cSAndroid Build Coastguard Worker 			hapd->iface->interfaces->global_ctrl_sock,
6250*03f9172cSAndroid Build Coastguard Worker 			&hapd->iface->interfaces->global_ctrl_dst,
6251*03f9172cSAndroid Build Coastguard Worker 			type != WPA_MSG_PER_INTERFACE ?
6252*03f9172cSAndroid Build Coastguard Worker 			NULL : hapd->conf->iface,
6253*03f9172cSAndroid Build Coastguard Worker 			level, buf, len);
6254*03f9172cSAndroid Build Coastguard Worker 	}
6255*03f9172cSAndroid Build Coastguard Worker 
6256*03f9172cSAndroid Build Coastguard Worker 	if (type != WPA_MSG_ONLY_GLOBAL) {
6257*03f9172cSAndroid Build Coastguard Worker 		hostapd_ctrl_iface_send_internal(
6258*03f9172cSAndroid Build Coastguard Worker 			hapd->ctrl_sock, &hapd->ctrl_dst,
6259*03f9172cSAndroid Build Coastguard Worker 			NULL, level, buf, len);
6260*03f9172cSAndroid Build Coastguard Worker 	}
6261*03f9172cSAndroid Build Coastguard Worker }
6262*03f9172cSAndroid Build Coastguard Worker 
6263*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NATIVE_WINDOWS */
6264