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