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