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