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