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