xref: /freebsd/contrib/wpa/hostapd/ctrl_iface.c (revision d6b92ffa)
1 /*
2  * hostapd / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #ifndef CONFIG_NATIVE_WINDOWS
12 
13 #ifdef CONFIG_TESTING_OPTIONS
14 #include <net/ethernet.h>
15 #include <netinet/ip.h>
16 #endif /* CONFIG_TESTING_OPTIONS */
17 
18 #include <sys/un.h>
19 #include <sys/stat.h>
20 #include <stddef.h>
21 
22 #include "utils/common.h"
23 #include "utils/eloop.h"
24 #include "common/version.h"
25 #include "common/ieee802_11_defs.h"
26 #include "crypto/tls.h"
27 #include "drivers/driver.h"
28 #include "eapol_auth/eapol_auth_sm.h"
29 #include "radius/radius_client.h"
30 #include "radius/radius_server.h"
31 #include "l2_packet/l2_packet.h"
32 #include "ap/hostapd.h"
33 #include "ap/ap_config.h"
34 #include "ap/ieee802_1x.h"
35 #include "ap/wpa_auth.h"
36 #include "ap/ieee802_11.h"
37 #include "ap/sta_info.h"
38 #include "ap/wps_hostapd.h"
39 #include "ap/ctrl_iface_ap.h"
40 #include "ap/ap_drv_ops.h"
41 #include "ap/hs20.h"
42 #include "ap/wnm_ap.h"
43 #include "ap/wpa_auth.h"
44 #include "ap/beacon.h"
45 #include "wps/wps_defs.h"
46 #include "wps/wps.h"
47 #include "fst/fst_ctrl_iface.h"
48 #include "config_file.h"
49 #include "ctrl_iface.h"
50 
51 
52 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
53 
54 struct wpa_ctrl_dst {
55 	struct wpa_ctrl_dst *next;
56 	struct sockaddr_un addr;
57 	socklen_t addrlen;
58 	int debug_level;
59 	int errors;
60 };
61 
62 
63 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
64 				    enum wpa_msg_type type,
65 				    const char *buf, size_t len);
66 
67 
68 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
69 				     struct sockaddr_un *from,
70 				     socklen_t fromlen)
71 {
72 	struct wpa_ctrl_dst *dst;
73 
74 	dst = os_zalloc(sizeof(*dst));
75 	if (dst == NULL)
76 		return -1;
77 	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
78 	dst->addrlen = fromlen;
79 	dst->debug_level = MSG_INFO;
80 	dst->next = hapd->ctrl_dst;
81 	hapd->ctrl_dst = dst;
82 	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
83 		    (u8 *) from->sun_path,
84 		    fromlen - offsetof(struct sockaddr_un, sun_path));
85 	return 0;
86 }
87 
88 
89 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
90 				     struct sockaddr_un *from,
91 				     socklen_t fromlen)
92 {
93 	struct wpa_ctrl_dst *dst, *prev = NULL;
94 
95 	dst = hapd->ctrl_dst;
96 	while (dst) {
97 		if (fromlen == dst->addrlen &&
98 		    os_memcmp(from->sun_path, dst->addr.sun_path,
99 			      fromlen - offsetof(struct sockaddr_un, sun_path))
100 		    == 0) {
101 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
102 				    (u8 *) from->sun_path,
103 				    fromlen -
104 				    offsetof(struct sockaddr_un, sun_path));
105 			if (prev == NULL)
106 				hapd->ctrl_dst = dst->next;
107 			else
108 				prev->next = dst->next;
109 			os_free(dst);
110 			return 0;
111 		}
112 		prev = dst;
113 		dst = dst->next;
114 	}
115 	return -1;
116 }
117 
118 
119 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
120 				    struct sockaddr_un *from,
121 				    socklen_t fromlen,
122 				    char *level)
123 {
124 	struct wpa_ctrl_dst *dst;
125 
126 	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
127 
128 	dst = hapd->ctrl_dst;
129 	while (dst) {
130 		if (fromlen == dst->addrlen &&
131 		    os_memcmp(from->sun_path, dst->addr.sun_path,
132 			      fromlen - offsetof(struct sockaddr_un, sun_path))
133 		    == 0) {
134 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
135 				    "level", (u8 *) from->sun_path, fromlen -
136 				    offsetof(struct sockaddr_un, sun_path));
137 			dst->debug_level = atoi(level);
138 			return 0;
139 		}
140 		dst = dst->next;
141 	}
142 
143 	return -1;
144 }
145 
146 
147 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
148 				      const char *txtaddr)
149 {
150 	u8 addr[ETH_ALEN];
151 	struct sta_info *sta;
152 
153 	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
154 
155 	if (hwaddr_aton(txtaddr, addr))
156 		return -1;
157 
158 	sta = ap_get_sta(hapd, addr);
159 	if (sta)
160 		return 0;
161 
162 	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
163 		   "notification", MAC2STR(addr));
164 	sta = ap_sta_add(hapd, addr);
165 	if (sta == NULL)
166 		return -1;
167 
168 	hostapd_new_assoc_sta(hapd, sta, 0);
169 	return 0;
170 }
171 
172 
173 #ifdef CONFIG_IEEE80211W
174 #ifdef NEED_AP_MLME
175 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
176 				       const char *txtaddr)
177 {
178 	u8 addr[ETH_ALEN];
179 	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
180 
181 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
182 
183 	if (hwaddr_aton(txtaddr, addr) ||
184 	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
185 		return -1;
186 
187 	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
188 
189 	return 0;
190 }
191 #endif /* NEED_AP_MLME */
192 #endif /* CONFIG_IEEE80211W */
193 
194 
195 #ifdef CONFIG_WPS
196 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
197 {
198 	char *pin = os_strchr(txt, ' ');
199 	char *timeout_txt;
200 	int timeout;
201 	u8 addr_buf[ETH_ALEN], *addr = NULL;
202 	char *pos;
203 
204 	if (pin == NULL)
205 		return -1;
206 	*pin++ = '\0';
207 
208 	timeout_txt = os_strchr(pin, ' ');
209 	if (timeout_txt) {
210 		*timeout_txt++ = '\0';
211 		timeout = atoi(timeout_txt);
212 		pos = os_strchr(timeout_txt, ' ');
213 		if (pos) {
214 			*pos++ = '\0';
215 			if (hwaddr_aton(pos, addr_buf) == 0)
216 				addr = addr_buf;
217 		}
218 	} else
219 		timeout = 0;
220 
221 	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
222 }
223 
224 
225 static int hostapd_ctrl_iface_wps_check_pin(
226 	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
227 {
228 	char pin[9];
229 	size_t len;
230 	char *pos;
231 	int ret;
232 
233 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
234 			      (u8 *) cmd, os_strlen(cmd));
235 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
236 		if (*pos < '0' || *pos > '9')
237 			continue;
238 		pin[len++] = *pos;
239 		if (len == 9) {
240 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
241 			return -1;
242 		}
243 	}
244 	if (len != 4 && len != 8) {
245 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
246 		return -1;
247 	}
248 	pin[len] = '\0';
249 
250 	if (len == 8) {
251 		unsigned int pin_val;
252 		pin_val = atoi(pin);
253 		if (!wps_pin_valid(pin_val)) {
254 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
255 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
256 			if (os_snprintf_error(buflen, ret))
257 				return -1;
258 			return ret;
259 		}
260 	}
261 
262 	ret = os_snprintf(buf, buflen, "%s", pin);
263 	if (os_snprintf_error(buflen, ret))
264 		return -1;
265 
266 	return ret;
267 }
268 
269 
270 #ifdef CONFIG_WPS_NFC
271 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
272 					       char *pos)
273 {
274 	size_t len;
275 	struct wpabuf *buf;
276 	int ret;
277 
278 	len = os_strlen(pos);
279 	if (len & 0x01)
280 		return -1;
281 	len /= 2;
282 
283 	buf = wpabuf_alloc(len);
284 	if (buf == NULL)
285 		return -1;
286 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
287 		wpabuf_free(buf);
288 		return -1;
289 	}
290 
291 	ret = hostapd_wps_nfc_tag_read(hapd, buf);
292 	wpabuf_free(buf);
293 
294 	return ret;
295 }
296 
297 
298 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
299 						   char *cmd, char *reply,
300 						   size_t max_len)
301 {
302 	int ndef;
303 	struct wpabuf *buf;
304 	int res;
305 
306 	if (os_strcmp(cmd, "WPS") == 0)
307 		ndef = 0;
308 	else if (os_strcmp(cmd, "NDEF") == 0)
309 		ndef = 1;
310 	else
311 		return -1;
312 
313 	buf = hostapd_wps_nfc_config_token(hapd, ndef);
314 	if (buf == NULL)
315 		return -1;
316 
317 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
318 					 wpabuf_len(buf));
319 	reply[res++] = '\n';
320 	reply[res] = '\0';
321 
322 	wpabuf_free(buf);
323 
324 	return res;
325 }
326 
327 
328 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
329 						char *reply, size_t max_len,
330 						int ndef)
331 {
332 	struct wpabuf *buf;
333 	int res;
334 
335 	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
336 	if (buf == NULL)
337 		return -1;
338 
339 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
340 					 wpabuf_len(buf));
341 	reply[res++] = '\n';
342 	reply[res] = '\0';
343 
344 	wpabuf_free(buf);
345 
346 	return res;
347 }
348 
349 
350 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
351 					    char *cmd, char *reply,
352 					    size_t max_len)
353 {
354 	if (os_strcmp(cmd, "WPS") == 0)
355 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
356 							    max_len, 0);
357 
358 	if (os_strcmp(cmd, "NDEF") == 0)
359 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
360 							    max_len, 1);
361 
362 	if (os_strcmp(cmd, "enable") == 0)
363 		return hostapd_wps_nfc_token_enable(hapd);
364 
365 	if (os_strcmp(cmd, "disable") == 0) {
366 		hostapd_wps_nfc_token_disable(hapd);
367 		return 0;
368 	}
369 
370 	return -1;
371 }
372 
373 
374 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
375 						   char *cmd, char *reply,
376 						   size_t max_len)
377 {
378 	struct wpabuf *buf;
379 	int res;
380 	char *pos;
381 	int ndef;
382 
383 	pos = os_strchr(cmd, ' ');
384 	if (pos == NULL)
385 		return -1;
386 	*pos++ = '\0';
387 
388 	if (os_strcmp(cmd, "WPS") == 0)
389 		ndef = 0;
390 	else if (os_strcmp(cmd, "NDEF") == 0)
391 		ndef = 1;
392 	else
393 		return -1;
394 
395 	if (os_strcmp(pos, "WPS-CR") == 0)
396 		buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
397 	else
398 		buf = NULL;
399 	if (buf == NULL)
400 		return -1;
401 
402 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
403 					 wpabuf_len(buf));
404 	reply[res++] = '\n';
405 	reply[res] = '\0';
406 
407 	wpabuf_free(buf);
408 
409 	return res;
410 }
411 
412 
413 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
414 						  char *cmd)
415 {
416 	size_t len;
417 	struct wpabuf *req, *sel;
418 	int ret;
419 	char *pos, *role, *type, *pos2;
420 
421 	role = cmd;
422 	pos = os_strchr(role, ' ');
423 	if (pos == NULL)
424 		return -1;
425 	*pos++ = '\0';
426 
427 	type = pos;
428 	pos = os_strchr(type, ' ');
429 	if (pos == NULL)
430 		return -1;
431 	*pos++ = '\0';
432 
433 	pos2 = os_strchr(pos, ' ');
434 	if (pos2 == NULL)
435 		return -1;
436 	*pos2++ = '\0';
437 
438 	len = os_strlen(pos);
439 	if (len & 0x01)
440 		return -1;
441 	len /= 2;
442 
443 	req = wpabuf_alloc(len);
444 	if (req == NULL)
445 		return -1;
446 	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
447 		wpabuf_free(req);
448 		return -1;
449 	}
450 
451 	len = os_strlen(pos2);
452 	if (len & 0x01) {
453 		wpabuf_free(req);
454 		return -1;
455 	}
456 	len /= 2;
457 
458 	sel = wpabuf_alloc(len);
459 	if (sel == NULL) {
460 		wpabuf_free(req);
461 		return -1;
462 	}
463 	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
464 		wpabuf_free(req);
465 		wpabuf_free(sel);
466 		return -1;
467 	}
468 
469 	if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
470 		ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
471 	} else {
472 		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
473 			   "reported: role=%s type=%s", role, type);
474 		ret = -1;
475 	}
476 	wpabuf_free(req);
477 	wpabuf_free(sel);
478 
479 	return ret;
480 }
481 
482 #endif /* CONFIG_WPS_NFC */
483 
484 
485 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
486 					 char *buf, size_t buflen)
487 {
488 	int timeout = 300;
489 	char *pos;
490 	const char *pin_txt;
491 
492 	pos = os_strchr(txt, ' ');
493 	if (pos)
494 		*pos++ = '\0';
495 
496 	if (os_strcmp(txt, "disable") == 0) {
497 		hostapd_wps_ap_pin_disable(hapd);
498 		return os_snprintf(buf, buflen, "OK\n");
499 	}
500 
501 	if (os_strcmp(txt, "random") == 0) {
502 		if (pos)
503 			timeout = atoi(pos);
504 		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
505 		if (pin_txt == NULL)
506 			return -1;
507 		return os_snprintf(buf, buflen, "%s", pin_txt);
508 	}
509 
510 	if (os_strcmp(txt, "get") == 0) {
511 		pin_txt = hostapd_wps_ap_pin_get(hapd);
512 		if (pin_txt == NULL)
513 			return -1;
514 		return os_snprintf(buf, buflen, "%s", pin_txt);
515 	}
516 
517 	if (os_strcmp(txt, "set") == 0) {
518 		char *pin;
519 		if (pos == NULL)
520 			return -1;
521 		pin = pos;
522 		pos = os_strchr(pos, ' ');
523 		if (pos) {
524 			*pos++ = '\0';
525 			timeout = atoi(pos);
526 		}
527 		if (os_strlen(pin) > buflen)
528 			return -1;
529 		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
530 			return -1;
531 		return os_snprintf(buf, buflen, "%s", pin);
532 	}
533 
534 	return -1;
535 }
536 
537 
538 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
539 {
540 	char *pos;
541 	char *ssid, *auth, *encr = NULL, *key = NULL;
542 
543 	ssid = txt;
544 	pos = os_strchr(txt, ' ');
545 	if (!pos)
546 		return -1;
547 	*pos++ = '\0';
548 
549 	auth = pos;
550 	pos = os_strchr(pos, ' ');
551 	if (pos) {
552 		*pos++ = '\0';
553 		encr = pos;
554 		pos = os_strchr(pos, ' ');
555 		if (pos) {
556 			*pos++ = '\0';
557 			key = pos;
558 		}
559 	}
560 
561 	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
562 }
563 
564 
565 static const char * pbc_status_str(enum pbc_status status)
566 {
567 	switch (status) {
568 	case WPS_PBC_STATUS_DISABLE:
569 		return "Disabled";
570 	case WPS_PBC_STATUS_ACTIVE:
571 		return "Active";
572 	case WPS_PBC_STATUS_TIMEOUT:
573 		return "Timed-out";
574 	case WPS_PBC_STATUS_OVERLAP:
575 		return "Overlap";
576 	default:
577 		return "Unknown";
578 	}
579 }
580 
581 
582 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
583 					     char *buf, size_t buflen)
584 {
585 	int ret;
586 	char *pos, *end;
587 
588 	pos = buf;
589 	end = buf + buflen;
590 
591 	ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
592 			  pbc_status_str(hapd->wps_stats.pbc_status));
593 
594 	if (os_snprintf_error(end - pos, ret))
595 		return pos - buf;
596 	pos += ret;
597 
598 	ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
599 			  (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
600 			   "Success":
601 			   (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
602 			    "Failed" : "None")));
603 
604 	if (os_snprintf_error(end - pos, ret))
605 		return pos - buf;
606 	pos += ret;
607 
608 	/* If status == Failure - Add possible Reasons */
609 	if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
610 	   hapd->wps_stats.failure_reason > 0) {
611 		ret = os_snprintf(pos, end - pos,
612 				  "Failure Reason: %s\n",
613 				  wps_ei_str(hapd->wps_stats.failure_reason));
614 
615 		if (os_snprintf_error(end - pos, ret))
616 			return pos - buf;
617 		pos += ret;
618 	}
619 
620 	if (hapd->wps_stats.status) {
621 		ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
622 				  MAC2STR(hapd->wps_stats.peer_addr));
623 
624 		if (os_snprintf_error(end - pos, ret))
625 			return pos - buf;
626 		pos += ret;
627 	}
628 
629 	return pos - buf;
630 }
631 
632 #endif /* CONFIG_WPS */
633 
634 #ifdef CONFIG_HS20
635 
636 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
637 					     const char *cmd)
638 {
639 	u8 addr[ETH_ALEN];
640 	const char *url;
641 
642 	if (hwaddr_aton(cmd, addr))
643 		return -1;
644 	url = cmd + 17;
645 	if (*url == '\0') {
646 		url = NULL;
647 	} else {
648 		if (*url != ' ')
649 			return -1;
650 		url++;
651 		if (*url == '\0')
652 			url = NULL;
653 	}
654 
655 	return hs20_send_wnm_notification(hapd, addr, 1, url);
656 }
657 
658 
659 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
660 					      const char *cmd)
661 {
662 	u8 addr[ETH_ALEN];
663 	int code, reauth_delay, ret;
664 	const char *pos;
665 	size_t url_len;
666 	struct wpabuf *req;
667 
668 	/* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
669 	if (hwaddr_aton(cmd, addr))
670 		return -1;
671 
672 	pos = os_strchr(cmd, ' ');
673 	if (pos == NULL)
674 		return -1;
675 	pos++;
676 	code = atoi(pos);
677 
678 	pos = os_strchr(pos, ' ');
679 	if (pos == NULL)
680 		return -1;
681 	pos++;
682 	reauth_delay = atoi(pos);
683 
684 	url_len = 0;
685 	pos = os_strchr(pos, ' ');
686 	if (pos) {
687 		pos++;
688 		url_len = os_strlen(pos);
689 	}
690 
691 	req = wpabuf_alloc(4 + url_len);
692 	if (req == NULL)
693 		return -1;
694 	wpabuf_put_u8(req, code);
695 	wpabuf_put_le16(req, reauth_delay);
696 	wpabuf_put_u8(req, url_len);
697 	if (pos)
698 		wpabuf_put_data(req, pos, url_len);
699 
700 	wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
701 		   " to indicate imminent deauthentication (code=%d "
702 		   "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
703 	ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
704 	wpabuf_free(req);
705 	return ret;
706 }
707 
708 #endif /* CONFIG_HS20 */
709 
710 
711 #ifdef CONFIG_INTERWORKING
712 
713 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
714 					      const char *cmd)
715 {
716 	u8 qos_map_set[16 + 2 * 21], count = 0;
717 	const char *pos = cmd;
718 	int val, ret;
719 
720 	for (;;) {
721 		if (count == sizeof(qos_map_set)) {
722 			wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
723 			return -1;
724 		}
725 
726 		val = atoi(pos);
727 		if (val < 0 || val > 255) {
728 			wpa_printf(MSG_INFO, "Invalid QoS Map Set");
729 			return -1;
730 		}
731 
732 		qos_map_set[count++] = val;
733 		pos = os_strchr(pos, ',');
734 		if (!pos)
735 			break;
736 		pos++;
737 	}
738 
739 	if (count < 16 || count & 1) {
740 		wpa_printf(MSG_INFO, "Invalid QoS Map Set");
741 		return -1;
742 	}
743 
744 	ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
745 	if (ret) {
746 		wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
747 		return -1;
748 	}
749 
750 	os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
751 	hapd->conf->qos_map_set_len = count;
752 
753 	return 0;
754 }
755 
756 
757 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
758 						const char *cmd)
759 {
760 	u8 addr[ETH_ALEN];
761 	struct sta_info *sta;
762 	struct wpabuf *buf;
763 	u8 *qos_map_set = hapd->conf->qos_map_set;
764 	u8 qos_map_set_len = hapd->conf->qos_map_set_len;
765 	int ret;
766 
767 	if (!qos_map_set_len) {
768 		wpa_printf(MSG_INFO, "QoS Map Set is not set");
769 		return -1;
770 	}
771 
772 	if (hwaddr_aton(cmd, addr))
773 		return -1;
774 
775 	sta = ap_get_sta(hapd, addr);
776 	if (sta == NULL) {
777 		wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
778 			   "for QoS Map Configuration message",
779 			   MAC2STR(addr));
780 		return -1;
781 	}
782 
783 	if (!sta->qos_map_enabled) {
784 		wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
785 			   "support for QoS Map", MAC2STR(addr));
786 		return -1;
787 	}
788 
789 	buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
790 	if (buf == NULL)
791 		return -1;
792 
793 	wpabuf_put_u8(buf, WLAN_ACTION_QOS);
794 	wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
795 
796 	/* QoS Map Set Element */
797 	wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
798 	wpabuf_put_u8(buf, qos_map_set_len);
799 	wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
800 
801 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
802 				      wpabuf_head(buf), wpabuf_len(buf));
803 	wpabuf_free(buf);
804 
805 	return ret;
806 }
807 
808 #endif /* CONFIG_INTERWORKING */
809 
810 
811 #ifdef CONFIG_WNM
812 
813 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
814 						const char *cmd)
815 {
816 	u8 addr[ETH_ALEN];
817 	int disassoc_timer;
818 	struct sta_info *sta;
819 
820 	if (hwaddr_aton(cmd, addr))
821 		return -1;
822 	if (cmd[17] != ' ')
823 		return -1;
824 	disassoc_timer = atoi(cmd + 17);
825 
826 	sta = ap_get_sta(hapd, addr);
827 	if (sta == NULL) {
828 		wpa_printf(MSG_DEBUG, "Station " MACSTR
829 			   " not found for disassociation imminent message",
830 			   MAC2STR(addr));
831 		return -1;
832 	}
833 
834 	return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
835 }
836 
837 
838 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
839 					   const char *cmd)
840 {
841 	u8 addr[ETH_ALEN];
842 	const char *url, *timerstr;
843 	int disassoc_timer;
844 	struct sta_info *sta;
845 
846 	if (hwaddr_aton(cmd, addr))
847 		return -1;
848 
849 	sta = ap_get_sta(hapd, addr);
850 	if (sta == NULL) {
851 		wpa_printf(MSG_DEBUG, "Station " MACSTR
852 			   " not found for ESS disassociation imminent message",
853 			   MAC2STR(addr));
854 		return -1;
855 	}
856 
857 	timerstr = cmd + 17;
858 	if (*timerstr != ' ')
859 		return -1;
860 	timerstr++;
861 	disassoc_timer = atoi(timerstr);
862 	if (disassoc_timer < 0 || disassoc_timer > 65535)
863 		return -1;
864 
865 	url = os_strchr(timerstr, ' ');
866 	if (url == NULL)
867 		return -1;
868 	url++;
869 
870 	return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
871 }
872 
873 
874 static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
875 					 const char *cmd)
876 {
877 	u8 addr[ETH_ALEN];
878 	const char *pos, *end;
879 	int disassoc_timer = 0;
880 	struct sta_info *sta;
881 	u8 req_mode = 0, valid_int = 0x01;
882 	u8 bss_term_dur[12];
883 	char *url = NULL;
884 	int ret;
885 	u8 nei_rep[1000];
886 	u8 *nei_pos = nei_rep;
887 
888 	if (hwaddr_aton(cmd, addr)) {
889 		wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
890 		return -1;
891 	}
892 
893 	sta = ap_get_sta(hapd, addr);
894 	if (sta == NULL) {
895 		wpa_printf(MSG_DEBUG, "Station " MACSTR
896 			   " not found for BSS TM Request message",
897 			   MAC2STR(addr));
898 		return -1;
899 	}
900 
901 	pos = os_strstr(cmd, " disassoc_timer=");
902 	if (pos) {
903 		pos += 16;
904 		disassoc_timer = atoi(pos);
905 		if (disassoc_timer < 0 || disassoc_timer > 65535) {
906 			wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
907 			return -1;
908 		}
909 	}
910 
911 	pos = os_strstr(cmd, " valid_int=");
912 	if (pos) {
913 		pos += 11;
914 		valid_int = atoi(pos);
915 	}
916 
917 	pos = os_strstr(cmd, " bss_term=");
918 	if (pos) {
919 		pos += 10;
920 		req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
921 		/* TODO: TSF configurable/learnable */
922 		bss_term_dur[0] = 4; /* Subelement ID */
923 		bss_term_dur[1] = 10; /* Length */
924 		os_memset(bss_term_dur, 2, 8);
925 		end = os_strchr(pos, ',');
926 		if (end == NULL) {
927 			wpa_printf(MSG_DEBUG, "Invalid bss_term data");
928 			return -1;
929 		}
930 		end++;
931 		WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
932 	}
933 
934 
935 	/*
936 	 * BSS Transition Candidate List Entries - Neighbor Report elements
937 	 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
938 	 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
939 	 */
940 	pos = cmd;
941 	while (pos) {
942 		u8 *nei_start;
943 		long int val;
944 		char *endptr, *tmp;
945 
946 		pos = os_strstr(pos, " neighbor=");
947 		if (!pos)
948 			break;
949 		if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
950 			wpa_printf(MSG_DEBUG,
951 				   "Not enough room for additional neighbor");
952 			return -1;
953 		}
954 		pos += 10;
955 
956 		nei_start = nei_pos;
957 		*nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
958 		nei_pos++; /* length to be filled in */
959 
960 		if (hwaddr_aton(pos, nei_pos)) {
961 			wpa_printf(MSG_DEBUG, "Invalid BSSID");
962 			return -1;
963 		}
964 		nei_pos += ETH_ALEN;
965 		pos += 17;
966 		if (*pos != ',') {
967 			wpa_printf(MSG_DEBUG, "Missing BSSID Information");
968 			return -1;
969 		}
970 		pos++;
971 
972 		val = strtol(pos, &endptr, 0);
973 		WPA_PUT_LE32(nei_pos, val);
974 		nei_pos += 4;
975 		if (*endptr != ',') {
976 			wpa_printf(MSG_DEBUG, "Missing Operating Class");
977 			return -1;
978 		}
979 		pos = endptr + 1;
980 
981 		*nei_pos++ = atoi(pos); /* Operating Class */
982 		pos = os_strchr(pos, ',');
983 		if (pos == NULL) {
984 			wpa_printf(MSG_DEBUG, "Missing Channel Number");
985 			return -1;
986 		}
987 		pos++;
988 
989 		*nei_pos++ = atoi(pos); /* Channel Number */
990 		pos = os_strchr(pos, ',');
991 		if (pos == NULL) {
992 			wpa_printf(MSG_DEBUG, "Missing PHY Type");
993 			return -1;
994 		}
995 		pos++;
996 
997 		*nei_pos++ = atoi(pos); /* PHY Type */
998 		end = os_strchr(pos, ' ');
999 		tmp = os_strchr(pos, ',');
1000 		if (tmp && (!end || tmp < end)) {
1001 			/* Optional Subelements (hexdump) */
1002 			size_t len;
1003 
1004 			pos = tmp + 1;
1005 			end = os_strchr(pos, ' ');
1006 			if (end)
1007 				len = end - pos;
1008 			else
1009 				len = os_strlen(pos);
1010 			if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
1011 				wpa_printf(MSG_DEBUG,
1012 					   "Not enough room for neighbor subelements");
1013 				return -1;
1014 			}
1015 			if (len & 0x01 ||
1016 			    hexstr2bin(pos, nei_pos, len / 2) < 0) {
1017 				wpa_printf(MSG_DEBUG,
1018 					   "Invalid neighbor subelement info");
1019 				return -1;
1020 			}
1021 			nei_pos += len / 2;
1022 			pos = end;
1023 		}
1024 
1025 		nei_start[1] = nei_pos - nei_start - 2;
1026 	}
1027 
1028 	pos = os_strstr(cmd, " url=");
1029 	if (pos) {
1030 		size_t len;
1031 		pos += 5;
1032 		end = os_strchr(pos, ' ');
1033 		if (end)
1034 			len = end - pos;
1035 		else
1036 			len = os_strlen(pos);
1037 		url = os_malloc(len + 1);
1038 		if (url == NULL)
1039 			return -1;
1040 		os_memcpy(url, pos, len);
1041 		url[len] = '\0';
1042 		req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
1043 	}
1044 
1045 	if (os_strstr(cmd, " pref=1"))
1046 		req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
1047 	if (os_strstr(cmd, " abridged=1"))
1048 		req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
1049 	if (os_strstr(cmd, " disassoc_imminent=1"))
1050 		req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
1051 
1052 	ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
1053 				  valid_int, bss_term_dur, url,
1054 				  nei_pos > nei_rep ? nei_rep : NULL,
1055 				  nei_pos - nei_rep);
1056 	os_free(url);
1057 	return ret;
1058 }
1059 
1060 #endif /* CONFIG_WNM */
1061 
1062 
1063 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
1064 					   char *buf, size_t buflen)
1065 {
1066 	int ret = 0;
1067 	char *pos, *end;
1068 
1069 	pos = buf;
1070 	end = buf + buflen;
1071 
1072 	WPA_ASSERT(hapd->conf->wpa_key_mgmt);
1073 
1074 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
1075 		ret = os_snprintf(pos, end - pos, "WPA-PSK ");
1076 		if (os_snprintf_error(end - pos, ret))
1077 			return pos - buf;
1078 		pos += ret;
1079 	}
1080 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1081 		ret = os_snprintf(pos, end - pos, "WPA-EAP ");
1082 		if (os_snprintf_error(end - pos, ret))
1083 			return pos - buf;
1084 		pos += ret;
1085 	}
1086 #ifdef CONFIG_IEEE80211R
1087 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1088 		ret = os_snprintf(pos, end - pos, "FT-PSK ");
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_IEEE8021X) {
1094 		ret = os_snprintf(pos, end - pos, "FT-EAP ");
1095 		if (os_snprintf_error(end - pos, ret))
1096 			return pos - buf;
1097 		pos += ret;
1098 	}
1099 #ifdef CONFIG_SAE
1100 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
1101 		ret = os_snprintf(pos, end - pos, "FT-SAE ");
1102 		if (os_snprintf_error(end - pos, ret))
1103 			return pos - buf;
1104 		pos += ret;
1105 	}
1106 #endif /* CONFIG_SAE */
1107 #endif /* CONFIG_IEEE80211R */
1108 #ifdef CONFIG_IEEE80211W
1109 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1110 		ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
1111 		if (os_snprintf_error(end - pos, ret))
1112 			return pos - buf;
1113 		pos += ret;
1114 	}
1115 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1116 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
1117 		if (os_snprintf_error(end - pos, ret))
1118 			return pos - buf;
1119 		pos += ret;
1120 	}
1121 #endif /* CONFIG_IEEE80211W */
1122 #ifdef CONFIG_SAE
1123 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
1124 		ret = os_snprintf(pos, end - pos, "SAE ");
1125 		if (os_snprintf_error(end - pos, ret))
1126 			return pos - buf;
1127 		pos += ret;
1128 	}
1129 #endif /* CONFIG_SAE */
1130 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1131 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
1132 		if (os_snprintf_error(end - pos, ret))
1133 			return pos - buf;
1134 		pos += ret;
1135 	}
1136 	if (hapd->conf->wpa_key_mgmt &
1137 	    WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1138 		ret = os_snprintf(pos, end - pos,
1139 				  "WPA-EAP-SUITE-B-192 ");
1140 		if (os_snprintf_error(end - pos, ret))
1141 			return pos - buf;
1142 		pos += ret;
1143 	}
1144 
1145 	if (pos > buf && *(pos - 1) == ' ') {
1146 		*(pos - 1) = '\0';
1147 		pos--;
1148 	}
1149 
1150 	return pos - buf;
1151 }
1152 
1153 
1154 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
1155 					 char *buf, size_t buflen)
1156 {
1157 	int ret;
1158 	char *pos, *end;
1159 
1160 	pos = buf;
1161 	end = buf + buflen;
1162 
1163 	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
1164 			  "ssid=%s\n",
1165 			  MAC2STR(hapd->own_addr),
1166 			  wpa_ssid_txt(hapd->conf->ssid.ssid,
1167 				       hapd->conf->ssid.ssid_len));
1168 	if (os_snprintf_error(end - pos, ret))
1169 		return pos - buf;
1170 	pos += ret;
1171 
1172 #ifdef CONFIG_WPS
1173 	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
1174 			  hapd->conf->wps_state == 0 ? "disabled" :
1175 			  (hapd->conf->wps_state == 1 ? "not configured" :
1176 			   "configured"));
1177 	if (os_snprintf_error(end - pos, ret))
1178 		return pos - buf;
1179 	pos += ret;
1180 
1181 	if (hapd->conf->wps_state && hapd->conf->wpa &&
1182 	    hapd->conf->ssid.wpa_passphrase) {
1183 		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
1184 				  hapd->conf->ssid.wpa_passphrase);
1185 		if (os_snprintf_error(end - pos, ret))
1186 			return pos - buf;
1187 		pos += ret;
1188 	}
1189 
1190 	if (hapd->conf->wps_state && hapd->conf->wpa &&
1191 	    hapd->conf->ssid.wpa_psk &&
1192 	    hapd->conf->ssid.wpa_psk->group) {
1193 		char hex[PMK_LEN * 2 + 1];
1194 		wpa_snprintf_hex(hex, sizeof(hex),
1195 				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
1196 		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
1197 		if (os_snprintf_error(end - pos, ret))
1198 			return pos - buf;
1199 		pos += ret;
1200 	}
1201 #endif /* CONFIG_WPS */
1202 
1203 	if (hapd->conf->wpa) {
1204 		ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
1205 		if (os_snprintf_error(end - pos, ret))
1206 			return pos - buf;
1207 		pos += ret;
1208 	}
1209 
1210 	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
1211 		ret = os_snprintf(pos, end - pos, "key_mgmt=");
1212 		if (os_snprintf_error(end - pos, ret))
1213 			return pos - buf;
1214 		pos += ret;
1215 
1216 		pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
1217 
1218 		ret = os_snprintf(pos, end - pos, "\n");
1219 		if (os_snprintf_error(end - pos, ret))
1220 			return pos - buf;
1221 		pos += ret;
1222 	}
1223 
1224 	if (hapd->conf->wpa) {
1225 		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
1226 				  wpa_cipher_txt(hapd->conf->wpa_group));
1227 		if (os_snprintf_error(end - pos, ret))
1228 			return pos - buf;
1229 		pos += ret;
1230 	}
1231 
1232 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
1233 		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
1234 		if (os_snprintf_error(end - pos, ret))
1235 			return pos - buf;
1236 		pos += ret;
1237 
1238 		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
1239 					" ");
1240 		if (ret < 0)
1241 			return pos - buf;
1242 		pos += ret;
1243 
1244 		ret = os_snprintf(pos, end - pos, "\n");
1245 		if (os_snprintf_error(end - pos, ret))
1246 			return pos - buf;
1247 		pos += ret;
1248 	}
1249 
1250 	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1251 		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1252 		if (os_snprintf_error(end - pos, ret))
1253 			return pos - buf;
1254 		pos += ret;
1255 
1256 		ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1257 					" ");
1258 		if (ret < 0)
1259 			return pos - buf;
1260 		pos += ret;
1261 
1262 		ret = os_snprintf(pos, end - pos, "\n");
1263 		if (os_snprintf_error(end - pos, ret))
1264 			return pos - buf;
1265 		pos += ret;
1266 	}
1267 
1268 	return pos - buf;
1269 }
1270 
1271 
1272 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1273 {
1274 	char *value;
1275 	int ret = 0;
1276 
1277 	value = os_strchr(cmd, ' ');
1278 	if (value == NULL)
1279 		return -1;
1280 	*value++ = '\0';
1281 
1282 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1283 	if (0) {
1284 #ifdef CONFIG_WPS_TESTING
1285 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1286 		long int val;
1287 		val = strtol(value, NULL, 0);
1288 		if (val < 0 || val > 0xff) {
1289 			ret = -1;
1290 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
1291 				   "wps_version_number %ld", val);
1292 		} else {
1293 			wps_version_number = val;
1294 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1295 				   "version %u.%u",
1296 				   (wps_version_number & 0xf0) >> 4,
1297 				   wps_version_number & 0x0f);
1298 			hostapd_wps_update_ie(hapd);
1299 		}
1300 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
1301 		wps_testing_dummy_cred = atoi(value);
1302 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
1303 			   wps_testing_dummy_cred);
1304 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1305 		wps_corrupt_pkhash = atoi(value);
1306 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1307 			   wps_corrupt_pkhash);
1308 #endif /* CONFIG_WPS_TESTING */
1309 #ifdef CONFIG_INTERWORKING
1310 	} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
1311 		int val = atoi(value);
1312 		if (val <= 0)
1313 			ret = -1;
1314 		else
1315 			hapd->gas_frag_limit = val;
1316 #endif /* CONFIG_INTERWORKING */
1317 #ifdef CONFIG_TESTING_OPTIONS
1318 	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1319 		hapd->ext_mgmt_frame_handling = atoi(value);
1320 	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
1321 		hapd->ext_eapol_frame_io = atoi(value);
1322 #endif /* CONFIG_TESTING_OPTIONS */
1323 	} else {
1324 		struct sta_info *sta;
1325 		int vlan_id;
1326 
1327 		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1328 		if (ret)
1329 			return ret;
1330 
1331 		if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1332 			for (sta = hapd->sta_list; sta; sta = sta->next) {
1333 				if (hostapd_maclist_found(
1334 					    hapd->conf->deny_mac,
1335 					    hapd->conf->num_deny_mac, sta->addr,
1336 					    &vlan_id) &&
1337 				    (!vlan_id || vlan_id == sta->vlan_id))
1338 					ap_sta_disconnect(
1339 						hapd, sta, sta->addr,
1340 						WLAN_REASON_UNSPECIFIED);
1341 			}
1342 		} else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
1343 			   os_strcasecmp(cmd, "accept_mac_file") == 0) {
1344 			for (sta = hapd->sta_list; sta; sta = sta->next) {
1345 				if (!hostapd_maclist_found(
1346 					    hapd->conf->accept_mac,
1347 					    hapd->conf->num_accept_mac,
1348 					    sta->addr, &vlan_id) ||
1349 				    (vlan_id && vlan_id != sta->vlan_id))
1350 					ap_sta_disconnect(
1351 						hapd, sta, sta->addr,
1352 						WLAN_REASON_UNSPECIFIED);
1353 			}
1354 		}
1355 	}
1356 
1357 	return ret;
1358 }
1359 
1360 
1361 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1362 				  char *buf, size_t buflen)
1363 {
1364 	int res;
1365 
1366 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1367 
1368 	if (os_strcmp(cmd, "version") == 0) {
1369 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1370 		if (os_snprintf_error(buflen, res))
1371 			return -1;
1372 		return res;
1373 	} else if (os_strcmp(cmd, "tls_library") == 0) {
1374 		res = tls_get_library_version(buf, buflen);
1375 		if (os_snprintf_error(buflen, res))
1376 			return -1;
1377 		return res;
1378 	}
1379 
1380 	return -1;
1381 }
1382 
1383 
1384 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1385 {
1386 	if (hostapd_enable_iface(iface) < 0) {
1387 		wpa_printf(MSG_ERROR, "Enabling of interface failed");
1388 		return -1;
1389 	}
1390 	return 0;
1391 }
1392 
1393 
1394 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1395 {
1396 	if (hostapd_reload_iface(iface) < 0) {
1397 		wpa_printf(MSG_ERROR, "Reloading of interface failed");
1398 		return -1;
1399 	}
1400 	return 0;
1401 }
1402 
1403 
1404 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1405 {
1406 	if (hostapd_disable_iface(iface) < 0) {
1407 		wpa_printf(MSG_ERROR, "Disabling of interface failed");
1408 		return -1;
1409 	}
1410 	return 0;
1411 }
1412 
1413 
1414 #ifdef CONFIG_TESTING_OPTIONS
1415 
1416 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1417 {
1418 	union wpa_event_data data;
1419 	char *pos, *param;
1420 	enum wpa_event_type event;
1421 
1422 	wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1423 
1424 	os_memset(&data, 0, sizeof(data));
1425 
1426 	param = os_strchr(cmd, ' ');
1427 	if (param == NULL)
1428 		return -1;
1429 	*param++ = '\0';
1430 
1431 	if (os_strcmp(cmd, "DETECTED") == 0)
1432 		event = EVENT_DFS_RADAR_DETECTED;
1433 	else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1434 		event = EVENT_DFS_CAC_FINISHED;
1435 	else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1436 		event = EVENT_DFS_CAC_ABORTED;
1437 	else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1438 		event = EVENT_DFS_NOP_FINISHED;
1439 	else {
1440 		wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1441 			   cmd);
1442 		return -1;
1443 	}
1444 
1445 	pos = os_strstr(param, "freq=");
1446 	if (pos)
1447 		data.dfs_event.freq = atoi(pos + 5);
1448 
1449 	pos = os_strstr(param, "ht_enabled=1");
1450 	if (pos)
1451 		data.dfs_event.ht_enabled = 1;
1452 
1453 	pos = os_strstr(param, "chan_offset=");
1454 	if (pos)
1455 		data.dfs_event.chan_offset = atoi(pos + 12);
1456 
1457 	pos = os_strstr(param, "chan_width=");
1458 	if (pos)
1459 		data.dfs_event.chan_width = atoi(pos + 11);
1460 
1461 	pos = os_strstr(param, "cf1=");
1462 	if (pos)
1463 		data.dfs_event.cf1 = atoi(pos + 4);
1464 
1465 	pos = os_strstr(param, "cf2=");
1466 	if (pos)
1467 		data.dfs_event.cf2 = atoi(pos + 4);
1468 
1469 	wpa_supplicant_event(hapd, event, &data);
1470 
1471 	return 0;
1472 }
1473 
1474 
1475 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1476 {
1477 	size_t len;
1478 	u8 *buf;
1479 	int res;
1480 
1481 	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1482 
1483 	len = os_strlen(cmd);
1484 	if (len & 1)
1485 		return -1;
1486 	len /= 2;
1487 
1488 	buf = os_malloc(len);
1489 	if (buf == NULL)
1490 		return -1;
1491 
1492 	if (hexstr2bin(cmd, buf, len) < 0) {
1493 		os_free(buf);
1494 		return -1;
1495 	}
1496 
1497 	res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1498 	os_free(buf);
1499 	return res;
1500 }
1501 
1502 
1503 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1504 {
1505 	char *pos;
1506 	u8 src[ETH_ALEN], *buf;
1507 	int used;
1508 	size_t len;
1509 
1510 	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1511 
1512 	pos = cmd;
1513 	used = hwaddr_aton2(pos, src);
1514 	if (used < 0)
1515 		return -1;
1516 	pos += used;
1517 	while (*pos == ' ')
1518 		pos++;
1519 
1520 	len = os_strlen(pos);
1521 	if (len & 1)
1522 		return -1;
1523 	len /= 2;
1524 
1525 	buf = os_malloc(len);
1526 	if (buf == NULL)
1527 		return -1;
1528 
1529 	if (hexstr2bin(pos, buf, len) < 0) {
1530 		os_free(buf);
1531 		return -1;
1532 	}
1533 
1534 	ieee802_1x_receive(hapd, src, buf, len);
1535 	os_free(buf);
1536 
1537 	return 0;
1538 }
1539 
1540 
1541 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1542 {
1543 	size_t i;
1544 	u32 sum = 0;
1545 	const u16 *pos = buf;
1546 
1547 	for (i = 0; i < len / 2; i++)
1548 		sum += *pos++;
1549 
1550 	while (sum >> 16)
1551 		sum = (sum & 0xffff) + (sum >> 16);
1552 
1553 	return sum ^ 0xffff;
1554 }
1555 
1556 
1557 #define HWSIM_PACKETLEN 1500
1558 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1559 
1560 void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1561 			  size_t len)
1562 {
1563 	struct hostapd_data *hapd = ctx;
1564 	const struct ether_header *eth;
1565 	struct iphdr ip;
1566 	const u8 *pos;
1567 	unsigned int i;
1568 
1569 	if (len != HWSIM_PACKETLEN)
1570 		return;
1571 
1572 	eth = (const struct ether_header *) buf;
1573 	os_memcpy(&ip, eth + 1, sizeof(ip));
1574 	pos = &buf[sizeof(*eth) + sizeof(ip)];
1575 
1576 	if (ip.ihl != 5 || ip.version != 4 ||
1577 	    ntohs(ip.tot_len) != HWSIM_IP_LEN)
1578 		return;
1579 
1580 	for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
1581 		if (*pos != (u8) i)
1582 			return;
1583 		pos++;
1584 	}
1585 
1586 	wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
1587 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
1588 }
1589 
1590 
1591 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1592 					       char *cmd)
1593 {
1594 	int enabled = atoi(cmd);
1595 	char *pos;
1596 	const char *ifname;
1597 
1598 	if (!enabled) {
1599 		if (hapd->l2_test) {
1600 			l2_packet_deinit(hapd->l2_test);
1601 			hapd->l2_test = NULL;
1602 			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1603 				"test data: Disabled");
1604 		}
1605 		return 0;
1606 	}
1607 
1608 	if (hapd->l2_test)
1609 		return 0;
1610 
1611 	pos = os_strstr(cmd, " ifname=");
1612 	if (pos)
1613 		ifname = pos + 8;
1614 	else
1615 		ifname = hapd->conf->iface;
1616 
1617 	hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
1618 					ETHERTYPE_IP, hostapd_data_test_rx,
1619 					hapd, 1);
1620 	if (hapd->l2_test == NULL)
1621 		return -1;
1622 
1623 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1624 
1625 	return 0;
1626 }
1627 
1628 
1629 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1630 {
1631 	u8 dst[ETH_ALEN], src[ETH_ALEN];
1632 	char *pos;
1633 	int used;
1634 	long int val;
1635 	u8 tos;
1636 	u8 buf[2 + HWSIM_PACKETLEN];
1637 	struct ether_header *eth;
1638 	struct iphdr *ip;
1639 	u8 *dpos;
1640 	unsigned int i;
1641 
1642 	if (hapd->l2_test == NULL)
1643 		return -1;
1644 
1645 	/* format: <dst> <src> <tos> */
1646 
1647 	pos = cmd;
1648 	used = hwaddr_aton2(pos, dst);
1649 	if (used < 0)
1650 		return -1;
1651 	pos += used;
1652 	while (*pos == ' ')
1653 		pos++;
1654 	used = hwaddr_aton2(pos, src);
1655 	if (used < 0)
1656 		return -1;
1657 	pos += used;
1658 
1659 	val = strtol(pos, NULL, 0);
1660 	if (val < 0 || val > 0xff)
1661 		return -1;
1662 	tos = val;
1663 
1664 	eth = (struct ether_header *) &buf[2];
1665 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
1666 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
1667 	eth->ether_type = htons(ETHERTYPE_IP);
1668 	ip = (struct iphdr *) (eth + 1);
1669 	os_memset(ip, 0, sizeof(*ip));
1670 	ip->ihl = 5;
1671 	ip->version = 4;
1672 	ip->ttl = 64;
1673 	ip->tos = tos;
1674 	ip->tot_len = htons(HWSIM_IP_LEN);
1675 	ip->protocol = 1;
1676 	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
1677 	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
1678 	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
1679 	dpos = (u8 *) (ip + 1);
1680 	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
1681 		*dpos++ = i;
1682 
1683 	if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
1684 			   HWSIM_PACKETLEN) < 0)
1685 		return -1;
1686 
1687 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
1688 		" src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
1689 
1690 	return 0;
1691 }
1692 
1693 
1694 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
1695 					      char *cmd)
1696 {
1697 	u8 *buf;
1698 	struct ether_header *eth;
1699 	struct l2_packet_data *l2 = NULL;
1700 	size_t len;
1701 	u16 ethertype;
1702 	int res = -1;
1703 	const char *ifname = hapd->conf->iface;
1704 
1705 	if (os_strncmp(cmd, "ifname=", 7) == 0) {
1706 		cmd += 7;
1707 		ifname = cmd;
1708 		cmd = os_strchr(cmd, ' ');
1709 		if (cmd == NULL)
1710 			return -1;
1711 		*cmd++ = '\0';
1712 	}
1713 
1714 	len = os_strlen(cmd);
1715 	if (len & 1 || len < ETH_HLEN * 2)
1716 		return -1;
1717 	len /= 2;
1718 
1719 	buf = os_malloc(len);
1720 	if (buf == NULL)
1721 		return -1;
1722 
1723 	if (hexstr2bin(cmd, buf, len) < 0)
1724 		goto done;
1725 
1726 	eth = (struct ether_header *) buf;
1727 	ethertype = ntohs(eth->ether_type);
1728 
1729 	l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
1730 			    hostapd_data_test_rx, hapd, 1);
1731 	if (l2 == NULL)
1732 		goto done;
1733 
1734 	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
1735 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
1736 done:
1737 	if (l2)
1738 		l2_packet_deinit(l2);
1739 	os_free(buf);
1740 
1741 	return res < 0 ? -1 : 0;
1742 }
1743 
1744 
1745 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
1746 {
1747 #ifdef WPA_TRACE_BFD
1748 	extern char wpa_trace_fail_func[256];
1749 	extern unsigned int wpa_trace_fail_after;
1750 	char *pos;
1751 
1752 	wpa_trace_fail_after = atoi(cmd);
1753 	pos = os_strchr(cmd, ':');
1754 	if (pos) {
1755 		pos++;
1756 		os_strlcpy(wpa_trace_fail_func, pos,
1757 			   sizeof(wpa_trace_fail_func));
1758 	} else {
1759 		wpa_trace_fail_after = 0;
1760 	}
1761 
1762 	return 0;
1763 #else /* WPA_TRACE_BFD */
1764 	return -1;
1765 #endif /* WPA_TRACE_BFD */
1766 }
1767 
1768 
1769 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
1770 				       char *buf, size_t buflen)
1771 {
1772 #ifdef WPA_TRACE_BFD
1773 	extern char wpa_trace_fail_func[256];
1774 	extern unsigned int wpa_trace_fail_after;
1775 
1776 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
1777 			   wpa_trace_fail_func);
1778 #else /* WPA_TRACE_BFD */
1779 	return -1;
1780 #endif /* WPA_TRACE_BFD */
1781 }
1782 
1783 
1784 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
1785 {
1786 #ifdef WPA_TRACE_BFD
1787 	extern char wpa_trace_test_fail_func[256];
1788 	extern unsigned int wpa_trace_test_fail_after;
1789 	char *pos;
1790 
1791 	wpa_trace_test_fail_after = atoi(cmd);
1792 	pos = os_strchr(cmd, ':');
1793 	if (pos) {
1794 		pos++;
1795 		os_strlcpy(wpa_trace_test_fail_func, pos,
1796 			   sizeof(wpa_trace_test_fail_func));
1797 	} else {
1798 		wpa_trace_test_fail_after = 0;
1799 	}
1800 
1801 	return 0;
1802 #else /* WPA_TRACE_BFD */
1803 	return -1;
1804 #endif /* WPA_TRACE_BFD */
1805 }
1806 
1807 
1808 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
1809 				 char *buf, size_t buflen)
1810 {
1811 #ifdef WPA_TRACE_BFD
1812 	extern char wpa_trace_test_fail_func[256];
1813 	extern unsigned int wpa_trace_test_fail_after;
1814 
1815 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
1816 			   wpa_trace_test_fail_func);
1817 #else /* WPA_TRACE_BFD */
1818 	return -1;
1819 #endif /* WPA_TRACE_BFD */
1820 }
1821 
1822 #endif /* CONFIG_TESTING_OPTIONS */
1823 
1824 
1825 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
1826 					  char *pos)
1827 {
1828 #ifdef NEED_AP_MLME
1829 	struct csa_settings settings;
1830 	int ret;
1831 	unsigned int i;
1832 
1833 	ret = hostapd_parse_csa_settings(pos, &settings);
1834 	if (ret)
1835 		return ret;
1836 
1837 	for (i = 0; i < iface->num_bss; i++) {
1838 		ret = hostapd_switch_channel(iface->bss[i], &settings);
1839 		if (ret) {
1840 			/* FIX: What do we do if CSA fails in the middle of
1841 			 * submitting multi-BSS CSA requests? */
1842 			return ret;
1843 		}
1844 	}
1845 
1846 	return 0;
1847 #else /* NEED_AP_MLME */
1848 	return -1;
1849 #endif /* NEED_AP_MLME */
1850 }
1851 
1852 
1853 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
1854 				  int reply_size, const char *param)
1855 {
1856 #ifdef RADIUS_SERVER
1857 	if (os_strcmp(param, "radius_server") == 0) {
1858 		return radius_server_get_mib(hapd->radius_srv, reply,
1859 					     reply_size);
1860 	}
1861 #endif /* RADIUS_SERVER */
1862 	return -1;
1863 }
1864 
1865 
1866 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
1867 				     char *buf, size_t buflen)
1868 {
1869 	int ret;
1870 	char *pos;
1871 	u8 *data = NULL;
1872 	unsigned int vendor_id, subcmd;
1873 	struct wpabuf *reply;
1874 	size_t data_len = 0;
1875 
1876 	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
1877 	vendor_id = strtoul(cmd, &pos, 16);
1878 	if (!isblank(*pos))
1879 		return -EINVAL;
1880 
1881 	subcmd = strtoul(pos, &pos, 10);
1882 
1883 	if (*pos != '\0') {
1884 		if (!isblank(*pos++))
1885 			return -EINVAL;
1886 		data_len = os_strlen(pos);
1887 	}
1888 
1889 	if (data_len) {
1890 		data_len /= 2;
1891 		data = os_malloc(data_len);
1892 		if (!data)
1893 			return -ENOBUFS;
1894 
1895 		if (hexstr2bin(pos, data, data_len)) {
1896 			wpa_printf(MSG_DEBUG,
1897 				   "Vendor command: wrong parameter format");
1898 			os_free(data);
1899 			return -EINVAL;
1900 		}
1901 	}
1902 
1903 	reply = wpabuf_alloc((buflen - 1) / 2);
1904 	if (!reply) {
1905 		os_free(data);
1906 		return -ENOBUFS;
1907 	}
1908 
1909 	ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
1910 				     reply);
1911 
1912 	if (ret == 0)
1913 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
1914 				       wpabuf_len(reply));
1915 
1916 	wpabuf_free(reply);
1917 	os_free(data);
1918 
1919 	return ret;
1920 }
1921 
1922 
1923 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
1924 					   const char *cmd)
1925 {
1926 	u8 addr[ETH_ALEN];
1927 	struct sta_info *sta;
1928 
1929 	if (hwaddr_aton(cmd, addr))
1930 		return -1;
1931 
1932 	sta = ap_get_sta(hapd, addr);
1933 	if (!sta || !sta->eapol_sm)
1934 		return -1;
1935 
1936 	eapol_auth_reauthenticate(sta->eapol_sm);
1937 	return 0;
1938 }
1939 
1940 
1941 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
1942 {
1943 	u8 addr[ETH_ALEN];
1944 	struct sta_info *sta;
1945 	char *pos = cmd, *param;
1946 
1947 	if (hwaddr_aton(pos, addr) || pos[17] != ' ')
1948 		return -1;
1949 	pos += 18;
1950 	param = pos;
1951 	pos = os_strchr(pos, ' ');
1952 	if (!pos)
1953 		return -1;
1954 	*pos++ = '\0';
1955 
1956 	sta = ap_get_sta(hapd, addr);
1957 	if (!sta || !sta->eapol_sm)
1958 		return -1;
1959 
1960 	return eapol_auth_set_conf(sta->eapol_sm, param, pos);
1961 }
1962 
1963 
1964 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
1965 					char *buf, size_t buflen)
1966 {
1967 	char *pos, *end, *stamp;
1968 	int ret;
1969 
1970 	/* cmd: "LOG_LEVEL [<level>]" */
1971 	if (*cmd == '\0') {
1972 		pos = buf;
1973 		end = buf + buflen;
1974 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
1975 				  "Timestamp: %d\n",
1976 				  debug_level_str(wpa_debug_level),
1977 				  wpa_debug_timestamp);
1978 		if (os_snprintf_error(end - pos, ret))
1979 			ret = 0;
1980 
1981 		return ret;
1982 	}
1983 
1984 	while (*cmd == ' ')
1985 		cmd++;
1986 
1987 	stamp = os_strchr(cmd, ' ');
1988 	if (stamp) {
1989 		*stamp++ = '\0';
1990 		while (*stamp == ' ') {
1991 			stamp++;
1992 		}
1993 	}
1994 
1995 	if (os_strlen(cmd)) {
1996 		int level = str_to_debug_level(cmd);
1997 		if (level < 0)
1998 			return -1;
1999 		wpa_debug_level = level;
2000 	}
2001 
2002 	if (stamp && os_strlen(stamp))
2003 		wpa_debug_timestamp = atoi(stamp);
2004 
2005 	os_memcpy(buf, "OK\n", 3);
2006 	return 3;
2007 }
2008 
2009 
2010 #ifdef NEED_AP_MLME
2011 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
2012 					     char *buf, size_t buflen)
2013 {
2014 	struct hostapd_iface *iface = hapd->iface;
2015 	char *pos, *end;
2016 	struct hostapd_sta_info *info;
2017 	struct os_reltime now;
2018 
2019 	sta_track_expire(iface, 0);
2020 
2021 	pos = buf;
2022 	end = buf + buflen;
2023 
2024 	os_get_reltime(&now);
2025 	dl_list_for_each_reverse(info, &iface->sta_seen,
2026 				 struct hostapd_sta_info, list) {
2027 		struct os_reltime age;
2028 		int ret;
2029 
2030 		os_reltime_sub(&now, &info->last_seen, &age);
2031 		ret = os_snprintf(pos, end - pos, MACSTR " %u\n",
2032 				  MAC2STR(info->addr), (unsigned int) age.sec);
2033 		if (os_snprintf_error(end - pos, ret))
2034 			break;
2035 		pos += ret;
2036 	}
2037 
2038 	return pos - buf;
2039 }
2040 #endif /* NEED_AP_MLME */
2041 
2042 
2043 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
2044 					      char *buf, char *reply,
2045 					      int reply_size,
2046 					      struct sockaddr_un *from,
2047 					      socklen_t fromlen)
2048 {
2049 	int reply_len, res;
2050 
2051 	os_memcpy(reply, "OK\n", 3);
2052 	reply_len = 3;
2053 
2054 	if (os_strcmp(buf, "PING") == 0) {
2055 		os_memcpy(reply, "PONG\n", 5);
2056 		reply_len = 5;
2057 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
2058 		if (wpa_debug_reopen_file() < 0)
2059 			reply_len = -1;
2060 	} else if (os_strcmp(buf, "STATUS") == 0) {
2061 		reply_len = hostapd_ctrl_iface_status(hapd, reply,
2062 						      reply_size);
2063 	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
2064 		reply_len = hostapd_drv_status(hapd, reply, reply_size);
2065 	} else if (os_strcmp(buf, "MIB") == 0) {
2066 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
2067 		if (reply_len >= 0) {
2068 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
2069 					  reply_size - reply_len);
2070 			if (res < 0)
2071 				reply_len = -1;
2072 			else
2073 				reply_len += res;
2074 		}
2075 		if (reply_len >= 0) {
2076 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
2077 						 reply_size - reply_len);
2078 			if (res < 0)
2079 				reply_len = -1;
2080 			else
2081 				reply_len += res;
2082 		}
2083 #ifndef CONFIG_NO_RADIUS
2084 		if (reply_len >= 0) {
2085 			res = radius_client_get_mib(hapd->radius,
2086 						    reply + reply_len,
2087 						    reply_size - reply_len);
2088 			if (res < 0)
2089 				reply_len = -1;
2090 			else
2091 				reply_len += res;
2092 		}
2093 #endif /* CONFIG_NO_RADIUS */
2094 	} else if (os_strncmp(buf, "MIB ", 4) == 0) {
2095 		reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
2096 						   buf + 4);
2097 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
2098 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
2099 							 reply_size);
2100 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
2101 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
2102 						   reply_size);
2103 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
2104 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
2105 							reply_size);
2106 	} else if (os_strcmp(buf, "ATTACH") == 0) {
2107 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
2108 			reply_len = -1;
2109 	} else if (os_strcmp(buf, "DETACH") == 0) {
2110 		if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
2111 			reply_len = -1;
2112 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
2113 		if (hostapd_ctrl_iface_level(hapd, from, fromlen,
2114 						    buf + 6))
2115 			reply_len = -1;
2116 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
2117 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
2118 			reply_len = -1;
2119 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
2120 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
2121 			reply_len = -1;
2122 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
2123 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
2124 			reply_len = -1;
2125 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
2126 		if (hostapd_ctrl_iface_stop_ap(hapd))
2127 			reply_len = -1;
2128 #ifdef CONFIG_IEEE80211W
2129 #ifdef NEED_AP_MLME
2130 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
2131 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
2132 			reply_len = -1;
2133 #endif /* NEED_AP_MLME */
2134 #endif /* CONFIG_IEEE80211W */
2135 #ifdef CONFIG_WPS
2136 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2137 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
2138 			reply_len = -1;
2139 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
2140 		reply_len = hostapd_ctrl_iface_wps_check_pin(
2141 			hapd, buf + 14, reply, reply_size);
2142 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
2143 		if (hostapd_wps_button_pushed(hapd, NULL))
2144 			reply_len = -1;
2145 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
2146 		if (hostapd_wps_cancel(hapd))
2147 			reply_len = -1;
2148 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
2149 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
2150 							  reply, reply_size);
2151 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
2152 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
2153 			reply_len = -1;
2154 	} else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
2155 		reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
2156 							      reply_size);
2157 #ifdef CONFIG_WPS_NFC
2158 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
2159 		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
2160 			reply_len = -1;
2161 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
2162 		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
2163 			hapd, buf + 21, reply, reply_size);
2164 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
2165 		reply_len = hostapd_ctrl_iface_wps_nfc_token(
2166 			hapd, buf + 14, reply, reply_size);
2167 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
2168 		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
2169 			hapd, buf + 21, reply, reply_size);
2170 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
2171 		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
2172 			reply_len = -1;
2173 #endif /* CONFIG_WPS_NFC */
2174 #endif /* CONFIG_WPS */
2175 #ifdef CONFIG_INTERWORKING
2176 	} else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
2177 		if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
2178 			reply_len = -1;
2179 	} else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
2180 		if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
2181 			reply_len = -1;
2182 #endif /* CONFIG_INTERWORKING */
2183 #ifdef CONFIG_HS20
2184 	} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
2185 		if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
2186 			reply_len = -1;
2187 	} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
2188 		if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
2189 			reply_len = -1;
2190 #endif /* CONFIG_HS20 */
2191 #ifdef CONFIG_WNM
2192 	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
2193 		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
2194 			reply_len = -1;
2195 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
2196 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
2197 			reply_len = -1;
2198 	} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
2199 		if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
2200 			reply_len = -1;
2201 #endif /* CONFIG_WNM */
2202 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
2203 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
2204 							  reply_size);
2205 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
2206 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
2207 			reply_len = -1;
2208 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
2209 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
2210 						   reply_size);
2211 	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
2212 		if (hostapd_ctrl_iface_enable(hapd->iface))
2213 			reply_len = -1;
2214 	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
2215 		if (hostapd_ctrl_iface_reload(hapd->iface))
2216 			reply_len = -1;
2217 	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
2218 		if (hostapd_ctrl_iface_disable(hapd->iface))
2219 			reply_len = -1;
2220 	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
2221 		if (ieee802_11_set_beacon(hapd))
2222 			reply_len = -1;
2223 #ifdef CONFIG_TESTING_OPTIONS
2224 	} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
2225 		if (hostapd_ctrl_iface_radar(hapd, buf + 6))
2226 			reply_len = -1;
2227 	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
2228 		if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
2229 			reply_len = -1;
2230 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
2231 		if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
2232 			reply_len = -1;
2233 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
2234 		if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
2235 			reply_len = -1;
2236 	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
2237 		if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
2238 			reply_len = -1;
2239 	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
2240 		if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
2241 			reply_len = -1;
2242 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
2243 		if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
2244 			reply_len = -1;
2245 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
2246 		reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
2247 							reply_size);
2248 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
2249 		if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
2250 			reply_len = -1;
2251 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
2252 		reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
2253 #endif /* CONFIG_TESTING_OPTIONS */
2254 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
2255 		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
2256 			reply_len = -1;
2257 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
2258 		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
2259 						      reply_size);
2260 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
2261 		ieee802_1x_erp_flush(hapd);
2262 #ifdef RADIUS_SERVER
2263 		radius_server_erp_flush(hapd->radius_srv);
2264 #endif /* RADIUS_SERVER */
2265 	} else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
2266 		if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
2267 			reply_len = -1;
2268 	} else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
2269 		if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
2270 			reply_len = -1;
2271 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
2272 		reply_len = hostapd_ctrl_iface_log_level(
2273 			hapd, buf + 9, reply, reply_size);
2274 #ifdef NEED_AP_MLME
2275 	} else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
2276 		reply_len = hostapd_ctrl_iface_track_sta_list(
2277 			hapd, reply, reply_size);
2278 #endif /* NEED_AP_MLME */
2279 	} else {
2280 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2281 		reply_len = 16;
2282 	}
2283 
2284 	if (reply_len < 0) {
2285 		os_memcpy(reply, "FAIL\n", 5);
2286 		reply_len = 5;
2287 	}
2288 
2289 	return reply_len;
2290 }
2291 
2292 
2293 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
2294 				       void *sock_ctx)
2295 {
2296 	struct hostapd_data *hapd = eloop_ctx;
2297 	char buf[4096];
2298 	int res;
2299 	struct sockaddr_un from;
2300 	socklen_t fromlen = sizeof(from);
2301 	char *reply;
2302 	const int reply_size = 4096;
2303 	int reply_len;
2304 	int level = MSG_DEBUG;
2305 
2306 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2307 		       (struct sockaddr *) &from, &fromlen);
2308 	if (res < 0) {
2309 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2310 			   strerror(errno));
2311 		return;
2312 	}
2313 	buf[res] = '\0';
2314 	if (os_strcmp(buf, "PING") == 0)
2315 		level = MSG_EXCESSIVE;
2316 	wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
2317 
2318 	reply = os_malloc(reply_size);
2319 	if (reply == NULL) {
2320 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2321 			   fromlen) < 0) {
2322 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2323 				   strerror(errno));
2324 		}
2325 		return;
2326 	}
2327 
2328 	reply_len = hostapd_ctrl_iface_receive_process(hapd, buf,
2329 						       reply, reply_size,
2330 						       &from, fromlen);
2331 
2332 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2333 		   fromlen) < 0) {
2334 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2335 			   strerror(errno));
2336 	}
2337 	os_free(reply);
2338 }
2339 
2340 
2341 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
2342 {
2343 	char *buf;
2344 	size_t len;
2345 
2346 	if (hapd->conf->ctrl_interface == NULL)
2347 		return NULL;
2348 
2349 	len = os_strlen(hapd->conf->ctrl_interface) +
2350 		os_strlen(hapd->conf->iface) + 2;
2351 	buf = os_malloc(len);
2352 	if (buf == NULL)
2353 		return NULL;
2354 
2355 	os_snprintf(buf, len, "%s/%s",
2356 		    hapd->conf->ctrl_interface, hapd->conf->iface);
2357 	buf[len - 1] = '\0';
2358 	return buf;
2359 }
2360 
2361 
2362 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
2363 				      enum wpa_msg_type type,
2364 				      const char *txt, size_t len)
2365 {
2366 	struct hostapd_data *hapd = ctx;
2367 	if (hapd == NULL)
2368 		return;
2369 	hostapd_ctrl_iface_send(hapd, level, type, txt, len);
2370 }
2371 
2372 
2373 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
2374 {
2375 	struct sockaddr_un addr;
2376 	int s = -1;
2377 	char *fname = NULL;
2378 
2379 	if (hapd->ctrl_sock > -1) {
2380 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2381 		return 0;
2382 	}
2383 
2384 	if (hapd->conf->ctrl_interface == NULL)
2385 		return 0;
2386 
2387 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2388 		if (errno == EEXIST) {
2389 			wpa_printf(MSG_DEBUG, "Using existing control "
2390 				   "interface directory.");
2391 		} else {
2392 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
2393 				   strerror(errno));
2394 			goto fail;
2395 		}
2396 	}
2397 
2398 	if (hapd->conf->ctrl_interface_gid_set &&
2399 	    chown(hapd->conf->ctrl_interface, -1,
2400 		  hapd->conf->ctrl_interface_gid) < 0) {
2401 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2402 			   strerror(errno));
2403 		return -1;
2404 	}
2405 
2406 	if (!hapd->conf->ctrl_interface_gid_set &&
2407 	    hapd->iface->interfaces->ctrl_iface_group &&
2408 	    chown(hapd->conf->ctrl_interface, -1,
2409 		  hapd->iface->interfaces->ctrl_iface_group) < 0) {
2410 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2411 			   strerror(errno));
2412 		return -1;
2413 	}
2414 
2415 #ifdef ANDROID
2416 	/*
2417 	 * Android is using umask 0077 which would leave the control interface
2418 	 * directory without group access. This breaks things since Wi-Fi
2419 	 * framework assumes that this directory can be accessed by other
2420 	 * applications in the wifi group. Fix this by adding group access even
2421 	 * if umask value would prevent this.
2422 	 */
2423 	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2424 		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
2425 			   strerror(errno));
2426 		/* Try to continue anyway */
2427 	}
2428 #endif /* ANDROID */
2429 
2430 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
2431 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
2432 		goto fail;
2433 
2434 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
2435 	if (s < 0) {
2436 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
2437 		goto fail;
2438 	}
2439 
2440 	os_memset(&addr, 0, sizeof(addr));
2441 #ifdef __FreeBSD__
2442 	addr.sun_len = sizeof(addr);
2443 #endif /* __FreeBSD__ */
2444 	addr.sun_family = AF_UNIX;
2445 	fname = hostapd_ctrl_iface_path(hapd);
2446 	if (fname == NULL)
2447 		goto fail;
2448 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
2449 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2450 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
2451 			   strerror(errno));
2452 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2453 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
2454 				   " allow connections - assuming it was left"
2455 				   "over from forced program termination");
2456 			if (unlink(fname) < 0) {
2457 				wpa_printf(MSG_ERROR,
2458 					   "Could not unlink existing ctrl_iface socket '%s': %s",
2459 					   fname, strerror(errno));
2460 				goto fail;
2461 			}
2462 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
2463 			    0) {
2464 				wpa_printf(MSG_ERROR,
2465 					   "hostapd-ctrl-iface: bind(PF_UNIX): %s",
2466 					   strerror(errno));
2467 				goto fail;
2468 			}
2469 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
2470 				   "ctrl_iface socket '%s'", fname);
2471 		} else {
2472 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
2473 				   "be in use - cannot override it");
2474 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
2475 				   "not used anymore", fname);
2476 			os_free(fname);
2477 			fname = NULL;
2478 			goto fail;
2479 		}
2480 	}
2481 
2482 	if (hapd->conf->ctrl_interface_gid_set &&
2483 	    chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
2484 		wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2485 			   strerror(errno));
2486 		goto fail;
2487 	}
2488 
2489 	if (!hapd->conf->ctrl_interface_gid_set &&
2490 	    hapd->iface->interfaces->ctrl_iface_group &&
2491 	    chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
2492 		wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2493 			   strerror(errno));
2494 		goto fail;
2495 	}
2496 
2497 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
2498 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
2499 			   strerror(errno));
2500 		goto fail;
2501 	}
2502 	os_free(fname);
2503 
2504 	hapd->ctrl_sock = s;
2505 	if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
2506 				     NULL) < 0) {
2507 		hostapd_ctrl_iface_deinit(hapd);
2508 		return -1;
2509 	}
2510 	hapd->msg_ctx = hapd;
2511 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2512 
2513 	return 0;
2514 
2515 fail:
2516 	if (s >= 0)
2517 		close(s);
2518 	if (fname) {
2519 		unlink(fname);
2520 		os_free(fname);
2521 	}
2522 	return -1;
2523 }
2524 
2525 
2526 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
2527 {
2528 	struct wpa_ctrl_dst *dst, *prev;
2529 
2530 	if (hapd->ctrl_sock > -1) {
2531 		char *fname;
2532 		eloop_unregister_read_sock(hapd->ctrl_sock);
2533 		close(hapd->ctrl_sock);
2534 		hapd->ctrl_sock = -1;
2535 		fname = hostapd_ctrl_iface_path(hapd);
2536 		if (fname)
2537 			unlink(fname);
2538 		os_free(fname);
2539 
2540 		if (hapd->conf->ctrl_interface &&
2541 		    rmdir(hapd->conf->ctrl_interface) < 0) {
2542 			if (errno == ENOTEMPTY) {
2543 				wpa_printf(MSG_DEBUG, "Control interface "
2544 					   "directory not empty - leaving it "
2545 					   "behind");
2546 			} else {
2547 				wpa_printf(MSG_ERROR,
2548 					   "rmdir[ctrl_interface=%s]: %s",
2549 					   hapd->conf->ctrl_interface,
2550 					   strerror(errno));
2551 			}
2552 		}
2553 	}
2554 
2555 	dst = hapd->ctrl_dst;
2556 	hapd->ctrl_dst = NULL;
2557 	while (dst) {
2558 		prev = dst;
2559 		dst = dst->next;
2560 		os_free(prev);
2561 	}
2562 
2563 #ifdef CONFIG_TESTING_OPTIONS
2564 	l2_packet_deinit(hapd->l2_test);
2565 	hapd->l2_test = NULL;
2566 #endif /* CONFIG_TESTING_OPTIONS */
2567 }
2568 
2569 
2570 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
2571 				  char *buf)
2572 {
2573 	if (hostapd_add_iface(interfaces, buf) < 0) {
2574 		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
2575 		return -1;
2576 	}
2577 	return 0;
2578 }
2579 
2580 
2581 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
2582 				     char *buf)
2583 {
2584 	if (hostapd_remove_iface(interfaces, buf) < 0) {
2585 		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
2586 		return -1;
2587 	}
2588 	return 0;
2589 }
2590 
2591 
2592 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
2593 					    struct sockaddr_un *from,
2594 					    socklen_t fromlen)
2595 {
2596 	struct wpa_ctrl_dst *dst;
2597 
2598 	dst = os_zalloc(sizeof(*dst));
2599 	if (dst == NULL)
2600 		return -1;
2601 	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
2602 	dst->addrlen = fromlen;
2603 	dst->debug_level = MSG_INFO;
2604 	dst->next = interfaces->global_ctrl_dst;
2605 	interfaces->global_ctrl_dst = dst;
2606 	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached (global)",
2607 		    from->sun_path,
2608 		    fromlen - offsetof(struct sockaddr_un, sun_path));
2609 	return 0;
2610 }
2611 
2612 
2613 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
2614 					    struct sockaddr_un *from,
2615 					    socklen_t fromlen)
2616 {
2617 	struct wpa_ctrl_dst *dst, *prev = NULL;
2618 
2619 	dst = interfaces->global_ctrl_dst;
2620 	while (dst) {
2621 		if (fromlen == dst->addrlen &&
2622 		    os_memcmp(from->sun_path, dst->addr.sun_path,
2623 			      fromlen - offsetof(struct sockaddr_un, sun_path))
2624 		    == 0) {
2625 			wpa_hexdump(MSG_DEBUG,
2626 				    "CTRL_IFACE monitor detached (global)",
2627 				    from->sun_path,
2628 				    fromlen -
2629 				    offsetof(struct sockaddr_un, sun_path));
2630 			if (prev == NULL)
2631 				interfaces->global_ctrl_dst = dst->next;
2632 			else
2633 				prev->next = dst->next;
2634 			os_free(dst);
2635 			return 0;
2636 		}
2637 		prev = dst;
2638 		dst = dst->next;
2639 	}
2640 	return -1;
2641 }
2642 
2643 
2644 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
2645 {
2646 #ifdef CONFIG_WPS_TESTING
2647 	wps_version_number = 0x20;
2648 	wps_testing_dummy_cred = 0;
2649 	wps_corrupt_pkhash = 0;
2650 #endif /* CONFIG_WPS_TESTING */
2651 }
2652 
2653 
2654 #ifdef CONFIG_FST
2655 
2656 static int
2657 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
2658 				     const char *cmd)
2659 {
2660 	char ifname[IFNAMSIZ + 1];
2661 	struct fst_iface_cfg cfg;
2662 	struct hostapd_data *hapd;
2663 	struct fst_wpa_obj iface_obj;
2664 
2665 	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
2666 		hapd = hostapd_get_iface(interfaces, ifname);
2667 		if (hapd) {
2668 			if (hapd->iface->fst) {
2669 				wpa_printf(MSG_INFO, "FST: Already attached");
2670 				return -1;
2671 			}
2672 			fst_hostapd_fill_iface_obj(hapd, &iface_obj);
2673 			hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
2674 						      &iface_obj, &cfg);
2675 			if (hapd->iface->fst)
2676 				return 0;
2677 		}
2678 	}
2679 
2680 	return -EINVAL;
2681 }
2682 
2683 
2684 static int
2685 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
2686 				     const char *cmd)
2687 {
2688 	char ifname[IFNAMSIZ + 1];
2689 	struct hostapd_data * hapd;
2690 
2691 	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
2692 		hapd = hostapd_get_iface(interfaces, ifname);
2693 		if (hapd) {
2694 			if (!fst_iface_detach(ifname)) {
2695 				hapd->iface->fst = NULL;
2696 				hapd->iface->fst_ies = NULL;
2697 				return 0;
2698 			}
2699 		}
2700 	}
2701 
2702 	return -EINVAL;
2703 }
2704 
2705 #endif /* CONFIG_FST */
2706 
2707 
2708 static struct hostapd_data *
2709 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
2710 			    const char *ifname)
2711 {
2712 	size_t i, j;
2713 
2714 	for (i = 0; i < interfaces->count; i++) {
2715 		struct hostapd_iface *iface = interfaces->iface[i];
2716 
2717 		for (j = 0; j < iface->num_bss; j++) {
2718 			struct hostapd_data *hapd;
2719 
2720 			hapd = iface->bss[j];
2721 			if (os_strcmp(ifname, hapd->conf->iface) == 0)
2722 				return hapd;
2723 		}
2724 	}
2725 
2726 	return NULL;
2727 }
2728 
2729 
2730 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
2731 					struct hostapd_data *dst_hapd,
2732 					const char *param)
2733 {
2734 	int res;
2735 	char *value;
2736 
2737 	value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2738 	if (!value) {
2739 		wpa_printf(MSG_ERROR,
2740 			   "DUP: cannot allocate buffer to stringify %s",
2741 			   param);
2742 		goto error_return;
2743 	}
2744 
2745 	if (os_strcmp(param, "wpa") == 0) {
2746 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
2747 			    src_hapd->conf->wpa);
2748 	} else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
2749 		   src_hapd->conf->wpa_key_mgmt) {
2750 		res = hostapd_ctrl_iface_get_key_mgmt(
2751 			src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2752 		if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
2753 			goto error_stringify;
2754 	} else if (os_strcmp(param, "wpa_pairwise") == 0 &&
2755 		   src_hapd->conf->wpa_pairwise) {
2756 		res = wpa_write_ciphers(value,
2757 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2758 					src_hapd->conf->wpa_pairwise, " ");
2759 		if (res < 0)
2760 			goto error_stringify;
2761 	} else if (os_strcmp(param, "rsn_pairwise") == 0 &&
2762 		   src_hapd->conf->rsn_pairwise) {
2763 		res = wpa_write_ciphers(value,
2764 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2765 					src_hapd->conf->rsn_pairwise, " ");
2766 		if (res < 0)
2767 			goto error_stringify;
2768 	} else if (os_strcmp(param, "wpa_passphrase") == 0 &&
2769 		   src_hapd->conf->ssid.wpa_passphrase) {
2770 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
2771 			    src_hapd->conf->ssid.wpa_passphrase);
2772 	} else if (os_strcmp(param, "wpa_psk") == 0 &&
2773 		   src_hapd->conf->ssid.wpa_psk_set) {
2774 		wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2775 			src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
2776 	} else {
2777 		wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
2778 		goto error_return;
2779 	}
2780 
2781 	res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
2782 	os_free(value);
2783 	return res;
2784 
2785 error_stringify:
2786 	wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
2787 error_return:
2788 	os_free(value);
2789 	return -1;
2790 }
2791 
2792 
2793 static int
2794 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
2795 				      char *cmd)
2796 {
2797 	char *p_start = cmd, *p_end;
2798 	struct hostapd_data *src_hapd, *dst_hapd;
2799 
2800 	/* cmd: "<src ifname> <dst ifname> <variable name> */
2801 
2802 	p_end = os_strchr(p_start, ' ');
2803 	if (!p_end) {
2804 		wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
2805 			   cmd);
2806 		return -1;
2807 	}
2808 
2809 	*p_end = '\0';
2810 	src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
2811 	if (!src_hapd) {
2812 		wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
2813 			   p_start);
2814 		return -1;
2815 	}
2816 
2817 	p_start = p_end + 1;
2818 	p_end = os_strchr(p_start, ' ');
2819 	if (!p_end) {
2820 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
2821 			   cmd);
2822 		return -1;
2823 	}
2824 
2825 	*p_end = '\0';
2826 	dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
2827 	if (!dst_hapd) {
2828 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
2829 			   p_start);
2830 		return -1;
2831 	}
2832 
2833 	p_start = p_end + 1;
2834 	return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
2835 }
2836 
2837 
2838 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
2839 					    const char *ifname,
2840 					    char *buf, char *reply,
2841 					    int reply_size,
2842 					    struct sockaddr_un *from,
2843 					    socklen_t fromlen)
2844 {
2845 	struct hostapd_data *hapd;
2846 
2847 	hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
2848 	if (hapd == NULL) {
2849 		int res;
2850 
2851 		res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
2852 		if (os_snprintf_error(reply_size, res))
2853 			return -1;
2854 		return res;
2855 	}
2856 
2857 	return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
2858 						  from, fromlen);
2859 }
2860 
2861 
2862 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
2863 					      void *sock_ctx)
2864 {
2865 	void *interfaces = eloop_ctx;
2866 	char buf[256];
2867 	int res;
2868 	struct sockaddr_un from;
2869 	socklen_t fromlen = sizeof(from);
2870 	char *reply;
2871 	int reply_len;
2872 	const int reply_size = 4096;
2873 
2874 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2875 		       (struct sockaddr *) &from, &fromlen);
2876 	if (res < 0) {
2877 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2878 			   strerror(errno));
2879 		return;
2880 	}
2881 	buf[res] = '\0';
2882 	wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
2883 
2884 	reply = os_malloc(reply_size);
2885 	if (reply == NULL) {
2886 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2887 			   fromlen) < 0) {
2888 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2889 				   strerror(errno));
2890 		}
2891 		return;
2892 	}
2893 
2894 	os_memcpy(reply, "OK\n", 3);
2895 	reply_len = 3;
2896 
2897 	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
2898 		char *pos = os_strchr(buf + 7, ' ');
2899 
2900 		if (pos) {
2901 			*pos++ = '\0';
2902 			reply_len = hostapd_global_ctrl_iface_ifname(
2903 				interfaces, buf + 7, pos, reply, reply_size,
2904 				&from, fromlen);
2905 			goto send_reply;
2906 		}
2907 	}
2908 
2909 	if (os_strcmp(buf, "PING") == 0) {
2910 		os_memcpy(reply, "PONG\n", 5);
2911 		reply_len = 5;
2912 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
2913 		if (wpa_debug_reopen_file() < 0)
2914 			reply_len = -1;
2915 	} else if (os_strcmp(buf, "FLUSH") == 0) {
2916 		hostapd_ctrl_iface_flush(interfaces);
2917 	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
2918 		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
2919 			reply_len = -1;
2920 	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
2921 		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
2922 			reply_len = -1;
2923 	} else if (os_strcmp(buf, "ATTACH") == 0) {
2924 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
2925 						     fromlen))
2926 			reply_len = -1;
2927 	} else if (os_strcmp(buf, "DETACH") == 0) {
2928 		if (hostapd_global_ctrl_iface_detach(interfaces, &from,
2929 			fromlen))
2930 			reply_len = -1;
2931 #ifdef CONFIG_MODULE_TESTS
2932 	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
2933 		int hapd_module_tests(void);
2934 		if (hapd_module_tests() < 0)
2935 			reply_len = -1;
2936 #endif /* CONFIG_MODULE_TESTS */
2937 #ifdef CONFIG_FST
2938 	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
2939 		if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
2940 			reply_len = os_snprintf(reply, reply_size, "OK\n");
2941 		else
2942 			reply_len = -1;
2943 	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
2944 		if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
2945 			reply_len = os_snprintf(reply, reply_size, "OK\n");
2946 		else
2947 			reply_len = -1;
2948 	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
2949 		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
2950 #endif /* CONFIG_FST */
2951 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
2952 		if (!hostapd_global_ctrl_iface_dup_network(interfaces,
2953 							   buf + 12))
2954 			reply_len = os_snprintf(reply, reply_size, "OK\n");
2955 		else
2956 			reply_len = -1;
2957 	} else {
2958 		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
2959 			   "ignored");
2960 		reply_len = -1;
2961 	}
2962 
2963 send_reply:
2964 	if (reply_len < 0) {
2965 		os_memcpy(reply, "FAIL\n", 5);
2966 		reply_len = 5;
2967 	}
2968 
2969 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2970 		   fromlen) < 0) {
2971 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2972 			   strerror(errno));
2973 	}
2974 	os_free(reply);
2975 }
2976 
2977 
2978 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
2979 {
2980 	char *buf;
2981 	size_t len;
2982 
2983 	if (interface->global_iface_path == NULL)
2984 		return NULL;
2985 
2986 	len = os_strlen(interface->global_iface_path) +
2987 		os_strlen(interface->global_iface_name) + 2;
2988 	buf = os_malloc(len);
2989 	if (buf == NULL)
2990 		return NULL;
2991 
2992 	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
2993 		    interface->global_iface_name);
2994 	buf[len - 1] = '\0';
2995 	return buf;
2996 }
2997 
2998 
2999 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
3000 {
3001 	struct sockaddr_un addr;
3002 	int s = -1;
3003 	char *fname = NULL;
3004 
3005 	if (interface->global_iface_path == NULL) {
3006 		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
3007 		return 0;
3008 	}
3009 
3010 	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
3011 		if (errno == EEXIST) {
3012 			wpa_printf(MSG_DEBUG, "Using existing control "
3013 				   "interface directory.");
3014 		} else {
3015 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
3016 				   strerror(errno));
3017 			goto fail;
3018 		}
3019 	} else if (interface->ctrl_iface_group &&
3020 		   chown(interface->global_iface_path, -1,
3021 			 interface->ctrl_iface_group) < 0) {
3022 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3023 			   strerror(errno));
3024 		goto fail;
3025 	}
3026 
3027 	if (os_strlen(interface->global_iface_path) + 1 +
3028 	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
3029 		goto fail;
3030 
3031 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
3032 	if (s < 0) {
3033 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
3034 		goto fail;
3035 	}
3036 
3037 	os_memset(&addr, 0, sizeof(addr));
3038 #ifdef __FreeBSD__
3039 	addr.sun_len = sizeof(addr);
3040 #endif /* __FreeBSD__ */
3041 	addr.sun_family = AF_UNIX;
3042 	fname = hostapd_global_ctrl_iface_path(interface);
3043 	if (fname == NULL)
3044 		goto fail;
3045 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
3046 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3047 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
3048 			   strerror(errno));
3049 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3050 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
3051 				   " allow connections - assuming it was left"
3052 				   "over from forced program termination");
3053 			if (unlink(fname) < 0) {
3054 				wpa_printf(MSG_ERROR,
3055 					   "Could not unlink existing ctrl_iface socket '%s': %s",
3056 					   fname, strerror(errno));
3057 				goto fail;
3058 			}
3059 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
3060 			    0) {
3061 				wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
3062 					   strerror(errno));
3063 				goto fail;
3064 			}
3065 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
3066 				   "ctrl_iface socket '%s'", fname);
3067 		} else {
3068 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
3069 				   "be in use - cannot override it");
3070 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
3071 				   "not used anymore", fname);
3072 			os_free(fname);
3073 			fname = NULL;
3074 			goto fail;
3075 		}
3076 	}
3077 
3078 	if (interface->ctrl_iface_group &&
3079 	    chown(fname, -1, interface->ctrl_iface_group) < 0) {
3080 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3081 			   strerror(errno));
3082 		goto fail;
3083 	}
3084 
3085 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
3086 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
3087 			   strerror(errno));
3088 		goto fail;
3089 	}
3090 	os_free(fname);
3091 
3092 	interface->global_ctrl_sock = s;
3093 	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
3094 				 interface, NULL);
3095 
3096 	return 0;
3097 
3098 fail:
3099 	if (s >= 0)
3100 		close(s);
3101 	if (fname) {
3102 		unlink(fname);
3103 		os_free(fname);
3104 	}
3105 	return -1;
3106 }
3107 
3108 
3109 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
3110 {
3111 	char *fname = NULL;
3112 	struct wpa_ctrl_dst *dst, *prev;
3113 
3114 	if (interfaces->global_ctrl_sock > -1) {
3115 		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
3116 		close(interfaces->global_ctrl_sock);
3117 		interfaces->global_ctrl_sock = -1;
3118 		fname = hostapd_global_ctrl_iface_path(interfaces);
3119 		if (fname) {
3120 			unlink(fname);
3121 			os_free(fname);
3122 		}
3123 
3124 		if (interfaces->global_iface_path &&
3125 		    rmdir(interfaces->global_iface_path) < 0) {
3126 			if (errno == ENOTEMPTY) {
3127 				wpa_printf(MSG_DEBUG, "Control interface "
3128 					   "directory not empty - leaving it "
3129 					   "behind");
3130 			} else {
3131 				wpa_printf(MSG_ERROR,
3132 					   "rmdir[ctrl_interface=%s]: %s",
3133 					   interfaces->global_iface_path,
3134 					   strerror(errno));
3135 			}
3136 		}
3137 	}
3138 
3139 	os_free(interfaces->global_iface_path);
3140 	interfaces->global_iface_path = NULL;
3141 
3142 	dst = interfaces->global_ctrl_dst;
3143 	interfaces->global_ctrl_dst = NULL;
3144 	while (dst) {
3145 		prev = dst;
3146 		dst = dst->next;
3147 		os_free(prev);
3148 	}
3149 }
3150 
3151 
3152 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
3153 				    enum wpa_msg_type type,
3154 				    const char *buf, size_t len)
3155 {
3156 	struct wpa_ctrl_dst *dst, *next;
3157 	struct msghdr msg;
3158 	int idx;
3159 	struct iovec io[2];
3160 	char levelstr[10];
3161 	int s;
3162 
3163 	if (type != WPA_MSG_ONLY_GLOBAL) {
3164 		s = hapd->ctrl_sock;
3165 		dst = hapd->ctrl_dst;
3166 	} else {
3167 		s = hapd->iface->interfaces->global_ctrl_sock;
3168 		dst = hapd->iface->interfaces->global_ctrl_dst;
3169 	}
3170 
3171 	if (s < 0 || dst == NULL)
3172 		return;
3173 
3174 	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
3175 	io[0].iov_base = levelstr;
3176 	io[0].iov_len = os_strlen(levelstr);
3177 	io[1].iov_base = (char *) buf;
3178 	io[1].iov_len = len;
3179 	os_memset(&msg, 0, sizeof(msg));
3180 	msg.msg_iov = io;
3181 	msg.msg_iovlen = 2;
3182 
3183 	idx = 0;
3184 	while (dst) {
3185 		next = dst->next;
3186 		if (level >= dst->debug_level) {
3187 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
3188 				    (u8 *) dst->addr.sun_path, dst->addrlen -
3189 				    offsetof(struct sockaddr_un, sun_path));
3190 			msg.msg_name = &dst->addr;
3191 			msg.msg_namelen = dst->addrlen;
3192 			if (sendmsg(s, &msg, 0) < 0) {
3193 				int _errno = errno;
3194 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
3195 					   "%d - %s",
3196 					   idx, errno, strerror(errno));
3197 				dst->errors++;
3198 				if (dst->errors > 10 || _errno == ENOENT) {
3199 					if (type != WPA_MSG_ONLY_GLOBAL)
3200 						hostapd_ctrl_iface_detach(
3201 							hapd, &dst->addr,
3202 							dst->addrlen);
3203 					else
3204 						hostapd_global_ctrl_iface_detach(
3205 							hapd->iface->interfaces,
3206 							&dst->addr,
3207 							dst->addrlen);
3208 				}
3209 			} else
3210 				dst->errors = 0;
3211 		}
3212 		idx++;
3213 		dst = next;
3214 	}
3215 }
3216 
3217 #endif /* CONFIG_NATIVE_WINDOWS */
3218