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