ctrl_iface.c revision 657a704326e96437d8edaf37fcb6c354b7114358
1/*
2 * WPA Supplicant / Control interface (shared code for all backends)
3 * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "utils/includes.h"
16
17#include "utils/common.h"
18#include "utils/eloop.h"
19#include "common/version.h"
20#include "common/ieee802_11_defs.h"
21#include "common/wpa_ctrl.h"
22#include "eap_peer/eap.h"
23#include "eapol_supp/eapol_supp_sm.h"
24#include "rsn_supp/wpa.h"
25#include "rsn_supp/preauth.h"
26#include "rsn_supp/pmksa_cache.h"
27#include "l2_packet/l2_packet.h"
28#include "wps/wps.h"
29#include "config.h"
30#include "wpa_supplicant_i.h"
31#include "driver_i.h"
32#include "wps_supplicant.h"
33#include "ibss_rsn.h"
34#include "ap.h"
35#include "p2p_supplicant.h"
36#include "p2p/p2p.h"
37#include "notify.h"
38#include "bss.h"
39#include "scan.h"
40#include "ctrl_iface.h"
41#include "blacklist.h"
42
43extern struct wpa_driver_ops *wpa_drivers[];
44
45static int wpa_supplicant_global_iface_list(struct wpa_global *global,
46					    char *buf, int len);
47static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
48						  char *buf, int len);
49
50
51static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
52					 char *cmd)
53{
54	char *value;
55	int ret = 0;
56
57	value = os_strchr(cmd, ' ');
58	if (value == NULL)
59		return -1;
60	*value++ = '\0';
61
62	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
63	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
64		eapol_sm_configure(wpa_s->eapol,
65				   atoi(value), -1, -1, -1);
66	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
67		eapol_sm_configure(wpa_s->eapol,
68				   -1, atoi(value), -1, -1);
69	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
70		eapol_sm_configure(wpa_s->eapol,
71				   -1, -1, atoi(value), -1);
72	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
73		eapol_sm_configure(wpa_s->eapol,
74				   -1, -1, -1, atoi(value));
75	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
76		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
77				     atoi(value)))
78			ret = -1;
79	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
80		   0) {
81		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
82				     atoi(value)))
83			ret = -1;
84	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
85		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
86			ret = -1;
87	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
88		wpa_s->wps_fragment_size = atoi(value);
89#ifdef CONFIG_WPS_TESTING
90	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
91		long int val;
92		val = strtol(value, NULL, 0);
93		if (val < 0 || val > 0xff) {
94			ret = -1;
95			wpa_printf(MSG_DEBUG, "WPS: Invalid "
96				   "wps_version_number %ld", val);
97		} else {
98			wps_version_number = val;
99			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
100				   "version %u.%u",
101				   (wps_version_number & 0xf0) >> 4,
102				   wps_version_number & 0x0f);
103		}
104	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
105		wps_testing_dummy_cred = atoi(value);
106		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
107			   wps_testing_dummy_cred);
108#endif /* CONFIG_WPS_TESTING */
109	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
110		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
111			ret = -1;
112#ifdef CONFIG_TDLS_TESTING
113	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
114		extern unsigned int tdls_testing;
115		tdls_testing = strtol(value, NULL, 0);
116		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
117#endif /* CONFIG_TDLS_TESTING */
118#ifdef CONFIG_TDLS
119	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
120		int disabled = atoi(value);
121		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
122		if (disabled) {
123			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
124				ret = -1;
125		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
126			ret = -1;
127		wpa_tdls_enable(wpa_s->wpa, !disabled);
128#endif /* CONFIG_TDLS */
129	} else {
130		value[-1] = '=';
131		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
132		if (ret == 0)
133			wpa_supplicant_update_config(wpa_s);
134	}
135
136	return ret;
137}
138
139
140static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
141					 char *cmd, char *buf, size_t buflen)
142{
143	int res;
144
145	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
146
147	if (os_strcmp(cmd, "version") == 0) {
148		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
149		if (res < 0 || (unsigned int) res >= buflen)
150			return -1;
151		return res;
152	}
153
154	return -1;
155}
156
157
158#ifdef IEEE8021X_EAPOL
159static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
160					     char *addr)
161{
162	u8 bssid[ETH_ALEN];
163	struct wpa_ssid *ssid = wpa_s->current_ssid;
164
165	if (hwaddr_aton(addr, bssid)) {
166		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
167			   "'%s'", addr);
168		return -1;
169	}
170
171	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
172	rsn_preauth_deinit(wpa_s->wpa);
173	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
174		return -1;
175
176	return 0;
177}
178#endif /* IEEE8021X_EAPOL */
179
180
181#ifdef CONFIG_PEERKEY
182/* MLME-STKSTART.request(peer) */
183static int wpa_supplicant_ctrl_iface_stkstart(
184	struct wpa_supplicant *wpa_s, char *addr)
185{
186	u8 peer[ETH_ALEN];
187
188	if (hwaddr_aton(addr, peer)) {
189		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
190			   "address '%s'", addr);
191		return -1;
192	}
193
194	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
195		   MAC2STR(peer));
196
197	return wpa_sm_stkstart(wpa_s->wpa, peer);
198}
199#endif /* CONFIG_PEERKEY */
200
201
202#ifdef CONFIG_TDLS
203
204static int wpa_supplicant_ctrl_iface_tdls_discover(
205	struct wpa_supplicant *wpa_s, char *addr)
206{
207	u8 peer[ETH_ALEN];
208
209	if (hwaddr_aton(addr, peer)) {
210		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
211			   "address '%s'", addr);
212		return -1;
213	}
214
215	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
216		   MAC2STR(peer));
217
218	return wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
219}
220
221
222static int wpa_supplicant_ctrl_iface_tdls_setup(
223	struct wpa_supplicant *wpa_s, char *addr)
224{
225	u8 peer[ETH_ALEN];
226	int ret;
227
228	if (hwaddr_aton(addr, peer)) {
229		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
230			   "address '%s'", addr);
231		return -1;
232	}
233
234	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
235		   MAC2STR(peer));
236
237	ret = wpa_tdls_reneg(wpa_s->wpa, peer);
238	if (ret)
239		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
240	return ret;
241}
242
243
244static int wpa_supplicant_ctrl_iface_tdls_teardown(
245	struct wpa_supplicant *wpa_s, char *addr)
246{
247	u8 peer[ETH_ALEN];
248
249	if (hwaddr_aton(addr, peer)) {
250		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
251			   "address '%s'", addr);
252		return -1;
253	}
254
255	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
256		   MAC2STR(peer));
257
258	return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
259}
260
261#endif /* CONFIG_TDLS */
262
263
264#ifdef CONFIG_IEEE80211R
265static int wpa_supplicant_ctrl_iface_ft_ds(
266	struct wpa_supplicant *wpa_s, char *addr)
267{
268	u8 target_ap[ETH_ALEN];
269	struct wpa_bss *bss;
270	const u8 *mdie;
271
272	if (hwaddr_aton(addr, target_ap)) {
273		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
274			   "address '%s'", addr);
275		return -1;
276	}
277
278	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
279
280	bss = wpa_bss_get_bssid(wpa_s, target_ap);
281	if (bss)
282		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
283	else
284		mdie = NULL;
285
286	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
287}
288#endif /* CONFIG_IEEE80211R */
289
290
291#ifdef CONFIG_WPS
292static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
293					     char *cmd)
294{
295	u8 bssid[ETH_ALEN], *_bssid = bssid;
296	u8 p2p_dev_addr[ETH_ALEN], *_p2p_dev_addr = NULL;
297
298	if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
299		_bssid = NULL;
300#ifdef CONFIG_P2P
301	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
302		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
303			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
304				   "P2P Device Address '%s'",
305				   cmd + 13);
306			return -1;
307		}
308		_p2p_dev_addr = p2p_dev_addr;
309#endif /* CONFIG_P2P */
310	} else if (hwaddr_aton(cmd, bssid)) {
311		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
312			   cmd);
313		return -1;
314	}
315
316#ifdef CONFIG_AP
317	if (wpa_s->ap_iface)
318		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
319#endif /* CONFIG_AP */
320
321	return wpas_wps_start_pbc(wpa_s, _bssid, 0);
322}
323
324
325static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
326					     char *cmd, char *buf,
327					     size_t buflen)
328{
329	u8 bssid[ETH_ALEN], *_bssid = bssid;
330	char *pin;
331	int ret;
332
333	pin = os_strchr(cmd, ' ');
334	if (pin)
335		*pin++ = '\0';
336
337	if (os_strcmp(cmd, "any") == 0)
338		_bssid = NULL;
339	else if (hwaddr_aton(cmd, bssid)) {
340		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
341			   cmd);
342		return -1;
343	}
344
345#ifdef CONFIG_AP
346	if (wpa_s->ap_iface)
347		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
348						 buf, buflen);
349#endif /* CONFIG_AP */
350
351	if (pin) {
352		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
353					 DEV_PW_DEFAULT);
354		if (ret < 0)
355			return -1;
356		ret = os_snprintf(buf, buflen, "%s", pin);
357		if (ret < 0 || (size_t) ret >= buflen)
358			return -1;
359		return ret;
360	}
361
362	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
363	if (ret < 0)
364		return -1;
365
366	/* Return the generated PIN */
367	ret = os_snprintf(buf, buflen, "%08d", ret);
368	if (ret < 0 || (size_t) ret >= buflen)
369		return -1;
370	return ret;
371}
372
373
374static int wpa_supplicant_ctrl_iface_wps_check_pin(
375	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
376{
377	char pin[9];
378	size_t len;
379	char *pos;
380	int ret;
381
382	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
383			      (u8 *) cmd, os_strlen(cmd));
384	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
385		if (*pos < '0' || *pos > '9')
386			continue;
387		pin[len++] = *pos;
388		if (len == 9) {
389			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
390			return -1;
391		}
392	}
393	if (len != 4 && len != 8) {
394		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
395		return -1;
396	}
397	pin[len] = '\0';
398
399	if (len == 8) {
400		unsigned int pin_val;
401		pin_val = atoi(pin);
402		if (!wps_pin_valid(pin_val)) {
403			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
404			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
405			if (ret < 0 || (size_t) ret >= buflen)
406				return -1;
407			return ret;
408		}
409	}
410
411	ret = os_snprintf(buf, buflen, "%s", pin);
412	if (ret < 0 || (size_t) ret >= buflen)
413		return -1;
414
415	return ret;
416}
417
418
419#ifdef CONFIG_WPS_OOB
420static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
421					     char *cmd)
422{
423	char *path, *method, *name;
424
425	path = os_strchr(cmd, ' ');
426	if (path == NULL)
427		return -1;
428	*path++ = '\0';
429
430	method = os_strchr(path, ' ');
431	if (method == NULL)
432		return -1;
433	*method++ = '\0';
434
435	name = os_strchr(method, ' ');
436	if (name != NULL)
437		*name++ = '\0';
438
439	return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
440}
441#endif /* CONFIG_WPS_OOB */
442
443
444static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
445					     char *cmd)
446{
447	u8 bssid[ETH_ALEN];
448	char *pin;
449	char *new_ssid;
450	char *new_auth;
451	char *new_encr;
452	char *new_key;
453	struct wps_new_ap_settings ap;
454
455	pin = os_strchr(cmd, ' ');
456	if (pin == NULL)
457		return -1;
458	*pin++ = '\0';
459
460	if (hwaddr_aton(cmd, bssid)) {
461		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
462			   cmd);
463		return -1;
464	}
465
466	new_ssid = os_strchr(pin, ' ');
467	if (new_ssid == NULL)
468		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
469	*new_ssid++ = '\0';
470
471	new_auth = os_strchr(new_ssid, ' ');
472	if (new_auth == NULL)
473		return -1;
474	*new_auth++ = '\0';
475
476	new_encr = os_strchr(new_auth, ' ');
477	if (new_encr == NULL)
478		return -1;
479	*new_encr++ = '\0';
480
481	new_key = os_strchr(new_encr, ' ');
482	if (new_key == NULL)
483		return -1;
484	*new_key++ = '\0';
485
486	os_memset(&ap, 0, sizeof(ap));
487	ap.ssid_hex = new_ssid;
488	ap.auth = new_auth;
489	ap.encr = new_encr;
490	ap.key_hex = new_key;
491	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
492}
493
494
495#ifdef CONFIG_AP
496static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
497						char *cmd, char *buf,
498						size_t buflen)
499{
500	int timeout = 300;
501	char *pos;
502	const char *pin_txt;
503
504	if (!wpa_s->ap_iface)
505		return -1;
506
507	pos = os_strchr(cmd, ' ');
508	if (pos)
509		*pos++ = '\0';
510
511	if (os_strcmp(cmd, "disable") == 0) {
512		wpas_wps_ap_pin_disable(wpa_s);
513		return os_snprintf(buf, buflen, "OK\n");
514	}
515
516	if (os_strcmp(cmd, "random") == 0) {
517		if (pos)
518			timeout = atoi(pos);
519		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
520		if (pin_txt == NULL)
521			return -1;
522		return os_snprintf(buf, buflen, "%s", pin_txt);
523	}
524
525	if (os_strcmp(cmd, "get") == 0) {
526		pin_txt = wpas_wps_ap_pin_get(wpa_s);
527		if (pin_txt == NULL)
528			return -1;
529		return os_snprintf(buf, buflen, "%s", pin_txt);
530	}
531
532	if (os_strcmp(cmd, "set") == 0) {
533		char *pin;
534		if (pos == NULL)
535			return -1;
536		pin = pos;
537		pos = os_strchr(pos, ' ');
538		if (pos) {
539			*pos++ = '\0';
540			timeout = atoi(pos);
541		}
542		if (os_strlen(pin) > buflen)
543			return -1;
544		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
545			return -1;
546		return os_snprintf(buf, buflen, "%s", pin);
547	}
548
549	return -1;
550}
551#endif /* CONFIG_AP */
552
553
554#ifdef CONFIG_WPS_ER
555static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
556						char *cmd)
557{
558	char *uuid = cmd, *pin, *pos;
559	u8 addr_buf[ETH_ALEN], *addr = NULL;
560	pin = os_strchr(uuid, ' ');
561	if (pin == NULL)
562		return -1;
563	*pin++ = '\0';
564	pos = os_strchr(pin, ' ');
565	if (pos) {
566		*pos++ = '\0';
567		if (hwaddr_aton(pos, addr_buf) == 0)
568			addr = addr_buf;
569	}
570	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
571}
572
573
574static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
575						  char *cmd)
576{
577	char *uuid = cmd, *pin;
578	pin = os_strchr(uuid, ' ');
579	if (pin == NULL)
580		return -1;
581	*pin++ = '\0';
582	return wpas_wps_er_learn(wpa_s, uuid, pin);
583}
584
585
586static int wpa_supplicant_ctrl_iface_wps_er_set_config(
587	struct wpa_supplicant *wpa_s, char *cmd)
588{
589	char *uuid = cmd, *id;
590	id = os_strchr(uuid, ' ');
591	if (id == NULL)
592		return -1;
593	*id++ = '\0';
594	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
595}
596
597
598static int wpa_supplicant_ctrl_iface_wps_er_config(
599	struct wpa_supplicant *wpa_s, char *cmd)
600{
601	char *pin;
602	char *new_ssid;
603	char *new_auth;
604	char *new_encr;
605	char *new_key;
606	struct wps_new_ap_settings ap;
607
608	pin = os_strchr(cmd, ' ');
609	if (pin == NULL)
610		return -1;
611	*pin++ = '\0';
612
613	new_ssid = os_strchr(pin, ' ');
614	if (new_ssid == NULL)
615		return -1;
616	*new_ssid++ = '\0';
617
618	new_auth = os_strchr(new_ssid, ' ');
619	if (new_auth == NULL)
620		return -1;
621	*new_auth++ = '\0';
622
623	new_encr = os_strchr(new_auth, ' ');
624	if (new_encr == NULL)
625		return -1;
626	*new_encr++ = '\0';
627
628	new_key = os_strchr(new_encr, ' ');
629	if (new_key == NULL)
630		return -1;
631	*new_key++ = '\0';
632
633	os_memset(&ap, 0, sizeof(ap));
634	ap.ssid_hex = new_ssid;
635	ap.auth = new_auth;
636	ap.encr = new_encr;
637	ap.key_hex = new_key;
638	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
639}
640#endif /* CONFIG_WPS_ER */
641
642#endif /* CONFIG_WPS */
643
644
645#ifdef CONFIG_IBSS_RSN
646static int wpa_supplicant_ctrl_iface_ibss_rsn(
647	struct wpa_supplicant *wpa_s, char *addr)
648{
649	u8 peer[ETH_ALEN];
650
651	if (hwaddr_aton(addr, peer)) {
652		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
653			   "address '%s'", addr);
654		return -1;
655	}
656
657	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
658		   MAC2STR(peer));
659
660	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
661}
662#endif /* CONFIG_IBSS_RSN */
663
664
665static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
666					      char *rsp)
667{
668#ifdef IEEE8021X_EAPOL
669	char *pos, *id_pos;
670	int id;
671	struct wpa_ssid *ssid;
672	struct eap_peer_config *eap;
673
674	pos = os_strchr(rsp, '-');
675	if (pos == NULL)
676		return -1;
677	*pos++ = '\0';
678	id_pos = pos;
679	pos = os_strchr(pos, ':');
680	if (pos == NULL)
681		return -1;
682	*pos++ = '\0';
683	id = atoi(id_pos);
684	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
685	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
686			      (u8 *) pos, os_strlen(pos));
687
688	ssid = wpa_config_get_network(wpa_s->conf, id);
689	if (ssid == NULL) {
690		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
691			   "to update", id);
692		return -1;
693	}
694	eap = &ssid->eap;
695
696	if (os_strcmp(rsp, "IDENTITY") == 0) {
697		os_free(eap->identity);
698		eap->identity = (u8 *) os_strdup(pos);
699		eap->identity_len = os_strlen(pos);
700		eap->pending_req_identity = 0;
701		if (ssid == wpa_s->current_ssid)
702			wpa_s->reassociate = 1;
703	} else if (os_strcmp(rsp, "PASSWORD") == 0) {
704		os_free(eap->password);
705		eap->password = (u8 *) os_strdup(pos);
706		eap->password_len = os_strlen(pos);
707		eap->pending_req_password = 0;
708		if (ssid == wpa_s->current_ssid)
709			wpa_s->reassociate = 1;
710	} else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
711		os_free(eap->new_password);
712		eap->new_password = (u8 *) os_strdup(pos);
713		eap->new_password_len = os_strlen(pos);
714		eap->pending_req_new_password = 0;
715		if (ssid == wpa_s->current_ssid)
716			wpa_s->reassociate = 1;
717	} else if (os_strcmp(rsp, "PIN") == 0) {
718		os_free(eap->pin);
719		eap->pin = os_strdup(pos);
720		eap->pending_req_pin = 0;
721		if (ssid == wpa_s->current_ssid)
722			wpa_s->reassociate = 1;
723	} else if (os_strcmp(rsp, "OTP") == 0) {
724		os_free(eap->otp);
725		eap->otp = (u8 *) os_strdup(pos);
726		eap->otp_len = os_strlen(pos);
727		os_free(eap->pending_req_otp);
728		eap->pending_req_otp = NULL;
729		eap->pending_req_otp_len = 0;
730	} else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
731		os_free(eap->private_key_passwd);
732		eap->private_key_passwd = (u8 *) os_strdup(pos);
733		eap->pending_req_passphrase = 0;
734		if (ssid == wpa_s->current_ssid)
735			wpa_s->reassociate = 1;
736	} else {
737		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
738		return -1;
739	}
740
741	return 0;
742#else /* IEEE8021X_EAPOL */
743	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
744	return -1;
745#endif /* IEEE8021X_EAPOL */
746}
747
748
749static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
750					    const char *params,
751					    char *buf, size_t buflen)
752{
753	char *pos, *end, tmp[30];
754	int res, verbose, ret;
755
756	verbose = os_strcmp(params, "-VERBOSE") == 0;
757	pos = buf;
758	end = buf + buflen;
759	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
760		struct wpa_ssid *ssid = wpa_s->current_ssid;
761		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
762				  MAC2STR(wpa_s->bssid));
763		if (ret < 0 || ret >= end - pos)
764			return pos - buf;
765		pos += ret;
766		if (ssid) {
767			u8 *_ssid = ssid->ssid;
768			size_t ssid_len = ssid->ssid_len;
769			u8 ssid_buf[MAX_SSID_LEN];
770			if (ssid_len == 0) {
771				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
772				if (_res < 0)
773					ssid_len = 0;
774				else
775					ssid_len = _res;
776				_ssid = ssid_buf;
777			}
778			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
779					  wpa_ssid_txt(_ssid, ssid_len),
780					  ssid->id);
781			if (ret < 0 || ret >= end - pos)
782				return pos - buf;
783			pos += ret;
784
785			if (ssid->id_str) {
786				ret = os_snprintf(pos, end - pos,
787						  "id_str=%s\n",
788						  ssid->id_str);
789				if (ret < 0 || ret >= end - pos)
790					return pos - buf;
791				pos += ret;
792			}
793
794			switch (ssid->mode) {
795			case WPAS_MODE_INFRA:
796				ret = os_snprintf(pos, end - pos,
797						  "mode=station\n");
798				break;
799			case WPAS_MODE_IBSS:
800				ret = os_snprintf(pos, end - pos,
801						  "mode=IBSS\n");
802				break;
803			case WPAS_MODE_AP:
804				ret = os_snprintf(pos, end - pos,
805						  "mode=AP\n");
806				break;
807			case WPAS_MODE_P2P_GO:
808				ret = os_snprintf(pos, end - pos,
809						  "mode=P2P GO\n");
810				break;
811			case WPAS_MODE_P2P_GROUP_FORMATION:
812				ret = os_snprintf(pos, end - pos,
813						  "mode=P2P GO - group "
814						  "formation\n");
815				break;
816			default:
817				ret = 0;
818				break;
819			}
820			if (ret < 0 || ret >= end - pos)
821				return pos - buf;
822			pos += ret;
823		}
824
825#ifdef CONFIG_AP
826		if (wpa_s->ap_iface) {
827			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
828							    end - pos,
829							    verbose);
830		} else
831#endif /* CONFIG_AP */
832		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
833	}
834	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
835			  wpa_supplicant_state_txt(wpa_s->wpa_state));
836	if (ret < 0 || ret >= end - pos)
837		return pos - buf;
838	pos += ret;
839
840	if (wpa_s->l2 &&
841	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
842		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
843		if (ret < 0 || ret >= end - pos)
844			return pos - buf;
845		pos += ret;
846	}
847
848#ifdef CONFIG_P2P
849	if (wpa_s->global->p2p) {
850		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
851				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
852		if (ret < 0 || ret >= end - pos)
853			return pos - buf;
854		pos += ret;
855	}
856#endif /* CONFIG_P2P */
857
858	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
859			  MAC2STR(wpa_s->own_addr));
860	if (ret < 0 || ret >= end - pos)
861		return pos - buf;
862	pos += ret;
863
864	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
865	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
866		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
867					  verbose);
868		if (res >= 0)
869			pos += res;
870	}
871
872	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
873	if (res >= 0)
874		pos += res;
875
876	return pos - buf;
877}
878
879
880static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
881					   char *cmd)
882{
883	char *pos;
884	int id;
885	struct wpa_ssid *ssid;
886	u8 bssid[ETH_ALEN];
887
888	/* cmd: "<network id> <BSSID>" */
889	pos = os_strchr(cmd, ' ');
890	if (pos == NULL)
891		return -1;
892	*pos++ = '\0';
893	id = atoi(cmd);
894	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
895	if (hwaddr_aton(pos, bssid)) {
896		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
897		return -1;
898	}
899
900	ssid = wpa_config_get_network(wpa_s->conf, id);
901	if (ssid == NULL) {
902		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
903			   "to update", id);
904		return -1;
905	}
906
907	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
908	ssid->bssid_set = !is_zero_ether_addr(bssid);
909
910	return 0;
911}
912
913
914extern int wpa_debug_level;
915extern int wpa_debug_timestamp;
916
917static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
918					char *cmd, char *buf, size_t buflen)
919{
920	char *pos, *end, *stamp;
921	int ret;
922
923	if (cmd == NULL)
924		return -1;
925	/* cmd: "LOG_LEVEL [<level>]" */
926	if (*cmd == '\0') {
927		pos = buf;
928		end = buf + buflen;
929		ret = os_snprintf(pos, end-pos, "Current level: %d\n"
930			"{0-EXCESSIVE, 1-MSGDUMP, 2-DEBUG, 3-INFO, 4-WARNING, 5-ERROR}\n"
931			"Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp);
932		if ((ret < 0) || (ret >= end - pos))
933			ret = 0;
934		return ret;
935	}
936
937	cmd++;
938	stamp = os_strchr(cmd, ' ');
939	if (stamp) {
940		*stamp++ = '\0';
941		while (*stamp == ' ')
942			stamp++;
943	}
944
945	if (cmd && os_strlen(cmd))
946		wpa_debug_level = atoi(cmd);
947
948	if (stamp && os_strlen(stamp))
949		wpa_debug_timestamp = atoi(stamp);
950
951	os_memcpy(buf, "OK\n", 3);
952	return 3;
953}
954
955
956static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
957					char *cmd, char *buf, size_t buflen)
958{
959	u8 bssid[ETH_ALEN];
960	struct wpa_blacklist *e;
961	char *pos, *end;
962	int ret;
963
964	/* cmd: "BLACKLIST [<BSSID>]" */
965	if (*cmd == '\0') {
966		pos = buf;
967		end = buf + buflen;
968		e = wpa_s->blacklist;
969		while (e) {
970			ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid));
971			if ((ret < 0) || (ret >= end - pos))
972				return pos - buf;
973			pos += ret;
974			e = e->next;
975		}
976		return pos - buf;
977	}
978
979	cmd++;
980	if (os_strncmp(cmd, "clear", 5) == 0) {
981		wpa_blacklist_clear(wpa_s);
982		os_memcpy(buf, "OK\n", 3);
983		return 3;
984	}
985
986	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
987	if (hwaddr_aton(cmd, bssid)) {
988		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd);
989		return -1;
990	}
991
992	/* Add the BSSID twice, so its count will be 2, causing it to be
993	   skipped when processing scan results. */
994	ret = wpa_blacklist_add(wpa_s, bssid);
995	if (ret < 0)
996		return -1;
997	ret = wpa_blacklist_add(wpa_s, bssid);
998	if (ret < 0)
999		return -1;
1000	os_memcpy(buf, "OK\n", 3);
1001	return 3;
1002}
1003
1004
1005static int wpa_supplicant_ctrl_iface_list_networks(
1006	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1007{
1008	char *pos, *end;
1009	struct wpa_ssid *ssid;
1010	int ret;
1011
1012	pos = buf;
1013	end = buf + buflen;
1014	ret = os_snprintf(pos, end - pos,
1015			  "network id / ssid / bssid / flags\n");
1016	if (ret < 0 || ret >= end - pos)
1017		return pos - buf;
1018	pos += ret;
1019
1020	ssid = wpa_s->conf->ssid;
1021	while (ssid) {
1022		ret = os_snprintf(pos, end - pos, "%d\t%s",
1023				  ssid->id,
1024				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1025		if (ret < 0 || ret >= end - pos)
1026			return pos - buf;
1027		pos += ret;
1028		if (ssid->bssid_set) {
1029			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1030					  MAC2STR(ssid->bssid));
1031		} else {
1032			ret = os_snprintf(pos, end - pos, "\tany");
1033		}
1034		if (ret < 0 || ret >= end - pos)
1035			return pos - buf;
1036		pos += ret;
1037		ret = os_snprintf(pos, end - pos, "\t%s%s%s",
1038				  ssid == wpa_s->current_ssid ?
1039				  "[CURRENT]" : "",
1040				  ssid->disabled ? "[DISABLED]" : "",
1041				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1042				  "");
1043		if (ret < 0 || ret >= end - pos)
1044			return pos - buf;
1045		pos += ret;
1046		ret = os_snprintf(pos, end - pos, "\n");
1047		if (ret < 0 || ret >= end - pos)
1048			return pos - buf;
1049		pos += ret;
1050
1051		ssid = ssid->next;
1052	}
1053
1054	return pos - buf;
1055}
1056
1057
1058static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1059{
1060	int first = 1, ret;
1061	ret = os_snprintf(pos, end - pos, "-");
1062	if (ret < 0 || ret >= end - pos)
1063		return pos;
1064	pos += ret;
1065	if (cipher & WPA_CIPHER_NONE) {
1066		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
1067		if (ret < 0 || ret >= end - pos)
1068			return pos;
1069		pos += ret;
1070		first = 0;
1071	}
1072	if (cipher & WPA_CIPHER_WEP40) {
1073		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
1074		if (ret < 0 || ret >= end - pos)
1075			return pos;
1076		pos += ret;
1077		first = 0;
1078	}
1079	if (cipher & WPA_CIPHER_WEP104) {
1080		ret = os_snprintf(pos, end - pos, "%sWEP104",
1081				  first ? "" : "+");
1082		if (ret < 0 || ret >= end - pos)
1083			return pos;
1084		pos += ret;
1085		first = 0;
1086	}
1087	if (cipher & WPA_CIPHER_TKIP) {
1088		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
1089		if (ret < 0 || ret >= end - pos)
1090			return pos;
1091		pos += ret;
1092		first = 0;
1093	}
1094	if (cipher & WPA_CIPHER_CCMP) {
1095		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
1096		if (ret < 0 || ret >= end - pos)
1097			return pos;
1098		pos += ret;
1099		first = 0;
1100	}
1101	return pos;
1102}
1103
1104
1105static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1106				    const u8 *ie, size_t ie_len)
1107{
1108	struct wpa_ie_data data;
1109	int first, ret;
1110
1111	ret = os_snprintf(pos, end - pos, "[%s-", proto);
1112	if (ret < 0 || ret >= end - pos)
1113		return pos;
1114	pos += ret;
1115
1116	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1117		ret = os_snprintf(pos, end - pos, "?]");
1118		if (ret < 0 || ret >= end - pos)
1119			return pos;
1120		pos += ret;
1121		return pos;
1122	}
1123
1124	first = 1;
1125	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1126		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
1127		if (ret < 0 || ret >= end - pos)
1128			return pos;
1129		pos += ret;
1130		first = 0;
1131	}
1132	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
1133		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1134		if (ret < 0 || ret >= end - pos)
1135			return pos;
1136		pos += ret;
1137		first = 0;
1138	}
1139	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1140		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1141		if (ret < 0 || ret >= end - pos)
1142			return pos;
1143		pos += ret;
1144		first = 0;
1145	}
1146#ifdef CONFIG_IEEE80211R
1147	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1148		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1149				  first ? "" : "+");
1150		if (ret < 0 || ret >= end - pos)
1151			return pos;
1152		pos += ret;
1153		first = 0;
1154	}
1155	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1156		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1157				  first ? "" : "+");
1158		if (ret < 0 || ret >= end - pos)
1159			return pos;
1160		pos += ret;
1161		first = 0;
1162	}
1163#endif /* CONFIG_IEEE80211R */
1164#ifdef CONFIG_IEEE80211W
1165	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1166		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1167				  first ? "" : "+");
1168		if (ret < 0 || ret >= end - pos)
1169			return pos;
1170		pos += ret;
1171		first = 0;
1172	}
1173	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1174		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1175				  first ? "" : "+");
1176		if (ret < 0 || ret >= end - pos)
1177			return pos;
1178		pos += ret;
1179		first = 0;
1180	}
1181#endif /* CONFIG_IEEE80211W */
1182
1183	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1184
1185	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1186		ret = os_snprintf(pos, end - pos, "-preauth");
1187		if (ret < 0 || ret >= end - pos)
1188			return pos;
1189		pos += ret;
1190	}
1191
1192	ret = os_snprintf(pos, end - pos, "]");
1193	if (ret < 0 || ret >= end - pos)
1194		return pos;
1195	pos += ret;
1196
1197	return pos;
1198}
1199
1200
1201#ifdef CONFIG_WPS
1202static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1203					    char *pos, char *end,
1204					    struct wpabuf *wps_ie)
1205{
1206	int ret;
1207	const char *txt;
1208
1209	if (wps_ie == NULL)
1210		return pos;
1211	if (wps_is_selected_pbc_registrar(wps_ie))
1212		txt = "[WPS-PBC]";
1213#ifdef CONFIG_WPS2
1214	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
1215		txt = "[WPS-AUTH]";
1216#endif /* CONFIG_WPS2 */
1217	else if (wps_is_selected_pin_registrar(wps_ie))
1218		txt = "[WPS-PIN]";
1219	else
1220		txt = "[WPS]";
1221
1222	ret = os_snprintf(pos, end - pos, "%s", txt);
1223	if (ret >= 0 && ret < end - pos)
1224		pos += ret;
1225	wpabuf_free(wps_ie);
1226	return pos;
1227}
1228#endif /* CONFIG_WPS */
1229
1230
1231static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
1232					char *pos, char *end,
1233					const struct wpa_bss *bss)
1234{
1235#ifdef CONFIG_WPS
1236	struct wpabuf *wps_ie;
1237	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1238	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
1239#else /* CONFIG_WPS */
1240	return pos;
1241#endif /* CONFIG_WPS */
1242}
1243
1244
1245/* Format one result on one text line into a buffer. */
1246static int wpa_supplicant_ctrl_iface_scan_result(
1247	struct wpa_supplicant *wpa_s,
1248	const struct wpa_bss *bss, char *buf, size_t buflen)
1249{
1250	char *pos, *end;
1251	int ret;
1252	const u8 *ie, *ie2, *p2p;
1253
1254	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
1255	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
1256	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
1257	    0)
1258		return 0; /* Do not show P2P listen discovery results here */
1259
1260	pos = buf;
1261	end = buf + buflen;
1262
1263	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
1264			  MAC2STR(bss->bssid), bss->freq, bss->level);
1265	if (ret < 0 || ret >= end - pos)
1266		return -1;
1267	pos += ret;
1268	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1269	if (ie)
1270		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1271	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1272	if (ie2)
1273		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1274	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
1275	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1276		ret = os_snprintf(pos, end - pos, "[WEP]");
1277		if (ret < 0 || ret >= end - pos)
1278			return -1;
1279		pos += ret;
1280	}
1281	if (bss->caps & IEEE80211_CAP_IBSS) {
1282		ret = os_snprintf(pos, end - pos, "[IBSS]");
1283		if (ret < 0 || ret >= end - pos)
1284			return -1;
1285		pos += ret;
1286	}
1287	if (bss->caps & IEEE80211_CAP_ESS) {
1288		ret = os_snprintf(pos, end - pos, "[ESS]");
1289		if (ret < 0 || ret >= end - pos)
1290			return -1;
1291		pos += ret;
1292	}
1293	if (p2p) {
1294		ret = os_snprintf(pos, end - pos, "[P2P]");
1295		if (ret < 0 || ret >= end - pos)
1296			return -1;
1297		pos += ret;
1298	}
1299
1300	ret = os_snprintf(pos, end - pos, "\t%s",
1301			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
1302	if (ret < 0 || ret >= end - pos)
1303		return -1;
1304	pos += ret;
1305
1306	ret = os_snprintf(pos, end - pos, "\n");
1307	if (ret < 0 || ret >= end - pos)
1308		return -1;
1309	pos += ret;
1310
1311	return pos - buf;
1312}
1313
1314
1315static int wpa_supplicant_ctrl_iface_scan_results(
1316	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1317{
1318	char *pos, *end;
1319	struct wpa_bss *bss;
1320	int ret;
1321
1322	pos = buf;
1323	end = buf + buflen;
1324	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
1325			  "flags / ssid\n");
1326	if (ret < 0 || ret >= end - pos)
1327		return pos - buf;
1328	pos += ret;
1329
1330	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1331		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
1332							    end - pos);
1333		if (ret < 0 || ret >= end - pos)
1334			return pos - buf;
1335		pos += ret;
1336	}
1337
1338	return pos - buf;
1339}
1340
1341
1342static int wpa_supplicant_ctrl_iface_select_network(
1343	struct wpa_supplicant *wpa_s, char *cmd)
1344{
1345	int id;
1346	struct wpa_ssid *ssid;
1347
1348	/* cmd: "<network id>" or "any" */
1349	if (os_strcmp(cmd, "any") == 0) {
1350		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
1351		ssid = NULL;
1352	} else {
1353		id = atoi(cmd);
1354		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
1355
1356		ssid = wpa_config_get_network(wpa_s->conf, id);
1357		if (ssid == NULL) {
1358			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1359				   "network id=%d", id);
1360			return -1;
1361		}
1362		if (ssid->disabled == 2) {
1363			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1364				   "SELECT_NETWORK with persistent P2P group");
1365			return -1;
1366		}
1367	}
1368
1369	wpa_supplicant_select_network(wpa_s, ssid);
1370
1371	return 0;
1372}
1373
1374
1375static int wpa_supplicant_ctrl_iface_enable_network(
1376	struct wpa_supplicant *wpa_s, char *cmd)
1377{
1378	int id;
1379	struct wpa_ssid *ssid;
1380
1381	/* cmd: "<network id>" or "all" */
1382	if (os_strcmp(cmd, "all") == 0) {
1383		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
1384		ssid = NULL;
1385	} else {
1386		id = atoi(cmd);
1387		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
1388
1389		ssid = wpa_config_get_network(wpa_s->conf, id);
1390		if (ssid == NULL) {
1391			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1392				   "network id=%d", id);
1393			return -1;
1394		}
1395		if (ssid->disabled == 2) {
1396			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1397				   "ENABLE_NETWORK with persistent P2P group");
1398			return -1;
1399		}
1400	}
1401	wpa_supplicant_enable_network(wpa_s, ssid);
1402
1403	return 0;
1404}
1405
1406
1407static int wpa_supplicant_ctrl_iface_disable_network(
1408	struct wpa_supplicant *wpa_s, char *cmd)
1409{
1410	int id;
1411	struct wpa_ssid *ssid;
1412
1413	/* cmd: "<network id>" or "all" */
1414	if (os_strcmp(cmd, "all") == 0) {
1415		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
1416		ssid = NULL;
1417	} else {
1418		id = atoi(cmd);
1419		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
1420
1421		ssid = wpa_config_get_network(wpa_s->conf, id);
1422		if (ssid == NULL) {
1423			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1424				   "network id=%d", id);
1425			return -1;
1426		}
1427		if (ssid->disabled == 2) {
1428			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1429				   "DISABLE_NETWORK with persistent P2P "
1430				   "group");
1431			return -1;
1432		}
1433	}
1434	wpa_supplicant_disable_network(wpa_s, ssid);
1435
1436	return 0;
1437}
1438
1439
1440static int wpa_supplicant_ctrl_iface_add_network(
1441	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1442{
1443	struct wpa_ssid *ssid;
1444	int ret;
1445
1446	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1447
1448	ssid = wpa_config_add_network(wpa_s->conf);
1449	if (ssid == NULL)
1450		return -1;
1451
1452	wpas_notify_network_added(wpa_s, ssid);
1453
1454	ssid->disabled = 1;
1455	wpa_config_set_network_defaults(ssid);
1456
1457	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1458	if (ret < 0 || (size_t) ret >= buflen)
1459		return -1;
1460	return ret;
1461}
1462
1463
1464static int wpa_supplicant_ctrl_iface_remove_network(
1465	struct wpa_supplicant *wpa_s, char *cmd)
1466{
1467	int id;
1468	struct wpa_ssid *ssid;
1469
1470	/* cmd: "<network id>" or "all" */
1471	if (os_strcmp(cmd, "all") == 0) {
1472		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1473		ssid = wpa_s->conf->ssid;
1474		while (ssid) {
1475			struct wpa_ssid *remove_ssid = ssid;
1476			id = ssid->id;
1477			ssid = ssid->next;
1478			wpas_notify_network_removed(wpa_s, remove_ssid);
1479			wpa_config_remove_network(wpa_s->conf, id);
1480		}
1481		if (wpa_s->current_ssid) {
1482			eapol_sm_invalidate_cached_session(wpa_s->eapol);
1483			wpa_supplicant_disassociate(wpa_s,
1484				                    WLAN_REASON_DEAUTH_LEAVING);
1485		}
1486		return 0;
1487	}
1488
1489	id = atoi(cmd);
1490	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1491
1492	ssid = wpa_config_get_network(wpa_s->conf, id);
1493	if (ssid == NULL ||
1494	    wpa_config_remove_network(wpa_s->conf, id) < 0) {
1495		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1496			   "id=%d", id);
1497		return -1;
1498	}
1499
1500	if (ssid == wpa_s->current_ssid) {
1501		/*
1502		 * Invalidate the EAP session cache if the current network is
1503		 * removed.
1504		 */
1505		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1506
1507		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1508	}
1509
1510	return 0;
1511}
1512
1513
1514static int wpa_supplicant_ctrl_iface_set_network(
1515	struct wpa_supplicant *wpa_s, char *cmd)
1516{
1517	int id;
1518	struct wpa_ssid *ssid;
1519	char *name, *value;
1520
1521	/* cmd: "<network id> <variable name> <value>" */
1522	name = os_strchr(cmd, ' ');
1523	if (name == NULL)
1524		return -1;
1525	*name++ = '\0';
1526
1527	value = os_strchr(name, ' ');
1528	if (value == NULL)
1529		return -1;
1530	*value++ = '\0';
1531
1532	id = atoi(cmd);
1533	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1534		   id, name);
1535	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1536			      (u8 *) value, os_strlen(value));
1537
1538	ssid = wpa_config_get_network(wpa_s->conf, id);
1539	if (ssid == NULL) {
1540		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1541			   "id=%d", id);
1542		return -1;
1543	}
1544
1545	if (wpa_config_set(ssid, name, value, 0) < 0) {
1546		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1547			   "variable '%s'", name);
1548		return -1;
1549	}
1550
1551	if (wpa_s->current_ssid == ssid) {
1552		/*
1553		 * Invalidate the EAP session cache if anything in the current
1554		 * configuration changes.
1555		 */
1556		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1557	}
1558
1559	if ((os_strcmp(name, "psk") == 0 &&
1560	     value[0] == '"' && ssid->ssid_len) ||
1561	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1562		wpa_config_update_psk(ssid);
1563	else if (os_strcmp(name, "priority") == 0)
1564		wpa_config_update_prio_list(wpa_s->conf);
1565
1566	return 0;
1567}
1568
1569
1570static int wpa_supplicant_ctrl_iface_get_network(
1571	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1572{
1573	int id;
1574	size_t res;
1575	struct wpa_ssid *ssid;
1576	char *name, *value;
1577
1578	/* cmd: "<network id> <variable name>" */
1579	name = os_strchr(cmd, ' ');
1580	if (name == NULL || buflen == 0)
1581		return -1;
1582	*name++ = '\0';
1583
1584	id = atoi(cmd);
1585	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1586		   id, name);
1587
1588	ssid = wpa_config_get_network(wpa_s->conf, id);
1589	if (ssid == NULL) {
1590		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1591			   "id=%d", id);
1592		return -1;
1593	}
1594
1595	value = wpa_config_get_no_key(ssid, name);
1596	if (value == NULL) {
1597		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1598			   "variable '%s'", name);
1599		return -1;
1600	}
1601
1602	res = os_strlcpy(buf, value, buflen);
1603	if (res >= buflen) {
1604		os_free(value);
1605		return -1;
1606	}
1607
1608	os_free(value);
1609
1610	return res;
1611}
1612
1613
1614#ifndef CONFIG_NO_CONFIG_WRITE
1615static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1616{
1617	int ret;
1618
1619	if (!wpa_s->conf->update_config) {
1620		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1621			   "to update configuration (update_config=0)");
1622		return -1;
1623	}
1624
1625	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1626	if (ret) {
1627		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1628			   "update configuration");
1629	} else {
1630		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1631			   " updated");
1632	}
1633
1634	return ret;
1635}
1636#endif /* CONFIG_NO_CONFIG_WRITE */
1637
1638
1639static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1640					      struct wpa_driver_capa *capa,
1641					      char *buf, size_t buflen)
1642{
1643	int ret, first = 1;
1644	char *pos, *end;
1645	size_t len;
1646
1647	pos = buf;
1648	end = pos + buflen;
1649
1650	if (res < 0) {
1651		if (strict)
1652			return 0;
1653		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1654		if (len >= buflen)
1655			return -1;
1656		return len;
1657	}
1658
1659	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1660		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1661		if (ret < 0 || ret >= end - pos)
1662			return pos - buf;
1663		pos += ret;
1664		first = 0;
1665	}
1666
1667	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1668		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1669		if (ret < 0 || ret >= end - pos)
1670			return pos - buf;
1671		pos += ret;
1672		first = 0;
1673	}
1674
1675	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1676		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1677		if (ret < 0 || ret >= end - pos)
1678			return pos - buf;
1679		pos += ret;
1680		first = 0;
1681	}
1682
1683	return pos - buf;
1684}
1685
1686
1687static int ctrl_iface_get_capability_group(int res, char *strict,
1688					   struct wpa_driver_capa *capa,
1689					   char *buf, size_t buflen)
1690{
1691	int ret, first = 1;
1692	char *pos, *end;
1693	size_t len;
1694
1695	pos = buf;
1696	end = pos + buflen;
1697
1698	if (res < 0) {
1699		if (strict)
1700			return 0;
1701		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1702		if (len >= buflen)
1703			return -1;
1704		return len;
1705	}
1706
1707	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1708		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1709		if (ret < 0 || ret >= end - pos)
1710			return pos - buf;
1711		pos += ret;
1712		first = 0;
1713	}
1714
1715	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1716		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1717		if (ret < 0 || ret >= end - pos)
1718			return pos - buf;
1719		pos += ret;
1720		first = 0;
1721	}
1722
1723	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1724		ret = os_snprintf(pos, end - pos, "%sWEP104",
1725				  first ? "" : " ");
1726		if (ret < 0 || ret >= end - pos)
1727			return pos - buf;
1728		pos += ret;
1729		first = 0;
1730	}
1731
1732	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1733		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1734		if (ret < 0 || ret >= end - pos)
1735			return pos - buf;
1736		pos += ret;
1737		first = 0;
1738	}
1739
1740	return pos - buf;
1741}
1742
1743
1744static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1745					      struct wpa_driver_capa *capa,
1746					      char *buf, size_t buflen)
1747{
1748	int ret;
1749	char *pos, *end;
1750	size_t len;
1751
1752	pos = buf;
1753	end = pos + buflen;
1754
1755	if (res < 0) {
1756		if (strict)
1757			return 0;
1758		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1759				 "NONE", buflen);
1760		if (len >= buflen)
1761			return -1;
1762		return len;
1763	}
1764
1765	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1766	if (ret < 0 || ret >= end - pos)
1767		return pos - buf;
1768	pos += ret;
1769
1770	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1771			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1772		ret = os_snprintf(pos, end - pos, " WPA-EAP");
1773		if (ret < 0 || ret >= end - pos)
1774			return pos - buf;
1775		pos += ret;
1776	}
1777
1778	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1779			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1780		ret = os_snprintf(pos, end - pos, " WPA-PSK");
1781		if (ret < 0 || ret >= end - pos)
1782			return pos - buf;
1783		pos += ret;
1784	}
1785
1786	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1787		ret = os_snprintf(pos, end - pos, " WPA-NONE");
1788		if (ret < 0 || ret >= end - pos)
1789			return pos - buf;
1790		pos += ret;
1791	}
1792
1793	return pos - buf;
1794}
1795
1796
1797static int ctrl_iface_get_capability_proto(int res, char *strict,
1798					   struct wpa_driver_capa *capa,
1799					   char *buf, size_t buflen)
1800{
1801	int ret, first = 1;
1802	char *pos, *end;
1803	size_t len;
1804
1805	pos = buf;
1806	end = pos + buflen;
1807
1808	if (res < 0) {
1809		if (strict)
1810			return 0;
1811		len = os_strlcpy(buf, "RSN WPA", buflen);
1812		if (len >= buflen)
1813			return -1;
1814		return len;
1815	}
1816
1817	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1818			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1819		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1820		if (ret < 0 || ret >= end - pos)
1821			return pos - buf;
1822		pos += ret;
1823		first = 0;
1824	}
1825
1826	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1827			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1828		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1829		if (ret < 0 || ret >= end - pos)
1830			return pos - buf;
1831		pos += ret;
1832		first = 0;
1833	}
1834
1835	return pos - buf;
1836}
1837
1838
1839static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1840					      struct wpa_driver_capa *capa,
1841					      char *buf, size_t buflen)
1842{
1843	int ret, first = 1;
1844	char *pos, *end;
1845	size_t len;
1846
1847	pos = buf;
1848	end = pos + buflen;
1849
1850	if (res < 0) {
1851		if (strict)
1852			return 0;
1853		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1854		if (len >= buflen)
1855			return -1;
1856		return len;
1857	}
1858
1859	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1860		ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1861		if (ret < 0 || ret >= end - pos)
1862			return pos - buf;
1863		pos += ret;
1864		first = 0;
1865	}
1866
1867	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1868		ret = os_snprintf(pos, end - pos, "%sSHARED",
1869				  first ? "" : " ");
1870		if (ret < 0 || ret >= end - pos)
1871			return pos - buf;
1872		pos += ret;
1873		first = 0;
1874	}
1875
1876	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1877		ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1878		if (ret < 0 || ret >= end - pos)
1879			return pos - buf;
1880		pos += ret;
1881		first = 0;
1882	}
1883
1884	return pos - buf;
1885}
1886
1887
1888static int wpa_supplicant_ctrl_iface_get_capability(
1889	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1890	size_t buflen)
1891{
1892	struct wpa_driver_capa capa;
1893	int res;
1894	char *strict;
1895	char field[30];
1896	size_t len;
1897
1898	/* Determine whether or not strict checking was requested */
1899	len = os_strlcpy(field, _field, sizeof(field));
1900	if (len >= sizeof(field))
1901		return -1;
1902	strict = os_strchr(field, ' ');
1903	if (strict != NULL) {
1904		*strict++ = '\0';
1905		if (os_strcmp(strict, "strict") != 0)
1906			return -1;
1907	}
1908
1909	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1910		field, strict ? strict : "");
1911
1912	if (os_strcmp(field, "eap") == 0) {
1913		return eap_get_names(buf, buflen);
1914	}
1915
1916	res = wpa_drv_get_capa(wpa_s, &capa);
1917
1918	if (os_strcmp(field, "pairwise") == 0)
1919		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1920							  buf, buflen);
1921
1922	if (os_strcmp(field, "group") == 0)
1923		return ctrl_iface_get_capability_group(res, strict, &capa,
1924						       buf, buflen);
1925
1926	if (os_strcmp(field, "key_mgmt") == 0)
1927		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1928							  buf, buflen);
1929
1930	if (os_strcmp(field, "proto") == 0)
1931		return ctrl_iface_get_capability_proto(res, strict, &capa,
1932						       buf, buflen);
1933
1934	if (os_strcmp(field, "auth_alg") == 0)
1935		return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1936							  buf, buflen);
1937
1938	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1939		   field);
1940
1941	return -1;
1942}
1943
1944
1945static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
1946					 const char *cmd, char *buf,
1947					 size_t buflen)
1948{
1949	u8 bssid[ETH_ALEN];
1950	size_t i;
1951	struct wpa_bss *bss;
1952	int ret;
1953	char *pos, *end;
1954	const u8 *ie, *ie2;
1955
1956	if (os_strcmp(cmd, "FIRST") == 0)
1957		bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
1958	else if (os_strncmp(cmd, "ID-", 3) == 0) {
1959		i = atoi(cmd + 3);
1960		bss = wpa_bss_get_id(wpa_s, i);
1961	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
1962		i = atoi(cmd + 5);
1963		bss = wpa_bss_get_id(wpa_s, i);
1964		if (bss) {
1965			struct dl_list *next = bss->list_id.next;
1966			if (next == &wpa_s->bss_id)
1967				bss = NULL;
1968			else
1969				bss = dl_list_entry(next, struct wpa_bss,
1970						    list_id);
1971		}
1972	} else if (hwaddr_aton(cmd, bssid) == 0)
1973		bss = wpa_bss_get_bssid(wpa_s, bssid);
1974	else {
1975		struct wpa_bss *tmp;
1976		i = atoi(cmd);
1977		bss = NULL;
1978		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
1979		{
1980			if (i-- == 0) {
1981				bss = tmp;
1982				break;
1983			}
1984		}
1985	}
1986
1987	if (bss == NULL)
1988		return 0;
1989
1990	pos = buf;
1991	end = buf + buflen;
1992	ret = os_snprintf(pos, end - pos,
1993			  "id=%u\n"
1994			  "bssid=" MACSTR "\n"
1995			  "freq=%d\n"
1996			  "beacon_int=%d\n"
1997			  "capabilities=0x%04x\n"
1998			  "qual=%d\n"
1999			  "noise=%d\n"
2000			  "level=%d\n"
2001			  "tsf=%016llu\n"
2002			  "ie=",
2003			  bss->id,
2004			  MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
2005			  bss->caps, bss->qual, bss->noise, bss->level,
2006			  (unsigned long long) bss->tsf);
2007	if (ret < 0 || ret >= end - pos)
2008		return pos - buf;
2009	pos += ret;
2010
2011	ie = (const u8 *) (bss + 1);
2012	for (i = 0; i < bss->ie_len; i++) {
2013		ret = os_snprintf(pos, end - pos, "%02x", *ie++);
2014		if (ret < 0 || ret >= end - pos)
2015			return pos - buf;
2016		pos += ret;
2017	}
2018	if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
2019		ret = os_snprintf(pos, end - pos, "[P2P]");
2020		if (ret < 0 || ret >= end - pos)
2021			return pos - buf;
2022		pos += ret;
2023	}
2024
2025	ret = os_snprintf(pos, end - pos, "\n");
2026	if (ret < 0 || ret >= end - pos)
2027		return pos - buf;
2028	pos += ret;
2029
2030	ret = os_snprintf(pos, end - pos, "flags=");
2031	if (ret < 0 || ret >= end - pos)
2032		return pos - buf;
2033	pos += ret;
2034
2035	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2036	if (ie)
2037		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2038	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2039	if (ie2)
2040		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2041	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2042	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2043		ret = os_snprintf(pos, end - pos, "[WEP]");
2044		if (ret < 0 || ret >= end - pos)
2045			return pos - buf;
2046		pos += ret;
2047	}
2048	if (bss->caps & IEEE80211_CAP_IBSS) {
2049		ret = os_snprintf(pos, end - pos, "[IBSS]");
2050		if (ret < 0 || ret >= end - pos)
2051			return pos - buf;
2052		pos += ret;
2053	}
2054	if (bss->caps & IEEE80211_CAP_ESS) {
2055		ret = os_snprintf(pos, end - pos, "[ESS]");
2056		if (ret < 0 || ret >= end - pos)
2057			return pos - buf;
2058		pos += ret;
2059	}
2060
2061	ret = os_snprintf(pos, end - pos, "\n");
2062	if (ret < 0 || ret >= end - pos)
2063		return pos - buf;
2064	pos += ret;
2065
2066	ret = os_snprintf(pos, end - pos, "ssid=%s\n",
2067			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
2068	if (ret < 0 || ret >= end - pos)
2069		return pos - buf;
2070	pos += ret;
2071
2072#ifdef CONFIG_WPS
2073	ie = (const u8 *) (bss + 1);
2074	ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
2075	if (ret < 0 || ret >= end - pos)
2076		return pos - buf;
2077	pos += ret;
2078#endif /* CONFIG_WPS */
2079
2080#ifdef CONFIG_P2P
2081	ie = (const u8 *) (bss + 1);
2082	ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
2083	if (ret < 0 || ret >= end - pos)
2084		return pos - buf;
2085	pos += ret;
2086#endif /* CONFIG_P2P */
2087
2088	return pos - buf;
2089}
2090
2091
2092static int wpa_supplicant_ctrl_iface_ap_scan(
2093	struct wpa_supplicant *wpa_s, char *cmd)
2094{
2095	int ap_scan = atoi(cmd);
2096	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
2097}
2098
2099
2100static int wpa_supplicant_ctrl_iface_scan_interval(
2101	struct wpa_supplicant *wpa_s, char *cmd)
2102{
2103	int scan_int = atoi(cmd);
2104	if (scan_int < 0)
2105		return -1;
2106	wpa_s->scan_interval = scan_int;
2107	return 0;
2108}
2109
2110
2111static int wpa_supplicant_ctrl_iface_bss_expire_age(
2112	struct wpa_supplicant *wpa_s, char *cmd)
2113{
2114	int expire_age = atoi(cmd);
2115	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
2116}
2117
2118
2119static int wpa_supplicant_ctrl_iface_bss_expire_count(
2120	struct wpa_supplicant *wpa_s, char *cmd)
2121{
2122	int expire_count = atoi(cmd);
2123	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
2124}
2125
2126
2127static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
2128{
2129	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
2130	/* MLME-DELETEKEYS.request */
2131	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
2132	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
2133	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
2134	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
2135#ifdef CONFIG_IEEE80211W
2136	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
2137	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
2138#endif /* CONFIG_IEEE80211W */
2139
2140	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
2141			0);
2142	/* MLME-SETPROTECTION.request(None) */
2143	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
2144				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
2145				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
2146	wpa_sm_drop_sa(wpa_s->wpa);
2147}
2148
2149
2150static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
2151					  char *addr)
2152{
2153	u8 bssid[ETH_ALEN];
2154	struct wpa_bss *bss;
2155	struct wpa_ssid *ssid = wpa_s->current_ssid;
2156
2157	if (hwaddr_aton(addr, bssid)) {
2158		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
2159			   "address '%s'", addr);
2160		return -1;
2161	}
2162
2163	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
2164
2165	bss = wpa_bss_get_bssid(wpa_s, bssid);
2166	if (!bss) {
2167		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
2168			   "from BSS table");
2169		return -1;
2170	}
2171
2172	/*
2173	 * TODO: Find best network configuration block from configuration to
2174	 * allow roaming to other networks
2175	 */
2176
2177	if (!ssid) {
2178		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
2179			   "configuration known for the target AP");
2180		return -1;
2181	}
2182
2183	wpa_s->reassociate = 1;
2184	wpa_supplicant_connect(wpa_s, bss, ssid);
2185
2186	return 0;
2187}
2188
2189
2190#ifdef CONFIG_P2P
2191static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
2192{
2193	unsigned int timeout = atoi(cmd);
2194	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
2195
2196	if (os_strstr(cmd, "type=social"))
2197		type = P2P_FIND_ONLY_SOCIAL;
2198	else if (os_strstr(cmd, "type=progressive"))
2199		type = P2P_FIND_PROGRESSIVE;
2200
2201	return wpas_p2p_find(wpa_s, timeout, type, 0, NULL);
2202}
2203
2204
2205static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
2206			    char *buf, size_t buflen)
2207{
2208	u8 addr[ETH_ALEN];
2209	char *pos, *pos2;
2210	char *pin = NULL;
2211	enum p2p_wps_method wps_method;
2212	int new_pin;
2213	int ret;
2214	int persistent_group;
2215	int join;
2216	int auth;
2217	int go_intent = -1;
2218	int freq = 0;
2219
2220	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent]
2221	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
2222
2223	if (hwaddr_aton(cmd, addr))
2224		return -1;
2225
2226	pos = cmd + 17;
2227	if (*pos != ' ')
2228		return -1;
2229	pos++;
2230
2231	persistent_group = os_strstr(pos, " persistent") != NULL;
2232	join = os_strstr(pos, " join") != NULL;
2233	auth = os_strstr(pos, " auth") != NULL;
2234
2235	pos2 = os_strstr(pos, " go_intent=");
2236	if (pos2) {
2237		pos2 += 11;
2238		go_intent = atoi(pos2);
2239		if (go_intent < 0 || go_intent > 15)
2240			return -1;
2241	}
2242
2243	pos2 = os_strstr(pos, " freq=");
2244	if (pos2) {
2245		pos2 += 6;
2246		freq = atoi(pos2);
2247		if (freq <= 0)
2248			return -1;
2249	}
2250
2251	if (os_strncmp(pos, "pin", 3) == 0) {
2252		/* Request random PIN (to be displayed) and enable the PIN */
2253		wps_method = WPS_PIN_DISPLAY;
2254	} else if (os_strncmp(pos, "pbc", 3) == 0) {
2255		wps_method = WPS_PBC;
2256	} else {
2257		pin = pos;
2258		pos = os_strchr(pin, ' ');
2259		wps_method = WPS_PIN_KEYPAD;
2260		if (pos) {
2261			*pos++ = '\0';
2262			if (os_strncmp(pos, "label", 5) == 0)
2263				wps_method = WPS_PIN_LABEL;
2264			else if (os_strncmp(pos, "display", 7) == 0)
2265				wps_method = WPS_PIN_DISPLAY;
2266		}
2267	}
2268
2269	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
2270				   persistent_group, join, auth, go_intent,
2271				   freq);
2272	if (new_pin == -2) {
2273		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
2274		return 25;
2275	}
2276	if (new_pin == -3) {
2277		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
2278		return 25;
2279	}
2280	if (new_pin < 0)
2281		return -1;
2282	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
2283		ret = os_snprintf(buf, buflen, "%08d", new_pin);
2284		if (ret < 0 || (size_t) ret >= buflen)
2285			return -1;
2286		return ret;
2287	}
2288
2289	os_memcpy(buf, "OK\n", 3);
2290	return 3;
2291}
2292
2293
2294static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
2295{
2296	unsigned int timeout = atoi(cmd);
2297	return wpas_p2p_listen(wpa_s, timeout);
2298}
2299
2300
2301static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
2302{
2303	u8 addr[ETH_ALEN];
2304	char *pos;
2305
2306	/* <addr> <config method> */
2307
2308	if (hwaddr_aton(cmd, addr))
2309		return -1;
2310
2311	pos = cmd + 17;
2312	if (*pos != ' ')
2313		return -1;
2314	pos++;
2315
2316	return wpas_p2p_prov_disc(wpa_s, addr, pos);
2317}
2318
2319
2320static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
2321			      size_t buflen)
2322{
2323	struct wpa_ssid *ssid = wpa_s->current_ssid;
2324
2325	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
2326	    ssid->passphrase == NULL)
2327		return -1;
2328
2329	os_strlcpy(buf, ssid->passphrase, buflen);
2330	return os_strlen(buf);
2331}
2332
2333
2334static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
2335				  char *buf, size_t buflen)
2336{
2337	u64 ref;
2338	int res;
2339	u8 dst_buf[ETH_ALEN], *dst;
2340	struct wpabuf *tlvs;
2341	char *pos;
2342	size_t len;
2343
2344	if (hwaddr_aton(cmd, dst_buf))
2345		return -1;
2346	dst = dst_buf;
2347	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
2348	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
2349		dst = NULL;
2350	pos = cmd + 17;
2351	if (*pos != ' ')
2352		return -1;
2353	pos++;
2354
2355	if (os_strncmp(pos, "upnp ", 5) == 0) {
2356		u8 version;
2357		pos += 5;
2358		if (hexstr2bin(pos, &version, 1) < 0)
2359			return -1;
2360		pos += 2;
2361		if (*pos != ' ')
2362			return -1;
2363		pos++;
2364		ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, dst,
2365							       version, pos);
2366	} else {
2367		len = os_strlen(pos);
2368		if (len & 1)
2369			return -1;
2370		len /= 2;
2371		tlvs = wpabuf_alloc(len);
2372		if (tlvs == NULL)
2373			return -1;
2374		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
2375			wpabuf_free(tlvs);
2376			return -1;
2377		}
2378
2379		ref = (unsigned long) wpas_p2p_sd_request(wpa_s, dst, tlvs);
2380		wpabuf_free(tlvs);
2381	}
2382	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
2383	if (res < 0 || (unsigned) res >= buflen)
2384		return -1;
2385	return res;
2386}
2387
2388
2389static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
2390					 char *cmd)
2391{
2392	long long unsigned val;
2393	u64 req;
2394	if (sscanf(cmd, "%llx", &val) != 1)
2395		return -1;
2396	req = val;
2397	return wpas_p2p_sd_cancel_request(wpa_s, (void *) (unsigned long) req);
2398}
2399
2400
2401static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
2402{
2403	int freq;
2404	u8 dst[ETH_ALEN];
2405	u8 dialog_token;
2406	struct wpabuf *resp_tlvs;
2407	char *pos, *pos2;
2408	size_t len;
2409
2410	pos = os_strchr(cmd, ' ');
2411	if (pos == NULL)
2412		return -1;
2413	*pos++ = '\0';
2414	freq = atoi(cmd);
2415	if (freq == 0)
2416		return -1;
2417
2418	if (hwaddr_aton(pos, dst))
2419		return -1;
2420	pos += 17;
2421	if (*pos != ' ')
2422		return -1;
2423	pos++;
2424
2425	pos2 = os_strchr(pos, ' ');
2426	if (pos2 == NULL)
2427		return -1;
2428	*pos2++ = '\0';
2429	dialog_token = atoi(pos);
2430
2431	len = os_strlen(pos2);
2432	if (len & 1)
2433		return -1;
2434	len /= 2;
2435	resp_tlvs = wpabuf_alloc(len);
2436	if (resp_tlvs == NULL)
2437		return -1;
2438	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
2439		wpabuf_free(resp_tlvs);
2440		return -1;
2441	}
2442
2443	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
2444	wpabuf_free(resp_tlvs);
2445	return 0;
2446}
2447
2448
2449static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
2450				       char *cmd)
2451{
2452	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
2453	return 0;
2454}
2455
2456
2457static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
2458					char *cmd)
2459{
2460	char *pos;
2461	size_t len;
2462	struct wpabuf *query, *resp;
2463
2464	pos = os_strchr(cmd, ' ');
2465	if (pos == NULL)
2466		return -1;
2467	*pos++ = '\0';
2468
2469	len = os_strlen(cmd);
2470	if (len & 1)
2471		return -1;
2472	len /= 2;
2473	query = wpabuf_alloc(len);
2474	if (query == NULL)
2475		return -1;
2476	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2477		wpabuf_free(query);
2478		return -1;
2479	}
2480
2481	len = os_strlen(pos);
2482	if (len & 1) {
2483		wpabuf_free(query);
2484		return -1;
2485	}
2486	len /= 2;
2487	resp = wpabuf_alloc(len);
2488	if (resp == NULL) {
2489		wpabuf_free(query);
2490		return -1;
2491	}
2492	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
2493		wpabuf_free(query);
2494		wpabuf_free(resp);
2495		return -1;
2496	}
2497
2498	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
2499		wpabuf_free(query);
2500		wpabuf_free(resp);
2501		return -1;
2502	}
2503	return 0;
2504}
2505
2506
2507static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2508{
2509	char *pos;
2510	u8 version;
2511
2512	pos = os_strchr(cmd, ' ');
2513	if (pos == NULL)
2514		return -1;
2515	*pos++ = '\0';
2516
2517	if (hexstr2bin(cmd, &version, 1) < 0)
2518		return -1;
2519
2520	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
2521}
2522
2523
2524static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
2525{
2526	char *pos;
2527
2528	pos = os_strchr(cmd, ' ');
2529	if (pos == NULL)
2530		return -1;
2531	*pos++ = '\0';
2532
2533	if (os_strcmp(cmd, "bonjour") == 0)
2534		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
2535	if (os_strcmp(cmd, "upnp") == 0)
2536		return p2p_ctrl_service_add_upnp(wpa_s, pos);
2537	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2538	return -1;
2539}
2540
2541
2542static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
2543					char *cmd)
2544{
2545	size_t len;
2546	struct wpabuf *query;
2547	int ret;
2548
2549	len = os_strlen(cmd);
2550	if (len & 1)
2551		return -1;
2552	len /= 2;
2553	query = wpabuf_alloc(len);
2554	if (query == NULL)
2555		return -1;
2556	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2557		wpabuf_free(query);
2558		return -1;
2559	}
2560
2561	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2562	wpabuf_free(query);
2563	return ret;
2564}
2565
2566
2567static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2568{
2569	char *pos;
2570	u8 version;
2571
2572	pos = os_strchr(cmd, ' ');
2573	if (pos == NULL)
2574		return -1;
2575	*pos++ = '\0';
2576
2577	if (hexstr2bin(cmd, &version, 1) < 0)
2578		return -1;
2579
2580	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
2581}
2582
2583
2584static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
2585{
2586	char *pos;
2587
2588	pos = os_strchr(cmd, ' ');
2589	if (pos == NULL)
2590		return -1;
2591	*pos++ = '\0';
2592
2593	if (os_strcmp(cmd, "bonjour") == 0)
2594		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
2595	if (os_strcmp(cmd, "upnp") == 0)
2596		return p2p_ctrl_service_del_upnp(wpa_s, pos);
2597	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2598	return -1;
2599}
2600
2601
2602static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
2603{
2604	u8 addr[ETH_ALEN];
2605
2606	/* <addr> */
2607
2608	if (hwaddr_aton(cmd, addr))
2609		return -1;
2610
2611	return wpas_p2p_reject(wpa_s, addr);
2612}
2613
2614
2615static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
2616{
2617	char *pos;
2618	int id;
2619	struct wpa_ssid *ssid;
2620	u8 peer[ETH_ALEN];
2621
2622	id = atoi(cmd);
2623	pos = os_strstr(cmd, " peer=");
2624	if (pos) {
2625		pos += 6;
2626		if (hwaddr_aton(pos, peer))
2627			return -1;
2628	}
2629	ssid = wpa_config_get_network(wpa_s->conf, id);
2630	if (ssid == NULL || ssid->disabled != 2) {
2631		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2632			   "for persistent P2P group",
2633			   id);
2634		return -1;
2635	}
2636
2637	return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
2638}
2639
2640
2641static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
2642{
2643	char *pos;
2644	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
2645
2646	pos = os_strstr(cmd, " peer=");
2647	if (!pos)
2648		return -1;
2649
2650	*pos = '\0';
2651	pos += 6;
2652	if (hwaddr_aton(pos, peer)) {
2653		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
2654		return -1;
2655	}
2656
2657	pos = os_strstr(pos, " go_dev_addr=");
2658	if (pos) {
2659		pos += 13;
2660		if (hwaddr_aton(pos, go_dev_addr)) {
2661			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
2662				   pos);
2663			return -1;
2664		}
2665		go_dev = go_dev_addr;
2666	}
2667
2668	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
2669}
2670
2671
2672static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
2673{
2674	if (os_strncmp(cmd, "persistent=", 11) == 0)
2675		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
2676	if (os_strncmp(cmd, "group=", 6) == 0)
2677		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
2678
2679	return -1;
2680}
2681
2682
2683static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
2684					 char *cmd, int freq)
2685{
2686	int id;
2687	struct wpa_ssid *ssid;
2688
2689	id = atoi(cmd);
2690	ssid = wpa_config_get_network(wpa_s->conf, id);
2691	if (ssid == NULL || ssid->disabled != 2) {
2692		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2693			   "for persistent P2P group",
2694			   id);
2695		return -1;
2696	}
2697
2698	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
2699}
2700
2701
2702static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
2703{
2704	int freq = 0;
2705	char *pos;
2706
2707	pos = os_strstr(cmd, "freq=");
2708	if (pos)
2709		freq = atoi(pos + 5);
2710
2711	if (os_strncmp(cmd, "persistent=", 11) == 0)
2712		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
2713	if (os_strcmp(cmd, "persistent") == 0 ||
2714	    os_strncmp(cmd, "persistent ", 11) == 0)
2715		return wpas_p2p_group_add(wpa_s, 1, freq);
2716	if (os_strncmp(cmd, "freq=", 5) == 0)
2717		return wpas_p2p_group_add(wpa_s, 0, freq);
2718
2719	wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
2720		   cmd);
2721	return -1;
2722}
2723
2724
2725static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
2726			 char *buf, size_t buflen)
2727{
2728	u8 addr[ETH_ALEN], *addr_ptr;
2729	int next;
2730
2731	if (!wpa_s->global->p2p)
2732		return -1;
2733
2734	if (os_strcmp(cmd, "FIRST") == 0) {
2735		addr_ptr = NULL;
2736		next = 0;
2737	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2738		if (hwaddr_aton(cmd + 5, addr) < 0)
2739			return -1;
2740		addr_ptr = addr;
2741		next = 1;
2742	} else {
2743		if (hwaddr_aton(cmd, addr) < 0)
2744			return -1;
2745		addr_ptr = addr;
2746		next = 0;
2747	}
2748
2749	return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next,
2750				 buf, buflen);
2751}
2752
2753
2754static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
2755{
2756	char *param;
2757
2758	if (wpa_s->global->p2p == NULL)
2759		return -1;
2760
2761	param = os_strchr(cmd, ' ');
2762	if (param == NULL)
2763		return -1;
2764	*param++ = '\0';
2765
2766	if (os_strcmp(cmd, "discoverability") == 0) {
2767		p2p_set_client_discoverability(wpa_s->global->p2p,
2768					       atoi(param));
2769		return 0;
2770	}
2771
2772	if (os_strcmp(cmd, "managed") == 0) {
2773		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
2774		return 0;
2775	}
2776
2777	if (os_strcmp(cmd, "listen_channel") == 0) {
2778		return p2p_set_listen_channel(wpa_s->global->p2p, 81,
2779					      atoi(param));
2780	}
2781
2782	if (os_strcmp(cmd, "ssid_postfix") == 0) {
2783		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
2784					    os_strlen(param));
2785	}
2786
2787	if (os_strcmp(cmd, "noa") == 0) {
2788		char *pos;
2789		int count, start, duration;
2790		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
2791		count = atoi(param);
2792		pos = os_strchr(param, ',');
2793		if (pos == NULL)
2794			return -1;
2795		pos++;
2796		start = atoi(pos);
2797		pos = os_strchr(pos, ',');
2798		if (pos == NULL)
2799			return -1;
2800		pos++;
2801		duration = atoi(pos);
2802		if (count < 0 || count > 255 || start < 0 || duration < 0)
2803			return -1;
2804		if (count == 0 && duration > 0)
2805			return -1;
2806		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
2807			   "start=%d duration=%d", count, start, duration);
2808		return wpas_p2p_set_noa(wpa_s, count, start, duration);
2809	}
2810
2811	if (os_strcmp(cmd, "ps") == 0)
2812		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
2813
2814	if (os_strcmp(cmd, "oppps") == 0)
2815		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
2816
2817	if (os_strcmp(cmd, "ctwindow") == 0)
2818		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
2819
2820	if (os_strcmp(cmd, "disabled") == 0) {
2821		wpa_s->global->p2p_disabled = atoi(param);
2822		wpa_printf(MSG_DEBUG, "P2P functionality %s",
2823			   wpa_s->global->p2p_disabled ?
2824			   "disabled" : "enabled");
2825		if (wpa_s->global->p2p_disabled) {
2826			wpas_p2p_stop_find(wpa_s);
2827			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2828			p2p_flush(wpa_s->global->p2p);
2829		}
2830		return 0;
2831	}
2832
2833	if (os_strcmp(cmd, "force_long_sd") == 0) {
2834		wpa_s->force_long_sd = atoi(param);
2835		return 0;
2836	}
2837
2838	if (os_strcmp(cmd, "peer_filter") == 0) {
2839		u8 addr[ETH_ALEN];
2840		if (hwaddr_aton(param, addr))
2841			return -1;
2842		p2p_set_peer_filter(wpa_s->global->p2p, addr);
2843		return 0;
2844	}
2845
2846	if (os_strcmp(cmd, "cross_connect") == 0)
2847		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
2848
2849	if (os_strcmp(cmd, "go_apsd") == 0) {
2850		if (os_strcmp(param, "disable") == 0)
2851			wpa_s->set_ap_uapsd = 0;
2852		else {
2853			wpa_s->set_ap_uapsd = 1;
2854			wpa_s->ap_uapsd = atoi(param);
2855		}
2856		return 0;
2857	}
2858
2859	if (os_strcmp(cmd, "client_apsd") == 0) {
2860		if (os_strcmp(param, "disable") == 0)
2861			wpa_s->set_sta_uapsd = 0;
2862		else {
2863			int be, bk, vi, vo;
2864			char *pos;
2865			/* format: BE,BK,VI,VO;max SP Length */
2866			be = atoi(param);
2867			pos = os_strchr(param, ',');
2868			if (pos == NULL)
2869				return -1;
2870			pos++;
2871			bk = atoi(pos);
2872			pos = os_strchr(pos, ',');
2873			if (pos == NULL)
2874				return -1;
2875			pos++;
2876			vi = atoi(pos);
2877			pos = os_strchr(pos, ',');
2878			if (pos == NULL)
2879				return -1;
2880			pos++;
2881			vo = atoi(pos);
2882			/* ignore max SP Length for now */
2883
2884			wpa_s->set_sta_uapsd = 1;
2885			wpa_s->sta_uapsd = 0;
2886			if (be)
2887				wpa_s->sta_uapsd |= BIT(0);
2888			if (bk)
2889				wpa_s->sta_uapsd |= BIT(1);
2890			if (vi)
2891				wpa_s->sta_uapsd |= BIT(2);
2892			if (vo)
2893				wpa_s->sta_uapsd |= BIT(3);
2894		}
2895		return 0;
2896	}
2897
2898	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
2899		   cmd);
2900
2901	return -1;
2902}
2903
2904
2905static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
2906{
2907	char *pos, *pos2;
2908	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
2909
2910	if (cmd[0]) {
2911		pos = os_strchr(cmd, ' ');
2912		if (pos == NULL)
2913			return -1;
2914		*pos++ = '\0';
2915		dur1 = atoi(cmd);
2916
2917		pos2 = os_strchr(pos, ' ');
2918		if (pos2)
2919			*pos2++ = '\0';
2920		int1 = atoi(pos);
2921	} else
2922		pos2 = NULL;
2923
2924	if (pos2) {
2925		pos = os_strchr(pos2, ' ');
2926		if (pos == NULL)
2927			return -1;
2928		*pos++ = '\0';
2929		dur2 = atoi(pos2);
2930		int2 = atoi(pos);
2931	}
2932
2933	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
2934}
2935
2936
2937static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
2938{
2939	char *pos;
2940	unsigned int period = 0, interval = 0;
2941
2942	if (cmd[0]) {
2943		pos = os_strchr(cmd, ' ');
2944		if (pos == NULL)
2945			return -1;
2946		*pos++ = '\0';
2947		period = atoi(cmd);
2948		interval = atoi(pos);
2949	}
2950
2951	return wpas_p2p_ext_listen(wpa_s, period, interval);
2952}
2953
2954#endif /* CONFIG_P2P */
2955
2956
2957static int wpa_supplicant_ctrl_iface_sta_autoconnect(
2958	struct wpa_supplicant *wpa_s, char *cmd)
2959{
2960	wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
2961	return 0;
2962}
2963
2964
2965static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
2966				      size_t buflen)
2967{
2968	struct wpa_signal_info si;
2969	int ret;
2970
2971	ret = wpa_drv_signal_poll(wpa_s, &si);
2972	if (ret)
2973		return -1;
2974
2975	ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
2976			  "NOISE=%d\nFREQUENCY=%u\n",
2977			  si.current_signal, si.current_txrate / 1000,
2978			  si.current_noise, si.frequency);
2979	if (ret < 0 || (unsigned int) ret > buflen)
2980		return -1;
2981	return ret;
2982}
2983
2984
2985char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
2986					 char *buf, size_t *resp_len)
2987{
2988	char *reply;
2989	const int reply_size = 4096;
2990	int ctrl_rsp = 0;
2991	int reply_len;
2992
2993	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
2994	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
2995		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
2996				      (const u8 *) buf, os_strlen(buf));
2997	} else {
2998		int level = MSG_DEBUG;
2999		if (os_strcmp(buf, "PING") == 0)
3000			level = MSG_EXCESSIVE;
3001		wpa_hexdump_ascii(level, "RX ctrl_iface",
3002				  (const u8 *) buf, os_strlen(buf));
3003	}
3004
3005	reply = os_malloc(reply_size);
3006	if (reply == NULL) {
3007		*resp_len = 1;
3008		return NULL;
3009	}
3010
3011	os_memcpy(reply, "OK\n", 3);
3012	reply_len = 3;
3013
3014	if (os_strcmp(buf, "PING") == 0) {
3015		os_memcpy(reply, "PONG\n", 5);
3016		reply_len = 5;
3017	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
3018		if (wpa_debug_reopen_file() < 0)
3019			reply_len = -1;
3020	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
3021		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
3022	} else if (os_strcmp(buf, "MIB") == 0) {
3023		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
3024		if (reply_len >= 0) {
3025			int res;
3026			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
3027					       reply_size - reply_len);
3028			if (res < 0)
3029				reply_len = -1;
3030			else
3031				reply_len += res;
3032		}
3033	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
3034		reply_len = wpa_supplicant_ctrl_iface_status(
3035			wpa_s, buf + 6, reply, reply_size);
3036	} else if (os_strcmp(buf, "PMKSA") == 0) {
3037		reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
3038						    reply_size);
3039	} else if (os_strncmp(buf, "SET ", 4) == 0) {
3040		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
3041			reply_len = -1;
3042	} else if (os_strncmp(buf, "GET ", 4) == 0) {
3043		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
3044							  reply, reply_size);
3045	} else if (os_strcmp(buf, "LOGON") == 0) {
3046		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
3047	} else if (os_strcmp(buf, "LOGOFF") == 0) {
3048		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
3049	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
3050		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3051			reply_len = -1;
3052		else {
3053			wpa_s->disconnected = 0;
3054			wpa_s->reassociate = 1;
3055			wpa_supplicant_req_scan(wpa_s, 0, 0);
3056		}
3057	} else if (os_strcmp(buf, "RECONNECT") == 0) {
3058		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3059			reply_len = -1;
3060		else if (wpa_s->disconnected) {
3061			wpa_s->disconnected = 0;
3062			wpa_s->reassociate = 1;
3063			wpa_supplicant_req_scan(wpa_s, 0, 0);
3064		}
3065#ifdef IEEE8021X_EAPOL
3066	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
3067		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
3068			reply_len = -1;
3069#endif /* IEEE8021X_EAPOL */
3070#ifdef CONFIG_PEERKEY
3071	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
3072		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
3073			reply_len = -1;
3074#endif /* CONFIG_PEERKEY */
3075#ifdef CONFIG_IEEE80211R
3076	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
3077		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
3078			reply_len = -1;
3079#endif /* CONFIG_IEEE80211R */
3080#ifdef CONFIG_WPS
3081	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
3082		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
3083		if (res == -2) {
3084			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3085			reply_len = 17;
3086		} else if (res)
3087			reply_len = -1;
3088	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
3089		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
3090		if (res == -2) {
3091			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3092			reply_len = 17;
3093		} else if (res)
3094			reply_len = -1;
3095	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
3096		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
3097							      reply,
3098							      reply_size);
3099	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
3100		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
3101			wpa_s, buf + 14, reply, reply_size);
3102	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
3103		if (wpas_wps_cancel(wpa_s))
3104			reply_len = -1;
3105#ifdef CONFIG_WPS_OOB
3106	} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
3107		if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
3108			reply_len = -1;
3109#endif /* CONFIG_WPS_OOB */
3110	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
3111		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
3112			reply_len = -1;
3113#ifdef CONFIG_AP
3114	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
3115		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
3116			wpa_s, buf + 11, reply, reply_size);
3117#endif /* CONFIG_AP */
3118#ifdef CONFIG_WPS_ER
3119	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
3120		if (wpas_wps_er_start(wpa_s, NULL))
3121			reply_len = -1;
3122	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
3123		if (wpas_wps_er_start(wpa_s, buf + 13))
3124			reply_len = -1;
3125	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
3126		if (wpas_wps_er_stop(wpa_s))
3127			reply_len = -1;
3128	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
3129		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
3130			reply_len = -1;
3131	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
3132		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
3133		if (ret == -2) {
3134			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3135			reply_len = 17;
3136		} else if (ret == -3) {
3137			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
3138			reply_len = 18;
3139		} else if (ret == -4) {
3140			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
3141			reply_len = 20;
3142		} else if (ret)
3143			reply_len = -1;
3144	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
3145		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
3146			reply_len = -1;
3147	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
3148		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
3149								buf + 18))
3150			reply_len = -1;
3151	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
3152		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
3153			reply_len = -1;
3154#endif /* CONFIG_WPS_ER */
3155#endif /* CONFIG_WPS */
3156#ifdef CONFIG_IBSS_RSN
3157	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
3158		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
3159			reply_len = -1;
3160#endif /* CONFIG_IBSS_RSN */
3161#ifdef CONFIG_P2P
3162	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
3163		if (p2p_ctrl_find(wpa_s, buf + 9))
3164			reply_len = -1;
3165	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
3166		if (p2p_ctrl_find(wpa_s, ""))
3167			reply_len = -1;
3168	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
3169		wpas_p2p_stop_find(wpa_s);
3170	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
3171		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
3172					     reply_size);
3173	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
3174		if (p2p_ctrl_listen(wpa_s, buf + 11))
3175			reply_len = -1;
3176	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
3177		if (p2p_ctrl_listen(wpa_s, ""))
3178			reply_len = -1;
3179	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
3180		if (wpas_p2p_group_remove(wpa_s, buf + 17))
3181			reply_len = -1;
3182	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
3183		if (wpas_p2p_group_add(wpa_s, 0, 0))
3184			reply_len = -1;
3185	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
3186		if (p2p_ctrl_group_add(wpa_s, buf + 14))
3187			reply_len = -1;
3188	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
3189		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
3190			reply_len = -1;
3191	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
3192		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
3193	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
3194		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
3195						   reply_size);
3196	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
3197		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
3198			reply_len = -1;
3199	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
3200		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
3201			reply_len = -1;
3202	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
3203		wpas_p2p_sd_service_update(wpa_s);
3204	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
3205		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
3206			reply_len = -1;
3207	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
3208		wpas_p2p_service_flush(wpa_s);
3209	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
3210		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
3211			reply_len = -1;
3212	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
3213		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
3214			reply_len = -1;
3215	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
3216		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
3217			reply_len = -1;
3218	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
3219		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
3220			reply_len = -1;
3221	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
3222		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
3223					      reply_size);
3224	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
3225		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
3226			reply_len = -1;
3227	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
3228		os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
3229		wpa_s->force_long_sd = 0;
3230		if (wpa_s->global->p2p)
3231			p2p_flush(wpa_s->global->p2p);
3232	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
3233		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
3234			reply_len = -1;
3235	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
3236		if (wpas_p2p_cancel(wpa_s))
3237			reply_len = -1;
3238	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
3239		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
3240			reply_len = -1;
3241	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
3242		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
3243			reply_len = -1;
3244	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
3245		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
3246			reply_len = -1;
3247	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
3248		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
3249			reply_len = -1;
3250#endif /* CONFIG_P2P */
3251	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
3252	{
3253		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
3254			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
3255			reply_len = -1;
3256		else
3257			ctrl_rsp = 1;
3258	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
3259		if (wpa_supplicant_reload_configuration(wpa_s))
3260			reply_len = -1;
3261	} else if (os_strcmp(buf, "TERMINATE") == 0) {
3262		wpa_supplicant_terminate_proc(wpa_s->global);
3263	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
3264		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
3265			reply_len = -1;
3266	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
3267		reply_len = wpa_supplicant_ctrl_iface_log_level(wpa_s, buf + 9,
3268							reply, reply_size);
3269	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
3270		reply_len = wpa_supplicant_ctrl_iface_blacklist(wpa_s, buf + 9,
3271							reply, reply_size);
3272	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
3273		reply_len = wpa_supplicant_ctrl_iface_list_networks(
3274			wpa_s, reply, reply_size);
3275	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
3276		wpa_s->reassociate = 0;
3277		wpa_s->disconnected = 1;
3278		wpa_supplicant_deauthenticate(wpa_s,
3279					      WLAN_REASON_DEAUTH_LEAVING);
3280	} else if (os_strcmp(buf, "SCAN") == 0) {
3281		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3282			reply_len = -1;
3283		else {
3284			if (!wpa_s->scanning &&
3285			    ((wpa_s->wpa_state <= WPA_SCANNING) ||
3286			     (wpa_s->wpa_state == WPA_COMPLETED))) {
3287				wpa_s->scan_req = 2;
3288				wpa_supplicant_req_scan(wpa_s, 0, 0);
3289			} else {
3290				wpa_printf(MSG_DEBUG, "Ongoing scan action - "
3291					   "reject new request");
3292				reply_len = os_snprintf(reply, reply_size,
3293							"FAIL-BUSY\n");
3294			}
3295		}
3296	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
3297		reply_len = wpa_supplicant_ctrl_iface_scan_results(
3298			wpa_s, reply, reply_size);
3299	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
3300		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
3301			reply_len = -1;
3302	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
3303		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
3304			reply_len = -1;
3305	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
3306		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
3307			reply_len = -1;
3308	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
3309		reply_len = wpa_supplicant_ctrl_iface_add_network(
3310			wpa_s, reply, reply_size);
3311	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
3312		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
3313			reply_len = -1;
3314	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3315		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
3316			reply_len = -1;
3317	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
3318		reply_len = wpa_supplicant_ctrl_iface_get_network(
3319			wpa_s, buf + 12, reply, reply_size);
3320#ifndef CONFIG_NO_CONFIG_WRITE
3321	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
3322		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
3323			reply_len = -1;
3324#endif /* CONFIG_NO_CONFIG_WRITE */
3325	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
3326		reply_len = wpa_supplicant_ctrl_iface_get_capability(
3327			wpa_s, buf + 15, reply, reply_size);
3328	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
3329		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
3330			reply_len = -1;
3331	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
3332		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
3333			reply_len = -1;
3334	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3335		reply_len = wpa_supplicant_global_iface_list(
3336			wpa_s->global, reply, reply_size);
3337	} else if (os_strcmp(buf, "INTERFACES") == 0) {
3338		reply_len = wpa_supplicant_global_iface_interfaces(
3339			wpa_s->global, reply, reply_size);
3340	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
3341		reply_len = wpa_supplicant_ctrl_iface_bss(
3342			wpa_s, buf + 4, reply, reply_size);
3343#ifdef CONFIG_AP
3344	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
3345		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
3346	} else if (os_strncmp(buf, "STA ", 4) == 0) {
3347		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
3348					      reply_size);
3349	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
3350		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
3351						   reply_size);
3352#endif /* CONFIG_AP */
3353	} else if (os_strcmp(buf, "SUSPEND") == 0) {
3354		wpas_notify_suspend(wpa_s->global);
3355	} else if (os_strcmp(buf, "RESUME") == 0) {
3356		wpas_notify_resume(wpa_s->global);
3357	} else if (os_strcmp(buf, "DROP_SA") == 0) {
3358		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
3359	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
3360		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
3361			reply_len = -1;
3362	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
3363		if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
3364			reply_len = -1;
3365	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
3366		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
3367			reply_len = -1;
3368	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
3369		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
3370							       buf + 17))
3371			reply_len = -1;
3372#ifdef CONFIG_TDLS
3373	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
3374		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
3375			reply_len = -1;
3376	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
3377		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
3378			reply_len = -1;
3379	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
3380		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
3381			reply_len = -1;
3382#endif /* CONFIG_TDLS */
3383	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
3384		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
3385						       reply_size);
3386	} else {
3387		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3388		reply_len = 16;
3389	}
3390
3391	if (reply_len < 0) {
3392		os_memcpy(reply, "FAIL\n", 5);
3393		reply_len = 5;
3394	}
3395
3396	if (ctrl_rsp)
3397		eapol_sm_notify_ctrl_response(wpa_s->eapol);
3398
3399	*resp_len = reply_len;
3400	return reply;
3401}
3402
3403
3404static int wpa_supplicant_global_iface_add(struct wpa_global *global,
3405					   char *cmd)
3406{
3407	struct wpa_interface iface;
3408	char *pos;
3409
3410	/*
3411	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
3412	 * TAB<bridge_ifname>
3413	 */
3414	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
3415
3416	os_memset(&iface, 0, sizeof(iface));
3417
3418	do {
3419		iface.ifname = pos = cmd;
3420		pos = os_strchr(pos, '\t');
3421		if (pos)
3422			*pos++ = '\0';
3423		if (iface.ifname[0] == '\0')
3424			return -1;
3425		if (pos == NULL)
3426			break;
3427
3428		iface.confname = pos;
3429		pos = os_strchr(pos, '\t');
3430		if (pos)
3431			*pos++ = '\0';
3432		if (iface.confname[0] == '\0')
3433			iface.confname = NULL;
3434		if (pos == NULL)
3435			break;
3436
3437		iface.driver = pos;
3438		pos = os_strchr(pos, '\t');
3439		if (pos)
3440			*pos++ = '\0';
3441		if (iface.driver[0] == '\0')
3442			iface.driver = NULL;
3443		if (pos == NULL)
3444			break;
3445
3446		iface.ctrl_interface = pos;
3447		pos = os_strchr(pos, '\t');
3448		if (pos)
3449			*pos++ = '\0';
3450		if (iface.ctrl_interface[0] == '\0')
3451			iface.ctrl_interface = NULL;
3452		if (pos == NULL)
3453			break;
3454
3455		iface.driver_param = pos;
3456		pos = os_strchr(pos, '\t');
3457		if (pos)
3458			*pos++ = '\0';
3459		if (iface.driver_param[0] == '\0')
3460			iface.driver_param = NULL;
3461		if (pos == NULL)
3462			break;
3463
3464		iface.bridge_ifname = pos;
3465		pos = os_strchr(pos, '\t');
3466		if (pos)
3467			*pos++ = '\0';
3468		if (iface.bridge_ifname[0] == '\0')
3469			iface.bridge_ifname = NULL;
3470		if (pos == NULL)
3471			break;
3472	} while (0);
3473
3474	if (wpa_supplicant_get_iface(global, iface.ifname))
3475		return -1;
3476
3477	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
3478}
3479
3480
3481static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
3482					      char *cmd)
3483{
3484	struct wpa_supplicant *wpa_s;
3485
3486	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
3487
3488	wpa_s = wpa_supplicant_get_iface(global, cmd);
3489	if (wpa_s == NULL)
3490		return -1;
3491	return wpa_supplicant_remove_iface(global, wpa_s);
3492}
3493
3494
3495static void wpa_free_iface_info(struct wpa_interface_info *iface)
3496{
3497	struct wpa_interface_info *prev;
3498
3499	while (iface) {
3500		prev = iface;
3501		iface = iface->next;
3502
3503		os_free(prev->ifname);
3504		os_free(prev->desc);
3505		os_free(prev);
3506	}
3507}
3508
3509
3510static int wpa_supplicant_global_iface_list(struct wpa_global *global,
3511					    char *buf, int len)
3512{
3513	int i, res;
3514	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
3515	char *pos, *end;
3516
3517	for (i = 0; wpa_drivers[i]; i++) {
3518		struct wpa_driver_ops *drv = wpa_drivers[i];
3519		if (drv->get_interfaces == NULL)
3520			continue;
3521		tmp = drv->get_interfaces(global->drv_priv[i]);
3522		if (tmp == NULL)
3523			continue;
3524
3525		if (last == NULL)
3526			iface = last = tmp;
3527		else
3528			last->next = tmp;
3529		while (last->next)
3530			last = last->next;
3531	}
3532
3533	pos = buf;
3534	end = buf + len;
3535	for (tmp = iface; tmp; tmp = tmp->next) {
3536		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
3537				  tmp->drv_name, tmp->ifname,
3538				  tmp->desc ? tmp->desc : "");
3539		if (res < 0 || res >= end - pos) {
3540			*pos = '\0';
3541			break;
3542		}
3543		pos += res;
3544	}
3545
3546	wpa_free_iface_info(iface);
3547
3548	return pos - buf;
3549}
3550
3551
3552static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
3553						  char *buf, int len)
3554{
3555	int res;
3556	char *pos, *end;
3557	struct wpa_supplicant *wpa_s;
3558
3559	wpa_s = global->ifaces;
3560	pos = buf;
3561	end = buf + len;
3562
3563	while (wpa_s) {
3564		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
3565		if (res < 0 || res >= end - pos) {
3566			*pos = '\0';
3567			break;
3568		}
3569		pos += res;
3570		wpa_s = wpa_s->next;
3571	}
3572	return pos - buf;
3573}
3574
3575
3576char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
3577						char *buf, size_t *resp_len)
3578{
3579	char *reply;
3580	const int reply_size = 2048;
3581	int reply_len;
3582
3583	wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
3584			  (const u8 *) buf, os_strlen(buf));
3585
3586	reply = os_malloc(reply_size);
3587	if (reply == NULL) {
3588		*resp_len = 1;
3589		return NULL;
3590	}
3591
3592	os_memcpy(reply, "OK\n", 3);
3593	reply_len = 3;
3594
3595	if (os_strcmp(buf, "PING") == 0) {
3596		os_memcpy(reply, "PONG\n", 5);
3597		reply_len = 5;
3598	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
3599		if (wpa_supplicant_global_iface_add(global, buf + 14))
3600			reply_len = -1;
3601	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
3602		if (wpa_supplicant_global_iface_remove(global, buf + 17))
3603			reply_len = -1;
3604	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3605		reply_len = wpa_supplicant_global_iface_list(
3606			global, reply, reply_size);
3607	} else if (os_strcmp(buf, "INTERFACES") == 0) {
3608		reply_len = wpa_supplicant_global_iface_interfaces(
3609			global, reply, reply_size);
3610	} else if (os_strcmp(buf, "TERMINATE") == 0) {
3611		wpa_supplicant_terminate_proc(global);
3612	} else if (os_strcmp(buf, "SUSPEND") == 0) {
3613		wpas_notify_suspend(global);
3614	} else if (os_strcmp(buf, "RESUME") == 0) {
3615		wpas_notify_resume(global);
3616	} else {
3617		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3618		reply_len = 16;
3619	}
3620
3621	if (reply_len < 0) {
3622		os_memcpy(reply, "FAIL\n", 5);
3623		reply_len = 5;
3624	}
3625
3626	*resp_len = reply_len;
3627	return reply;
3628}
3629