xref: /freebsd/contrib/wpa/hostapd/ctrl_iface.c (revision 2f513db7)
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], 0, 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 static int
1492 hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd,
1493 					      struct sta_info *sta, void *ctx)
1494 {
1495 	struct hostapd_wpa_psk *psk;
1496 	const u8 *pmk;
1497 	int pmk_len;
1498 	int pmk_match;
1499 	int sta_match;
1500 	int bss_match;
1501 	int reason;
1502 
1503 	pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
1504 
1505 	for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) {
1506 		pmk_match = PMK_LEN == pmk_len &&
1507 			os_memcmp(psk->psk, pmk, pmk_len) == 0;
1508 		sta_match = psk->group == 0 &&
1509 			os_memcmp(sta->addr, psk->addr, ETH_ALEN) == 0;
1510 		bss_match = psk->group == 1;
1511 
1512 		if (pmk_match && (sta_match || bss_match))
1513 			return 0;
1514 	}
1515 
1516 	wpa_printf(MSG_INFO, "STA " MACSTR
1517 		   " PSK/passphrase no longer valid - disconnect",
1518 		   MAC2STR(sta->addr));
1519 	reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1520 	hostapd_drv_sta_deauth(hapd, sta->addr, reason);
1521 	ap_sta_deauthenticate(hapd, sta, reason);
1522 
1523 	return 0;
1524 }
1525 
1526 
1527 static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd)
1528 {
1529 	struct hostapd_bss_config *conf = hapd->conf;
1530 	int err;
1531 
1532 	hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
1533 
1534 	err = hostapd_setup_wpa_psk(conf);
1535 	if (err < 0) {
1536 		wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d",
1537 			   err);
1538 		return -1;
1539 	}
1540 
1541 	ap_for_each_sta(hapd, hostapd_ctrl_iface_kick_mismatch_psk_sta_iter,
1542 			NULL);
1543 
1544 	return 0;
1545 }
1546 
1547 
1548 #ifdef CONFIG_TESTING_OPTIONS
1549 
1550 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1551 {
1552 	union wpa_event_data data;
1553 	char *pos, *param;
1554 	enum wpa_event_type event;
1555 
1556 	wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1557 
1558 	os_memset(&data, 0, sizeof(data));
1559 
1560 	param = os_strchr(cmd, ' ');
1561 	if (param == NULL)
1562 		return -1;
1563 	*param++ = '\0';
1564 
1565 	if (os_strcmp(cmd, "DETECTED") == 0)
1566 		event = EVENT_DFS_RADAR_DETECTED;
1567 	else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1568 		event = EVENT_DFS_CAC_FINISHED;
1569 	else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1570 		event = EVENT_DFS_CAC_ABORTED;
1571 	else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1572 		event = EVENT_DFS_NOP_FINISHED;
1573 	else {
1574 		wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1575 			   cmd);
1576 		return -1;
1577 	}
1578 
1579 	pos = os_strstr(param, "freq=");
1580 	if (pos)
1581 		data.dfs_event.freq = atoi(pos + 5);
1582 
1583 	pos = os_strstr(param, "ht_enabled=1");
1584 	if (pos)
1585 		data.dfs_event.ht_enabled = 1;
1586 
1587 	pos = os_strstr(param, "chan_offset=");
1588 	if (pos)
1589 		data.dfs_event.chan_offset = atoi(pos + 12);
1590 
1591 	pos = os_strstr(param, "chan_width=");
1592 	if (pos)
1593 		data.dfs_event.chan_width = atoi(pos + 11);
1594 
1595 	pos = os_strstr(param, "cf1=");
1596 	if (pos)
1597 		data.dfs_event.cf1 = atoi(pos + 4);
1598 
1599 	pos = os_strstr(param, "cf2=");
1600 	if (pos)
1601 		data.dfs_event.cf2 = atoi(pos + 4);
1602 
1603 	wpa_supplicant_event(hapd, event, &data);
1604 
1605 	return 0;
1606 }
1607 
1608 
1609 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1610 {
1611 	size_t len;
1612 	u8 *buf;
1613 	int res;
1614 
1615 	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1616 
1617 	len = os_strlen(cmd);
1618 	if (len & 1)
1619 		return -1;
1620 	len /= 2;
1621 
1622 	buf = os_malloc(len);
1623 	if (buf == NULL)
1624 		return -1;
1625 
1626 	if (hexstr2bin(cmd, buf, len) < 0) {
1627 		os_free(buf);
1628 		return -1;
1629 	}
1630 
1631 	res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1632 	os_free(buf);
1633 	return res;
1634 }
1635 
1636 
1637 static int hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data *hapd,
1638 						     char *cmd)
1639 {
1640 	char *pos, *param;
1641 	size_t len;
1642 	u8 *buf;
1643 	int stype = 0, ok = 0;
1644 	union wpa_event_data event;
1645 
1646 	if (!hapd->ext_mgmt_frame_handling)
1647 		return -1;
1648 
1649 	/* stype=<val> ok=<0/1> buf=<frame hexdump> */
1650 
1651 	wpa_printf(MSG_DEBUG, "External MGMT TX status process: %s", cmd);
1652 
1653 	pos = cmd;
1654 	param = os_strstr(pos, "stype=");
1655 	if (param) {
1656 		param += 6;
1657 		stype = atoi(param);
1658 	}
1659 
1660 	param = os_strstr(pos, " ok=");
1661 	if (param) {
1662 		param += 4;
1663 		ok = atoi(param);
1664 	}
1665 
1666 	param = os_strstr(pos, " buf=");
1667 	if (!param)
1668 		return -1;
1669 	param += 5;
1670 
1671 	len = os_strlen(param);
1672 	if (len & 1)
1673 		return -1;
1674 	len /= 2;
1675 
1676 	buf = os_malloc(len);
1677 	if (!buf || hexstr2bin(param, buf, len) < 0) {
1678 		os_free(buf);
1679 		return -1;
1680 	}
1681 
1682 	os_memset(&event, 0, sizeof(event));
1683 	event.tx_status.type = WLAN_FC_TYPE_MGMT;
1684 	event.tx_status.data = buf;
1685 	event.tx_status.data_len = len;
1686 	event.tx_status.stype = stype;
1687 	event.tx_status.ack = ok;
1688 	hapd->ext_mgmt_frame_handling = 0;
1689 	wpa_supplicant_event(hapd, EVENT_TX_STATUS, &event);
1690 	hapd->ext_mgmt_frame_handling = 1;
1691 
1692 	os_free(buf);
1693 
1694 	return 0;
1695 }
1696 
1697 
1698 static int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd,
1699 					      char *cmd)
1700 {
1701 	char *pos, *param;
1702 	size_t len;
1703 	u8 *buf;
1704 	int freq = 0, datarate = 0, ssi_signal = 0;
1705 	union wpa_event_data event;
1706 
1707 	if (!hapd->ext_mgmt_frame_handling)
1708 		return -1;
1709 
1710 	/* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
1711 
1712 	wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
1713 
1714 	pos = cmd;
1715 	param = os_strstr(pos, "freq=");
1716 	if (param) {
1717 		param += 5;
1718 		freq = atoi(param);
1719 	}
1720 
1721 	param = os_strstr(pos, " datarate=");
1722 	if (param) {
1723 		param += 10;
1724 		datarate = atoi(param);
1725 	}
1726 
1727 	param = os_strstr(pos, " ssi_signal=");
1728 	if (param) {
1729 		param += 12;
1730 		ssi_signal = atoi(param);
1731 	}
1732 
1733 	param = os_strstr(pos, " frame=");
1734 	if (param == NULL)
1735 		return -1;
1736 	param += 7;
1737 
1738 	len = os_strlen(param);
1739 	if (len & 1)
1740 		return -1;
1741 	len /= 2;
1742 
1743 	buf = os_malloc(len);
1744 	if (buf == NULL)
1745 		return -1;
1746 
1747 	if (hexstr2bin(param, buf, len) < 0) {
1748 		os_free(buf);
1749 		return -1;
1750 	}
1751 
1752 	os_memset(&event, 0, sizeof(event));
1753 	event.rx_mgmt.freq = freq;
1754 	event.rx_mgmt.frame = buf;
1755 	event.rx_mgmt.frame_len = len;
1756 	event.rx_mgmt.ssi_signal = ssi_signal;
1757 	event.rx_mgmt.datarate = datarate;
1758 	hapd->ext_mgmt_frame_handling = 0;
1759 	wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event);
1760 	hapd->ext_mgmt_frame_handling = 1;
1761 
1762 	os_free(buf);
1763 
1764 	return 0;
1765 }
1766 
1767 
1768 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1769 {
1770 	char *pos;
1771 	u8 src[ETH_ALEN], *buf;
1772 	int used;
1773 	size_t len;
1774 
1775 	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1776 
1777 	pos = cmd;
1778 	used = hwaddr_aton2(pos, src);
1779 	if (used < 0)
1780 		return -1;
1781 	pos += used;
1782 	while (*pos == ' ')
1783 		pos++;
1784 
1785 	len = os_strlen(pos);
1786 	if (len & 1)
1787 		return -1;
1788 	len /= 2;
1789 
1790 	buf = os_malloc(len);
1791 	if (buf == NULL)
1792 		return -1;
1793 
1794 	if (hexstr2bin(pos, buf, len) < 0) {
1795 		os_free(buf);
1796 		return -1;
1797 	}
1798 
1799 	ieee802_1x_receive(hapd, src, buf, len);
1800 	os_free(buf);
1801 
1802 	return 0;
1803 }
1804 
1805 
1806 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1807 {
1808 	size_t i;
1809 	u32 sum = 0;
1810 	const u16 *pos = buf;
1811 
1812 	for (i = 0; i < len / 2; i++)
1813 		sum += *pos++;
1814 
1815 	while (sum >> 16)
1816 		sum = (sum & 0xffff) + (sum >> 16);
1817 
1818 	return sum ^ 0xffff;
1819 }
1820 
1821 
1822 #define HWSIM_PACKETLEN 1500
1823 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1824 
1825 static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1826 				 size_t len)
1827 {
1828 	struct hostapd_data *hapd = ctx;
1829 	const struct ether_header *eth;
1830 	struct iphdr ip;
1831 	const u8 *pos;
1832 	unsigned int i;
1833 	char extra[30];
1834 
1835 	if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
1836 		wpa_printf(MSG_DEBUG,
1837 			   "test data: RX - ignore unexpected length %d",
1838 			   (int) len);
1839 		return;
1840 	}
1841 
1842 	eth = (const struct ether_header *) buf;
1843 	os_memcpy(&ip, eth + 1, sizeof(ip));
1844 	pos = &buf[sizeof(*eth) + sizeof(ip)];
1845 
1846 	if (ip.ihl != 5 || ip.version != 4 ||
1847 	    ntohs(ip.tot_len) > HWSIM_IP_LEN) {
1848 		wpa_printf(MSG_DEBUG,
1849 			   "test data: RX - ignore unexpect IP header");
1850 		return;
1851 	}
1852 
1853 	for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
1854 		if (*pos != (u8) i) {
1855 			wpa_printf(MSG_DEBUG,
1856 				   "test data: RX - ignore mismatching payload");
1857 			return;
1858 		}
1859 		pos++;
1860 	}
1861 
1862 	extra[0] = '\0';
1863 	if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
1864 		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
1865 	wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
1866 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
1867 }
1868 
1869 
1870 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1871 					       char *cmd)
1872 {
1873 	int enabled = atoi(cmd);
1874 	char *pos;
1875 	const char *ifname;
1876 
1877 	if (!enabled) {
1878 		if (hapd->l2_test) {
1879 			l2_packet_deinit(hapd->l2_test);
1880 			hapd->l2_test = NULL;
1881 			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1882 				"test data: Disabled");
1883 		}
1884 		return 0;
1885 	}
1886 
1887 	if (hapd->l2_test)
1888 		return 0;
1889 
1890 	pos = os_strstr(cmd, " ifname=");
1891 	if (pos)
1892 		ifname = pos + 8;
1893 	else
1894 		ifname = hapd->conf->iface;
1895 
1896 	hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
1897 					ETHERTYPE_IP, hostapd_data_test_rx,
1898 					hapd, 1);
1899 	if (hapd->l2_test == NULL)
1900 		return -1;
1901 
1902 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1903 
1904 	return 0;
1905 }
1906 
1907 
1908 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1909 {
1910 	u8 dst[ETH_ALEN], src[ETH_ALEN];
1911 	char *pos, *pos2;
1912 	int used;
1913 	long int val;
1914 	u8 tos;
1915 	u8 buf[2 + HWSIM_PACKETLEN];
1916 	struct ether_header *eth;
1917 	struct iphdr *ip;
1918 	u8 *dpos;
1919 	unsigned int i;
1920 	size_t send_len = HWSIM_IP_LEN;
1921 
1922 	if (hapd->l2_test == NULL)
1923 		return -1;
1924 
1925 	/* format: <dst> <src> <tos> [len=<length>] */
1926 
1927 	pos = cmd;
1928 	used = hwaddr_aton2(pos, dst);
1929 	if (used < 0)
1930 		return -1;
1931 	pos += used;
1932 	while (*pos == ' ')
1933 		pos++;
1934 	used = hwaddr_aton2(pos, src);
1935 	if (used < 0)
1936 		return -1;
1937 	pos += used;
1938 
1939 	val = strtol(pos, &pos2, 0);
1940 	if (val < 0 || val > 0xff)
1941 		return -1;
1942 	tos = val;
1943 
1944 	pos = os_strstr(pos2, " len=");
1945 	if (pos) {
1946 		i = atoi(pos + 5);
1947 		if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
1948 			return -1;
1949 		send_len = i;
1950 	}
1951 
1952 	eth = (struct ether_header *) &buf[2];
1953 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
1954 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
1955 	eth->ether_type = htons(ETHERTYPE_IP);
1956 	ip = (struct iphdr *) (eth + 1);
1957 	os_memset(ip, 0, sizeof(*ip));
1958 	ip->ihl = 5;
1959 	ip->version = 4;
1960 	ip->ttl = 64;
1961 	ip->tos = tos;
1962 	ip->tot_len = htons(send_len);
1963 	ip->protocol = 1;
1964 	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
1965 	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
1966 	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
1967 	dpos = (u8 *) (ip + 1);
1968 	for (i = 0; i < send_len - sizeof(*ip); i++)
1969 		*dpos++ = i;
1970 
1971 	if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
1972 			   sizeof(struct ether_header) + send_len) < 0)
1973 		return -1;
1974 
1975 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
1976 		" src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
1977 
1978 	return 0;
1979 }
1980 
1981 
1982 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
1983 					      char *cmd)
1984 {
1985 	u8 *buf;
1986 	struct ether_header *eth;
1987 	struct l2_packet_data *l2 = NULL;
1988 	size_t len;
1989 	u16 ethertype;
1990 	int res = -1;
1991 	const char *ifname = hapd->conf->iface;
1992 
1993 	if (os_strncmp(cmd, "ifname=", 7) == 0) {
1994 		cmd += 7;
1995 		ifname = cmd;
1996 		cmd = os_strchr(cmd, ' ');
1997 		if (cmd == NULL)
1998 			return -1;
1999 		*cmd++ = '\0';
2000 	}
2001 
2002 	len = os_strlen(cmd);
2003 	if (len & 1 || len < ETH_HLEN * 2)
2004 		return -1;
2005 	len /= 2;
2006 
2007 	buf = os_malloc(len);
2008 	if (buf == NULL)
2009 		return -1;
2010 
2011 	if (hexstr2bin(cmd, buf, len) < 0)
2012 		goto done;
2013 
2014 	eth = (struct ether_header *) buf;
2015 	ethertype = ntohs(eth->ether_type);
2016 
2017 	l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
2018 			    hostapd_data_test_rx, hapd, 1);
2019 	if (l2 == NULL)
2020 		goto done;
2021 
2022 	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
2023 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
2024 done:
2025 	if (l2)
2026 		l2_packet_deinit(l2);
2027 	os_free(buf);
2028 
2029 	return res < 0 ? -1 : 0;
2030 }
2031 
2032 
2033 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
2034 {
2035 #ifdef WPA_TRACE_BFD
2036 	char *pos;
2037 
2038 	wpa_trace_fail_after = atoi(cmd);
2039 	pos = os_strchr(cmd, ':');
2040 	if (pos) {
2041 		pos++;
2042 		os_strlcpy(wpa_trace_fail_func, pos,
2043 			   sizeof(wpa_trace_fail_func));
2044 	} else {
2045 		wpa_trace_fail_after = 0;
2046 	}
2047 
2048 	return 0;
2049 #else /* WPA_TRACE_BFD */
2050 	return -1;
2051 #endif /* WPA_TRACE_BFD */
2052 }
2053 
2054 
2055 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
2056 				       char *buf, size_t buflen)
2057 {
2058 #ifdef WPA_TRACE_BFD
2059 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
2060 			   wpa_trace_fail_func);
2061 #else /* WPA_TRACE_BFD */
2062 	return -1;
2063 #endif /* WPA_TRACE_BFD */
2064 }
2065 
2066 
2067 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
2068 {
2069 #ifdef WPA_TRACE_BFD
2070 	char *pos;
2071 
2072 	wpa_trace_test_fail_after = atoi(cmd);
2073 	pos = os_strchr(cmd, ':');
2074 	if (pos) {
2075 		pos++;
2076 		os_strlcpy(wpa_trace_test_fail_func, pos,
2077 			   sizeof(wpa_trace_test_fail_func));
2078 	} else {
2079 		wpa_trace_test_fail_after = 0;
2080 	}
2081 
2082 	return 0;
2083 #else /* WPA_TRACE_BFD */
2084 	return -1;
2085 #endif /* WPA_TRACE_BFD */
2086 }
2087 
2088 
2089 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
2090 				 char *buf, size_t buflen)
2091 {
2092 #ifdef WPA_TRACE_BFD
2093 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
2094 			   wpa_trace_test_fail_func);
2095 #else /* WPA_TRACE_BFD */
2096 	return -1;
2097 #endif /* WPA_TRACE_BFD */
2098 }
2099 
2100 
2101 static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
2102 {
2103 	struct sta_info *sta;
2104 	u8 addr[ETH_ALEN];
2105 	u8 zero[WPA_TK_MAX_LEN];
2106 
2107 	os_memset(zero, 0, sizeof(zero));
2108 
2109 	if (hwaddr_aton(cmd, addr))
2110 		return -1;
2111 
2112 #ifdef CONFIG_IEEE80211W
2113 	if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
2114 		if (hapd->last_igtk_alg == WPA_ALG_NONE)
2115 			return -1;
2116 
2117 		wpa_printf(MSG_INFO, "TESTING: Reset IPN for IGTK");
2118 
2119 		/* First, use a zero key to avoid any possible duplicate key
2120 		 * avoidance in the driver. */
2121 		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2122 					hapd->last_igtk_alg,
2123 					broadcast_ether_addr,
2124 					hapd->last_igtk_key_idx, 1, NULL, 0,
2125 					zero, hapd->last_igtk_len) < 0)
2126 			return -1;
2127 
2128 		/* Set the previously configured key to reset its TSC */
2129 		return hostapd_drv_set_key(hapd->conf->iface, hapd,
2130 					   hapd->last_igtk_alg,
2131 					   broadcast_ether_addr,
2132 					   hapd->last_igtk_key_idx, 1, NULL, 0,
2133 					   hapd->last_igtk,
2134 					   hapd->last_igtk_len);
2135 	}
2136 #endif /* CONFIG_IEEE80211W */
2137 
2138 	if (is_broadcast_ether_addr(addr)) {
2139 		if (hapd->last_gtk_alg == WPA_ALG_NONE)
2140 			return -1;
2141 
2142 		wpa_printf(MSG_INFO, "TESTING: Reset PN for GTK");
2143 
2144 		/* First, use a zero key to avoid any possible duplicate key
2145 		 * avoidance in the driver. */
2146 		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2147 					hapd->last_gtk_alg,
2148 					broadcast_ether_addr,
2149 					hapd->last_gtk_key_idx, 1, NULL, 0,
2150 					zero, hapd->last_gtk_len) < 0)
2151 			return -1;
2152 
2153 		/* Set the previously configured key to reset its TSC */
2154 		return hostapd_drv_set_key(hapd->conf->iface, hapd,
2155 					   hapd->last_gtk_alg,
2156 					   broadcast_ether_addr,
2157 					   hapd->last_gtk_key_idx, 1, NULL, 0,
2158 					   hapd->last_gtk, hapd->last_gtk_len);
2159 	}
2160 
2161 	sta = ap_get_sta(hapd, addr);
2162 	if (!sta)
2163 		return -1;
2164 
2165 	if (sta->last_tk_alg == WPA_ALG_NONE)
2166 		return -1;
2167 
2168 	wpa_printf(MSG_INFO, "TESTING: Reset PN for " MACSTR,
2169 		   MAC2STR(sta->addr));
2170 
2171 	/* First, use a zero key to avoid any possible duplicate key avoidance
2172 	 * in the driver. */
2173 	if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2174 				sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
2175 				zero, sta->last_tk_len) < 0)
2176 		return -1;
2177 
2178 	/* Set the previously configured key to reset its TSC/RSC */
2179 	return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2180 				   sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
2181 				   sta->last_tk, sta->last_tk_len);
2182 }
2183 
2184 
2185 static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
2186 {
2187 	u8 addr[ETH_ALEN];
2188 	const char *pos = cmd;
2189 	enum wpa_alg alg;
2190 	int idx, set_tx;
2191 	u8 seq[6], key[WPA_TK_MAX_LEN];
2192 	size_t key_len;
2193 
2194 	/* parameters: alg addr idx set_tx seq key */
2195 
2196 	alg = atoi(pos);
2197 	pos = os_strchr(pos, ' ');
2198 	if (!pos)
2199 		return -1;
2200 	pos++;
2201 	if (hwaddr_aton(pos, addr))
2202 		return -1;
2203 	pos += 17;
2204 	if (*pos != ' ')
2205 		return -1;
2206 	pos++;
2207 	idx = atoi(pos);
2208 	pos = os_strchr(pos, ' ');
2209 	if (!pos)
2210 		return -1;
2211 	pos++;
2212 	set_tx = atoi(pos);
2213 	pos = os_strchr(pos, ' ');
2214 	if (!pos)
2215 		return -1;
2216 	pos++;
2217 	if (hexstr2bin(pos, seq, sizeof(seq)) < 0)
2218 		return -1;
2219 	pos += 2 * 6;
2220 	if (*pos != ' ')
2221 		return -1;
2222 	pos++;
2223 	key_len = os_strlen(pos) / 2;
2224 	if (hexstr2bin(pos, key, key_len) < 0)
2225 		return -1;
2226 
2227 	wpa_printf(MSG_INFO, "TESTING: Set key");
2228 	return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx,
2229 				   set_tx, seq, 6, key, key_len);
2230 }
2231 
2232 
2233 static void restore_tk(void *ctx1, void *ctx2)
2234 {
2235 	struct hostapd_data *hapd = ctx1;
2236 	struct sta_info *sta = ctx2;
2237 
2238 	wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR,
2239 		   MAC2STR(sta->addr));
2240 	/* This does not really restore the TSC properly, so this will result
2241 	 * in replay protection issues for now since there is no clean way of
2242 	 * preventing encryption of a single EAPOL frame. */
2243 	hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2244 			    sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
2245 			    sta->last_tk, sta->last_tk_len);
2246 }
2247 
2248 
2249 static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
2250 {
2251 	struct sta_info *sta;
2252 	u8 addr[ETH_ALEN];
2253 	int plain = os_strstr(cmd, "plaintext") != NULL;
2254 
2255 	if (hwaddr_aton(cmd, addr))
2256 		return -1;
2257 
2258 	sta = ap_get_sta(hapd, addr);
2259 	if (!sta || !sta->wpa_sm)
2260 		return -1;
2261 
2262 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2263 		plain = 0; /* no need for special processing */
2264 	if (plain) {
2265 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2266 			   MAC2STR(sta->addr));
2267 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2268 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
2269 				    NULL, 0);
2270 	}
2271 
2272 	wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
2273 	return wpa_auth_resend_m1(sta->wpa_sm,
2274 				  os_strstr(cmd, "change-anonce") != NULL,
2275 				  plain ? restore_tk : NULL, hapd, sta);
2276 }
2277 
2278 
2279 static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
2280 {
2281 	struct sta_info *sta;
2282 	u8 addr[ETH_ALEN];
2283 	int plain = os_strstr(cmd, "plaintext") != NULL;
2284 
2285 	if (hwaddr_aton(cmd, addr))
2286 		return -1;
2287 
2288 	sta = ap_get_sta(hapd, addr);
2289 	if (!sta || !sta->wpa_sm)
2290 		return -1;
2291 
2292 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2293 		plain = 0; /* no need for special processing */
2294 	if (plain) {
2295 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2296 			   MAC2STR(sta->addr));
2297 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2298 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
2299 				    NULL, 0);
2300 	}
2301 
2302 	wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
2303 	return wpa_auth_resend_m3(sta->wpa_sm,
2304 				  plain ? restore_tk : NULL, hapd, sta);
2305 }
2306 
2307 
2308 static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
2309 					const char *cmd)
2310 {
2311 	struct sta_info *sta;
2312 	u8 addr[ETH_ALEN];
2313 	int plain = os_strstr(cmd, "plaintext") != NULL;
2314 
2315 	if (hwaddr_aton(cmd, addr))
2316 		return -1;
2317 
2318 	sta = ap_get_sta(hapd, addr);
2319 	if (!sta || !sta->wpa_sm)
2320 		return -1;
2321 
2322 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2323 		plain = 0; /* no need for special processing */
2324 	if (plain) {
2325 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2326 			   MAC2STR(sta->addr));
2327 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2328 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
2329 				    NULL, 0);
2330 	}
2331 
2332 	wpa_printf(MSG_INFO,
2333 		   "TESTING: Send group M1 for the same GTK and zero RSC to "
2334 		   MACSTR, MAC2STR(sta->addr));
2335 	return wpa_auth_resend_group_m1(sta->wpa_sm,
2336 					plain ? restore_tk : NULL, hapd, sta);
2337 }
2338 
2339 #endif /* CONFIG_TESTING_OPTIONS */
2340 
2341 
2342 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
2343 					  char *pos)
2344 {
2345 #ifdef NEED_AP_MLME
2346 	struct csa_settings settings;
2347 	int ret;
2348 	unsigned int i;
2349 
2350 	ret = hostapd_parse_csa_settings(pos, &settings);
2351 	if (ret)
2352 		return ret;
2353 
2354 	for (i = 0; i < iface->num_bss; i++) {
2355 
2356 		/* Save CHAN_SWITCH VHT config */
2357 		hostapd_chan_switch_vht_config(
2358 			iface->bss[i], settings.freq_params.vht_enabled);
2359 
2360 		ret = hostapd_switch_channel(iface->bss[i], &settings);
2361 		if (ret) {
2362 			/* FIX: What do we do if CSA fails in the middle of
2363 			 * submitting multi-BSS CSA requests? */
2364 			return ret;
2365 		}
2366 	}
2367 
2368 	return 0;
2369 #else /* NEED_AP_MLME */
2370 	return -1;
2371 #endif /* NEED_AP_MLME */
2372 }
2373 
2374 
2375 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
2376 				  int reply_size, const char *param)
2377 {
2378 #ifdef RADIUS_SERVER
2379 	if (os_strcmp(param, "radius_server") == 0) {
2380 		return radius_server_get_mib(hapd->radius_srv, reply,
2381 					     reply_size);
2382 	}
2383 #endif /* RADIUS_SERVER */
2384 	return -1;
2385 }
2386 
2387 
2388 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
2389 				     char *buf, size_t buflen)
2390 {
2391 	int ret;
2392 	char *pos;
2393 	u8 *data = NULL;
2394 	unsigned int vendor_id, subcmd;
2395 	struct wpabuf *reply;
2396 	size_t data_len = 0;
2397 
2398 	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
2399 	vendor_id = strtoul(cmd, &pos, 16);
2400 	if (!isblank((unsigned char) *pos))
2401 		return -EINVAL;
2402 
2403 	subcmd = strtoul(pos, &pos, 10);
2404 
2405 	if (*pos != '\0') {
2406 		if (!isblank((unsigned char) *pos++))
2407 			return -EINVAL;
2408 		data_len = os_strlen(pos);
2409 	}
2410 
2411 	if (data_len) {
2412 		data_len /= 2;
2413 		data = os_malloc(data_len);
2414 		if (!data)
2415 			return -ENOBUFS;
2416 
2417 		if (hexstr2bin(pos, data, data_len)) {
2418 			wpa_printf(MSG_DEBUG,
2419 				   "Vendor command: wrong parameter format");
2420 			os_free(data);
2421 			return -EINVAL;
2422 		}
2423 	}
2424 
2425 	reply = wpabuf_alloc((buflen - 1) / 2);
2426 	if (!reply) {
2427 		os_free(data);
2428 		return -ENOBUFS;
2429 	}
2430 
2431 	ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
2432 				     reply);
2433 
2434 	if (ret == 0)
2435 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
2436 				       wpabuf_len(reply));
2437 
2438 	wpabuf_free(reply);
2439 	os_free(data);
2440 
2441 	return ret;
2442 }
2443 
2444 
2445 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
2446 					   const char *cmd)
2447 {
2448 	u8 addr[ETH_ALEN];
2449 	struct sta_info *sta;
2450 
2451 	if (hwaddr_aton(cmd, addr))
2452 		return -1;
2453 
2454 	sta = ap_get_sta(hapd, addr);
2455 	if (!sta || !sta->eapol_sm)
2456 		return -1;
2457 
2458 	eapol_auth_reauthenticate(sta->eapol_sm);
2459 	return 0;
2460 }
2461 
2462 
2463 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
2464 {
2465 	u8 addr[ETH_ALEN];
2466 	struct sta_info *sta;
2467 	char *pos = cmd, *param;
2468 
2469 	if (hwaddr_aton(pos, addr) || pos[17] != ' ')
2470 		return -1;
2471 	pos += 18;
2472 	param = pos;
2473 	pos = os_strchr(pos, ' ');
2474 	if (!pos)
2475 		return -1;
2476 	*pos++ = '\0';
2477 
2478 	sta = ap_get_sta(hapd, addr);
2479 	if (!sta || !sta->eapol_sm)
2480 		return -1;
2481 
2482 	return eapol_auth_set_conf(sta->eapol_sm, param, pos);
2483 }
2484 
2485 
2486 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
2487 					char *buf, size_t buflen)
2488 {
2489 	char *pos, *end, *stamp;
2490 	int ret;
2491 
2492 	/* cmd: "LOG_LEVEL [<level>]" */
2493 	if (*cmd == '\0') {
2494 		pos = buf;
2495 		end = buf + buflen;
2496 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2497 				  "Timestamp: %d\n",
2498 				  debug_level_str(wpa_debug_level),
2499 				  wpa_debug_timestamp);
2500 		if (os_snprintf_error(end - pos, ret))
2501 			ret = 0;
2502 
2503 		return ret;
2504 	}
2505 
2506 	while (*cmd == ' ')
2507 		cmd++;
2508 
2509 	stamp = os_strchr(cmd, ' ');
2510 	if (stamp) {
2511 		*stamp++ = '\0';
2512 		while (*stamp == ' ') {
2513 			stamp++;
2514 		}
2515 	}
2516 
2517 	if (os_strlen(cmd)) {
2518 		int level = str_to_debug_level(cmd);
2519 		if (level < 0)
2520 			return -1;
2521 		wpa_debug_level = level;
2522 	}
2523 
2524 	if (stamp && os_strlen(stamp))
2525 		wpa_debug_timestamp = atoi(stamp);
2526 
2527 	os_memcpy(buf, "OK\n", 3);
2528 	return 3;
2529 }
2530 
2531 
2532 #ifdef NEED_AP_MLME
2533 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
2534 					     char *buf, size_t buflen)
2535 {
2536 	struct hostapd_iface *iface = hapd->iface;
2537 	char *pos, *end;
2538 	struct hostapd_sta_info *info;
2539 	struct os_reltime now;
2540 
2541 	if (!iface->num_sta_seen)
2542 		return 0;
2543 
2544 	sta_track_expire(iface, 0);
2545 
2546 	pos = buf;
2547 	end = buf + buflen;
2548 
2549 	os_get_reltime(&now);
2550 	dl_list_for_each_reverse(info, &iface->sta_seen,
2551 				 struct hostapd_sta_info, list) {
2552 		struct os_reltime age;
2553 		int ret;
2554 
2555 		os_reltime_sub(&now, &info->last_seen, &age);
2556 		ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n",
2557 				  MAC2STR(info->addr), (unsigned int) age.sec,
2558 				  info->ssi_signal);
2559 		if (os_snprintf_error(end - pos, ret))
2560 			break;
2561 		pos += ret;
2562 	}
2563 
2564 	return pos - buf;
2565 }
2566 #endif /* NEED_AP_MLME */
2567 
2568 
2569 static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd,
2570 				      const char *cmd)
2571 {
2572 	u8 addr[ETH_ALEN];
2573 
2574 	if (hwaddr_aton(cmd, addr)) {
2575 		wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address");
2576 		return -1;
2577 	}
2578 
2579 	return hostapd_send_lci_req(hapd, addr);
2580 }
2581 
2582 
2583 static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd)
2584 {
2585 	u8 addr[ETH_ALEN];
2586 	char *token, *context = NULL;
2587 	int random_interval, min_ap;
2588 	u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS];
2589 	unsigned int n_responders;
2590 
2591 	token = str_token(cmd, " ", &context);
2592 	if (!token || hwaddr_aton(token, addr)) {
2593 		wpa_printf(MSG_INFO,
2594 			   "CTRL: REQ_RANGE - Bad destination address");
2595 		return -1;
2596 	}
2597 
2598 	token = str_token(cmd, " ", &context);
2599 	if (!token)
2600 		return -1;
2601 
2602 	random_interval = atoi(token);
2603 	if (random_interval < 0 || random_interval > 0xffff)
2604 		return -1;
2605 
2606 	token = str_token(cmd, " ", &context);
2607 	if (!token)
2608 		return -1;
2609 
2610 	min_ap = atoi(token);
2611 	if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP)
2612 		return -1;
2613 
2614 	n_responders = 0;
2615 	while ((token = str_token(cmd, " ", &context))) {
2616 		if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) {
2617 			wpa_printf(MSG_INFO,
2618 				   "CTRL: REQ_RANGE: Too many responders");
2619 			return -1;
2620 		}
2621 
2622 		if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) {
2623 			wpa_printf(MSG_INFO,
2624 				   "CTRL: REQ_RANGE: Bad responder address");
2625 			return -1;
2626 		}
2627 
2628 		n_responders++;
2629 	}
2630 
2631 	if (!n_responders) {
2632 		wpa_printf(MSG_INFO,
2633 			   "CTRL: REQ_RANGE - No FTM responder address");
2634 		return -1;
2635 	}
2636 
2637 	return hostapd_send_range_req(hapd, addr, random_interval, min_ap,
2638 				      responders, n_responders);
2639 }
2640 
2641 
2642 static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
2643 					 const char *cmd, char *reply,
2644 					 size_t reply_size)
2645 {
2646 	u8 addr[ETH_ALEN];
2647 	const char *pos;
2648 	struct wpabuf *req;
2649 	int ret;
2650 	u8 req_mode = 0;
2651 
2652 	if (hwaddr_aton(cmd, addr))
2653 		return -1;
2654 	pos = os_strchr(cmd, ' ');
2655 	if (!pos)
2656 		return -1;
2657 	pos++;
2658 	if (os_strncmp(pos, "req_mode=", 9) == 0) {
2659 		int val = hex2byte(pos + 9);
2660 
2661 		if (val < 0)
2662 			return -1;
2663 		req_mode = val;
2664 		pos += 11;
2665 		pos = os_strchr(pos, ' ');
2666 		if (!pos)
2667 			return -1;
2668 		pos++;
2669 	}
2670 	req = wpabuf_parse_bin(pos);
2671 	if (!req)
2672 		return -1;
2673 
2674 	ret = hostapd_send_beacon_req(hapd, addr, req_mode, req);
2675 	wpabuf_free(req);
2676 	if (ret >= 0)
2677 		ret = os_snprintf(reply, reply_size, "%d", ret);
2678 	return ret;
2679 }
2680 
2681 
2682 static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
2683 {
2684 	struct wpa_ssid_value ssid;
2685 	u8 bssid[ETH_ALEN];
2686 	struct wpabuf *nr, *lci = NULL, *civic = NULL;
2687 	int stationary = 0;
2688 	char *tmp;
2689 	int ret;
2690 
2691 	if (!(hapd->conf->radio_measurements[0] &
2692 	      WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
2693 		wpa_printf(MSG_ERROR,
2694 			   "CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
2695 		return -1;
2696 	}
2697 
2698 	if (hwaddr_aton(buf, bssid)) {
2699 		wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
2700 		return -1;
2701 	}
2702 
2703 	tmp = os_strstr(buf, "ssid=");
2704 	if (!tmp || ssid_parse(tmp + 5, &ssid)) {
2705 		wpa_printf(MSG_ERROR,
2706 			   "CTRL: SET_NEIGHBOR: Bad or missing SSID");
2707 		return -1;
2708 	}
2709 	buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
2710 	if (!buf)
2711 		return -1;
2712 
2713 	tmp = os_strstr(buf, "nr=");
2714 	if (!tmp) {
2715 		wpa_printf(MSG_ERROR,
2716 			   "CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
2717 		return -1;
2718 	}
2719 
2720 	buf = os_strchr(tmp, ' ');
2721 	if (buf)
2722 		*buf++ = '\0';
2723 
2724 	nr = wpabuf_parse_bin(tmp + 3);
2725 	if (!nr) {
2726 		wpa_printf(MSG_ERROR,
2727 			   "CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
2728 		return -1;
2729 	}
2730 
2731 	if (!buf)
2732 		goto set;
2733 
2734 	tmp = os_strstr(buf, "lci=");
2735 	if (tmp) {
2736 		buf = os_strchr(tmp, ' ');
2737 		if (buf)
2738 			*buf++ = '\0';
2739 		lci = wpabuf_parse_bin(tmp + 4);
2740 		if (!lci) {
2741 			wpa_printf(MSG_ERROR,
2742 				   "CTRL: SET_NEIGHBOR: Bad LCI subelement");
2743 			wpabuf_free(nr);
2744 			return -1;
2745 		}
2746 	}
2747 
2748 	if (!buf)
2749 		goto set;
2750 
2751 	tmp = os_strstr(buf, "civic=");
2752 	if (tmp) {
2753 		buf = os_strchr(tmp, ' ');
2754 		if (buf)
2755 			*buf++ = '\0';
2756 		civic = wpabuf_parse_bin(tmp + 6);
2757 		if (!civic) {
2758 			wpa_printf(MSG_ERROR,
2759 				   "CTRL: SET_NEIGHBOR: Bad civic subelement");
2760 			wpabuf_free(nr);
2761 			wpabuf_free(lci);
2762 			return -1;
2763 		}
2764 	}
2765 
2766 	if (!buf)
2767 		goto set;
2768 
2769 	if (os_strstr(buf, "stat"))
2770 		stationary = 1;
2771 
2772 set:
2773 	ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic,
2774 				   stationary);
2775 
2776 	wpabuf_free(nr);
2777 	wpabuf_free(lci);
2778 	wpabuf_free(civic);
2779 
2780 	return ret;
2781 }
2782 
2783 
2784 static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
2785 					      char *buf)
2786 {
2787 	struct wpa_ssid_value ssid;
2788 	u8 bssid[ETH_ALEN];
2789 	char *tmp;
2790 
2791 	if (hwaddr_aton(buf, bssid)) {
2792 		wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
2793 		return -1;
2794 	}
2795 
2796 	tmp = os_strstr(buf, "ssid=");
2797 	if (!tmp || ssid_parse(tmp + 5, &ssid)) {
2798 		wpa_printf(MSG_ERROR,
2799 			   "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
2800 		return -1;
2801 	}
2802 
2803 	return hostapd_neighbor_remove(hapd, bssid, &ssid);
2804 }
2805 
2806 
2807 static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
2808 				     size_t buflen)
2809 {
2810 	int ret, i;
2811 	char *pos, *end;
2812 
2813 	ret = os_snprintf(buf, buflen, "%016llX:\n",
2814 			  (long long unsigned) iface->drv_flags);
2815 	if (os_snprintf_error(buflen, ret))
2816 		return -1;
2817 
2818 	pos = buf + ret;
2819 	end = buf + buflen;
2820 
2821 	for (i = 0; i < 64; i++) {
2822 		if (iface->drv_flags & (1LLU << i)) {
2823 			ret = os_snprintf(pos, end - pos, "%s\n",
2824 					  driver_flag_to_string(1LLU << i));
2825 			if (os_snprintf_error(end - pos, ret))
2826 				return -1;
2827 			pos += ret;
2828 		}
2829 	}
2830 
2831 	return pos - buf;
2832 }
2833 
2834 
2835 static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num,
2836 					  const char *txtaddr)
2837 {
2838 	u8 addr[ETH_ALEN];
2839 	struct vlan_description vlan_id;
2840 
2841 	if (!(*num))
2842 		return 0;
2843 
2844 	if (hwaddr_aton(txtaddr, addr))
2845 		return -1;
2846 
2847 	if (hostapd_maclist_found(*acl, *num, addr, &vlan_id))
2848 		hostapd_remove_acl_mac(acl, num, addr);
2849 
2850 	return 0;
2851 }
2852 
2853 
2854 static void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl,
2855 					      int *num)
2856 {
2857 	while (*num)
2858 		hostapd_remove_acl_mac(acl, num, (*acl)[0].addr);
2859 }
2860 
2861 
2862 static int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num,
2863 					   char *buf, size_t buflen)
2864 {
2865 	int i = 0, len = 0, ret = 0;
2866 
2867 	if (!acl)
2868 		return 0;
2869 
2870 	while (i < num) {
2871 		ret = os_snprintf(buf + len, buflen - len,
2872 				  MACSTR " VLAN_ID=%d\n",
2873 				  MAC2STR(acl[i].addr),
2874 				  acl[i].vlan_id.untagged);
2875 		if (ret < 0 || (size_t) ret >= buflen - len)
2876 			return len;
2877 		i++;
2878 		len += ret;
2879 	}
2880 	return len;
2881 }
2882 
2883 
2884 static int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num,
2885 					  const char *cmd)
2886 {
2887 	u8 addr[ETH_ALEN];
2888 	struct vlan_description vlan_id;
2889 	int ret = 0, vlanid = 0;
2890 	const char *pos;
2891 
2892 	if (hwaddr_aton(cmd, addr))
2893 		return -1;
2894 
2895 	pos = os_strstr(cmd, "VLAN_ID=");
2896 	if (pos)
2897 		vlanid = atoi(pos + 8);
2898 
2899 	if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) {
2900 		ret = hostapd_add_acl_maclist(acl, num, vlanid, addr);
2901 		if (ret != -1 && *acl)
2902 			qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
2903 	}
2904 
2905 	return ret < 0 ? -1 : 0;
2906 }
2907 
2908 
2909 static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd,
2910 					     const char *field, char *buf,
2911 					     size_t buflen)
2912 {
2913 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
2914 
2915 #ifdef CONFIG_DPP
2916 	if (os_strcmp(field, "dpp") == 0) {
2917 		int res;
2918 
2919 #ifdef CONFIG_DPP2
2920 		res = os_snprintf(buf, buflen, "DPP=2");
2921 #else /* CONFIG_DPP2 */
2922 		res = os_snprintf(buf, buflen, "DPP=1");
2923 #endif /* CONFIG_DPP2 */
2924 		if (os_snprintf_error(buflen, res))
2925 			return -1;
2926 		return res;
2927 	}
2928 #endif /* CONFIG_DPP */
2929 
2930 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
2931 		   field);
2932 
2933 	return -1;
2934 }
2935 
2936 
2937 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
2938 					      char *buf, char *reply,
2939 					      int reply_size,
2940 					      struct sockaddr_storage *from,
2941 					      socklen_t fromlen)
2942 {
2943 	int reply_len, res;
2944 
2945 	os_memcpy(reply, "OK\n", 3);
2946 	reply_len = 3;
2947 
2948 	if (os_strcmp(buf, "PING") == 0) {
2949 		os_memcpy(reply, "PONG\n", 5);
2950 		reply_len = 5;
2951 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
2952 		if (wpa_debug_reopen_file() < 0)
2953 			reply_len = -1;
2954 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
2955 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
2956 	} else if (os_strcmp(buf, "STATUS") == 0) {
2957 		reply_len = hostapd_ctrl_iface_status(hapd, reply,
2958 						      reply_size);
2959 	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
2960 		reply_len = hostapd_drv_status(hapd, reply, reply_size);
2961 	} else if (os_strcmp(buf, "MIB") == 0) {
2962 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
2963 		if (reply_len >= 0) {
2964 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
2965 					  reply_size - reply_len);
2966 			if (res < 0)
2967 				reply_len = -1;
2968 			else
2969 				reply_len += res;
2970 		}
2971 		if (reply_len >= 0) {
2972 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
2973 						 reply_size - reply_len);
2974 			if (res < 0)
2975 				reply_len = -1;
2976 			else
2977 				reply_len += res;
2978 		}
2979 #ifndef CONFIG_NO_RADIUS
2980 		if (reply_len >= 0) {
2981 			res = radius_client_get_mib(hapd->radius,
2982 						    reply + reply_len,
2983 						    reply_size - reply_len);
2984 			if (res < 0)
2985 				reply_len = -1;
2986 			else
2987 				reply_len += res;
2988 		}
2989 #endif /* CONFIG_NO_RADIUS */
2990 	} else if (os_strncmp(buf, "MIB ", 4) == 0) {
2991 		reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
2992 						   buf + 4);
2993 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
2994 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
2995 							 reply_size);
2996 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
2997 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
2998 						   reply_size);
2999 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
3000 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
3001 							reply_size);
3002 	} else if (os_strcmp(buf, "ATTACH") == 0) {
3003 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL))
3004 			reply_len = -1;
3005 	} else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
3006 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen, buf + 7))
3007 			reply_len = -1;
3008 	} else if (os_strcmp(buf, "DETACH") == 0) {
3009 		if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
3010 			reply_len = -1;
3011 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
3012 		if (hostapd_ctrl_iface_level(hapd, from, fromlen,
3013 						    buf + 6))
3014 			reply_len = -1;
3015 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
3016 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
3017 			reply_len = -1;
3018 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
3019 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
3020 			reply_len = -1;
3021 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
3022 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
3023 			reply_len = -1;
3024 #ifdef CONFIG_TAXONOMY
3025 	} else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) {
3026 		reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10,
3027 							 reply, reply_size);
3028 #endif /* CONFIG_TAXONOMY */
3029 	} else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
3030 		if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
3031 			reply_len = -1;
3032 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
3033 		if (hostapd_ctrl_iface_stop_ap(hapd))
3034 			reply_len = -1;
3035 #ifdef CONFIG_IEEE80211W
3036 #ifdef NEED_AP_MLME
3037 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
3038 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
3039 			reply_len = -1;
3040 #endif /* NEED_AP_MLME */
3041 #endif /* CONFIG_IEEE80211W */
3042 #ifdef CONFIG_WPS
3043 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
3044 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
3045 			reply_len = -1;
3046 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
3047 		reply_len = hostapd_ctrl_iface_wps_check_pin(
3048 			hapd, buf + 14, reply, reply_size);
3049 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
3050 		if (hostapd_wps_button_pushed(hapd, NULL))
3051 			reply_len = -1;
3052 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
3053 		if (hostapd_wps_cancel(hapd))
3054 			reply_len = -1;
3055 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
3056 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
3057 							  reply, reply_size);
3058 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
3059 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
3060 			reply_len = -1;
3061 	} else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
3062 		reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
3063 							      reply_size);
3064 #ifdef CONFIG_WPS_NFC
3065 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
3066 		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
3067 			reply_len = -1;
3068 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
3069 		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
3070 			hapd, buf + 21, reply, reply_size);
3071 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
3072 		reply_len = hostapd_ctrl_iface_wps_nfc_token(
3073 			hapd, buf + 14, reply, reply_size);
3074 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
3075 		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
3076 			hapd, buf + 21, reply, reply_size);
3077 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
3078 		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
3079 			reply_len = -1;
3080 #endif /* CONFIG_WPS_NFC */
3081 #endif /* CONFIG_WPS */
3082 #ifdef CONFIG_INTERWORKING
3083 	} else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
3084 		if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
3085 			reply_len = -1;
3086 	} else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
3087 		if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
3088 			reply_len = -1;
3089 #endif /* CONFIG_INTERWORKING */
3090 #ifdef CONFIG_HS20
3091 	} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
3092 		if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
3093 			reply_len = -1;
3094 	} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
3095 		if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
3096 			reply_len = -1;
3097 #endif /* CONFIG_HS20 */
3098 #ifdef CONFIG_WNM_AP
3099 	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
3100 		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
3101 			reply_len = -1;
3102 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
3103 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
3104 			reply_len = -1;
3105 	} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
3106 		if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
3107 			reply_len = -1;
3108 	} else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) {
3109 		if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
3110 			reply_len = -1;
3111 #endif /* CONFIG_WNM_AP */
3112 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
3113 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
3114 							  reply_size);
3115 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
3116 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
3117 			reply_len = -1;
3118 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
3119 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
3120 						   reply_size);
3121 	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
3122 		if (hostapd_ctrl_iface_enable(hapd->iface))
3123 			reply_len = -1;
3124 	} else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) {
3125 		if (hostapd_ctrl_iface_reload_wpa_psk(hapd))
3126 			reply_len = -1;
3127 	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
3128 		if (hostapd_ctrl_iface_reload(hapd->iface))
3129 			reply_len = -1;
3130 	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
3131 		if (hostapd_ctrl_iface_disable(hapd->iface))
3132 			reply_len = -1;
3133 	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
3134 		if (ieee802_11_set_beacon(hapd))
3135 			reply_len = -1;
3136 #ifdef CONFIG_TESTING_OPTIONS
3137 	} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
3138 		if (hostapd_ctrl_iface_radar(hapd, buf + 6))
3139 			reply_len = -1;
3140 	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
3141 		if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
3142 			reply_len = -1;
3143 	} else if (os_strncmp(buf, "MGMT_TX_STATUS_PROCESS ", 23) == 0) {
3144 		if (hostapd_ctrl_iface_mgmt_tx_status_process(hapd,
3145 							      buf + 23) < 0)
3146 			reply_len = -1;
3147 	} else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
3148 		if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0)
3149 			reply_len = -1;
3150 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
3151 		if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
3152 			reply_len = -1;
3153 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
3154 		if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
3155 			reply_len = -1;
3156 	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
3157 		if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
3158 			reply_len = -1;
3159 	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
3160 		if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
3161 			reply_len = -1;
3162 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
3163 		if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
3164 			reply_len = -1;
3165 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
3166 		reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
3167 							reply_size);
3168 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
3169 		if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
3170 			reply_len = -1;
3171 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
3172 		reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
3173 	} else if (os_strncmp(buf, "RESET_PN ", 9) == 0) {
3174 		if (hostapd_ctrl_reset_pn(hapd, buf + 9) < 0)
3175 			reply_len = -1;
3176 	} else if (os_strncmp(buf, "SET_KEY ", 8) == 0) {
3177 		if (hostapd_ctrl_set_key(hapd, buf + 8) < 0)
3178 			reply_len = -1;
3179 	} else if (os_strncmp(buf, "RESEND_M1 ", 10) == 0) {
3180 		if (hostapd_ctrl_resend_m1(hapd, buf + 10) < 0)
3181 			reply_len = -1;
3182 	} else if (os_strncmp(buf, "RESEND_M3 ", 10) == 0) {
3183 		if (hostapd_ctrl_resend_m3(hapd, buf + 10) < 0)
3184 			reply_len = -1;
3185 	} else if (os_strncmp(buf, "RESEND_GROUP_M1 ", 16) == 0) {
3186 		if (hostapd_ctrl_resend_group_m1(hapd, buf + 16) < 0)
3187 			reply_len = -1;
3188 	} else if (os_strcmp(buf, "REKEY_GTK") == 0) {
3189 		if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0)
3190 			reply_len = -1;
3191 #endif /* CONFIG_TESTING_OPTIONS */
3192 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
3193 		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
3194 			reply_len = -1;
3195 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
3196 		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
3197 						      reply_size);
3198 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
3199 		ieee802_1x_erp_flush(hapd);
3200 #ifdef RADIUS_SERVER
3201 		radius_server_erp_flush(hapd->radius_srv);
3202 #endif /* RADIUS_SERVER */
3203 	} else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
3204 		if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
3205 			reply_len = -1;
3206 	} else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
3207 		if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
3208 			reply_len = -1;
3209 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
3210 		reply_len = hostapd_ctrl_iface_log_level(
3211 			hapd, buf + 9, reply, reply_size);
3212 #ifdef NEED_AP_MLME
3213 	} else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
3214 		reply_len = hostapd_ctrl_iface_track_sta_list(
3215 			hapd, reply, reply_size);
3216 #endif /* NEED_AP_MLME */
3217 	} else if (os_strcmp(buf, "PMKSA") == 0) {
3218 		reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
3219 							  reply_size);
3220 	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
3221 		hostapd_ctrl_iface_pmksa_flush(hapd);
3222 	} else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
3223 		if (hostapd_ctrl_iface_pmksa_add(hapd, buf + 10) < 0)
3224 			reply_len = -1;
3225 	} else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
3226 		if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
3227 			reply_len = -1;
3228 	} else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
3229 		if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
3230 			reply_len = -1;
3231 	} else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) {
3232 		if (hostapd_ctrl_iface_req_lci(hapd, buf + 8))
3233 			reply_len = -1;
3234 	} else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
3235 		if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
3236 			reply_len = -1;
3237 	} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
3238 		reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
3239 							  reply, reply_size);
3240 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
3241 		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
3242 						      reply_size);
3243 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
3244 		eloop_terminate();
3245 	} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
3246 		if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
3247 			if (!hostapd_ctrl_iface_acl_add_mac(
3248 				    &hapd->conf->accept_mac,
3249 				    &hapd->conf->num_accept_mac, buf + 19))
3250 				hostapd_disassoc_accept_mac(hapd);
3251 			else
3252 				reply_len = -1;
3253 		} else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
3254 			hostapd_ctrl_iface_acl_del_mac(
3255 				&hapd->conf->accept_mac,
3256 				&hapd->conf->num_accept_mac, buf + 19);
3257 		} else if (os_strcmp(buf + 11, "SHOW") == 0) {
3258 			reply_len = hostapd_ctrl_iface_acl_show_mac(
3259 				hapd->conf->accept_mac,
3260 				hapd->conf->num_accept_mac, reply, reply_size);
3261 		} else if (os_strcmp(buf + 11, "CLEAR") == 0) {
3262 			hostapd_ctrl_iface_acl_clear_list(
3263 				&hapd->conf->accept_mac,
3264 				&hapd->conf->num_accept_mac);
3265 		}
3266 	} else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
3267 		if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
3268 			if (!hostapd_ctrl_iface_acl_add_mac(
3269 				    &hapd->conf->deny_mac,
3270 				    &hapd->conf->num_deny_mac, buf + 17))
3271 				hostapd_disassoc_deny_mac(hapd);
3272 		} else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
3273 			hostapd_ctrl_iface_acl_del_mac(
3274 				&hapd->conf->deny_mac,
3275 				&hapd->conf->num_deny_mac, buf + 17);
3276 		} else if (os_strcmp(buf + 9, "SHOW") == 0) {
3277 			reply_len = hostapd_ctrl_iface_acl_show_mac(
3278 				hapd->conf->deny_mac,
3279 				hapd->conf->num_deny_mac, reply, reply_size);
3280 		} else if (os_strcmp(buf + 9, "CLEAR") == 0) {
3281 			hostapd_ctrl_iface_acl_clear_list(
3282 				&hapd->conf->deny_mac,
3283 				&hapd->conf->num_deny_mac);
3284 		}
3285 #ifdef CONFIG_DPP
3286 	} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
3287 		res = hostapd_dpp_qr_code(hapd, buf + 12);
3288 		if (res < 0) {
3289 			reply_len = -1;
3290 		} else {
3291 			reply_len = os_snprintf(reply, reply_size, "%d", res);
3292 			if (os_snprintf_error(reply_size, reply_len))
3293 				reply_len = -1;
3294 		}
3295 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
3296 		res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
3297 		if (res < 0) {
3298 			reply_len = -1;
3299 		} else {
3300 			reply_len = os_snprintf(reply, reply_size, "%d", res);
3301 			if (os_snprintf_error(reply_size, reply_len))
3302 				reply_len = -1;
3303 		}
3304 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
3305 		if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp,
3306 					 buf + 21) < 0)
3307 			reply_len = -1;
3308 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
3309 		const char *uri;
3310 
3311 		uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp,
3312 					    atoi(buf + 22));
3313 		if (!uri) {
3314 			reply_len = -1;
3315 		} else {
3316 			reply_len = os_snprintf(reply, reply_size, "%s", uri);
3317 			if (os_snprintf_error(reply_size, reply_len))
3318 				reply_len = -1;
3319 		}
3320 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
3321 		reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
3322 					       atoi(buf + 19),
3323 			reply, reply_size);
3324 	} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
3325 		if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
3326 			reply_len = -1;
3327 	} else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
3328 		if (hostapd_dpp_listen(hapd, buf + 11) < 0)
3329 			reply_len = -1;
3330 	} else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
3331 		hostapd_dpp_stop(hapd);
3332 		hostapd_dpp_listen_stop(hapd);
3333 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
3334 		res = dpp_configurator_add(hapd->iface->interfaces->dpp,
3335 					   buf + 20);
3336 		if (res < 0) {
3337 			reply_len = -1;
3338 		} else {
3339 			reply_len = os_snprintf(reply, reply_size, "%d", res);
3340 			if (os_snprintf_error(reply_size, reply_len))
3341 				reply_len = -1;
3342 		}
3343 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
3344 		if (dpp_configurator_remove(hapd->iface->interfaces->dpp,
3345 					    buf + 24) < 0)
3346 			reply_len = -1;
3347 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
3348 		if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0)
3349 			reply_len = -1;
3350 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
3351 		reply_len = dpp_configurator_get_key_id(
3352 			hapd->iface->interfaces->dpp,
3353 			atoi(buf + 25),
3354 			reply, reply_size);
3355 	} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
3356 		res = hostapd_dpp_pkex_add(hapd, buf + 12);
3357 		if (res < 0) {
3358 			reply_len = -1;
3359 		} else {
3360 			reply_len = os_snprintf(reply, reply_size, "%d", res);
3361 			if (os_snprintf_error(reply_size, reply_len))
3362 				reply_len = -1;
3363 		}
3364 	} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
3365 		if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0)
3366 			reply_len = -1;
3367 #endif /* CONFIG_DPP */
3368 #ifdef RADIUS_SERVER
3369 	} else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
3370 		if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0)
3371 			reply_len = -1;
3372 #endif /* RADIUS_SERVER */
3373 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
3374 		reply_len = hostapd_ctrl_iface_get_capability(
3375 			hapd, buf + 15, reply, reply_size);
3376 	} else {
3377 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3378 		reply_len = 16;
3379 	}
3380 
3381 	if (reply_len < 0) {
3382 		os_memcpy(reply, "FAIL\n", 5);
3383 		reply_len = 5;
3384 	}
3385 
3386 	return reply_len;
3387 }
3388 
3389 
3390 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
3391 				       void *sock_ctx)
3392 {
3393 	struct hostapd_data *hapd = eloop_ctx;
3394 	char buf[4096];
3395 	int res;
3396 	struct sockaddr_storage from;
3397 	socklen_t fromlen = sizeof(from);
3398 	char *reply, *pos = buf;
3399 	const int reply_size = 4096;
3400 	int reply_len;
3401 	int level = MSG_DEBUG;
3402 #ifdef CONFIG_CTRL_IFACE_UDP
3403 	unsigned char lcookie[COOKIE_LEN];
3404 #endif /* CONFIG_CTRL_IFACE_UDP */
3405 
3406 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
3407 		       (struct sockaddr *) &from, &fromlen);
3408 	if (res < 0) {
3409 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
3410 			   strerror(errno));
3411 		return;
3412 	}
3413 	buf[res] = '\0';
3414 
3415 	reply = os_malloc(reply_size);
3416 	if (reply == NULL) {
3417 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
3418 			   fromlen) < 0) {
3419 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3420 				   strerror(errno));
3421 		}
3422 		return;
3423 	}
3424 
3425 #ifdef CONFIG_CTRL_IFACE_UDP
3426 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
3427 		os_memcpy(reply, "COOKIE=", 7);
3428 		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
3429 				 cookie, COOKIE_LEN);
3430 		reply_len = 7 + 2 * COOKIE_LEN;
3431 		goto done;
3432 	}
3433 
3434 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
3435 	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
3436 		wpa_printf(MSG_DEBUG,
3437 			   "CTRL: No cookie in the request - drop request");
3438 		os_free(reply);
3439 		return;
3440 	}
3441 
3442 	if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
3443 		wpa_printf(MSG_DEBUG,
3444 			   "CTRL: Invalid cookie in the request - drop request");
3445 		os_free(reply);
3446 		return;
3447 	}
3448 
3449 	pos = buf + 7 + 2 * COOKIE_LEN;
3450 	while (*pos == ' ')
3451 		pos++;
3452 #endif /* CONFIG_CTRL_IFACE_UDP */
3453 
3454 	if (os_strcmp(pos, "PING") == 0)
3455 		level = MSG_EXCESSIVE;
3456 	wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
3457 
3458 	reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
3459 						       reply, reply_size,
3460 						       &from, fromlen);
3461 
3462 #ifdef CONFIG_CTRL_IFACE_UDP
3463 done:
3464 #endif /* CONFIG_CTRL_IFACE_UDP */
3465 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
3466 		   fromlen) < 0) {
3467 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3468 			   strerror(errno));
3469 	}
3470 	os_free(reply);
3471 }
3472 
3473 
3474 #ifndef CONFIG_CTRL_IFACE_UDP
3475 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
3476 {
3477 	char *buf;
3478 	size_t len;
3479 
3480 	if (hapd->conf->ctrl_interface == NULL)
3481 		return NULL;
3482 
3483 	len = os_strlen(hapd->conf->ctrl_interface) +
3484 		os_strlen(hapd->conf->iface) + 2;
3485 	buf = os_malloc(len);
3486 	if (buf == NULL)
3487 		return NULL;
3488 
3489 	os_snprintf(buf, len, "%s/%s",
3490 		    hapd->conf->ctrl_interface, hapd->conf->iface);
3491 	buf[len - 1] = '\0';
3492 	return buf;
3493 }
3494 #endif /* CONFIG_CTRL_IFACE_UDP */
3495 
3496 
3497 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
3498 				      enum wpa_msg_type type,
3499 				      const char *txt, size_t len)
3500 {
3501 	struct hostapd_data *hapd = ctx;
3502 	if (hapd == NULL)
3503 		return;
3504 	hostapd_ctrl_iface_send(hapd, level, type, txt, len);
3505 }
3506 
3507 
3508 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
3509 {
3510 #ifdef CONFIG_CTRL_IFACE_UDP
3511 	int port = HOSTAPD_CTRL_IFACE_PORT;
3512 	char p[32] = { 0 };
3513 	char port_str[40], *tmp;
3514 	char *pos;
3515 	struct addrinfo hints = { 0 }, *res, *saveres;
3516 	int n;
3517 
3518 	if (hapd->ctrl_sock > -1) {
3519 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
3520 		return 0;
3521 	}
3522 
3523 	if (hapd->conf->ctrl_interface == NULL)
3524 		return 0;
3525 
3526 	pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
3527 	if (pos) {
3528 		pos += 4;
3529 		port = atoi(pos);
3530 		if (port <= 0) {
3531 			wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
3532 			goto fail;
3533 		}
3534 	}
3535 
3536 	dl_list_init(&hapd->ctrl_dst);
3537 	hapd->ctrl_sock = -1;
3538 	os_get_random(cookie, COOKIE_LEN);
3539 
3540 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3541 	hints.ai_flags = AI_PASSIVE;
3542 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3543 
3544 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
3545 	hints.ai_family = AF_INET6;
3546 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3547 	hints.ai_family = AF_INET;
3548 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3549 	hints.ai_socktype = SOCK_DGRAM;
3550 
3551 try_again:
3552 	os_snprintf(p, sizeof(p), "%d", port);
3553 	n = getaddrinfo(NULL, p, &hints, &res);
3554 	if (n) {
3555 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
3556 		goto fail;
3557 	}
3558 
3559 	saveres = res;
3560 	hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
3561 				 res->ai_protocol);
3562 	if (hapd->ctrl_sock < 0) {
3563 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
3564 		goto fail;
3565 	}
3566 
3567 	if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
3568 		port--;
3569 		if ((HOSTAPD_CTRL_IFACE_PORT - port) <
3570 		    HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
3571 			goto try_again;
3572 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
3573 		goto fail;
3574 	}
3575 
3576 	freeaddrinfo(saveres);
3577 
3578 	os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
3579 	tmp = os_strdup(port_str);
3580 	if (tmp) {
3581 		os_free(hapd->conf->ctrl_interface);
3582 		hapd->conf->ctrl_interface = tmp;
3583 	}
3584 	wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
3585 
3586 	if (eloop_register_read_sock(hapd->ctrl_sock,
3587 				     hostapd_ctrl_iface_receive, hapd, NULL) <
3588 	    0) {
3589 		hostapd_ctrl_iface_deinit(hapd);
3590 		return -1;
3591 	}
3592 
3593 	hapd->msg_ctx = hapd;
3594 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
3595 
3596 	return 0;
3597 
3598 fail:
3599 	if (hapd->ctrl_sock >= 0)
3600 		close(hapd->ctrl_sock);
3601 	return -1;
3602 #else /* CONFIG_CTRL_IFACE_UDP */
3603 	struct sockaddr_un addr;
3604 	int s = -1;
3605 	char *fname = NULL;
3606 
3607 	if (hapd->ctrl_sock > -1) {
3608 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
3609 		return 0;
3610 	}
3611 
3612 	dl_list_init(&hapd->ctrl_dst);
3613 
3614 	if (hapd->conf->ctrl_interface == NULL)
3615 		return 0;
3616 
3617 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
3618 		if (errno == EEXIST) {
3619 			wpa_printf(MSG_DEBUG, "Using existing control "
3620 				   "interface directory.");
3621 		} else {
3622 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
3623 				   strerror(errno));
3624 			goto fail;
3625 		}
3626 	}
3627 
3628 	if (hapd->conf->ctrl_interface_gid_set &&
3629 	    lchown(hapd->conf->ctrl_interface, -1,
3630 		   hapd->conf->ctrl_interface_gid) < 0) {
3631 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
3632 			   strerror(errno));
3633 		return -1;
3634 	}
3635 
3636 	if (!hapd->conf->ctrl_interface_gid_set &&
3637 	    hapd->iface->interfaces->ctrl_iface_group &&
3638 	    lchown(hapd->conf->ctrl_interface, -1,
3639 		   hapd->iface->interfaces->ctrl_iface_group) < 0) {
3640 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
3641 			   strerror(errno));
3642 		return -1;
3643 	}
3644 
3645 #ifdef ANDROID
3646 	/*
3647 	 * Android is using umask 0077 which would leave the control interface
3648 	 * directory without group access. This breaks things since Wi-Fi
3649 	 * framework assumes that this directory can be accessed by other
3650 	 * applications in the wifi group. Fix this by adding group access even
3651 	 * if umask value would prevent this.
3652 	 */
3653 	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
3654 		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
3655 			   strerror(errno));
3656 		/* Try to continue anyway */
3657 	}
3658 #endif /* ANDROID */
3659 
3660 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
3661 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
3662 		goto fail;
3663 
3664 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
3665 	if (s < 0) {
3666 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
3667 		goto fail;
3668 	}
3669 
3670 	os_memset(&addr, 0, sizeof(addr));
3671 #ifdef __FreeBSD__
3672 	addr.sun_len = sizeof(addr);
3673 #endif /* __FreeBSD__ */
3674 	addr.sun_family = AF_UNIX;
3675 	fname = hostapd_ctrl_iface_path(hapd);
3676 	if (fname == NULL)
3677 		goto fail;
3678 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
3679 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3680 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
3681 			   strerror(errno));
3682 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3683 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
3684 				   " allow connections - assuming it was left"
3685 				   "over from forced program termination");
3686 			if (unlink(fname) < 0) {
3687 				wpa_printf(MSG_ERROR,
3688 					   "Could not unlink existing ctrl_iface socket '%s': %s",
3689 					   fname, strerror(errno));
3690 				goto fail;
3691 			}
3692 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
3693 			    0) {
3694 				wpa_printf(MSG_ERROR,
3695 					   "hostapd-ctrl-iface: bind(PF_UNIX): %s",
3696 					   strerror(errno));
3697 				goto fail;
3698 			}
3699 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
3700 				   "ctrl_iface socket '%s'", fname);
3701 		} else {
3702 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
3703 				   "be in use - cannot override it");
3704 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
3705 				   "not used anymore", fname);
3706 			os_free(fname);
3707 			fname = NULL;
3708 			goto fail;
3709 		}
3710 	}
3711 
3712 	if (hapd->conf->ctrl_interface_gid_set &&
3713 	    lchown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
3714 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
3715 			   strerror(errno));
3716 		goto fail;
3717 	}
3718 
3719 	if (!hapd->conf->ctrl_interface_gid_set &&
3720 	    hapd->iface->interfaces->ctrl_iface_group &&
3721 	    lchown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
3722 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
3723 			   strerror(errno));
3724 		goto fail;
3725 	}
3726 
3727 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
3728 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
3729 			   strerror(errno));
3730 		goto fail;
3731 	}
3732 	os_free(fname);
3733 
3734 	hapd->ctrl_sock = s;
3735 	if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
3736 				     NULL) < 0) {
3737 		hostapd_ctrl_iface_deinit(hapd);
3738 		return -1;
3739 	}
3740 	hapd->msg_ctx = hapd;
3741 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
3742 
3743 	return 0;
3744 
3745 fail:
3746 	if (s >= 0)
3747 		close(s);
3748 	if (fname) {
3749 		unlink(fname);
3750 		os_free(fname);
3751 	}
3752 	return -1;
3753 #endif /* CONFIG_CTRL_IFACE_UDP */
3754 }
3755 
3756 
3757 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
3758 {
3759 	struct wpa_ctrl_dst *dst, *prev;
3760 
3761 	if (hapd->ctrl_sock > -1) {
3762 #ifndef CONFIG_CTRL_IFACE_UDP
3763 		char *fname;
3764 #endif /* !CONFIG_CTRL_IFACE_UDP */
3765 
3766 		eloop_unregister_read_sock(hapd->ctrl_sock);
3767 		close(hapd->ctrl_sock);
3768 		hapd->ctrl_sock = -1;
3769 #ifndef CONFIG_CTRL_IFACE_UDP
3770 		fname = hostapd_ctrl_iface_path(hapd);
3771 		if (fname)
3772 			unlink(fname);
3773 		os_free(fname);
3774 
3775 		if (hapd->conf->ctrl_interface &&
3776 		    rmdir(hapd->conf->ctrl_interface) < 0) {
3777 			if (errno == ENOTEMPTY) {
3778 				wpa_printf(MSG_DEBUG, "Control interface "
3779 					   "directory not empty - leaving it "
3780 					   "behind");
3781 			} else {
3782 				wpa_printf(MSG_ERROR,
3783 					   "rmdir[ctrl_interface=%s]: %s",
3784 					   hapd->conf->ctrl_interface,
3785 					   strerror(errno));
3786 			}
3787 		}
3788 #endif /* !CONFIG_CTRL_IFACE_UDP */
3789 	}
3790 
3791 	dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
3792 			      list)
3793 		os_free(dst);
3794 
3795 #ifdef CONFIG_TESTING_OPTIONS
3796 	l2_packet_deinit(hapd->l2_test);
3797 	hapd->l2_test = NULL;
3798 #endif /* CONFIG_TESTING_OPTIONS */
3799 }
3800 
3801 
3802 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
3803 				  char *buf)
3804 {
3805 	if (hostapd_add_iface(interfaces, buf) < 0) {
3806 		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
3807 		return -1;
3808 	}
3809 	return 0;
3810 }
3811 
3812 
3813 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
3814 				     char *buf)
3815 {
3816 	if (hostapd_remove_iface(interfaces, buf) < 0) {
3817 		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
3818 		return -1;
3819 	}
3820 	return 0;
3821 }
3822 
3823 
3824 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
3825 					    struct sockaddr_storage *from,
3826 					    socklen_t fromlen, char *input)
3827 {
3828 	return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen,
3829 				 input);
3830 }
3831 
3832 
3833 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
3834 					    struct sockaddr_storage *from,
3835 					    socklen_t fromlen)
3836 {
3837 	return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
3838 }
3839 
3840 
3841 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
3842 {
3843 #ifdef CONFIG_WPS_TESTING
3844 	wps_version_number = 0x20;
3845 	wps_testing_dummy_cred = 0;
3846 	wps_corrupt_pkhash = 0;
3847 #endif /* CONFIG_WPS_TESTING */
3848 
3849 #ifdef CONFIG_TESTING_OPTIONS
3850 #ifdef CONFIG_DPP
3851 	dpp_test = DPP_TEST_DISABLED;
3852 #endif /* CONFIG_DPP */
3853 #endif /* CONFIG_TESTING_OPTIONS */
3854 
3855 #ifdef CONFIG_DPP
3856 	dpp_global_clear(interfaces->dpp);
3857 #endif /* CONFIG_DPP */
3858 }
3859 
3860 
3861 #ifdef CONFIG_FST
3862 
3863 static int
3864 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
3865 				     const char *cmd)
3866 {
3867 	char ifname[IFNAMSIZ + 1];
3868 	struct fst_iface_cfg cfg;
3869 	struct hostapd_data *hapd;
3870 	struct fst_wpa_obj iface_obj;
3871 
3872 	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
3873 		hapd = hostapd_get_iface(interfaces, ifname);
3874 		if (hapd) {
3875 			if (hapd->iface->fst) {
3876 				wpa_printf(MSG_INFO, "FST: Already attached");
3877 				return -1;
3878 			}
3879 			fst_hostapd_fill_iface_obj(hapd, &iface_obj);
3880 			hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
3881 						      &iface_obj, &cfg);
3882 			if (hapd->iface->fst)
3883 				return 0;
3884 		}
3885 	}
3886 
3887 	return -EINVAL;
3888 }
3889 
3890 
3891 static int
3892 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
3893 				     const char *cmd)
3894 {
3895 	char ifname[IFNAMSIZ + 1];
3896 	struct hostapd_data * hapd;
3897 
3898 	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
3899 		hapd = hostapd_get_iface(interfaces, ifname);
3900 		if (hapd) {
3901 			if (!fst_iface_detach(ifname)) {
3902 				hapd->iface->fst = NULL;
3903 				hapd->iface->fst_ies = NULL;
3904 				return 0;
3905 			}
3906 		}
3907 	}
3908 
3909 	return -EINVAL;
3910 }
3911 
3912 #endif /* CONFIG_FST */
3913 
3914 
3915 static struct hostapd_data *
3916 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
3917 			    const char *ifname)
3918 {
3919 	size_t i, j;
3920 
3921 	for (i = 0; i < interfaces->count; i++) {
3922 		struct hostapd_iface *iface = interfaces->iface[i];
3923 
3924 		for (j = 0; j < iface->num_bss; j++) {
3925 			struct hostapd_data *hapd;
3926 
3927 			hapd = iface->bss[j];
3928 			if (os_strcmp(ifname, hapd->conf->iface) == 0)
3929 				return hapd;
3930 		}
3931 	}
3932 
3933 	return NULL;
3934 }
3935 
3936 
3937 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
3938 					struct hostapd_data *dst_hapd,
3939 					const char *param)
3940 {
3941 	int res;
3942 	char *value;
3943 
3944 	value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
3945 	if (!value) {
3946 		wpa_printf(MSG_ERROR,
3947 			   "DUP: cannot allocate buffer to stringify %s",
3948 			   param);
3949 		goto error_return;
3950 	}
3951 
3952 	if (os_strcmp(param, "wpa") == 0) {
3953 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
3954 			    src_hapd->conf->wpa);
3955 	} else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
3956 		   src_hapd->conf->wpa_key_mgmt) {
3957 		res = hostapd_ctrl_iface_get_key_mgmt(
3958 			src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
3959 		if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
3960 			goto error_stringify;
3961 	} else if (os_strcmp(param, "wpa_pairwise") == 0 &&
3962 		   src_hapd->conf->wpa_pairwise) {
3963 		res = wpa_write_ciphers(value,
3964 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
3965 					src_hapd->conf->wpa_pairwise, " ");
3966 		if (res < 0)
3967 			goto error_stringify;
3968 	} else if (os_strcmp(param, "rsn_pairwise") == 0 &&
3969 		   src_hapd->conf->rsn_pairwise) {
3970 		res = wpa_write_ciphers(value,
3971 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
3972 					src_hapd->conf->rsn_pairwise, " ");
3973 		if (res < 0)
3974 			goto error_stringify;
3975 	} else if (os_strcmp(param, "wpa_passphrase") == 0 &&
3976 		   src_hapd->conf->ssid.wpa_passphrase) {
3977 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
3978 			    src_hapd->conf->ssid.wpa_passphrase);
3979 	} else if (os_strcmp(param, "wpa_psk") == 0 &&
3980 		   src_hapd->conf->ssid.wpa_psk_set) {
3981 		wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
3982 			src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
3983 	} else {
3984 		wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
3985 		goto error_return;
3986 	}
3987 
3988 	res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
3989 	os_free(value);
3990 	return res;
3991 
3992 error_stringify:
3993 	wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
3994 error_return:
3995 	os_free(value);
3996 	return -1;
3997 }
3998 
3999 
4000 static int
4001 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
4002 				     const char *input,
4003 				     char *reply, int reply_size)
4004 {
4005 	size_t i, j;
4006 	int res;
4007 	char *pos, *end;
4008 	struct hostapd_iface *iface;
4009 	int show_ctrl = 0;
4010 
4011 	if (input)
4012 		show_ctrl = !!os_strstr(input, "ctrl");
4013 
4014 	pos = reply;
4015 	end = reply + reply_size;
4016 
4017 	for (i = 0; i < interfaces->count; i++) {
4018 		iface = interfaces->iface[i];
4019 
4020 		for (j = 0; j < iface->num_bss; j++) {
4021 			struct hostapd_bss_config *conf;
4022 
4023 			conf = iface->conf->bss[j];
4024 			if (show_ctrl)
4025 				res = os_snprintf(pos, end - pos,
4026 						  "%s ctrl_iface=%s\n",
4027 						  conf->iface,
4028 						  conf->ctrl_interface ?
4029 						  conf->ctrl_interface : "N/A");
4030 			else
4031 				res = os_snprintf(pos, end - pos, "%s\n",
4032 						  conf->iface);
4033 			if (os_snprintf_error(end - pos, res)) {
4034 				*pos = '\0';
4035 				return pos - reply;
4036 			}
4037 			pos += res;
4038 		}
4039 	}
4040 
4041 	return pos - reply;
4042 }
4043 
4044 
4045 static int
4046 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
4047 				      char *cmd)
4048 {
4049 	char *p_start = cmd, *p_end;
4050 	struct hostapd_data *src_hapd, *dst_hapd;
4051 
4052 	/* cmd: "<src ifname> <dst ifname> <variable name> */
4053 
4054 	p_end = os_strchr(p_start, ' ');
4055 	if (!p_end) {
4056 		wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
4057 			   cmd);
4058 		return -1;
4059 	}
4060 
4061 	*p_end = '\0';
4062 	src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
4063 	if (!src_hapd) {
4064 		wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
4065 			   p_start);
4066 		return -1;
4067 	}
4068 
4069 	p_start = p_end + 1;
4070 	p_end = os_strchr(p_start, ' ');
4071 	if (!p_end) {
4072 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
4073 			   cmd);
4074 		return -1;
4075 	}
4076 
4077 	*p_end = '\0';
4078 	dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
4079 	if (!dst_hapd) {
4080 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
4081 			   p_start);
4082 		return -1;
4083 	}
4084 
4085 	p_start = p_end + 1;
4086 	return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
4087 }
4088 
4089 
4090 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
4091 					    const char *ifname,
4092 					    char *buf, char *reply,
4093 					    int reply_size,
4094 					    struct sockaddr_storage *from,
4095 					    socklen_t fromlen)
4096 {
4097 	struct hostapd_data *hapd;
4098 
4099 	hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
4100 	if (hapd == NULL) {
4101 		int res;
4102 
4103 		res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
4104 		if (os_snprintf_error(reply_size, res))
4105 			return -1;
4106 		return res;
4107 	}
4108 
4109 	return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
4110 						  from, fromlen);
4111 }
4112 
4113 
4114 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
4115 					      void *sock_ctx)
4116 {
4117 	void *interfaces = eloop_ctx;
4118 	char buffer[256], *buf = buffer;
4119 	int res;
4120 	struct sockaddr_storage from;
4121 	socklen_t fromlen = sizeof(from);
4122 	char *reply;
4123 	int reply_len;
4124 	const int reply_size = 4096;
4125 #ifdef CONFIG_CTRL_IFACE_UDP
4126 	unsigned char lcookie[COOKIE_LEN];
4127 #endif /* CONFIG_CTRL_IFACE_UDP */
4128 
4129 	res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
4130 		       (struct sockaddr *) &from, &fromlen);
4131 	if (res < 0) {
4132 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
4133 			   strerror(errno));
4134 		return;
4135 	}
4136 	buf[res] = '\0';
4137 	wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
4138 
4139 	reply = os_malloc(reply_size);
4140 	if (reply == NULL) {
4141 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
4142 			   fromlen) < 0) {
4143 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
4144 				   strerror(errno));
4145 		}
4146 		return;
4147 	}
4148 
4149 	os_memcpy(reply, "OK\n", 3);
4150 	reply_len = 3;
4151 
4152 #ifdef CONFIG_CTRL_IFACE_UDP
4153 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
4154 		os_memcpy(reply, "COOKIE=", 7);
4155 		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
4156 				 gcookie, COOKIE_LEN);
4157 		reply_len = 7 + 2 * COOKIE_LEN;
4158 		goto send_reply;
4159 	}
4160 
4161 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
4162 	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
4163 		wpa_printf(MSG_DEBUG,
4164 			   "CTRL: No cookie in the request - drop request");
4165 		os_free(reply);
4166 		return;
4167 	}
4168 
4169 	if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
4170 		wpa_printf(MSG_DEBUG,
4171 			   "CTRL: Invalid cookie in the request - drop request");
4172 		os_free(reply);
4173 		return;
4174 	}
4175 
4176 	buf += 7 + 2 * COOKIE_LEN;
4177 	while (*buf == ' ')
4178 		buf++;
4179 #endif /* CONFIG_CTRL_IFACE_UDP */
4180 
4181 	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
4182 		char *pos = os_strchr(buf + 7, ' ');
4183 
4184 		if (pos) {
4185 			*pos++ = '\0';
4186 			reply_len = hostapd_global_ctrl_iface_ifname(
4187 				interfaces, buf + 7, pos, reply, reply_size,
4188 				&from, fromlen);
4189 			goto send_reply;
4190 		}
4191 	}
4192 
4193 	if (os_strcmp(buf, "PING") == 0) {
4194 		os_memcpy(reply, "PONG\n", 5);
4195 		reply_len = 5;
4196 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
4197 		if (wpa_debug_reopen_file() < 0)
4198 			reply_len = -1;
4199 	} else if (os_strcmp(buf, "FLUSH") == 0) {
4200 		hostapd_ctrl_iface_flush(interfaces);
4201 	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
4202 		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
4203 			reply_len = -1;
4204 	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
4205 		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
4206 			reply_len = -1;
4207 	} else if (os_strcmp(buf, "ATTACH") == 0) {
4208 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
4209 						     fromlen, NULL))
4210 			reply_len = -1;
4211 	} else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
4212 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
4213 						     fromlen, buf + 7))
4214 			reply_len = -1;
4215 	} else if (os_strcmp(buf, "DETACH") == 0) {
4216 		if (hostapd_global_ctrl_iface_detach(interfaces, &from,
4217 			fromlen))
4218 			reply_len = -1;
4219 #ifdef CONFIG_MODULE_TESTS
4220 	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
4221 		if (hapd_module_tests() < 0)
4222 			reply_len = -1;
4223 #endif /* CONFIG_MODULE_TESTS */
4224 #ifdef CONFIG_FST
4225 	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
4226 		if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
4227 			reply_len = os_snprintf(reply, reply_size, "OK\n");
4228 		else
4229 			reply_len = -1;
4230 	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
4231 		if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
4232 			reply_len = os_snprintf(reply, reply_size, "OK\n");
4233 		else
4234 			reply_len = -1;
4235 	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
4236 		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
4237 #endif /* CONFIG_FST */
4238 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
4239 		if (!hostapd_global_ctrl_iface_dup_network(interfaces,
4240 							   buf + 12))
4241 			reply_len = os_snprintf(reply, reply_size, "OK\n");
4242 		else
4243 			reply_len = -1;
4244 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
4245 		reply_len = hostapd_global_ctrl_iface_interfaces(
4246 			interfaces, buf + 10, reply, sizeof(buffer));
4247 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
4248 		eloop_terminate();
4249 	} else {
4250 		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
4251 			   "ignored");
4252 		reply_len = -1;
4253 	}
4254 
4255 send_reply:
4256 	if (reply_len < 0) {
4257 		os_memcpy(reply, "FAIL\n", 5);
4258 		reply_len = 5;
4259 	}
4260 
4261 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
4262 		   fromlen) < 0) {
4263 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
4264 			   strerror(errno));
4265 	}
4266 	os_free(reply);
4267 }
4268 
4269 
4270 #ifndef CONFIG_CTRL_IFACE_UDP
4271 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
4272 {
4273 	char *buf;
4274 	size_t len;
4275 
4276 	if (interface->global_iface_path == NULL)
4277 		return NULL;
4278 
4279 	len = os_strlen(interface->global_iface_path) +
4280 		os_strlen(interface->global_iface_name) + 2;
4281 	buf = os_malloc(len);
4282 	if (buf == NULL)
4283 		return NULL;
4284 
4285 	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
4286 		    interface->global_iface_name);
4287 	buf[len - 1] = '\0';
4288 	return buf;
4289 }
4290 #endif /* CONFIG_CTRL_IFACE_UDP */
4291 
4292 
4293 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
4294 {
4295 #ifdef CONFIG_CTRL_IFACE_UDP
4296 	int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
4297 	char p[32] = { 0 };
4298 	char *pos;
4299 	struct addrinfo hints = { 0 }, *res, *saveres;
4300 	int n;
4301 
4302 	if (interface->global_ctrl_sock > -1) {
4303 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
4304 		return 0;
4305 	}
4306 
4307 	if (interface->global_iface_path == NULL)
4308 		return 0;
4309 
4310 	pos = os_strstr(interface->global_iface_path, "udp:");
4311 	if (pos) {
4312 		pos += 4;
4313 		port = atoi(pos);
4314 		if (port <= 0) {
4315 			wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
4316 			goto fail;
4317 		}
4318 	}
4319 
4320 	os_get_random(gcookie, COOKIE_LEN);
4321 
4322 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
4323 	hints.ai_flags = AI_PASSIVE;
4324 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
4325 
4326 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
4327 	hints.ai_family = AF_INET6;
4328 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
4329 	hints.ai_family = AF_INET;
4330 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
4331 	hints.ai_socktype = SOCK_DGRAM;
4332 
4333 try_again:
4334 	os_snprintf(p, sizeof(p), "%d", port);
4335 	n = getaddrinfo(NULL, p, &hints, &res);
4336 	if (n) {
4337 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
4338 		goto fail;
4339 	}
4340 
4341 	saveres = res;
4342 	interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
4343 					     res->ai_protocol);
4344 	if (interface->global_ctrl_sock < 0) {
4345 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
4346 		goto fail;
4347 	}
4348 
4349 	if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
4350 	    0) {
4351 		port++;
4352 		if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
4353 		    HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
4354 			goto try_again;
4355 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
4356 		goto fail;
4357 	}
4358 
4359 	freeaddrinfo(saveres);
4360 
4361 	wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
4362 
4363 	if (eloop_register_read_sock(interface->global_ctrl_sock,
4364 				     hostapd_global_ctrl_iface_receive,
4365 				     interface, NULL) < 0) {
4366 		hostapd_global_ctrl_iface_deinit(interface);
4367 		return -1;
4368 	}
4369 
4370 	return 0;
4371 
4372 fail:
4373 	if (interface->global_ctrl_sock >= 0)
4374 		close(interface->global_ctrl_sock);
4375 	return -1;
4376 #else /* CONFIG_CTRL_IFACE_UDP */
4377 	struct sockaddr_un addr;
4378 	int s = -1;
4379 	char *fname = NULL;
4380 
4381 	if (interface->global_iface_path == NULL) {
4382 		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
4383 		return 0;
4384 	}
4385 
4386 	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
4387 		if (errno == EEXIST) {
4388 			wpa_printf(MSG_DEBUG, "Using existing control "
4389 				   "interface directory.");
4390 		} else {
4391 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
4392 				   strerror(errno));
4393 			goto fail;
4394 		}
4395 	} else if (interface->ctrl_iface_group &&
4396 		   lchown(interface->global_iface_path, -1,
4397 			  interface->ctrl_iface_group) < 0) {
4398 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
4399 			   strerror(errno));
4400 		goto fail;
4401 	}
4402 
4403 	if (os_strlen(interface->global_iface_path) + 1 +
4404 	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
4405 		goto fail;
4406 
4407 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
4408 	if (s < 0) {
4409 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
4410 		goto fail;
4411 	}
4412 
4413 	os_memset(&addr, 0, sizeof(addr));
4414 #ifdef __FreeBSD__
4415 	addr.sun_len = sizeof(addr);
4416 #endif /* __FreeBSD__ */
4417 	addr.sun_family = AF_UNIX;
4418 	fname = hostapd_global_ctrl_iface_path(interface);
4419 	if (fname == NULL)
4420 		goto fail;
4421 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
4422 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
4423 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
4424 			   strerror(errno));
4425 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
4426 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
4427 				   " allow connections - assuming it was left"
4428 				   "over from forced program termination");
4429 			if (unlink(fname) < 0) {
4430 				wpa_printf(MSG_ERROR,
4431 					   "Could not unlink existing ctrl_iface socket '%s': %s",
4432 					   fname, strerror(errno));
4433 				goto fail;
4434 			}
4435 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
4436 			    0) {
4437 				wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
4438 					   strerror(errno));
4439 				goto fail;
4440 			}
4441 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
4442 				   "ctrl_iface socket '%s'", fname);
4443 		} else {
4444 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
4445 				   "be in use - cannot override it");
4446 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
4447 				   "not used anymore", fname);
4448 			os_free(fname);
4449 			fname = NULL;
4450 			goto fail;
4451 		}
4452 	}
4453 
4454 	if (interface->ctrl_iface_group &&
4455 	    lchown(fname, -1, interface->ctrl_iface_group) < 0) {
4456 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
4457 			   strerror(errno));
4458 		goto fail;
4459 	}
4460 
4461 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
4462 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
4463 			   strerror(errno));
4464 		goto fail;
4465 	}
4466 	os_free(fname);
4467 
4468 	interface->global_ctrl_sock = s;
4469 	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
4470 				 interface, NULL);
4471 
4472 	return 0;
4473 
4474 fail:
4475 	if (s >= 0)
4476 		close(s);
4477 	if (fname) {
4478 		unlink(fname);
4479 		os_free(fname);
4480 	}
4481 	return -1;
4482 #endif /* CONFIG_CTRL_IFACE_UDP */
4483 }
4484 
4485 
4486 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
4487 {
4488 #ifndef CONFIG_CTRL_IFACE_UDP
4489 	char *fname = NULL;
4490 #endif /* CONFIG_CTRL_IFACE_UDP */
4491 	struct wpa_ctrl_dst *dst, *prev;
4492 
4493 	if (interfaces->global_ctrl_sock > -1) {
4494 		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
4495 		close(interfaces->global_ctrl_sock);
4496 		interfaces->global_ctrl_sock = -1;
4497 #ifndef CONFIG_CTRL_IFACE_UDP
4498 		fname = hostapd_global_ctrl_iface_path(interfaces);
4499 		if (fname) {
4500 			unlink(fname);
4501 			os_free(fname);
4502 		}
4503 
4504 		if (interfaces->global_iface_path &&
4505 		    rmdir(interfaces->global_iface_path) < 0) {
4506 			if (errno == ENOTEMPTY) {
4507 				wpa_printf(MSG_DEBUG, "Control interface "
4508 					   "directory not empty - leaving it "
4509 					   "behind");
4510 			} else {
4511 				wpa_printf(MSG_ERROR,
4512 					   "rmdir[ctrl_interface=%s]: %s",
4513 					   interfaces->global_iface_path,
4514 					   strerror(errno));
4515 			}
4516 		}
4517 #endif /* CONFIG_CTRL_IFACE_UDP */
4518 	}
4519 
4520 	os_free(interfaces->global_iface_path);
4521 	interfaces->global_iface_path = NULL;
4522 
4523 	dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
4524 			      struct wpa_ctrl_dst, list)
4525 		os_free(dst);
4526 }
4527 
4528 
4529 static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst,
4530 					    const char *buf)
4531 {
4532 	/* Enable Probe Request events based on explicit request.
4533 	 * Other events are enabled by default.
4534 	 */
4535 	if (str_starts(buf, RX_PROBE_REQUEST))
4536 		return !!(dst->events & WPA_EVENT_RX_PROBE_REQUEST);
4537 	return 1;
4538 }
4539 
4540 
4541 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
4542 				    enum wpa_msg_type type,
4543 				    const char *buf, size_t len)
4544 {
4545 	struct wpa_ctrl_dst *dst, *next;
4546 	struct dl_list *ctrl_dst;
4547 	struct msghdr msg;
4548 	int idx;
4549 	struct iovec io[2];
4550 	char levelstr[10];
4551 	int s;
4552 
4553 	if (type != WPA_MSG_ONLY_GLOBAL) {
4554 		s = hapd->ctrl_sock;
4555 		ctrl_dst = &hapd->ctrl_dst;
4556 	} else {
4557 		s = hapd->iface->interfaces->global_ctrl_sock;
4558 		ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
4559 	}
4560 
4561 	if (s < 0 || dl_list_empty(ctrl_dst))
4562 		return;
4563 
4564 	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
4565 	io[0].iov_base = levelstr;
4566 	io[0].iov_len = os_strlen(levelstr);
4567 	io[1].iov_base = (char *) buf;
4568 	io[1].iov_len = len;
4569 	os_memset(&msg, 0, sizeof(msg));
4570 	msg.msg_iov = io;
4571 	msg.msg_iovlen = 2;
4572 
4573 	idx = 0;
4574 	dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
4575 		if ((level >= dst->debug_level) &&
4576 		     hostapd_ctrl_check_event_enabled(dst, buf)) {
4577 			sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
4578 				       &dst->addr, dst->addrlen);
4579 			msg.msg_name = &dst->addr;
4580 			msg.msg_namelen = dst->addrlen;
4581 			if (sendmsg(s, &msg, 0) < 0) {
4582 				int _errno = errno;
4583 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
4584 					   "%d - %s",
4585 					   idx, errno, strerror(errno));
4586 				dst->errors++;
4587 				if (dst->errors > 10 || _errno == ENOENT) {
4588 					if (type != WPA_MSG_ONLY_GLOBAL)
4589 						hostapd_ctrl_iface_detach(
4590 							hapd, &dst->addr,
4591 							dst->addrlen);
4592 					else
4593 						hostapd_global_ctrl_iface_detach(
4594 							hapd->iface->interfaces,
4595 							&dst->addr,
4596 							dst->addrlen);
4597 				}
4598 			} else
4599 				dst->errors = 0;
4600 		}
4601 		idx++;
4602 	}
4603 }
4604 
4605 #endif /* CONFIG_NATIVE_WINDOWS */
4606