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