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