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