1/*
2 * hostapd / UNIX domain socket -based control interface
3 * Copyright (c) 2004-2014, 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#include <sys/un.h>
14#include <sys/stat.h>
15#include <stddef.h>
16
17#include "utils/common.h"
18#include "utils/eloop.h"
19#include "common/version.h"
20#include "common/ieee802_11_defs.h"
21#include "drivers/driver.h"
22#include "radius/radius_client.h"
23#include "radius/radius_server.h"
24#include "ap/hostapd.h"
25#include "ap/ap_config.h"
26#include "ap/ieee802_1x.h"
27#include "ap/wpa_auth.h"
28#include "ap/ieee802_11.h"
29#include "ap/sta_info.h"
30#include "ap/wps_hostapd.h"
31#include "ap/ctrl_iface_ap.h"
32#include "ap/ap_drv_ops.h"
33#include "ap/hs20.h"
34#include "ap/wnm_ap.h"
35#include "ap/wpa_auth.h"
36#include "wps/wps_defs.h"
37#include "wps/wps.h"
38#include "config_file.h"
39#include "ctrl_iface.h"
40
41
42struct wpa_ctrl_dst {
43	struct wpa_ctrl_dst *next;
44	struct sockaddr_un addr;
45	socklen_t addrlen;
46	int debug_level;
47	int errors;
48};
49
50
51static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
52				    const char *buf, size_t len);
53
54
55static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
56				     struct sockaddr_un *from,
57				     socklen_t fromlen)
58{
59	struct wpa_ctrl_dst *dst;
60
61	dst = os_zalloc(sizeof(*dst));
62	if (dst == NULL)
63		return -1;
64	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
65	dst->addrlen = fromlen;
66	dst->debug_level = MSG_INFO;
67	dst->next = hapd->ctrl_dst;
68	hapd->ctrl_dst = dst;
69	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
70		    (u8 *) from->sun_path,
71		    fromlen - offsetof(struct sockaddr_un, sun_path));
72	return 0;
73}
74
75
76static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
77				     struct sockaddr_un *from,
78				     socklen_t fromlen)
79{
80	struct wpa_ctrl_dst *dst, *prev = NULL;
81
82	dst = hapd->ctrl_dst;
83	while (dst) {
84		if (fromlen == dst->addrlen &&
85		    os_memcmp(from->sun_path, dst->addr.sun_path,
86			      fromlen - offsetof(struct sockaddr_un, sun_path))
87		    == 0) {
88			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
89				    (u8 *) from->sun_path,
90				    fromlen -
91				    offsetof(struct sockaddr_un, sun_path));
92			if (prev == NULL)
93				hapd->ctrl_dst = dst->next;
94			else
95				prev->next = dst->next;
96			os_free(dst);
97			return 0;
98		}
99		prev = dst;
100		dst = dst->next;
101	}
102	return -1;
103}
104
105
106static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
107				    struct sockaddr_un *from,
108				    socklen_t fromlen,
109				    char *level)
110{
111	struct wpa_ctrl_dst *dst;
112
113	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
114
115	dst = hapd->ctrl_dst;
116	while (dst) {
117		if (fromlen == dst->addrlen &&
118		    os_memcmp(from->sun_path, dst->addr.sun_path,
119			      fromlen - offsetof(struct sockaddr_un, sun_path))
120		    == 0) {
121			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
122				    "level", (u8 *) from->sun_path, fromlen -
123				    offsetof(struct sockaddr_un, sun_path));
124			dst->debug_level = atoi(level);
125			return 0;
126		}
127		dst = dst->next;
128	}
129
130	return -1;
131}
132
133
134static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
135				      const char *txtaddr)
136{
137	u8 addr[ETH_ALEN];
138	struct sta_info *sta;
139
140	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
141
142	if (hwaddr_aton(txtaddr, addr))
143		return -1;
144
145	sta = ap_get_sta(hapd, addr);
146	if (sta)
147		return 0;
148
149	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
150		   "notification", MAC2STR(addr));
151	sta = ap_sta_add(hapd, addr);
152	if (sta == NULL)
153		return -1;
154
155	hostapd_new_assoc_sta(hapd, sta, 0);
156	return 0;
157}
158
159
160#ifdef CONFIG_IEEE80211W
161#ifdef NEED_AP_MLME
162static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
163				       const char *txtaddr)
164{
165	u8 addr[ETH_ALEN];
166	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
167
168	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
169
170	if (hwaddr_aton(txtaddr, addr) ||
171	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
172		return -1;
173
174	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
175
176	return 0;
177}
178#endif /* NEED_AP_MLME */
179#endif /* CONFIG_IEEE80211W */
180
181
182#ifdef CONFIG_WPS
183static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
184{
185	char *pin = os_strchr(txt, ' ');
186	char *timeout_txt;
187	int timeout;
188	u8 addr_buf[ETH_ALEN], *addr = NULL;
189	char *pos;
190
191	if (pin == NULL)
192		return -1;
193	*pin++ = '\0';
194
195	timeout_txt = os_strchr(pin, ' ');
196	if (timeout_txt) {
197		*timeout_txt++ = '\0';
198		timeout = atoi(timeout_txt);
199		pos = os_strchr(timeout_txt, ' ');
200		if (pos) {
201			*pos++ = '\0';
202			if (hwaddr_aton(pos, addr_buf) == 0)
203				addr = addr_buf;
204		}
205	} else
206		timeout = 0;
207
208	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
209}
210
211
212static int hostapd_ctrl_iface_wps_check_pin(
213	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
214{
215	char pin[9];
216	size_t len;
217	char *pos;
218	int ret;
219
220	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
221			      (u8 *) cmd, os_strlen(cmd));
222	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
223		if (*pos < '0' || *pos > '9')
224			continue;
225		pin[len++] = *pos;
226		if (len == 9) {
227			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
228			return -1;
229		}
230	}
231	if (len != 4 && len != 8) {
232		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
233		return -1;
234	}
235	pin[len] = '\0';
236
237	if (len == 8) {
238		unsigned int pin_val;
239		pin_val = atoi(pin);
240		if (!wps_pin_valid(pin_val)) {
241			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
242			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
243			if (ret < 0 || (size_t) ret >= buflen)
244				return -1;
245			return ret;
246		}
247	}
248
249	ret = os_snprintf(buf, buflen, "%s", pin);
250	if (ret < 0 || (size_t) ret >= buflen)
251		return -1;
252
253	return ret;
254}
255
256
257#ifdef CONFIG_WPS_NFC
258static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
259					       char *pos)
260{
261	size_t len;
262	struct wpabuf *buf;
263	int ret;
264
265	len = os_strlen(pos);
266	if (len & 0x01)
267		return -1;
268	len /= 2;
269
270	buf = wpabuf_alloc(len);
271	if (buf == NULL)
272		return -1;
273	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
274		wpabuf_free(buf);
275		return -1;
276	}
277
278	ret = hostapd_wps_nfc_tag_read(hapd, buf);
279	wpabuf_free(buf);
280
281	return ret;
282}
283
284
285static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
286						   char *cmd, char *reply,
287						   size_t max_len)
288{
289	int ndef;
290	struct wpabuf *buf;
291	int res;
292
293	if (os_strcmp(cmd, "WPS") == 0)
294		ndef = 0;
295	else if (os_strcmp(cmd, "NDEF") == 0)
296		ndef = 1;
297	else
298		return -1;
299
300	buf = hostapd_wps_nfc_config_token(hapd, ndef);
301	if (buf == NULL)
302		return -1;
303
304	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
305					 wpabuf_len(buf));
306	reply[res++] = '\n';
307	reply[res] = '\0';
308
309	wpabuf_free(buf);
310
311	return res;
312}
313
314
315static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
316						char *reply, size_t max_len,
317						int ndef)
318{
319	struct wpabuf *buf;
320	int res;
321
322	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
323	if (buf == NULL)
324		return -1;
325
326	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
327					 wpabuf_len(buf));
328	reply[res++] = '\n';
329	reply[res] = '\0';
330
331	wpabuf_free(buf);
332
333	return res;
334}
335
336
337static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
338					    char *cmd, char *reply,
339					    size_t max_len)
340{
341	if (os_strcmp(cmd, "WPS") == 0)
342		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
343							    max_len, 0);
344
345	if (os_strcmp(cmd, "NDEF") == 0)
346		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
347							    max_len, 1);
348
349	if (os_strcmp(cmd, "enable") == 0)
350		return hostapd_wps_nfc_token_enable(hapd);
351
352	if (os_strcmp(cmd, "disable") == 0) {
353		hostapd_wps_nfc_token_disable(hapd);
354		return 0;
355	}
356
357	return -1;
358}
359
360
361static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
362						   char *cmd, char *reply,
363						   size_t max_len)
364{
365	struct wpabuf *buf;
366	int res;
367	char *pos;
368	int ndef;
369
370	pos = os_strchr(cmd, ' ');
371	if (pos == NULL)
372		return -1;
373	*pos++ = '\0';
374
375	if (os_strcmp(cmd, "WPS") == 0)
376		ndef = 0;
377	else if (os_strcmp(cmd, "NDEF") == 0)
378		ndef = 1;
379	else
380		return -1;
381
382	if (os_strcmp(pos, "WPS-CR") == 0)
383		buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
384	else
385		buf = NULL;
386	if (buf == NULL)
387		return -1;
388
389	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
390					 wpabuf_len(buf));
391	reply[res++] = '\n';
392	reply[res] = '\0';
393
394	wpabuf_free(buf);
395
396	return res;
397}
398
399
400static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
401						  char *cmd)
402{
403	size_t len;
404	struct wpabuf *req, *sel;
405	int ret;
406	char *pos, *role, *type, *pos2;
407
408	role = cmd;
409	pos = os_strchr(role, ' ');
410	if (pos == NULL)
411		return -1;
412	*pos++ = '\0';
413
414	type = pos;
415	pos = os_strchr(type, ' ');
416	if (pos == NULL)
417		return -1;
418	*pos++ = '\0';
419
420	pos2 = os_strchr(pos, ' ');
421	if (pos2 == NULL)
422		return -1;
423	*pos2++ = '\0';
424
425	len = os_strlen(pos);
426	if (len & 0x01)
427		return -1;
428	len /= 2;
429
430	req = wpabuf_alloc(len);
431	if (req == NULL)
432		return -1;
433	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
434		wpabuf_free(req);
435		return -1;
436	}
437
438	len = os_strlen(pos2);
439	if (len & 0x01) {
440		wpabuf_free(req);
441		return -1;
442	}
443	len /= 2;
444
445	sel = wpabuf_alloc(len);
446	if (sel == NULL) {
447		wpabuf_free(req);
448		return -1;
449	}
450	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
451		wpabuf_free(req);
452		wpabuf_free(sel);
453		return -1;
454	}
455
456	if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
457		ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
458	} else {
459		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
460			   "reported: role=%s type=%s", role, type);
461		ret = -1;
462	}
463	wpabuf_free(req);
464	wpabuf_free(sel);
465
466	return ret;
467}
468
469#endif /* CONFIG_WPS_NFC */
470
471
472static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
473					 char *buf, size_t buflen)
474{
475	int timeout = 300;
476	char *pos;
477	const char *pin_txt;
478
479	pos = os_strchr(txt, ' ');
480	if (pos)
481		*pos++ = '\0';
482
483	if (os_strcmp(txt, "disable") == 0) {
484		hostapd_wps_ap_pin_disable(hapd);
485		return os_snprintf(buf, buflen, "OK\n");
486	}
487
488	if (os_strcmp(txt, "random") == 0) {
489		if (pos)
490			timeout = atoi(pos);
491		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
492		if (pin_txt == NULL)
493			return -1;
494		return os_snprintf(buf, buflen, "%s", pin_txt);
495	}
496
497	if (os_strcmp(txt, "get") == 0) {
498		pin_txt = hostapd_wps_ap_pin_get(hapd);
499		if (pin_txt == NULL)
500			return -1;
501		return os_snprintf(buf, buflen, "%s", pin_txt);
502	}
503
504	if (os_strcmp(txt, "set") == 0) {
505		char *pin;
506		if (pos == NULL)
507			return -1;
508		pin = pos;
509		pos = os_strchr(pos, ' ');
510		if (pos) {
511			*pos++ = '\0';
512			timeout = atoi(pos);
513		}
514		if (os_strlen(pin) > buflen)
515			return -1;
516		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
517			return -1;
518		return os_snprintf(buf, buflen, "%s", pin);
519	}
520
521	return -1;
522}
523
524
525static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
526{
527	char *pos;
528	char *ssid, *auth, *encr = NULL, *key = NULL;
529
530	ssid = txt;
531	pos = os_strchr(txt, ' ');
532	if (!pos)
533		return -1;
534	*pos++ = '\0';
535
536	auth = pos;
537	pos = os_strchr(pos, ' ');
538	if (pos) {
539		*pos++ = '\0';
540		encr = pos;
541		pos = os_strchr(pos, ' ');
542		if (pos) {
543			*pos++ = '\0';
544			key = pos;
545		}
546	}
547
548	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
549}
550
551
552static const char * pbc_status_str(enum pbc_status status)
553{
554	switch (status) {
555	case WPS_PBC_STATUS_DISABLE:
556		return "Disabled";
557	case WPS_PBC_STATUS_ACTIVE:
558		return "Active";
559	case WPS_PBC_STATUS_TIMEOUT:
560		return "Timed-out";
561	case WPS_PBC_STATUS_OVERLAP:
562		return "Overlap";
563	default:
564		return "Unknown";
565	}
566}
567
568
569static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
570					     char *buf, size_t buflen)
571{
572	int ret;
573	char *pos, *end;
574
575	pos = buf;
576	end = buf + buflen;
577
578	ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
579			  pbc_status_str(hapd->wps_stats.pbc_status));
580
581	if (ret < 0 || ret >= end - pos)
582		return pos - buf;
583	pos += ret;
584
585	ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
586			  (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
587			   "Success":
588			   (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
589			    "Failed" : "None")));
590
591	if (ret < 0 || ret >= end - pos)
592		return pos - buf;
593	pos += ret;
594
595	/* If status == Failure - Add possible Reasons */
596	if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
597	   hapd->wps_stats.failure_reason > 0) {
598		ret = os_snprintf(pos, end - pos,
599				  "Failure Reason: %s\n",
600				  wps_ei_str(hapd->wps_stats.failure_reason));
601
602		if (ret < 0 || ret >= end - pos)
603			return pos - buf;
604		pos += ret;
605	}
606
607	if (hapd->wps_stats.status) {
608		ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
609				  MAC2STR(hapd->wps_stats.peer_addr));
610
611		if (ret < 0 || ret >= end - pos)
612			return pos - buf;
613		pos += ret;
614	}
615
616	return pos - buf;
617}
618
619#endif /* CONFIG_WPS */
620
621#ifdef CONFIG_HS20
622
623static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
624					     const char *cmd)
625{
626	u8 addr[ETH_ALEN];
627	const char *url;
628
629	if (hwaddr_aton(cmd, addr))
630		return -1;
631	url = cmd + 17;
632	if (*url == '\0') {
633		url = NULL;
634	} else {
635		if (*url != ' ')
636			return -1;
637		url++;
638		if (*url == '\0')
639			url = NULL;
640	}
641
642	return hs20_send_wnm_notification(hapd, addr, 1, url);
643}
644
645
646static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
647					      const char *cmd)
648{
649	u8 addr[ETH_ALEN];
650	int code, reauth_delay, ret;
651	const char *pos;
652	size_t url_len;
653	struct wpabuf *req;
654
655	/* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
656	if (hwaddr_aton(cmd, addr))
657		return -1;
658
659	pos = os_strchr(cmd, ' ');
660	if (pos == NULL)
661		return -1;
662	pos++;
663	code = atoi(pos);
664
665	pos = os_strchr(pos, ' ');
666	if (pos == NULL)
667		return -1;
668	pos++;
669	reauth_delay = atoi(pos);
670
671	url_len = 0;
672	pos = os_strchr(pos, ' ');
673	if (pos) {
674		pos++;
675		url_len = os_strlen(pos);
676	}
677
678	req = wpabuf_alloc(4 + url_len);
679	if (req == NULL)
680		return -1;
681	wpabuf_put_u8(req, code);
682	wpabuf_put_le16(req, reauth_delay);
683	wpabuf_put_u8(req, url_len);
684	if (pos)
685		wpabuf_put_data(req, pos, url_len);
686
687	wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
688		   " to indicate imminent deauthentication (code=%d "
689		   "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
690	ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
691	wpabuf_free(req);
692	return ret;
693}
694
695#endif /* CONFIG_HS20 */
696
697
698#ifdef CONFIG_INTERWORKING
699
700static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
701					      const char *cmd)
702{
703	u8 qos_map_set[16 + 2 * 21], count = 0;
704	const char *pos = cmd;
705	int val, ret;
706
707	for (;;) {
708		if (count == sizeof(qos_map_set)) {
709			wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
710			return -1;
711		}
712
713		val = atoi(pos);
714		if (val < 0 || val > 255) {
715			wpa_printf(MSG_INFO, "Invalid QoS Map Set");
716			return -1;
717		}
718
719		qos_map_set[count++] = val;
720		pos = os_strchr(pos, ',');
721		if (!pos)
722			break;
723		pos++;
724	}
725
726	if (count < 16 || count & 1) {
727		wpa_printf(MSG_INFO, "Invalid QoS Map Set");
728		return -1;
729	}
730
731	ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
732	if (ret) {
733		wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
734		return -1;
735	}
736
737	os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
738	hapd->conf->qos_map_set_len = count;
739
740	return 0;
741}
742
743
744static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
745						const char *cmd)
746{
747	u8 addr[ETH_ALEN];
748	struct sta_info *sta;
749	struct wpabuf *buf;
750	u8 *qos_map_set = hapd->conf->qos_map_set;
751	u8 qos_map_set_len = hapd->conf->qos_map_set_len;
752	int ret;
753
754	if (!qos_map_set_len) {
755		wpa_printf(MSG_INFO, "QoS Map Set is not set");
756		return -1;
757	}
758
759	if (hwaddr_aton(cmd, addr))
760		return -1;
761
762	sta = ap_get_sta(hapd, addr);
763	if (sta == NULL) {
764		wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
765			   "for QoS Map Configuration message",
766			   MAC2STR(addr));
767		return -1;
768	}
769
770	if (!sta->qos_map_enabled) {
771		wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
772			   "support for QoS Map", MAC2STR(addr));
773		return -1;
774	}
775
776	buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
777	if (buf == NULL)
778		return -1;
779
780	wpabuf_put_u8(buf, WLAN_ACTION_QOS);
781	wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
782
783	/* QoS Map Set Element */
784	wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
785	wpabuf_put_u8(buf, qos_map_set_len);
786	wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
787
788	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
789				      wpabuf_head(buf), wpabuf_len(buf));
790	wpabuf_free(buf);
791
792	return ret;
793}
794
795#endif /* CONFIG_INTERWORKING */
796
797
798#ifdef CONFIG_WNM
799
800static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
801						const char *cmd)
802{
803	u8 addr[ETH_ALEN];
804	int disassoc_timer;
805	struct sta_info *sta;
806
807	if (hwaddr_aton(cmd, addr))
808		return -1;
809	if (cmd[17] != ' ')
810		return -1;
811	disassoc_timer = atoi(cmd + 17);
812
813	sta = ap_get_sta(hapd, addr);
814	if (sta == NULL) {
815		wpa_printf(MSG_DEBUG, "Station " MACSTR
816			   " not found for disassociation imminent message",
817			   MAC2STR(addr));
818		return -1;
819	}
820
821	return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
822}
823
824
825static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
826					   const char *cmd)
827{
828	u8 addr[ETH_ALEN];
829	const char *url, *timerstr;
830	int disassoc_timer;
831	struct sta_info *sta;
832
833	if (hwaddr_aton(cmd, addr))
834		return -1;
835
836	sta = ap_get_sta(hapd, addr);
837	if (sta == NULL) {
838		wpa_printf(MSG_DEBUG, "Station " MACSTR
839			   " not found for ESS disassociation imminent message",
840			   MAC2STR(addr));
841		return -1;
842	}
843
844	timerstr = cmd + 17;
845	if (*timerstr != ' ')
846		return -1;
847	timerstr++;
848	disassoc_timer = atoi(timerstr);
849	if (disassoc_timer < 0 || disassoc_timer > 65535)
850		return -1;
851
852	url = os_strchr(timerstr, ' ');
853	if (url == NULL)
854		return -1;
855	url++;
856
857	return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
858}
859
860#endif /* CONFIG_WNM */
861
862
863static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
864					 char *buf, size_t buflen)
865{
866	int ret;
867	char *pos, *end;
868
869	pos = buf;
870	end = buf + buflen;
871
872	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
873			  "ssid=%s\n",
874			  MAC2STR(hapd->own_addr),
875			  wpa_ssid_txt(hapd->conf->ssid.ssid,
876				       hapd->conf->ssid.ssid_len));
877	if (ret < 0 || ret >= end - pos)
878		return pos - buf;
879	pos += ret;
880
881#ifdef CONFIG_WPS
882	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
883			  hapd->conf->wps_state == 0 ? "disabled" :
884			  (hapd->conf->wps_state == 1 ? "not configured" :
885			   "configured"));
886	if (ret < 0 || ret >= end - pos)
887		return pos - buf;
888	pos += ret;
889
890	if (hapd->conf->wps_state && hapd->conf->wpa &&
891	    hapd->conf->ssid.wpa_passphrase) {
892		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
893				  hapd->conf->ssid.wpa_passphrase);
894		if (ret < 0 || ret >= end - pos)
895			return pos - buf;
896		pos += ret;
897	}
898
899	if (hapd->conf->wps_state && hapd->conf->wpa &&
900	    hapd->conf->ssid.wpa_psk &&
901	    hapd->conf->ssid.wpa_psk->group) {
902		char hex[PMK_LEN * 2 + 1];
903		wpa_snprintf_hex(hex, sizeof(hex),
904				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
905		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
906		if (ret < 0 || ret >= end - pos)
907			return pos - buf;
908		pos += ret;
909	}
910#endif /* CONFIG_WPS */
911
912	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
913		ret = os_snprintf(pos, end - pos, "key_mgmt=");
914		if (ret < 0 || ret >= end - pos)
915			return pos - buf;
916		pos += ret;
917
918		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
919			ret = os_snprintf(pos, end - pos, "WPA-PSK ");
920			if (ret < 0 || ret >= end - pos)
921				return pos - buf;
922			pos += ret;
923		}
924		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
925			ret = os_snprintf(pos, end - pos, "WPA-EAP ");
926			if (ret < 0 || ret >= end - pos)
927				return pos - buf;
928			pos += ret;
929		}
930#ifdef CONFIG_IEEE80211R
931		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
932			ret = os_snprintf(pos, end - pos, "FT-PSK ");
933			if (ret < 0 || ret >= end - pos)
934				return pos - buf;
935			pos += ret;
936		}
937		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
938			ret = os_snprintf(pos, end - pos, "FT-EAP ");
939			if (ret < 0 || ret >= end - pos)
940				return pos - buf;
941			pos += ret;
942		}
943#ifdef CONFIG_SAE
944		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
945			ret = os_snprintf(pos, end - pos, "FT-SAE ");
946			if (ret < 0 || ret >= end - pos)
947				return pos - buf;
948			pos += ret;
949		}
950#endif /* CONFIG_SAE */
951#endif /* CONFIG_IEEE80211R */
952#ifdef CONFIG_IEEE80211W
953		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
954			ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
955			if (ret < 0 || ret >= end - pos)
956				return pos - buf;
957			pos += ret;
958		}
959		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
960			ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
961			if (ret < 0 || ret >= end - pos)
962				return pos - buf;
963			pos += ret;
964		}
965#endif /* CONFIG_IEEE80211W */
966#ifdef CONFIG_SAE
967		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
968			ret = os_snprintf(pos, end - pos, "SAE ");
969			if (ret < 0 || ret >= end - pos)
970				return pos - buf;
971			pos += ret;
972		}
973#endif /* CONFIG_SAE */
974
975		ret = os_snprintf(pos, end - pos, "\n");
976		if (ret < 0 || ret >= end - pos)
977			return pos - buf;
978		pos += ret;
979	}
980
981	if (hapd->conf->wpa) {
982		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
983				  wpa_cipher_txt(hapd->conf->wpa_group));
984		if (ret < 0 || ret >= end - pos)
985			return pos - buf;
986		pos += ret;
987	}
988
989	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
990		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
991		if (ret < 0 || ret >= end - pos)
992			return pos - buf;
993		pos += ret;
994
995		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
996					" ");
997		if (ret < 0)
998			return pos - buf;
999		pos += ret;
1000
1001		ret = os_snprintf(pos, end - pos, "\n");
1002		if (ret < 0 || ret >= end - pos)
1003			return pos - buf;
1004		pos += ret;
1005	}
1006
1007	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1008		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1009		if (ret < 0 || ret >= end - pos)
1010			return pos - buf;
1011		pos += ret;
1012
1013		ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1014					" ");
1015		if (ret < 0)
1016			return pos - buf;
1017		pos += ret;
1018
1019		ret = os_snprintf(pos, end - pos, "\n");
1020		if (ret < 0 || ret >= end - pos)
1021			return pos - buf;
1022		pos += ret;
1023	}
1024
1025	return pos - buf;
1026}
1027
1028
1029static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1030{
1031	char *value;
1032	int ret = 0;
1033
1034	value = os_strchr(cmd, ' ');
1035	if (value == NULL)
1036		return -1;
1037	*value++ = '\0';
1038
1039	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1040	if (0) {
1041#ifdef CONFIG_WPS_TESTING
1042	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1043		long int val;
1044		val = strtol(value, NULL, 0);
1045		if (val < 0 || val > 0xff) {
1046			ret = -1;
1047			wpa_printf(MSG_DEBUG, "WPS: Invalid "
1048				   "wps_version_number %ld", val);
1049		} else {
1050			wps_version_number = val;
1051			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1052				   "version %u.%u",
1053				   (wps_version_number & 0xf0) >> 4,
1054				   wps_version_number & 0x0f);
1055			hostapd_wps_update_ie(hapd);
1056		}
1057	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
1058		wps_testing_dummy_cred = atoi(value);
1059		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
1060			   wps_testing_dummy_cred);
1061	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1062		wps_corrupt_pkhash = atoi(value);
1063		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1064			   wps_corrupt_pkhash);
1065#endif /* CONFIG_WPS_TESTING */
1066#ifdef CONFIG_INTERWORKING
1067	} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
1068		int val = atoi(value);
1069		if (val <= 0)
1070			ret = -1;
1071		else
1072			hapd->gas_frag_limit = val;
1073#endif /* CONFIG_INTERWORKING */
1074#ifdef CONFIG_TESTING_OPTIONS
1075	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1076		hapd->ext_mgmt_frame_handling = atoi(value);
1077#endif /* CONFIG_TESTING_OPTIONS */
1078	} else {
1079		struct sta_info *sta;
1080		int vlan_id;
1081
1082		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1083		if (ret)
1084			return ret;
1085
1086		if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1087			for (sta = hapd->sta_list; sta; sta = sta->next) {
1088				if (hostapd_maclist_found(
1089					    hapd->conf->deny_mac,
1090					    hapd->conf->num_deny_mac, sta->addr,
1091					    &vlan_id) &&
1092				    (!vlan_id || vlan_id == sta->vlan_id))
1093					ap_sta_disconnect(
1094						hapd, sta, sta->addr,
1095						WLAN_REASON_UNSPECIFIED);
1096			}
1097		} else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
1098			   os_strcasecmp(cmd, "accept_mac_file") == 0) {
1099			for (sta = hapd->sta_list; sta; sta = sta->next) {
1100				if (!hostapd_maclist_found(
1101					    hapd->conf->accept_mac,
1102					    hapd->conf->num_accept_mac,
1103					    sta->addr, &vlan_id) ||
1104				    (vlan_id && vlan_id != sta->vlan_id))
1105					ap_sta_disconnect(
1106						hapd, sta, sta->addr,
1107						WLAN_REASON_UNSPECIFIED);
1108			}
1109		}
1110	}
1111
1112	return ret;
1113}
1114
1115
1116static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1117				  char *buf, size_t buflen)
1118{
1119	int res;
1120
1121	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1122
1123	if (os_strcmp(cmd, "version") == 0) {
1124		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1125		if (res < 0 || (unsigned int) res >= buflen)
1126			return -1;
1127		return res;
1128	}
1129
1130	return -1;
1131}
1132
1133
1134static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1135{
1136	if (hostapd_enable_iface(iface) < 0) {
1137		wpa_printf(MSG_ERROR, "Enabling of interface failed");
1138		return -1;
1139	}
1140	return 0;
1141}
1142
1143
1144static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1145{
1146	if (hostapd_reload_iface(iface) < 0) {
1147		wpa_printf(MSG_ERROR, "Reloading of interface failed");
1148		return -1;
1149	}
1150	return 0;
1151}
1152
1153
1154static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1155{
1156	if (hostapd_disable_iface(iface) < 0) {
1157		wpa_printf(MSG_ERROR, "Disabling of interface failed");
1158		return -1;
1159	}
1160	return 0;
1161}
1162
1163
1164#ifdef CONFIG_TESTING_OPTIONS
1165
1166static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1167{
1168	union wpa_event_data data;
1169	char *pos, *param;
1170	enum wpa_event_type event;
1171
1172	wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1173
1174	os_memset(&data, 0, sizeof(data));
1175
1176	param = os_strchr(cmd, ' ');
1177	if (param == NULL)
1178		return -1;
1179	*param++ = '\0';
1180
1181	if (os_strcmp(cmd, "DETECTED") == 0)
1182		event = EVENT_DFS_RADAR_DETECTED;
1183	else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1184		event = EVENT_DFS_CAC_FINISHED;
1185	else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1186		event = EVENT_DFS_CAC_ABORTED;
1187	else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1188		event = EVENT_DFS_NOP_FINISHED;
1189	else {
1190		wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1191			   cmd);
1192		return -1;
1193	}
1194
1195	pos = os_strstr(param, "freq=");
1196	if (pos)
1197		data.dfs_event.freq = atoi(pos + 5);
1198
1199	pos = os_strstr(param, "ht_enabled=1");
1200	if (pos)
1201		data.dfs_event.ht_enabled = 1;
1202
1203	pos = os_strstr(param, "chan_offset=");
1204	if (pos)
1205		data.dfs_event.chan_offset = atoi(pos + 12);
1206
1207	pos = os_strstr(param, "chan_width=");
1208	if (pos)
1209		data.dfs_event.chan_width = atoi(pos + 11);
1210
1211	pos = os_strstr(param, "cf1=");
1212	if (pos)
1213		data.dfs_event.cf1 = atoi(pos + 4);
1214
1215	pos = os_strstr(param, "cf2=");
1216	if (pos)
1217		data.dfs_event.cf2 = atoi(pos + 4);
1218
1219	wpa_supplicant_event(hapd, event, &data);
1220
1221	return 0;
1222}
1223
1224
1225static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1226{
1227	size_t len;
1228	u8 *buf;
1229	int res;
1230
1231	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1232
1233	len = os_strlen(cmd);
1234	if (len & 1)
1235		return -1;
1236	len /= 2;
1237
1238	buf = os_malloc(len);
1239	if (buf == NULL)
1240		return -1;
1241
1242	if (hexstr2bin(cmd, buf, len) < 0) {
1243		os_free(buf);
1244		return -1;
1245	}
1246
1247	res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1248	os_free(buf);
1249	return res;
1250}
1251
1252#endif /* CONFIG_TESTING_OPTIONS */
1253
1254
1255static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
1256					  char *pos)
1257{
1258#ifdef NEED_AP_MLME
1259	struct csa_settings settings;
1260	int ret;
1261	unsigned int i;
1262
1263	ret = hostapd_parse_csa_settings(pos, &settings);
1264	if (ret)
1265		return ret;
1266
1267	for (i = 0; i < iface->num_bss; i++) {
1268		ret = hostapd_switch_channel(iface->bss[i], &settings);
1269		if (ret) {
1270			/* FIX: What do we do if CSA fails in the middle of
1271			 * submitting multi-BSS CSA requests? */
1272			return ret;
1273		}
1274	}
1275
1276	return 0;
1277#else /* NEED_AP_MLME */
1278	return -1;
1279#endif /* NEED_AP_MLME */
1280}
1281
1282
1283static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
1284				  int reply_size, const char *param)
1285{
1286#ifdef RADIUS_SERVER
1287	if (os_strcmp(param, "radius_server") == 0) {
1288		return radius_server_get_mib(hapd->radius_srv, reply,
1289					     reply_size);
1290	}
1291#endif /* RADIUS_SERVER */
1292	return -1;
1293}
1294
1295
1296static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
1297				     char *buf, size_t buflen)
1298{
1299	int ret;
1300	char *pos;
1301	u8 *data = NULL;
1302	unsigned int vendor_id, subcmd;
1303	struct wpabuf *reply;
1304	size_t data_len = 0;
1305
1306	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
1307	vendor_id = strtoul(cmd, &pos, 16);
1308	if (!isblank(*pos))
1309		return -EINVAL;
1310
1311	subcmd = strtoul(pos, &pos, 10);
1312
1313	if (*pos != '\0') {
1314		if (!isblank(*pos++))
1315			return -EINVAL;
1316		data_len = os_strlen(pos);
1317	}
1318
1319	if (data_len) {
1320		data_len /= 2;
1321		data = os_malloc(data_len);
1322		if (!data)
1323			return -ENOBUFS;
1324
1325		if (hexstr2bin(pos, data, data_len)) {
1326			wpa_printf(MSG_DEBUG,
1327				   "Vendor command: wrong parameter format");
1328			os_free(data);
1329			return -EINVAL;
1330		}
1331	}
1332
1333	reply = wpabuf_alloc((buflen - 1) / 2);
1334	if (!reply) {
1335		os_free(data);
1336		return -ENOBUFS;
1337	}
1338
1339	ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
1340				     reply);
1341
1342	if (ret == 0)
1343		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
1344				       wpabuf_len(reply));
1345
1346	wpabuf_free(reply);
1347	os_free(data);
1348
1349	return ret;
1350}
1351
1352
1353static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
1354				       void *sock_ctx)
1355{
1356	struct hostapd_data *hapd = eloop_ctx;
1357	char buf[4096];
1358	int res;
1359	struct sockaddr_un from;
1360	socklen_t fromlen = sizeof(from);
1361	char *reply;
1362	const int reply_size = 4096;
1363	int reply_len;
1364	int level = MSG_DEBUG;
1365
1366	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1367		       (struct sockaddr *) &from, &fromlen);
1368	if (res < 0) {
1369		perror("recvfrom(ctrl_iface)");
1370		return;
1371	}
1372	buf[res] = '\0';
1373	if (os_strcmp(buf, "PING") == 0)
1374		level = MSG_EXCESSIVE;
1375	wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
1376
1377	reply = os_malloc(reply_size);
1378	if (reply == NULL) {
1379		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
1380		       fromlen);
1381		return;
1382	}
1383
1384	os_memcpy(reply, "OK\n", 3);
1385	reply_len = 3;
1386
1387	if (os_strcmp(buf, "PING") == 0) {
1388		os_memcpy(reply, "PONG\n", 5);
1389		reply_len = 5;
1390	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
1391		if (wpa_debug_reopen_file() < 0)
1392			reply_len = -1;
1393	} else if (os_strcmp(buf, "STATUS") == 0) {
1394		reply_len = hostapd_ctrl_iface_status(hapd, reply,
1395						      reply_size);
1396	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
1397		reply_len = hostapd_drv_status(hapd, reply, reply_size);
1398	} else if (os_strcmp(buf, "MIB") == 0) {
1399		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
1400		if (reply_len >= 0) {
1401			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
1402					  reply_size - reply_len);
1403			if (res < 0)
1404				reply_len = -1;
1405			else
1406				reply_len += res;
1407		}
1408		if (reply_len >= 0) {
1409			res = ieee802_1x_get_mib(hapd, reply + reply_len,
1410						 reply_size - reply_len);
1411			if (res < 0)
1412				reply_len = -1;
1413			else
1414				reply_len += res;
1415		}
1416#ifndef CONFIG_NO_RADIUS
1417		if (reply_len >= 0) {
1418			res = radius_client_get_mib(hapd->radius,
1419						    reply + reply_len,
1420						    reply_size - reply_len);
1421			if (res < 0)
1422				reply_len = -1;
1423			else
1424				reply_len += res;
1425		}
1426#endif /* CONFIG_NO_RADIUS */
1427	} else if (os_strncmp(buf, "MIB ", 4) == 0) {
1428		reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
1429						   buf + 4);
1430	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
1431		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
1432							 reply_size);
1433	} else if (os_strncmp(buf, "STA ", 4) == 0) {
1434		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
1435						   reply_size);
1436	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
1437		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
1438							reply_size);
1439	} else if (os_strcmp(buf, "ATTACH") == 0) {
1440		if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
1441			reply_len = -1;
1442	} else if (os_strcmp(buf, "DETACH") == 0) {
1443		if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
1444			reply_len = -1;
1445	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
1446		if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
1447						    buf + 6))
1448			reply_len = -1;
1449	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
1450		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
1451			reply_len = -1;
1452	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
1453		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
1454			reply_len = -1;
1455	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
1456		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
1457			reply_len = -1;
1458#ifdef CONFIG_IEEE80211W
1459#ifdef NEED_AP_MLME
1460	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
1461		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
1462			reply_len = -1;
1463#endif /* NEED_AP_MLME */
1464#endif /* CONFIG_IEEE80211W */
1465#ifdef CONFIG_WPS
1466	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
1467		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
1468			reply_len = -1;
1469	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
1470		reply_len = hostapd_ctrl_iface_wps_check_pin(
1471			hapd, buf + 14, reply, reply_size);
1472	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
1473		if (hostapd_wps_button_pushed(hapd, NULL))
1474			reply_len = -1;
1475	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
1476		if (hostapd_wps_cancel(hapd))
1477			reply_len = -1;
1478	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
1479		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
1480							  reply, reply_size);
1481	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
1482		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
1483			reply_len = -1;
1484	} else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
1485		reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
1486							      reply_size);
1487#ifdef CONFIG_WPS_NFC
1488	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
1489		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
1490			reply_len = -1;
1491	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
1492		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
1493			hapd, buf + 21, reply, reply_size);
1494	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
1495		reply_len = hostapd_ctrl_iface_wps_nfc_token(
1496			hapd, buf + 14, reply, reply_size);
1497	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
1498		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
1499			hapd, buf + 21, reply, reply_size);
1500	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
1501		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
1502			reply_len = -1;
1503#endif /* CONFIG_WPS_NFC */
1504#endif /* CONFIG_WPS */
1505#ifdef CONFIG_INTERWORKING
1506	} else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
1507		if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
1508			reply_len = -1;
1509	} else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
1510		if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
1511			reply_len = -1;
1512#endif /* CONFIG_INTERWORKING */
1513#ifdef CONFIG_HS20
1514	} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
1515		if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
1516			reply_len = -1;
1517	} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
1518		if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
1519			reply_len = -1;
1520#endif /* CONFIG_HS20 */
1521#ifdef CONFIG_WNM
1522	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
1523		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
1524			reply_len = -1;
1525	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
1526		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
1527			reply_len = -1;
1528#endif /* CONFIG_WNM */
1529	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
1530		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
1531							  reply_size);
1532	} else if (os_strncmp(buf, "SET ", 4) == 0) {
1533		if (hostapd_ctrl_iface_set(hapd, buf + 4))
1534			reply_len = -1;
1535	} else if (os_strncmp(buf, "GET ", 4) == 0) {
1536		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
1537						   reply_size);
1538	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
1539		if (hostapd_ctrl_iface_enable(hapd->iface))
1540			reply_len = -1;
1541	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
1542		if (hostapd_ctrl_iface_reload(hapd->iface))
1543			reply_len = -1;
1544	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
1545		if (hostapd_ctrl_iface_disable(hapd->iface))
1546			reply_len = -1;
1547#ifdef CONFIG_TESTING_OPTIONS
1548	} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
1549		if (hostapd_ctrl_iface_radar(hapd, buf + 6))
1550			reply_len = -1;
1551	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
1552		if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
1553			reply_len = -1;
1554#endif /* CONFIG_TESTING_OPTIONS */
1555	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
1556		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
1557			reply_len = -1;
1558	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
1559		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
1560						      reply_size);
1561
1562	} else {
1563		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1564		reply_len = 16;
1565	}
1566
1567	if (reply_len < 0) {
1568		os_memcpy(reply, "FAIL\n", 5);
1569		reply_len = 5;
1570	}
1571	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1572	os_free(reply);
1573}
1574
1575
1576static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
1577{
1578	char *buf;
1579	size_t len;
1580
1581	if (hapd->conf->ctrl_interface == NULL)
1582		return NULL;
1583
1584	len = os_strlen(hapd->conf->ctrl_interface) +
1585		os_strlen(hapd->conf->iface) + 2;
1586	buf = os_malloc(len);
1587	if (buf == NULL)
1588		return NULL;
1589
1590	os_snprintf(buf, len, "%s/%s",
1591		    hapd->conf->ctrl_interface, hapd->conf->iface);
1592	buf[len - 1] = '\0';
1593	return buf;
1594}
1595
1596
1597static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
1598				      const char *txt, size_t len)
1599{
1600	struct hostapd_data *hapd = ctx;
1601	if (hapd == NULL)
1602		return;
1603	hostapd_ctrl_iface_send(hapd, level, txt, len);
1604}
1605
1606
1607int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
1608{
1609	struct sockaddr_un addr;
1610	int s = -1;
1611	char *fname = NULL;
1612
1613	if (hapd->ctrl_sock > -1) {
1614		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
1615		return 0;
1616	}
1617
1618	if (hapd->conf->ctrl_interface == NULL)
1619		return 0;
1620
1621	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1622		if (errno == EEXIST) {
1623			wpa_printf(MSG_DEBUG, "Using existing control "
1624				   "interface directory.");
1625		} else {
1626			perror("mkdir[ctrl_interface]");
1627			goto fail;
1628		}
1629	}
1630
1631	if (hapd->conf->ctrl_interface_gid_set &&
1632	    chown(hapd->conf->ctrl_interface, -1,
1633		  hapd->conf->ctrl_interface_gid) < 0) {
1634		perror("chown[ctrl_interface]");
1635		return -1;
1636	}
1637
1638	if (!hapd->conf->ctrl_interface_gid_set &&
1639	    hapd->iface->interfaces->ctrl_iface_group &&
1640	    chown(hapd->conf->ctrl_interface, -1,
1641		  hapd->iface->interfaces->ctrl_iface_group) < 0) {
1642		perror("chown[ctrl_interface]");
1643		return -1;
1644	}
1645
1646#ifdef ANDROID
1647	/*
1648	 * Android is using umask 0077 which would leave the control interface
1649	 * directory without group access. This breaks things since Wi-Fi
1650	 * framework assumes that this directory can be accessed by other
1651	 * applications in the wifi group. Fix this by adding group access even
1652	 * if umask value would prevent this.
1653	 */
1654	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1655		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
1656			   strerror(errno));
1657		/* Try to continue anyway */
1658	}
1659#endif /* ANDROID */
1660
1661	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
1662	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
1663		goto fail;
1664
1665	s = socket(PF_UNIX, SOCK_DGRAM, 0);
1666	if (s < 0) {
1667		perror("socket(PF_UNIX)");
1668		goto fail;
1669	}
1670
1671	os_memset(&addr, 0, sizeof(addr));
1672#ifdef __FreeBSD__
1673	addr.sun_len = sizeof(addr);
1674#endif /* __FreeBSD__ */
1675	addr.sun_family = AF_UNIX;
1676	fname = hostapd_ctrl_iface_path(hapd);
1677	if (fname == NULL)
1678		goto fail;
1679	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1680	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1681		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1682			   strerror(errno));
1683		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1684			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1685				   " allow connections - assuming it was left"
1686				   "over from forced program termination");
1687			if (unlink(fname) < 0) {
1688				perror("unlink[ctrl_iface]");
1689				wpa_printf(MSG_ERROR, "Could not unlink "
1690					   "existing ctrl_iface socket '%s'",
1691					   fname);
1692				goto fail;
1693			}
1694			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1695			    0) {
1696				perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1697				goto fail;
1698			}
1699			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1700				   "ctrl_iface socket '%s'", fname);
1701		} else {
1702			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1703				   "be in use - cannot override it");
1704			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1705				   "not used anymore", fname);
1706			os_free(fname);
1707			fname = NULL;
1708			goto fail;
1709		}
1710	}
1711
1712	if (hapd->conf->ctrl_interface_gid_set &&
1713	    chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
1714		perror("chown[ctrl_interface/ifname]");
1715		goto fail;
1716	}
1717
1718	if (!hapd->conf->ctrl_interface_gid_set &&
1719	    hapd->iface->interfaces->ctrl_iface_group &&
1720	    chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
1721		perror("chown[ctrl_interface/ifname]");
1722		goto fail;
1723	}
1724
1725	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1726		perror("chmod[ctrl_interface/ifname]");
1727		goto fail;
1728	}
1729	os_free(fname);
1730
1731	hapd->ctrl_sock = s;
1732	eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
1733				 NULL);
1734	hapd->msg_ctx = hapd;
1735	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
1736
1737	return 0;
1738
1739fail:
1740	if (s >= 0)
1741		close(s);
1742	if (fname) {
1743		unlink(fname);
1744		os_free(fname);
1745	}
1746	return -1;
1747}
1748
1749
1750void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
1751{
1752	struct wpa_ctrl_dst *dst, *prev;
1753
1754	if (hapd->ctrl_sock > -1) {
1755		char *fname;
1756		eloop_unregister_read_sock(hapd->ctrl_sock);
1757		close(hapd->ctrl_sock);
1758		hapd->ctrl_sock = -1;
1759		fname = hostapd_ctrl_iface_path(hapd);
1760		if (fname)
1761			unlink(fname);
1762		os_free(fname);
1763
1764		if (hapd->conf->ctrl_interface &&
1765		    rmdir(hapd->conf->ctrl_interface) < 0) {
1766			if (errno == ENOTEMPTY) {
1767				wpa_printf(MSG_DEBUG, "Control interface "
1768					   "directory not empty - leaving it "
1769					   "behind");
1770			} else {
1771				wpa_printf(MSG_ERROR,
1772					   "rmdir[ctrl_interface=%s]: %s",
1773					   hapd->conf->ctrl_interface,
1774					   strerror(errno));
1775			}
1776		}
1777	}
1778
1779	dst = hapd->ctrl_dst;
1780	while (dst) {
1781		prev = dst;
1782		dst = dst->next;
1783		os_free(prev);
1784	}
1785}
1786
1787
1788static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
1789				  char *buf)
1790{
1791	if (hostapd_add_iface(interfaces, buf) < 0) {
1792		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
1793		return -1;
1794	}
1795	return 0;
1796}
1797
1798
1799static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
1800				     char *buf)
1801{
1802	if (hostapd_remove_iface(interfaces, buf) < 0) {
1803		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
1804		return -1;
1805	}
1806	return 0;
1807}
1808
1809
1810static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
1811{
1812#ifdef CONFIG_WPS_TESTING
1813	wps_version_number = 0x20;
1814	wps_testing_dummy_cred = 0;
1815	wps_corrupt_pkhash = 0;
1816#endif /* CONFIG_WPS_TESTING */
1817}
1818
1819
1820static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
1821					      void *sock_ctx)
1822{
1823	void *interfaces = eloop_ctx;
1824	char buf[256];
1825	int res;
1826	struct sockaddr_un from;
1827	socklen_t fromlen = sizeof(from);
1828	char reply[24];
1829	int reply_len;
1830
1831	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1832		       (struct sockaddr *) &from, &fromlen);
1833	if (res < 0) {
1834		perror("recvfrom(ctrl_iface)");
1835		return;
1836	}
1837	buf[res] = '\0';
1838	wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
1839
1840	os_memcpy(reply, "OK\n", 3);
1841	reply_len = 3;
1842
1843	if (os_strcmp(buf, "PING") == 0) {
1844		os_memcpy(reply, "PONG\n", 5);
1845		reply_len = 5;
1846	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
1847		if (wpa_debug_reopen_file() < 0)
1848			reply_len = -1;
1849	} else if (os_strcmp(buf, "FLUSH") == 0) {
1850		hostapd_ctrl_iface_flush(interfaces);
1851	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
1852		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
1853			reply_len = -1;
1854	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
1855		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
1856			reply_len = -1;
1857#ifdef CONFIG_MODULE_TESTS
1858	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
1859		int hapd_module_tests(void);
1860		if (hapd_module_tests() < 0)
1861			reply_len = -1;
1862#endif /* CONFIG_MODULE_TESTS */
1863	} else {
1864		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
1865			   "ignored");
1866		reply_len = -1;
1867	}
1868
1869	if (reply_len < 0) {
1870		os_memcpy(reply, "FAIL\n", 5);
1871		reply_len = 5;
1872	}
1873
1874	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1875}
1876
1877
1878static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
1879{
1880	char *buf;
1881	size_t len;
1882
1883	if (interface->global_iface_path == NULL)
1884		return NULL;
1885
1886	len = os_strlen(interface->global_iface_path) +
1887		os_strlen(interface->global_iface_name) + 2;
1888	buf = os_malloc(len);
1889	if (buf == NULL)
1890		return NULL;
1891
1892	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
1893		    interface->global_iface_name);
1894	buf[len - 1] = '\0';
1895	return buf;
1896}
1897
1898
1899int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
1900{
1901	struct sockaddr_un addr;
1902	int s = -1;
1903	char *fname = NULL;
1904
1905	if (interface->global_iface_path == NULL) {
1906		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
1907		return 0;
1908	}
1909
1910	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
1911		if (errno == EEXIST) {
1912			wpa_printf(MSG_DEBUG, "Using existing control "
1913				   "interface directory.");
1914		} else {
1915			perror("mkdir[ctrl_interface]");
1916			goto fail;
1917		}
1918	} else if (interface->ctrl_iface_group &&
1919		   chown(interface->global_iface_path, -1,
1920			 interface->ctrl_iface_group) < 0) {
1921		perror("chown[ctrl_interface]");
1922		goto fail;
1923	}
1924
1925	if (os_strlen(interface->global_iface_path) + 1 +
1926	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
1927		goto fail;
1928
1929	s = socket(PF_UNIX, SOCK_DGRAM, 0);
1930	if (s < 0) {
1931		perror("socket(PF_UNIX)");
1932		goto fail;
1933	}
1934
1935	os_memset(&addr, 0, sizeof(addr));
1936#ifdef __FreeBSD__
1937	addr.sun_len = sizeof(addr);
1938#endif /* __FreeBSD__ */
1939	addr.sun_family = AF_UNIX;
1940	fname = hostapd_global_ctrl_iface_path(interface);
1941	if (fname == NULL)
1942		goto fail;
1943	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1944	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1945		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1946			   strerror(errno));
1947		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1948			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1949				   " allow connections - assuming it was left"
1950				   "over from forced program termination");
1951			if (unlink(fname) < 0) {
1952				perror("unlink[ctrl_iface]");
1953				wpa_printf(MSG_ERROR, "Could not unlink "
1954					   "existing ctrl_iface socket '%s'",
1955					   fname);
1956				goto fail;
1957			}
1958			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1959			    0) {
1960				perror("bind(PF_UNIX)");
1961				goto fail;
1962			}
1963			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1964				   "ctrl_iface socket '%s'", fname);
1965		} else {
1966			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1967				   "be in use - cannot override it");
1968			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1969				   "not used anymore", fname);
1970			os_free(fname);
1971			fname = NULL;
1972			goto fail;
1973		}
1974	}
1975
1976	if (interface->ctrl_iface_group &&
1977	    chown(fname, -1, interface->ctrl_iface_group) < 0) {
1978		perror("chown[ctrl_interface]");
1979		goto fail;
1980	}
1981
1982	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1983		perror("chmod[ctrl_interface/ifname]");
1984		goto fail;
1985	}
1986	os_free(fname);
1987
1988	interface->global_ctrl_sock = s;
1989	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
1990				 interface, NULL);
1991
1992	return 0;
1993
1994fail:
1995	if (s >= 0)
1996		close(s);
1997	if (fname) {
1998		unlink(fname);
1999		os_free(fname);
2000	}
2001	return -1;
2002}
2003
2004
2005void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
2006{
2007	char *fname = NULL;
2008
2009	if (interfaces->global_ctrl_sock > -1) {
2010		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
2011		close(interfaces->global_ctrl_sock);
2012		interfaces->global_ctrl_sock = -1;
2013		fname = hostapd_global_ctrl_iface_path(interfaces);
2014		if (fname) {
2015			unlink(fname);
2016			os_free(fname);
2017		}
2018
2019		if (interfaces->global_iface_path &&
2020		    rmdir(interfaces->global_iface_path) < 0) {
2021			if (errno == ENOTEMPTY) {
2022				wpa_printf(MSG_DEBUG, "Control interface "
2023					   "directory not empty - leaving it "
2024					   "behind");
2025			} else {
2026				wpa_printf(MSG_ERROR,
2027					   "rmdir[ctrl_interface=%s]: %s",
2028					   interfaces->global_iface_path,
2029					   strerror(errno));
2030			}
2031		}
2032		os_free(interfaces->global_iface_path);
2033		interfaces->global_iface_path = NULL;
2034	}
2035}
2036
2037
2038static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
2039				    const char *buf, size_t len)
2040{
2041	struct wpa_ctrl_dst *dst, *next;
2042	struct msghdr msg;
2043	int idx;
2044	struct iovec io[2];
2045	char levelstr[10];
2046
2047	dst = hapd->ctrl_dst;
2048	if (hapd->ctrl_sock < 0 || dst == NULL)
2049		return;
2050
2051	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
2052	io[0].iov_base = levelstr;
2053	io[0].iov_len = os_strlen(levelstr);
2054	io[1].iov_base = (char *) buf;
2055	io[1].iov_len = len;
2056	os_memset(&msg, 0, sizeof(msg));
2057	msg.msg_iov = io;
2058	msg.msg_iovlen = 2;
2059
2060	idx = 0;
2061	while (dst) {
2062		next = dst->next;
2063		if (level >= dst->debug_level) {
2064			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
2065				    (u8 *) dst->addr.sun_path, dst->addrlen -
2066				    offsetof(struct sockaddr_un, sun_path));
2067			msg.msg_name = &dst->addr;
2068			msg.msg_namelen = dst->addrlen;
2069			if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
2070				int _errno = errno;
2071				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
2072					   "%d - %s",
2073					   idx, errno, strerror(errno));
2074				dst->errors++;
2075				if (dst->errors > 10 || _errno == ENOENT) {
2076					hostapd_ctrl_iface_detach(
2077						hapd, &dst->addr,
2078						dst->addrlen);
2079				}
2080			} else
2081				dst->errors = 0;
2082		}
2083		idx++;
2084		dst = next;
2085	}
2086}
2087
2088#endif /* CONFIG_NATIVE_WINDOWS */
2089