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