1/*
2 * WPA Supplicant / Control interface (shared code for all backends)
3 * Copyright (c) 2004-2013, 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/ieee802_11_common.h"
16#include "common/wpa_ctrl.h"
17#include "eap_peer/eap.h"
18#include "eapol_supp/eapol_supp_sm.h"
19#include "rsn_supp/wpa.h"
20#include "rsn_supp/preauth.h"
21#include "rsn_supp/pmksa_cache.h"
22#include "l2_packet/l2_packet.h"
23#include "wps/wps.h"
24#include "config.h"
25#include "wpa_supplicant_i.h"
26#include "driver_i.h"
27#include "wps_supplicant.h"
28#include "ibss_rsn.h"
29#include "ap.h"
30#include "p2p_supplicant.h"
31#include "p2p/p2p.h"
32#include "hs20_supplicant.h"
33#include "wifi_display.h"
34#include "notify.h"
35#include "bss.h"
36#include "scan.h"
37#include "ctrl_iface.h"
38#include "interworking.h"
39#include "blacklist.h"
40#include "autoscan.h"
41#include "wnm_sta.h"
42
43extern struct wpa_driver_ops *wpa_drivers[];
44
45static int wpa_supplicant_global_iface_list(struct wpa_global *global,
46					    char *buf, int len);
47static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
48						  char *buf, int len);
49
50
51static int pno_start(struct wpa_supplicant *wpa_s)
52{
53	int ret;
54	size_t i, num_ssid;
55	struct wpa_ssid *ssid;
56	struct wpa_driver_scan_params params;
57
58	if (wpa_s->pno)
59		return 0;
60
61	if ((wpa_s->wpa_state > WPA_SCANNING) &&
62	    (wpa_s->wpa_state <= WPA_COMPLETED)) {
63		wpa_printf(MSG_ERROR, "PNO: In assoc process");
64		return -EAGAIN;
65	}
66
67	if (wpa_s->wpa_state == WPA_SCANNING) {
68		wpa_supplicant_cancel_sched_scan(wpa_s);
69		wpa_supplicant_cancel_scan(wpa_s);
70	}
71
72	os_memset(&params, 0, sizeof(params));
73
74	num_ssid = 0;
75	ssid = wpa_s->conf->ssid;
76	while (ssid) {
77		if (!wpas_network_disabled(wpa_s, ssid))
78			num_ssid++;
79		ssid = ssid->next;
80	}
81	if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
82		wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
83			   "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
84		num_ssid = WPAS_MAX_SCAN_SSIDS;
85	}
86
87	if (num_ssid == 0) {
88		wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
89		return -1;
90	}
91
92	params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
93					num_ssid);
94	if (params.filter_ssids == NULL)
95		return -1;
96	i = 0;
97	ssid = wpa_s->conf->ssid;
98	while (ssid) {
99		if (!wpas_network_disabled(wpa_s, ssid)) {
100			params.ssids[i].ssid = ssid->ssid;
101			params.ssids[i].ssid_len = ssid->ssid_len;
102			params.num_ssids++;
103			os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
104				  ssid->ssid_len);
105			params.filter_ssids[i].ssid_len = ssid->ssid_len;
106			params.num_filter_ssids++;
107			i++;
108			if (i == num_ssid)
109				break;
110		}
111		ssid = ssid->next;
112	}
113
114	if (wpa_s->conf->filter_rssi)
115		params.filter_rssi = wpa_s->conf->filter_rssi;
116
117	ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
118	os_free(params.filter_ssids);
119	if (ret == 0)
120		wpa_s->pno = 1;
121	return ret;
122}
123
124
125static int pno_stop(struct wpa_supplicant *wpa_s)
126{
127	int ret = 0;
128
129	if (wpa_s->pno) {
130		wpa_s->pno = 0;
131		ret = wpa_drv_stop_sched_scan(wpa_s);
132	}
133
134	if (wpa_s->wpa_state == WPA_SCANNING)
135		wpa_supplicant_req_scan(wpa_s, 0, 0);
136
137	return ret;
138}
139
140
141static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
142{
143	char *pos;
144	u8 addr[ETH_ALEN], *filter = NULL, *n;
145	size_t count = 0;
146
147	pos = val;
148	while (pos) {
149		if (*pos == '\0')
150			break;
151		if (hwaddr_aton(pos, addr)) {
152			os_free(filter);
153			return -1;
154		}
155		n = os_realloc_array(filter, count + 1, ETH_ALEN);
156		if (n == NULL) {
157			os_free(filter);
158			return -1;
159		}
160		filter = n;
161		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
162		count++;
163
164		pos = os_strchr(pos, ' ');
165		if (pos)
166			pos++;
167	}
168
169	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
170	os_free(wpa_s->bssid_filter);
171	wpa_s->bssid_filter = filter;
172	wpa_s->bssid_filter_count = count;
173
174	return 0;
175}
176
177
178static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
179{
180	char *pos;
181	u8 addr[ETH_ALEN], *bssid = NULL, *n;
182	struct wpa_ssid_value *ssid = NULL, *ns;
183	size_t count = 0, ssid_count = 0;
184	struct wpa_ssid *c;
185
186	/*
187	 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ��
188	 * SSID_SPEC ::= ssid <SSID_HEX>
189	 * BSSID_SPEC ::= bssid <BSSID_HEX>
190	 */
191
192	pos = val;
193	while (pos) {
194		if (*pos == '\0')
195			break;
196		if (os_strncmp(pos, "bssid ", 6) == 0) {
197			int res;
198			pos += 6;
199			res = hwaddr_aton2(pos, addr);
200			if (res < 0) {
201				os_free(ssid);
202				os_free(bssid);
203				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
204					   "BSSID value '%s'", pos);
205				return -1;
206			}
207			pos += res;
208			n = os_realloc_array(bssid, count + 1, ETH_ALEN);
209			if (n == NULL) {
210				os_free(ssid);
211				os_free(bssid);
212				return -1;
213			}
214			bssid = n;
215			os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
216			count++;
217		} else if (os_strncmp(pos, "ssid ", 5) == 0) {
218			char *end;
219			pos += 5;
220
221			end = pos;
222			while (*end) {
223				if (*end == '\0' || *end == ' ')
224					break;
225				end++;
226			}
227
228			ns = os_realloc_array(ssid, ssid_count + 1,
229					      sizeof(struct wpa_ssid_value));
230			if (ns == NULL) {
231				os_free(ssid);
232				os_free(bssid);
233				return -1;
234			}
235			ssid = ns;
236
237			if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
238			    hexstr2bin(pos, ssid[ssid_count].ssid,
239				       (end - pos) / 2) < 0) {
240				os_free(ssid);
241				os_free(bssid);
242				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
243					   "SSID value '%s'", pos);
244				return -1;
245			}
246			ssid[ssid_count].ssid_len = (end - pos) / 2;
247			wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
248					  ssid[ssid_count].ssid,
249					  ssid[ssid_count].ssid_len);
250			ssid_count++;
251			pos = end;
252		} else {
253			wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
254				   "'%s'", pos);
255			os_free(ssid);
256			os_free(bssid);
257			return -1;
258		}
259
260		pos = os_strchr(pos, ' ');
261		if (pos)
262			pos++;
263	}
264
265	wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
266	os_free(wpa_s->disallow_aps_bssid);
267	wpa_s->disallow_aps_bssid = bssid;
268	wpa_s->disallow_aps_bssid_count = count;
269
270	wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
271	os_free(wpa_s->disallow_aps_ssid);
272	wpa_s->disallow_aps_ssid = ssid;
273	wpa_s->disallow_aps_ssid_count = ssid_count;
274
275	if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
276		return 0;
277
278	c = wpa_s->current_ssid;
279	if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
280		return 0;
281
282	if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
283	    !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
284		return 0;
285
286	wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
287		   "because current AP was marked disallowed");
288
289#ifdef CONFIG_SME
290	wpa_s->sme.prev_bssid_set = 0;
291#endif /* CONFIG_SME */
292	wpa_s->reassociate = 1;
293	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
294	wpa_supplicant_req_scan(wpa_s, 0, 0);
295
296	return 0;
297}
298
299
300static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
301					 char *cmd)
302{
303	char *value;
304	int ret = 0;
305
306	value = os_strchr(cmd, ' ');
307	if (value == NULL)
308		return -1;
309	*value++ = '\0';
310
311	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
312	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
313		eapol_sm_configure(wpa_s->eapol,
314				   atoi(value), -1, -1, -1);
315	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
316		eapol_sm_configure(wpa_s->eapol,
317				   -1, atoi(value), -1, -1);
318	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
319		eapol_sm_configure(wpa_s->eapol,
320				   -1, -1, atoi(value), -1);
321	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
322		eapol_sm_configure(wpa_s->eapol,
323				   -1, -1, -1, atoi(value));
324	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
325		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
326				     atoi(value)))
327			ret = -1;
328	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
329		   0) {
330		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
331				     atoi(value)))
332			ret = -1;
333	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
334		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
335			ret = -1;
336	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
337		wpa_s->wps_fragment_size = atoi(value);
338#ifdef CONFIG_WPS_TESTING
339	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
340		long int val;
341		val = strtol(value, NULL, 0);
342		if (val < 0 || val > 0xff) {
343			ret = -1;
344			wpa_printf(MSG_DEBUG, "WPS: Invalid "
345				   "wps_version_number %ld", val);
346		} else {
347			wps_version_number = val;
348			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
349				   "version %u.%u",
350				   (wps_version_number & 0xf0) >> 4,
351				   wps_version_number & 0x0f);
352		}
353	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
354		wps_testing_dummy_cred = atoi(value);
355		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
356			   wps_testing_dummy_cred);
357#endif /* CONFIG_WPS_TESTING */
358	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
359		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
360			ret = -1;
361#ifdef CONFIG_TDLS_TESTING
362	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
363		extern unsigned int tdls_testing;
364		tdls_testing = strtol(value, NULL, 0);
365		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
366#endif /* CONFIG_TDLS_TESTING */
367#ifdef CONFIG_TDLS
368	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
369		int disabled = atoi(value);
370		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
371		if (disabled) {
372			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
373				ret = -1;
374		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
375			ret = -1;
376		wpa_tdls_enable(wpa_s->wpa, !disabled);
377#endif /* CONFIG_TDLS */
378	} else if (os_strcasecmp(cmd, "pno") == 0) {
379		if (atoi(value))
380			ret = pno_start(wpa_s);
381		else
382			ret = pno_stop(wpa_s);
383	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
384		int disabled = atoi(value);
385		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
386			ret = -1;
387		else if (disabled)
388			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
389	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
390		if (os_strcmp(value, "disable") == 0)
391			wpa_s->set_sta_uapsd = 0;
392		else {
393			int be, bk, vi, vo;
394			char *pos;
395			/* format: BE,BK,VI,VO;max SP Length */
396			be = atoi(value);
397			pos = os_strchr(value, ',');
398			if (pos == NULL)
399				return -1;
400			pos++;
401			bk = atoi(pos);
402			pos = os_strchr(pos, ',');
403			if (pos == NULL)
404				return -1;
405			pos++;
406			vi = atoi(pos);
407			pos = os_strchr(pos, ',');
408			if (pos == NULL)
409				return -1;
410			pos++;
411			vo = atoi(pos);
412			/* ignore max SP Length for now */
413
414			wpa_s->set_sta_uapsd = 1;
415			wpa_s->sta_uapsd = 0;
416			if (be)
417				wpa_s->sta_uapsd |= BIT(0);
418			if (bk)
419				wpa_s->sta_uapsd |= BIT(1);
420			if (vi)
421				wpa_s->sta_uapsd |= BIT(2);
422			if (vo)
423				wpa_s->sta_uapsd |= BIT(3);
424		}
425	} else if (os_strcasecmp(cmd, "ps") == 0) {
426		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
427#ifdef CONFIG_WIFI_DISPLAY
428	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
429		wifi_display_enable(wpa_s->global, !!atoi(value));
430#endif /* CONFIG_WIFI_DISPLAY */
431	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
432		ret = set_bssid_filter(wpa_s, value);
433	} else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
434		ret = set_disallow_aps(wpa_s, value);
435	} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
436		wpa_s->no_keep_alive = !!atoi(value);
437	} else {
438		value[-1] = '=';
439		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
440		if (ret == 0)
441			wpa_supplicant_update_config(wpa_s);
442	}
443
444	return ret;
445}
446
447
448static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
449					 char *cmd, char *buf, size_t buflen)
450{
451	int res = -1;
452
453	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
454
455	if (os_strcmp(cmd, "version") == 0) {
456		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
457	} else if (os_strcasecmp(cmd, "country") == 0) {
458		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
459			res = os_snprintf(buf, buflen, "%c%c",
460					  wpa_s->conf->country[0],
461					  wpa_s->conf->country[1]);
462#ifdef CONFIG_WIFI_DISPLAY
463	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
464		res = os_snprintf(buf, buflen, "%d",
465				  wpa_s->global->wifi_display);
466		if (res < 0 || (unsigned int) res >= buflen)
467			return -1;
468		return res;
469#endif /* CONFIG_WIFI_DISPLAY */
470#ifdef CONFIG_TESTING_GET_GTK
471	} else if (os_strcmp(cmd, "gtk") == 0) {
472		if (wpa_s->last_gtk_len == 0)
473			return -1;
474		res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
475				       wpa_s->last_gtk_len);
476		return res;
477#endif /* CONFIG_TESTING_GET_GTK */
478	}
479
480	if (res < 0 || (unsigned int) res >= buflen)
481		return -1;
482	return res;
483}
484
485
486#ifdef IEEE8021X_EAPOL
487static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
488					     char *addr)
489{
490	u8 bssid[ETH_ALEN];
491	struct wpa_ssid *ssid = wpa_s->current_ssid;
492
493	if (hwaddr_aton(addr, bssid)) {
494		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
495			   "'%s'", addr);
496		return -1;
497	}
498
499	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
500	rsn_preauth_deinit(wpa_s->wpa);
501	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
502		return -1;
503
504	return 0;
505}
506#endif /* IEEE8021X_EAPOL */
507
508
509#ifdef CONFIG_PEERKEY
510/* MLME-STKSTART.request(peer) */
511static int wpa_supplicant_ctrl_iface_stkstart(
512	struct wpa_supplicant *wpa_s, char *addr)
513{
514	u8 peer[ETH_ALEN];
515
516	if (hwaddr_aton(addr, peer)) {
517		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
518			   "address '%s'", addr);
519		return -1;
520	}
521
522	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
523		   MAC2STR(peer));
524
525	return wpa_sm_stkstart(wpa_s->wpa, peer);
526}
527#endif /* CONFIG_PEERKEY */
528
529
530#ifdef CONFIG_TDLS
531
532static int wpa_supplicant_ctrl_iface_tdls_discover(
533	struct wpa_supplicant *wpa_s, char *addr)
534{
535	u8 peer[ETH_ALEN];
536	int ret;
537
538	if (hwaddr_aton(addr, peer)) {
539		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
540			   "address '%s'", addr);
541		return -1;
542	}
543
544	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
545		   MAC2STR(peer));
546
547	if (wpa_tdls_is_external_setup(wpa_s->wpa))
548		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
549	else
550		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
551
552	return ret;
553}
554
555
556static int wpa_supplicant_ctrl_iface_tdls_setup(
557	struct wpa_supplicant *wpa_s, char *addr)
558{
559	u8 peer[ETH_ALEN];
560	int ret;
561
562	if (hwaddr_aton(addr, peer)) {
563		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
564			   "address '%s'", addr);
565		return -1;
566	}
567
568	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
569		   MAC2STR(peer));
570
571	if ((wpa_s->conf->tdls_external_control) &&
572	     wpa_tdls_is_external_setup(wpa_s->wpa)) {
573		return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
574	}
575
576	wpa_tdls_remove(wpa_s->wpa, peer);
577
578	if (wpa_tdls_is_external_setup(wpa_s->wpa))
579		ret = wpa_tdls_start(wpa_s->wpa, peer);
580	else
581		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
582
583	return ret;
584}
585
586
587static int wpa_supplicant_ctrl_iface_tdls_teardown(
588	struct wpa_supplicant *wpa_s, char *addr)
589{
590	u8 peer[ETH_ALEN];
591	int ret;
592
593	if (hwaddr_aton(addr, peer)) {
594		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
595			   "address '%s'", addr);
596		return -1;
597	}
598
599	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
600		   MAC2STR(peer));
601
602	if ((wpa_s->conf->tdls_external_control) &&
603	     wpa_tdls_is_external_setup(wpa_s->wpa)) {
604		return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
605	}
606
607	if (wpa_tdls_is_external_setup(wpa_s->wpa))
608		ret = wpa_tdls_teardown_link(
609			wpa_s->wpa, peer,
610			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
611	else
612		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
613
614	return ret;
615}
616
617#endif /* CONFIG_TDLS */
618
619
620#ifdef CONFIG_IEEE80211R
621static int wpa_supplicant_ctrl_iface_ft_ds(
622	struct wpa_supplicant *wpa_s, char *addr)
623{
624	u8 target_ap[ETH_ALEN];
625	struct wpa_bss *bss;
626	const u8 *mdie;
627
628	if (hwaddr_aton(addr, target_ap)) {
629		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
630			   "address '%s'", addr);
631		return -1;
632	}
633
634	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
635
636	bss = wpa_bss_get_bssid(wpa_s, target_ap);
637	if (bss)
638		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
639	else
640		mdie = NULL;
641
642	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
643}
644#endif /* CONFIG_IEEE80211R */
645
646
647#ifdef CONFIG_WPS
648static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
649					     char *cmd)
650{
651	u8 bssid[ETH_ALEN], *_bssid = bssid;
652#ifdef CONFIG_P2P
653	u8 p2p_dev_addr[ETH_ALEN];
654#endif /* CONFIG_P2P */
655#ifdef CONFIG_AP
656	u8 *_p2p_dev_addr = NULL;
657#endif /* CONFIG_AP */
658
659	if (cmd == NULL || os_strcmp(cmd, "any") == 0 || cmd[0] == '\0') {
660		_bssid = NULL;
661#ifdef CONFIG_P2P
662	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
663		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
664			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
665				   "P2P Device Address '%s'",
666				   cmd + 13);
667			return -1;
668		}
669		_p2p_dev_addr = p2p_dev_addr;
670#endif /* CONFIG_P2P */
671	} else if (hwaddr_aton(cmd, bssid)) {
672		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
673			   cmd);
674		return -1;
675	}
676
677#ifdef CONFIG_AP
678	if (wpa_s->ap_iface)
679		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
680#endif /* CONFIG_AP */
681
682	return wpas_wps_start_pbc(wpa_s, _bssid, 0);
683}
684
685
686static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
687					     char *cmd, char *buf,
688					     size_t buflen)
689{
690	u8 bssid[ETH_ALEN], *_bssid = bssid;
691	char *pin;
692	int ret;
693
694	pin = os_strchr(cmd, ' ');
695	if (pin)
696		*pin++ = '\0';
697
698	if (os_strcmp(cmd, "any") == 0)
699		_bssid = NULL;
700	else if (os_strcmp(cmd, "get") == 0) {
701		ret = wps_generate_pin();
702		goto done;
703	} else if (hwaddr_aton(cmd, bssid)) {
704		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
705			   cmd);
706		return -1;
707	}
708
709#ifdef CONFIG_AP
710	if (wpa_s->ap_iface) {
711		int timeout = 0;
712		char *pos;
713
714		if (pin) {
715			pos = os_strchr(pin, ' ');
716			if (pos) {
717				*pos++ = '\0';
718				timeout = atoi(pos);
719			}
720		}
721
722		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
723						 buf, buflen, timeout);
724	}
725#endif /* CONFIG_AP */
726
727	if (pin) {
728		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
729					 DEV_PW_DEFAULT);
730		if (ret < 0)
731			return -1;
732		ret = os_snprintf(buf, buflen, "%s", pin);
733		if (ret < 0 || (size_t) ret >= buflen)
734			return -1;
735		return ret;
736	}
737
738	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
739	if (ret < 0)
740		return -1;
741
742done:
743	/* Return the generated PIN */
744	ret = os_snprintf(buf, buflen, "%08d", ret);
745	if (ret < 0 || (size_t) ret >= buflen)
746		return -1;
747	return ret;
748}
749
750
751static int wpa_supplicant_ctrl_iface_wps_check_pin(
752	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
753{
754	char pin[9];
755	size_t len;
756	char *pos;
757	int ret;
758
759	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
760			      (u8 *) cmd, os_strlen(cmd));
761	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
762		if (*pos < '0' || *pos > '9')
763			continue;
764		pin[len++] = *pos;
765		if (len == 9) {
766			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
767			return -1;
768		}
769	}
770	if (len != 4 && len != 8) {
771		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
772		return -1;
773	}
774	pin[len] = '\0';
775
776	if (len == 8) {
777		unsigned int pin_val;
778		pin_val = atoi(pin);
779		if (!wps_pin_valid(pin_val)) {
780			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
781			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
782			if (ret < 0 || (size_t) ret >= buflen)
783				return -1;
784			return ret;
785		}
786	}
787
788	ret = os_snprintf(buf, buflen, "%s", pin);
789	if (ret < 0 || (size_t) ret >= buflen)
790		return -1;
791
792	return ret;
793}
794
795
796#ifdef CONFIG_WPS_NFC
797
798static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
799					     char *cmd)
800{
801	u8 bssid[ETH_ALEN], *_bssid = bssid;
802
803	if (cmd == NULL || cmd[0] == '\0')
804		_bssid = NULL;
805	else if (hwaddr_aton(cmd, bssid))
806		return -1;
807
808	return wpas_wps_start_nfc(wpa_s, _bssid);
809}
810
811
812static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
813	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
814{
815	int ndef;
816	struct wpabuf *buf;
817	int res;
818	char *pos;
819
820	pos = os_strchr(cmd, ' ');
821	if (pos)
822		*pos++ = '\0';
823	if (os_strcmp(cmd, "WPS") == 0)
824		ndef = 0;
825	else if (os_strcmp(cmd, "NDEF") == 0)
826		ndef = 1;
827	else
828		return -1;
829
830	buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
831	if (buf == NULL)
832		return -1;
833
834	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
835					 wpabuf_len(buf));
836	reply[res++] = '\n';
837	reply[res] = '\0';
838
839	wpabuf_free(buf);
840
841	return res;
842}
843
844
845static int wpa_supplicant_ctrl_iface_wps_nfc_token(
846	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
847{
848	int ndef;
849	struct wpabuf *buf;
850	int res;
851
852	if (os_strcmp(cmd, "WPS") == 0)
853		ndef = 0;
854	else if (os_strcmp(cmd, "NDEF") == 0)
855		ndef = 1;
856	else
857		return -1;
858
859	buf = wpas_wps_nfc_token(wpa_s, ndef);
860	if (buf == NULL)
861		return -1;
862
863	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
864					 wpabuf_len(buf));
865	reply[res++] = '\n';
866	reply[res] = '\0';
867
868	wpabuf_free(buf);
869
870	return res;
871}
872
873
874static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
875	struct wpa_supplicant *wpa_s, char *pos)
876{
877	size_t len;
878	struct wpabuf *buf;
879	int ret;
880
881	len = os_strlen(pos);
882	if (len & 0x01)
883		return -1;
884	len /= 2;
885
886	buf = wpabuf_alloc(len);
887	if (buf == NULL)
888		return -1;
889	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
890		wpabuf_free(buf);
891		return -1;
892	}
893
894	ret = wpas_wps_nfc_tag_read(wpa_s, buf);
895	wpabuf_free(buf);
896
897	return ret;
898}
899
900
901static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
902					      char *reply, size_t max_len,
903					      int cr)
904{
905	struct wpabuf *buf;
906	int res;
907
908	buf = wpas_wps_nfc_handover_req(wpa_s, cr);
909	if (buf == NULL)
910		return -1;
911
912	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
913					 wpabuf_len(buf));
914	reply[res++] = '\n';
915	reply[res] = '\0';
916
917	wpabuf_free(buf);
918
919	return res;
920}
921
922
923static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
924					  char *cmd, char *reply,
925					  size_t max_len)
926{
927	char *pos;
928
929	pos = os_strchr(cmd, ' ');
930	if (pos == NULL)
931		return -1;
932	*pos++ = '\0';
933
934	if (os_strcmp(cmd, "NDEF") != 0)
935		return -1;
936
937	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
938		return wpas_ctrl_nfc_get_handover_req_wps(
939			wpa_s, reply, max_len, os_strcmp(pos, "WPS-CR") == 0);
940	}
941
942	return -1;
943}
944
945
946static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
947					      char *reply, size_t max_len,
948					      int ndef, int cr, char *uuid)
949{
950	struct wpabuf *buf;
951	int res;
952
953	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
954	if (buf == NULL)
955		return -1;
956
957	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
958					 wpabuf_len(buf));
959	reply[res++] = '\n';
960	reply[res] = '\0';
961
962	wpabuf_free(buf);
963
964	return res;
965}
966
967
968static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
969					  char *cmd, char *reply,
970					  size_t max_len)
971{
972	char *pos, *pos2;
973	int ndef;
974
975	pos = os_strchr(cmd, ' ');
976	if (pos == NULL)
977		return -1;
978	*pos++ = '\0';
979
980	if (os_strcmp(cmd, "WPS") == 0)
981		ndef = 0;
982	else if (os_strcmp(cmd, "NDEF") == 0)
983		ndef = 1;
984	else
985		return -1;
986
987	pos2 = os_strchr(pos, ' ');
988	if (pos2)
989		*pos2++ = '\0';
990	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
991		return wpas_ctrl_nfc_get_handover_sel_wps(
992			wpa_s, reply, max_len, ndef,
993			os_strcmp(pos, "WPS-CR") == 0, pos2);
994	}
995
996	return -1;
997}
998
999
1000static int wpas_ctrl_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
1001					 char *cmd, char *reply,
1002					 size_t max_len)
1003{
1004	size_t len;
1005	struct wpabuf *buf;
1006	int ret;
1007
1008	len = os_strlen(cmd);
1009	if (len & 0x01)
1010		return -1;
1011	len /= 2;
1012
1013	buf = wpabuf_alloc(len);
1014	if (buf == NULL)
1015		return -1;
1016	if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
1017		wpabuf_free(buf);
1018		return -1;
1019	}
1020
1021	ret = wpas_wps_nfc_rx_handover_req(wpa_s, buf);
1022	wpabuf_free(buf);
1023
1024	return ret;
1025}
1026
1027
1028static int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
1029					 char *cmd)
1030{
1031	size_t len;
1032	struct wpabuf *buf;
1033	int ret;
1034
1035	len = os_strlen(cmd);
1036	if (len & 0x01)
1037		return -1;
1038	len /= 2;
1039
1040	buf = wpabuf_alloc(len);
1041	if (buf == NULL)
1042		return -1;
1043	if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
1044		wpabuf_free(buf);
1045		return -1;
1046	}
1047
1048	ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf);
1049	wpabuf_free(buf);
1050
1051	return ret;
1052}
1053
1054
1055static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1056					 char *cmd)
1057{
1058	size_t len;
1059	struct wpabuf *req, *sel;
1060	int ret;
1061	char *pos, *role, *type, *pos2;
1062
1063	role = cmd;
1064	pos = os_strchr(role, ' ');
1065	if (pos == NULL)
1066		return -1;
1067	*pos++ = '\0';
1068
1069	type = pos;
1070	pos = os_strchr(type, ' ');
1071	if (pos == NULL)
1072		return -1;
1073	*pos++ = '\0';
1074
1075	pos2 = os_strchr(pos, ' ');
1076	if (pos2 == NULL)
1077		return -1;
1078	*pos2++ = '\0';
1079
1080	len = os_strlen(pos);
1081	if (len & 0x01)
1082		return -1;
1083	len /= 2;
1084
1085	req = wpabuf_alloc(len);
1086	if (req == NULL)
1087		return -1;
1088	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1089		wpabuf_free(req);
1090		return -1;
1091	}
1092
1093	len = os_strlen(pos2);
1094	if (len & 0x01) {
1095		wpabuf_free(req);
1096		return -1;
1097	}
1098	len /= 2;
1099
1100	sel = wpabuf_alloc(len);
1101	if (sel == NULL) {
1102		wpabuf_free(req);
1103		return -1;
1104	}
1105	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1106		wpabuf_free(req);
1107		wpabuf_free(sel);
1108		return -1;
1109	}
1110
1111	if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1112		ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1113	} else {
1114		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1115			   "reported: role=%s type=%s", role, type);
1116		ret = -1;
1117	}
1118	wpabuf_free(req);
1119	wpabuf_free(sel);
1120
1121	return ret;
1122}
1123
1124#endif /* CONFIG_WPS_NFC */
1125
1126
1127static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1128					     char *cmd)
1129{
1130	u8 bssid[ETH_ALEN];
1131	char *pin;
1132	char *new_ssid;
1133	char *new_auth;
1134	char *new_encr;
1135	char *new_key;
1136	struct wps_new_ap_settings ap;
1137
1138	pin = os_strchr(cmd, ' ');
1139	if (pin == NULL)
1140		return -1;
1141	*pin++ = '\0';
1142
1143	if (hwaddr_aton(cmd, bssid)) {
1144		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1145			   cmd);
1146		return -1;
1147	}
1148
1149	new_ssid = os_strchr(pin, ' ');
1150	if (new_ssid == NULL)
1151		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1152	*new_ssid++ = '\0';
1153
1154	new_auth = os_strchr(new_ssid, ' ');
1155	if (new_auth == NULL)
1156		return -1;
1157	*new_auth++ = '\0';
1158
1159	new_encr = os_strchr(new_auth, ' ');
1160	if (new_encr == NULL)
1161		return -1;
1162	*new_encr++ = '\0';
1163
1164	new_key = os_strchr(new_encr, ' ');
1165	if (new_key == NULL)
1166		return -1;
1167	*new_key++ = '\0';
1168
1169	os_memset(&ap, 0, sizeof(ap));
1170	ap.ssid_hex = new_ssid;
1171	ap.auth = new_auth;
1172	ap.encr = new_encr;
1173	ap.key_hex = new_key;
1174	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1175}
1176
1177
1178#ifdef CONFIG_AP
1179static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1180						char *cmd, char *buf,
1181						size_t buflen)
1182{
1183	int timeout = 300;
1184	char *pos;
1185	const char *pin_txt;
1186
1187	if (!wpa_s->ap_iface)
1188		return -1;
1189
1190	pos = os_strchr(cmd, ' ');
1191	if (pos)
1192		*pos++ = '\0';
1193
1194	if (os_strcmp(cmd, "disable") == 0) {
1195		wpas_wps_ap_pin_disable(wpa_s);
1196		return os_snprintf(buf, buflen, "OK\n");
1197	}
1198
1199	if (os_strcmp(cmd, "random") == 0) {
1200		if (pos)
1201			timeout = atoi(pos);
1202		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1203		if (pin_txt == NULL)
1204			return -1;
1205		return os_snprintf(buf, buflen, "%s", pin_txt);
1206	}
1207
1208	if (os_strcmp(cmd, "get") == 0) {
1209		pin_txt = wpas_wps_ap_pin_get(wpa_s);
1210		if (pin_txt == NULL)
1211			return -1;
1212		return os_snprintf(buf, buflen, "%s", pin_txt);
1213	}
1214
1215	if (os_strcmp(cmd, "set") == 0) {
1216		char *pin;
1217		if (pos == NULL)
1218			return -1;
1219		pin = pos;
1220		pos = os_strchr(pos, ' ');
1221		if (pos) {
1222			*pos++ = '\0';
1223			timeout = atoi(pos);
1224		}
1225		if (os_strlen(pin) > buflen)
1226			return -1;
1227		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1228			return -1;
1229		return os_snprintf(buf, buflen, "%s", pin);
1230	}
1231
1232	return -1;
1233}
1234#endif /* CONFIG_AP */
1235
1236
1237#ifdef CONFIG_WPS_ER
1238static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1239						char *cmd)
1240{
1241	char *uuid = cmd, *pin, *pos;
1242	u8 addr_buf[ETH_ALEN], *addr = NULL;
1243	pin = os_strchr(uuid, ' ');
1244	if (pin == NULL)
1245		return -1;
1246	*pin++ = '\0';
1247	pos = os_strchr(pin, ' ');
1248	if (pos) {
1249		*pos++ = '\0';
1250		if (hwaddr_aton(pos, addr_buf) == 0)
1251			addr = addr_buf;
1252	}
1253	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
1254}
1255
1256
1257static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
1258						  char *cmd)
1259{
1260	char *uuid = cmd, *pin;
1261	pin = os_strchr(uuid, ' ');
1262	if (pin == NULL)
1263		return -1;
1264	*pin++ = '\0';
1265	return wpas_wps_er_learn(wpa_s, uuid, pin);
1266}
1267
1268
1269static int wpa_supplicant_ctrl_iface_wps_er_set_config(
1270	struct wpa_supplicant *wpa_s, char *cmd)
1271{
1272	char *uuid = cmd, *id;
1273	id = os_strchr(uuid, ' ');
1274	if (id == NULL)
1275		return -1;
1276	*id++ = '\0';
1277	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
1278}
1279
1280
1281static int wpa_supplicant_ctrl_iface_wps_er_config(
1282	struct wpa_supplicant *wpa_s, char *cmd)
1283{
1284	char *pin;
1285	char *new_ssid;
1286	char *new_auth;
1287	char *new_encr;
1288	char *new_key;
1289	struct wps_new_ap_settings ap;
1290
1291	pin = os_strchr(cmd, ' ');
1292	if (pin == NULL)
1293		return -1;
1294	*pin++ = '\0';
1295
1296	new_ssid = os_strchr(pin, ' ');
1297	if (new_ssid == NULL)
1298		return -1;
1299	*new_ssid++ = '\0';
1300
1301	new_auth = os_strchr(new_ssid, ' ');
1302	if (new_auth == NULL)
1303		return -1;
1304	*new_auth++ = '\0';
1305
1306	new_encr = os_strchr(new_auth, ' ');
1307	if (new_encr == NULL)
1308		return -1;
1309	*new_encr++ = '\0';
1310
1311	new_key = os_strchr(new_encr, ' ');
1312	if (new_key == NULL)
1313		return -1;
1314	*new_key++ = '\0';
1315
1316	os_memset(&ap, 0, sizeof(ap));
1317	ap.ssid_hex = new_ssid;
1318	ap.auth = new_auth;
1319	ap.encr = new_encr;
1320	ap.key_hex = new_key;
1321	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
1322}
1323
1324
1325#ifdef CONFIG_WPS_NFC
1326static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
1327	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1328{
1329	int ndef;
1330	struct wpabuf *buf;
1331	int res;
1332	char *uuid;
1333
1334	uuid = os_strchr(cmd, ' ');
1335	if (uuid == NULL)
1336		return -1;
1337	*uuid++ = '\0';
1338
1339	if (os_strcmp(cmd, "WPS") == 0)
1340		ndef = 0;
1341	else if (os_strcmp(cmd, "NDEF") == 0)
1342		ndef = 1;
1343	else
1344		return -1;
1345
1346	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
1347	if (buf == NULL)
1348		return -1;
1349
1350	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1351					 wpabuf_len(buf));
1352	reply[res++] = '\n';
1353	reply[res] = '\0';
1354
1355	wpabuf_free(buf);
1356
1357	return res;
1358}
1359#endif /* CONFIG_WPS_NFC */
1360#endif /* CONFIG_WPS_ER */
1361
1362#endif /* CONFIG_WPS */
1363
1364
1365#ifdef CONFIG_IBSS_RSN
1366static int wpa_supplicant_ctrl_iface_ibss_rsn(
1367	struct wpa_supplicant *wpa_s, char *addr)
1368{
1369	u8 peer[ETH_ALEN];
1370
1371	if (hwaddr_aton(addr, peer)) {
1372		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
1373			   "address '%s'", addr);
1374		return -1;
1375	}
1376
1377	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
1378		   MAC2STR(peer));
1379
1380	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
1381}
1382#endif /* CONFIG_IBSS_RSN */
1383
1384
1385static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
1386					      char *rsp)
1387{
1388#ifdef IEEE8021X_EAPOL
1389	char *pos, *id_pos;
1390	int id;
1391	struct wpa_ssid *ssid;
1392
1393	pos = os_strchr(rsp, '-');
1394	if (pos == NULL)
1395		return -1;
1396	*pos++ = '\0';
1397	id_pos = pos;
1398	pos = os_strchr(pos, ':');
1399	if (pos == NULL)
1400		return -1;
1401	*pos++ = '\0';
1402	id = atoi(id_pos);
1403	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
1404	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1405			      (u8 *) pos, os_strlen(pos));
1406
1407	ssid = wpa_config_get_network(wpa_s->conf, id);
1408	if (ssid == NULL) {
1409		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1410			   "to update", id);
1411		return -1;
1412	}
1413
1414	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
1415							 pos);
1416#else /* IEEE8021X_EAPOL */
1417	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1418	return -1;
1419#endif /* IEEE8021X_EAPOL */
1420}
1421
1422
1423static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
1424					    const char *params,
1425					    char *buf, size_t buflen)
1426{
1427	char *pos, *end, tmp[30];
1428	int res, verbose, wps, ret;
1429
1430	verbose = os_strcmp(params, "-VERBOSE") == 0;
1431	wps = os_strcmp(params, "-WPS") == 0;
1432	pos = buf;
1433	end = buf + buflen;
1434	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1435		struct wpa_ssid *ssid = wpa_s->current_ssid;
1436		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1437				  MAC2STR(wpa_s->bssid));
1438		if (ret < 0 || ret >= end - pos)
1439			return pos - buf;
1440		pos += ret;
1441		if (ssid) {
1442			u8 *_ssid = ssid->ssid;
1443			size_t ssid_len = ssid->ssid_len;
1444			u8 ssid_buf[MAX_SSID_LEN];
1445			if (ssid_len == 0) {
1446				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1447				if (_res < 0)
1448					ssid_len = 0;
1449				else
1450					ssid_len = _res;
1451				_ssid = ssid_buf;
1452			}
1453			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1454					  wpa_ssid_txt(_ssid, ssid_len),
1455					  ssid->id);
1456			if (ret < 0 || ret >= end - pos)
1457				return pos - buf;
1458			pos += ret;
1459
1460			if (wps && ssid->passphrase &&
1461			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1462			    (ssid->mode == WPAS_MODE_AP ||
1463			     ssid->mode == WPAS_MODE_P2P_GO)) {
1464				ret = os_snprintf(pos, end - pos,
1465						  "passphrase=%s\n",
1466						  ssid->passphrase);
1467				if (ret < 0 || ret >= end - pos)
1468					return pos - buf;
1469				pos += ret;
1470			}
1471			if (ssid->id_str) {
1472				ret = os_snprintf(pos, end - pos,
1473						  "id_str=%s\n",
1474						  ssid->id_str);
1475				if (ret < 0 || ret >= end - pos)
1476					return pos - buf;
1477				pos += ret;
1478			}
1479
1480			switch (ssid->mode) {
1481			case WPAS_MODE_INFRA:
1482				ret = os_snprintf(pos, end - pos,
1483						  "mode=station\n");
1484				break;
1485			case WPAS_MODE_IBSS:
1486				ret = os_snprintf(pos, end - pos,
1487						  "mode=IBSS\n");
1488				break;
1489			case WPAS_MODE_AP:
1490				ret = os_snprintf(pos, end - pos,
1491						  "mode=AP\n");
1492				break;
1493			case WPAS_MODE_P2P_GO:
1494				ret = os_snprintf(pos, end - pos,
1495						  "mode=P2P GO\n");
1496				break;
1497			case WPAS_MODE_P2P_GROUP_FORMATION:
1498				ret = os_snprintf(pos, end - pos,
1499						  "mode=P2P GO - group "
1500						  "formation\n");
1501				break;
1502			default:
1503				ret = 0;
1504				break;
1505			}
1506			if (ret < 0 || ret >= end - pos)
1507				return pos - buf;
1508			pos += ret;
1509		}
1510
1511#ifdef CONFIG_AP
1512		if (wpa_s->ap_iface) {
1513			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1514							    end - pos,
1515							    verbose);
1516		} else
1517#endif /* CONFIG_AP */
1518		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1519	}
1520#ifdef CONFIG_SAE
1521	if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
1522#ifdef CONFIG_AP
1523	    !wpa_s->ap_iface &&
1524#endif /* CONFIG_AP */
1525	    wpa_s->sme.sae.state == SAE_ACCEPTED) {
1526		ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
1527				  wpa_s->sme.sae.group);
1528		if (ret < 0 || ret >= end - pos)
1529			return pos - buf;
1530		pos += ret;
1531	}
1532#endif /* CONFIG_SAE */
1533	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1534			  wpa_supplicant_state_txt(wpa_s->wpa_state));
1535	if (ret < 0 || ret >= end - pos)
1536		return pos - buf;
1537	pos += ret;
1538
1539	if (wpa_s->l2 &&
1540	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1541		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1542		if (ret < 0 || ret >= end - pos)
1543			return pos - buf;
1544		pos += ret;
1545	}
1546
1547#ifdef CONFIG_P2P
1548	if (wpa_s->global->p2p) {
1549		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1550				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1551		if (ret < 0 || ret >= end - pos)
1552			return pos - buf;
1553		pos += ret;
1554	}
1555#endif /* CONFIG_P2P */
1556
1557	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1558			  MAC2STR(wpa_s->own_addr));
1559	if (ret < 0 || ret >= end - pos)
1560		return pos - buf;
1561	pos += ret;
1562
1563#ifdef CONFIG_HS20
1564	if (wpa_s->current_bss &&
1565	    wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) &&
1566	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
1567	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
1568		ret = os_snprintf(pos, end - pos, "hs20=1\n");
1569		if (ret < 0 || ret >= end - pos)
1570			return pos - buf;
1571		pos += ret;
1572	}
1573
1574	if (wpa_s->current_ssid) {
1575		struct wpa_cred *cred;
1576		char *type;
1577
1578		for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1579			if (wpa_s->current_ssid->parent_cred != cred)
1580				continue;
1581			if (!cred->domain)
1582				continue;
1583
1584			ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
1585					  cred->domain);
1586			if (ret < 0 || ret >= end - pos)
1587				return pos - buf;
1588			pos += ret;
1589
1590			if (wpa_s->current_bss == NULL ||
1591			    wpa_s->current_bss->anqp == NULL)
1592				res = -1;
1593			else
1594				res = interworking_home_sp_cred(
1595					wpa_s, cred,
1596					wpa_s->current_bss->anqp->domain_name);
1597			if (res > 0)
1598				type = "home";
1599			else if (res == 0)
1600				type = "roaming";
1601			else
1602				type = "unknown";
1603
1604			ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
1605			if (ret < 0 || ret >= end - pos)
1606				return pos - buf;
1607			pos += ret;
1608
1609			break;
1610		}
1611	}
1612#endif /* CONFIG_HS20 */
1613
1614	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1615	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1616		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1617					  verbose);
1618		if (res >= 0)
1619			pos += res;
1620	}
1621
1622	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1623	if (res >= 0)
1624		pos += res;
1625
1626#ifdef ANDROID
1627	wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
1628		     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
1629		     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
1630		     wpa_s->wpa_state,
1631		     MAC2STR(wpa_s->bssid),
1632		     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
1633		     wpa_ssid_txt(wpa_s->current_ssid->ssid,
1634		     wpa_s->current_ssid->ssid_len) : "");
1635	if (wpa_s->wpa_state == WPA_COMPLETED) {
1636		struct wpa_ssid *ssid = wpa_s->current_ssid;
1637		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- connection to "
1638			MACSTR " completed %s [id=%d id_str=%s]",
1639			MAC2STR(wpa_s->bssid), "(auth)",
1640			ssid ? ssid->id : -1,
1641			ssid && ssid->id_str ? ssid->id_str : "");
1642	}
1643#endif /* ANDROID */
1644
1645	return pos - buf;
1646}
1647
1648
1649static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
1650					   char *cmd)
1651{
1652	char *pos;
1653	int id;
1654	struct wpa_ssid *ssid;
1655	u8 bssid[ETH_ALEN];
1656
1657	/* cmd: "<network id> <BSSID>" */
1658	pos = os_strchr(cmd, ' ');
1659	if (pos == NULL)
1660		return -1;
1661	*pos++ = '\0';
1662	id = atoi(cmd);
1663	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
1664	if (hwaddr_aton(pos, bssid)) {
1665		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
1666		return -1;
1667	}
1668
1669	ssid = wpa_config_get_network(wpa_s->conf, id);
1670	if (ssid == NULL) {
1671		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1672			   "to update", id);
1673		return -1;
1674	}
1675
1676	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
1677	ssid->bssid_set = !is_zero_ether_addr(bssid);
1678
1679	return 0;
1680}
1681
1682
1683static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1684					       char *cmd, char *buf,
1685					       size_t buflen)
1686{
1687	u8 bssid[ETH_ALEN];
1688	struct wpa_blacklist *e;
1689	char *pos, *end;
1690	int ret;
1691
1692	/* cmd: "BLACKLIST [<BSSID>]" */
1693	if (*cmd == '\0') {
1694		pos = buf;
1695		end = buf + buflen;
1696		e = wpa_s->blacklist;
1697		while (e) {
1698			ret = os_snprintf(pos, end - pos, MACSTR "\n",
1699					  MAC2STR(e->bssid));
1700			if (ret < 0 || ret >= end - pos)
1701				return pos - buf;
1702			pos += ret;
1703			e = e->next;
1704		}
1705		return pos - buf;
1706	}
1707
1708	cmd++;
1709	if (os_strncmp(cmd, "clear", 5) == 0) {
1710		wpa_blacklist_clear(wpa_s);
1711		os_memcpy(buf, "OK\n", 3);
1712		return 3;
1713	}
1714
1715	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1716	if (hwaddr_aton(cmd, bssid)) {
1717		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
1718		return -1;
1719	}
1720
1721	/*
1722	 * Add the BSSID twice, so its count will be 2, causing it to be
1723	 * skipped when processing scan results.
1724	 */
1725	ret = wpa_blacklist_add(wpa_s, bssid);
1726	if (ret != 0)
1727		return -1;
1728	ret = wpa_blacklist_add(wpa_s, bssid);
1729	if (ret != 0)
1730		return -1;
1731	os_memcpy(buf, "OK\n", 3);
1732	return 3;
1733}
1734
1735
1736extern int wpa_debug_level;
1737extern int wpa_debug_timestamp;
1738
1739static const char * debug_level_str(int level)
1740{
1741	switch (level) {
1742	case MSG_EXCESSIVE:
1743		return "EXCESSIVE";
1744	case MSG_MSGDUMP:
1745		return "MSGDUMP";
1746	case MSG_DEBUG:
1747		return "DEBUG";
1748	case MSG_INFO:
1749		return "INFO";
1750	case MSG_WARNING:
1751		return "WARNING";
1752	case MSG_ERROR:
1753		return "ERROR";
1754	default:
1755		return "?";
1756	}
1757}
1758
1759
1760static int str_to_debug_level(const char *s)
1761{
1762	if (os_strcasecmp(s, "EXCESSIVE") == 0)
1763		return MSG_EXCESSIVE;
1764	if (os_strcasecmp(s, "MSGDUMP") == 0)
1765		return MSG_MSGDUMP;
1766	if (os_strcasecmp(s, "DEBUG") == 0)
1767		return MSG_DEBUG;
1768	if (os_strcasecmp(s, "INFO") == 0)
1769		return MSG_INFO;
1770	if (os_strcasecmp(s, "WARNING") == 0)
1771		return MSG_WARNING;
1772	if (os_strcasecmp(s, "ERROR") == 0)
1773		return MSG_ERROR;
1774	return -1;
1775}
1776
1777
1778static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
1779					       char *cmd, char *buf,
1780					       size_t buflen)
1781{
1782	char *pos, *end, *stamp;
1783	int ret;
1784
1785	if (cmd == NULL) {
1786		return -1;
1787	}
1788
1789	/* cmd: "LOG_LEVEL [<level>]" */
1790	if (*cmd == '\0') {
1791		pos = buf;
1792		end = buf + buflen;
1793		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
1794				  "Timestamp: %d\n",
1795				  debug_level_str(wpa_debug_level),
1796				  wpa_debug_timestamp);
1797		if (ret < 0 || ret >= end - pos)
1798			ret = 0;
1799
1800		return ret;
1801	}
1802
1803	while (*cmd == ' ')
1804		cmd++;
1805
1806	stamp = os_strchr(cmd, ' ');
1807	if (stamp) {
1808		*stamp++ = '\0';
1809		while (*stamp == ' ') {
1810			stamp++;
1811		}
1812	}
1813
1814	if (cmd && os_strlen(cmd)) {
1815		int level = str_to_debug_level(cmd);
1816		if (level < 0)
1817			return -1;
1818		wpa_debug_level = level;
1819	}
1820
1821	if (stamp && os_strlen(stamp))
1822		wpa_debug_timestamp = atoi(stamp);
1823
1824	os_memcpy(buf, "OK\n", 3);
1825	return 3;
1826}
1827
1828
1829static int wpa_supplicant_ctrl_iface_list_networks(
1830	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1831{
1832	char *pos, *end;
1833	struct wpa_ssid *ssid;
1834	int ret;
1835
1836	pos = buf;
1837	end = buf + buflen;
1838	ret = os_snprintf(pos, end - pos,
1839			  "network id / ssid / bssid / flags\n");
1840	if (ret < 0 || ret >= end - pos)
1841		return pos - buf;
1842	pos += ret;
1843
1844	ssid = wpa_s->conf->ssid;
1845	while (ssid) {
1846		ret = os_snprintf(pos, end - pos, "%d\t%s",
1847				  ssid->id,
1848				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1849		if (ret < 0 || ret >= end - pos)
1850			return pos - buf;
1851		pos += ret;
1852		if (ssid->bssid_set) {
1853			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1854					  MAC2STR(ssid->bssid));
1855		} else {
1856			ret = os_snprintf(pos, end - pos, "\tany");
1857		}
1858		if (ret < 0 || ret >= end - pos)
1859			return pos - buf;
1860		pos += ret;
1861		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
1862				  ssid == wpa_s->current_ssid ?
1863				  "[CURRENT]" : "",
1864				  ssid->disabled ? "[DISABLED]" : "",
1865				  ssid->disabled_until.sec ?
1866				  "[TEMP-DISABLED]" : "",
1867				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1868				  "");
1869		if (ret < 0 || ret >= end - pos)
1870			return pos - buf;
1871		pos += ret;
1872		ret = os_snprintf(pos, end - pos, "\n");
1873		if (ret < 0 || ret >= end - pos)
1874			return pos - buf;
1875		pos += ret;
1876
1877		ssid = ssid->next;
1878	}
1879
1880	return pos - buf;
1881}
1882
1883
1884static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1885{
1886	int ret;
1887	ret = os_snprintf(pos, end - pos, "-");
1888	if (ret < 0 || ret >= end - pos)
1889		return pos;
1890	pos += ret;
1891	ret = wpa_write_ciphers(pos, end, cipher, "+");
1892	if (ret < 0)
1893		return pos;
1894	pos += ret;
1895	return pos;
1896}
1897
1898
1899static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1900				    const u8 *ie, size_t ie_len)
1901{
1902	struct wpa_ie_data data;
1903	int first, ret;
1904
1905	ret = os_snprintf(pos, end - pos, "[%s-", proto);
1906	if (ret < 0 || ret >= end - pos)
1907		return pos;
1908	pos += ret;
1909
1910	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1911		ret = os_snprintf(pos, end - pos, "?]");
1912		if (ret < 0 || ret >= end - pos)
1913			return pos;
1914		pos += ret;
1915		return pos;
1916	}
1917
1918	first = 1;
1919	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1920		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
1921		if (ret < 0 || ret >= end - pos)
1922			return pos;
1923		pos += ret;
1924		first = 0;
1925	}
1926	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
1927		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1928		if (ret < 0 || ret >= end - pos)
1929			return pos;
1930		pos += ret;
1931		first = 0;
1932	}
1933	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1934		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1935		if (ret < 0 || ret >= end - pos)
1936			return pos;
1937		pos += ret;
1938		first = 0;
1939	}
1940#ifdef CONFIG_IEEE80211R
1941	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1942		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1943				  first ? "" : "+");
1944		if (ret < 0 || ret >= end - pos)
1945			return pos;
1946		pos += ret;
1947		first = 0;
1948	}
1949	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1950		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1951				  first ? "" : "+");
1952		if (ret < 0 || ret >= end - pos)
1953			return pos;
1954		pos += ret;
1955		first = 0;
1956	}
1957#endif /* CONFIG_IEEE80211R */
1958#ifdef CONFIG_IEEE80211W
1959	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1960		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1961				  first ? "" : "+");
1962		if (ret < 0 || ret >= end - pos)
1963			return pos;
1964		pos += ret;
1965		first = 0;
1966	}
1967	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1968		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1969				  first ? "" : "+");
1970		if (ret < 0 || ret >= end - pos)
1971			return pos;
1972		pos += ret;
1973		first = 0;
1974	}
1975#endif /* CONFIG_IEEE80211W */
1976
1977	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1978
1979	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1980		ret = os_snprintf(pos, end - pos, "-preauth");
1981		if (ret < 0 || ret >= end - pos)
1982			return pos;
1983		pos += ret;
1984	}
1985
1986	ret = os_snprintf(pos, end - pos, "]");
1987	if (ret < 0 || ret >= end - pos)
1988		return pos;
1989	pos += ret;
1990
1991	return pos;
1992}
1993
1994
1995#ifdef CONFIG_WPS
1996static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1997					    char *pos, char *end,
1998					    struct wpabuf *wps_ie)
1999{
2000	int ret;
2001	const char *txt;
2002
2003	if (wps_ie == NULL)
2004		return pos;
2005	if (wps_is_selected_pbc_registrar(wps_ie))
2006		txt = "[WPS-PBC]";
2007#ifdef CONFIG_WPS2
2008	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2009		txt = "[WPS-AUTH]";
2010#endif /* CONFIG_WPS2 */
2011	else if (wps_is_selected_pin_registrar(wps_ie))
2012		txt = "[WPS-PIN]";
2013	else
2014		txt = "[WPS]";
2015
2016	ret = os_snprintf(pos, end - pos, "%s", txt);
2017	if (ret >= 0 && ret < end - pos)
2018		pos += ret;
2019	wpabuf_free(wps_ie);
2020	return pos;
2021}
2022#endif /* CONFIG_WPS */
2023
2024
2025static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2026					char *pos, char *end,
2027					const struct wpa_bss *bss)
2028{
2029#ifdef CONFIG_WPS
2030	struct wpabuf *wps_ie;
2031	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2032	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2033#else /* CONFIG_WPS */
2034	return pos;
2035#endif /* CONFIG_WPS */
2036}
2037
2038
2039/* Format one result on one text line into a buffer. */
2040static int wpa_supplicant_ctrl_iface_scan_result(
2041	struct wpa_supplicant *wpa_s,
2042	const struct wpa_bss *bss, char *buf, size_t buflen)
2043{
2044	char *pos, *end;
2045	int ret;
2046	const u8 *ie, *ie2, *p2p;
2047
2048	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2049	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2050	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2051	    0)
2052		return 0; /* Do not show P2P listen discovery results here */
2053
2054	pos = buf;
2055	end = buf + buflen;
2056
2057	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2058			  MAC2STR(bss->bssid), bss->freq, bss->level);
2059	if (ret < 0 || ret >= end - pos)
2060		return -1;
2061	pos += ret;
2062	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2063	if (ie)
2064		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2065	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2066	if (ie2)
2067		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2068	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2069	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2070		ret = os_snprintf(pos, end - pos, "[WEP]");
2071		if (ret < 0 || ret >= end - pos)
2072			return -1;
2073		pos += ret;
2074	}
2075	if (bss->caps & IEEE80211_CAP_IBSS) {
2076		ret = os_snprintf(pos, end - pos, "[IBSS]");
2077		if (ret < 0 || ret >= end - pos)
2078			return -1;
2079		pos += ret;
2080	}
2081	if (bss->caps & IEEE80211_CAP_ESS) {
2082		ret = os_snprintf(pos, end - pos, "[ESS]");
2083		if (ret < 0 || ret >= end - pos)
2084			return -1;
2085		pos += ret;
2086	}
2087	if (p2p) {
2088		ret = os_snprintf(pos, end - pos, "[P2P]");
2089		if (ret < 0 || ret >= end - pos)
2090			return -1;
2091		pos += ret;
2092	}
2093#ifdef CONFIG_HS20
2094	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2095		ret = os_snprintf(pos, end - pos, "[HS20]");
2096		if (ret < 0 || ret >= end - pos)
2097			return -1;
2098		pos += ret;
2099	}
2100#endif /* CONFIG_HS20 */
2101
2102	ret = os_snprintf(pos, end - pos, "\t%s",
2103			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
2104	if (ret < 0 || ret >= end - pos)
2105		return -1;
2106	pos += ret;
2107
2108	ret = os_snprintf(pos, end - pos, "\n");
2109	if (ret < 0 || ret >= end - pos)
2110		return -1;
2111	pos += ret;
2112
2113	return pos - buf;
2114}
2115
2116
2117static int wpa_supplicant_ctrl_iface_scan_results(
2118	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2119{
2120	char *pos, *end;
2121	struct wpa_bss *bss;
2122	int ret;
2123
2124	pos = buf;
2125	end = buf + buflen;
2126	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2127			  "flags / ssid\n");
2128	if (ret < 0 || ret >= end - pos)
2129		return pos - buf;
2130	pos += ret;
2131
2132	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2133		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2134							    end - pos);
2135		if (ret < 0 || ret >= end - pos)
2136			return pos - buf;
2137		pos += ret;
2138	}
2139
2140	return pos - buf;
2141}
2142
2143
2144static int wpa_supplicant_ctrl_iface_select_network(
2145	struct wpa_supplicant *wpa_s, char *cmd)
2146{
2147	int id;
2148	struct wpa_ssid *ssid;
2149
2150	/* cmd: "<network id>" or "any" */
2151	if (os_strcmp(cmd, "any") == 0) {
2152		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
2153		ssid = NULL;
2154	} else {
2155		id = atoi(cmd);
2156		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
2157
2158		ssid = wpa_config_get_network(wpa_s->conf, id);
2159		if (ssid == NULL) {
2160			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2161				   "network id=%d", id);
2162			return -1;
2163		}
2164		if (ssid->disabled == 2) {
2165			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2166				   "SELECT_NETWORK with persistent P2P group");
2167			return -1;
2168		}
2169	}
2170
2171	wpa_supplicant_select_network(wpa_s, ssid);
2172
2173	return 0;
2174}
2175
2176
2177static int wpa_supplicant_ctrl_iface_enable_network(
2178	struct wpa_supplicant *wpa_s, char *cmd)
2179{
2180	int id;
2181	struct wpa_ssid *ssid;
2182
2183	/* cmd: "<network id>" or "all" */
2184	if (os_strcmp(cmd, "all") == 0) {
2185		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
2186		ssid = NULL;
2187	} else {
2188		id = atoi(cmd);
2189		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
2190
2191		ssid = wpa_config_get_network(wpa_s->conf, id);
2192		if (ssid == NULL) {
2193			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2194				   "network id=%d", id);
2195			return -1;
2196		}
2197		if (ssid->disabled == 2) {
2198			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2199				   "ENABLE_NETWORK with persistent P2P group");
2200			return -1;
2201		}
2202
2203		if (os_strstr(cmd, " no-connect")) {
2204			ssid->disabled = 0;
2205			return 0;
2206		}
2207	}
2208	wpa_supplicant_enable_network(wpa_s, ssid);
2209
2210	return 0;
2211}
2212
2213
2214static int wpa_supplicant_ctrl_iface_disable_network(
2215	struct wpa_supplicant *wpa_s, char *cmd)
2216{
2217	int id;
2218	struct wpa_ssid *ssid;
2219
2220	/* cmd: "<network id>" or "all" */
2221	if (os_strcmp(cmd, "all") == 0) {
2222		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
2223		ssid = NULL;
2224	} else {
2225		id = atoi(cmd);
2226		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
2227
2228		ssid = wpa_config_get_network(wpa_s->conf, id);
2229		if (ssid == NULL) {
2230			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2231				   "network id=%d", id);
2232			return -1;
2233		}
2234		if (ssid->disabled == 2) {
2235			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2236				   "DISABLE_NETWORK with persistent P2P "
2237				   "group");
2238			return -1;
2239		}
2240	}
2241	wpa_supplicant_disable_network(wpa_s, ssid);
2242
2243	return 0;
2244}
2245
2246
2247static int wpa_supplicant_ctrl_iface_add_network(
2248	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2249{
2250	struct wpa_ssid *ssid;
2251	int ret;
2252
2253	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
2254
2255	ssid = wpa_config_add_network(wpa_s->conf);
2256	if (ssid == NULL)
2257		return -1;
2258
2259	wpas_notify_network_added(wpa_s, ssid);
2260
2261	ssid->disabled = 1;
2262	wpa_config_set_network_defaults(ssid);
2263
2264	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
2265	if (ret < 0 || (size_t) ret >= buflen)
2266		return -1;
2267	return ret;
2268}
2269
2270
2271static int wpa_supplicant_ctrl_iface_remove_network(
2272	struct wpa_supplicant *wpa_s, char *cmd)
2273{
2274	int id;
2275	struct wpa_ssid *ssid;
2276	int was_disabled;
2277
2278	/* cmd: "<network id>" or "all" */
2279	if (os_strcmp(cmd, "all") == 0) {
2280		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
2281		if (wpa_s->sched_scanning)
2282			wpa_supplicant_cancel_sched_scan(wpa_s);
2283
2284		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2285		if (wpa_s->current_ssid) {
2286#ifdef CONFIG_SME
2287			wpa_s->sme.prev_bssid_set = 0;
2288#endif /* CONFIG_SME */
2289			wpa_sm_set_config(wpa_s->wpa, NULL);
2290			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2291			wpa_supplicant_deauthenticate(
2292				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2293		}
2294		ssid = wpa_s->conf->ssid;
2295		while (ssid) {
2296			struct wpa_ssid *remove_ssid = ssid;
2297			id = ssid->id;
2298			ssid = ssid->next;
2299			wpas_notify_network_removed(wpa_s, remove_ssid);
2300			wpa_config_remove_network(wpa_s->conf, id);
2301		}
2302		return 0;
2303	}
2304
2305	id = atoi(cmd);
2306	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
2307
2308	ssid = wpa_config_get_network(wpa_s->conf, id);
2309	if (ssid)
2310		wpas_notify_network_removed(wpa_s, ssid);
2311	if (ssid == NULL) {
2312		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2313			   "id=%d", id);
2314		return -1;
2315	}
2316
2317	if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2318#ifdef CONFIG_SME
2319		wpa_s->sme.prev_bssid_set = 0;
2320#endif /* CONFIG_SME */
2321		/*
2322		 * Invalidate the EAP session cache if the current or
2323		 * previously used network is removed.
2324		 */
2325		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2326	}
2327
2328	if (ssid == wpa_s->current_ssid) {
2329		wpa_sm_set_config(wpa_s->wpa, NULL);
2330		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2331
2332		wpa_supplicant_deauthenticate(wpa_s,
2333					      WLAN_REASON_DEAUTH_LEAVING);
2334	}
2335
2336	was_disabled = ssid->disabled;
2337
2338	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2339		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
2340			   "network id=%d", id);
2341		return -1;
2342	}
2343
2344	if (!was_disabled && wpa_s->sched_scanning) {
2345		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2346			   "network from filters");
2347		wpa_supplicant_cancel_sched_scan(wpa_s);
2348		wpa_supplicant_req_scan(wpa_s, 0, 0);
2349	}
2350
2351	return 0;
2352}
2353
2354
2355static int wpa_supplicant_ctrl_iface_set_network(
2356	struct wpa_supplicant *wpa_s, char *cmd)
2357{
2358	int id;
2359	struct wpa_ssid *ssid;
2360	char *name, *value;
2361
2362	/* cmd: "<network id> <variable name> <value>" */
2363	name = os_strchr(cmd, ' ');
2364	if (name == NULL)
2365		return -1;
2366	*name++ = '\0';
2367
2368	value = os_strchr(name, ' ');
2369	if (value == NULL)
2370		return -1;
2371	*value++ = '\0';
2372
2373	id = atoi(cmd);
2374	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
2375		   id, name);
2376	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2377			      (u8 *) value, os_strlen(value));
2378
2379	ssid = wpa_config_get_network(wpa_s->conf, id);
2380	if (ssid == NULL) {
2381		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2382			   "id=%d", id);
2383		return -1;
2384	}
2385
2386	if (wpa_config_set(ssid, name, value, 0) < 0) {
2387		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
2388			   "variable '%s'", name);
2389		return -1;
2390	}
2391
2392	if (os_strcmp(name, "bssid") != 0 &&
2393	    os_strcmp(name, "priority") != 0)
2394		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2395
2396	if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
2397		/*
2398		 * Invalidate the EAP session cache if anything in the current
2399		 * or previously used configuration changes.
2400		 */
2401		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2402	}
2403
2404	if ((os_strcmp(name, "psk") == 0 &&
2405	     value[0] == '"' && ssid->ssid_len) ||
2406	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
2407		wpa_config_update_psk(ssid);
2408	else if (os_strcmp(name, "priority") == 0)
2409		wpa_config_update_prio_list(wpa_s->conf);
2410
2411	return 0;
2412}
2413
2414
2415static int wpa_supplicant_ctrl_iface_get_network(
2416	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2417{
2418	int id;
2419	size_t res;
2420	struct wpa_ssid *ssid;
2421	char *name, *value;
2422
2423	/* cmd: "<network id> <variable name>" */
2424	name = os_strchr(cmd, ' ');
2425	if (name == NULL || buflen == 0)
2426		return -1;
2427	*name++ = '\0';
2428
2429	id = atoi(cmd);
2430	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
2431		   id, name);
2432
2433	ssid = wpa_config_get_network(wpa_s->conf, id);
2434	if (ssid == NULL) {
2435		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2436			   "id=%d", id);
2437		return -1;
2438	}
2439
2440	value = wpa_config_get_no_key(ssid, name);
2441	if (value == NULL) {
2442		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
2443			   "variable '%s'", name);
2444		return -1;
2445	}
2446
2447	res = os_strlcpy(buf, value, buflen);
2448	if (res >= buflen) {
2449		os_free(value);
2450		return -1;
2451	}
2452
2453	os_free(value);
2454
2455	return res;
2456}
2457
2458
2459static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
2460						char *buf, size_t buflen)
2461{
2462	char *pos, *end;
2463	struct wpa_cred *cred;
2464	int ret;
2465
2466	pos = buf;
2467	end = buf + buflen;
2468	ret = os_snprintf(pos, end - pos,
2469			  "cred id / realm / username / domain / imsi\n");
2470	if (ret < 0 || ret >= end - pos)
2471		return pos - buf;
2472	pos += ret;
2473
2474	cred = wpa_s->conf->cred;
2475	while (cred) {
2476		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
2477				  cred->id, cred->realm ? cred->realm : "",
2478				  cred->username ? cred->username : "",
2479				  cred->domain ? cred->domain : "",
2480				  cred->imsi ? cred->imsi : "");
2481		if (ret < 0 || ret >= end - pos)
2482			return pos - buf;
2483		pos += ret;
2484
2485		cred = cred->next;
2486	}
2487
2488	return pos - buf;
2489}
2490
2491
2492static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
2493					      char *buf, size_t buflen)
2494{
2495	struct wpa_cred *cred;
2496	int ret;
2497
2498	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
2499
2500	cred = wpa_config_add_cred(wpa_s->conf);
2501	if (cred == NULL)
2502		return -1;
2503
2504	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
2505	if (ret < 0 || (size_t) ret >= buflen)
2506		return -1;
2507	return ret;
2508}
2509
2510
2511static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
2512				 struct wpa_cred *cred)
2513{
2514	struct wpa_ssid *ssid;
2515	char str[20];
2516
2517	if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) {
2518		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
2519		return -1;
2520	}
2521
2522	/* Remove any network entry created based on the removed credential */
2523	ssid = wpa_s->conf->ssid;
2524	while (ssid) {
2525		if (ssid->parent_cred == cred) {
2526			wpa_printf(MSG_DEBUG, "Remove network id %d since it "
2527				   "used the removed credential", ssid->id);
2528			os_snprintf(str, sizeof(str), "%d", ssid->id);
2529			ssid = ssid->next;
2530			wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
2531		} else
2532			ssid = ssid->next;
2533	}
2534
2535	return 0;
2536}
2537
2538
2539static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
2540						 char *cmd)
2541{
2542	int id;
2543	struct wpa_cred *cred, *prev;
2544
2545	/* cmd: "<cred id>", "all", or "sp_fqdn=<FQDN>" */
2546	if (os_strcmp(cmd, "all") == 0) {
2547		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
2548		cred = wpa_s->conf->cred;
2549		while (cred) {
2550			prev = cred;
2551			cred = cred->next;
2552			wpas_ctrl_remove_cred(wpa_s, prev);
2553		}
2554		return 0;
2555	}
2556
2557	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
2558		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
2559			   cmd + 8);
2560		cred = wpa_s->conf->cred;
2561		while (cred) {
2562			prev = cred;
2563			cred = cred->next;
2564			if (prev->domain &&
2565			    os_strcmp(prev->domain, cmd + 8) == 0)
2566				wpas_ctrl_remove_cred(wpa_s, prev);
2567		}
2568		return 0;
2569	}
2570
2571	id = atoi(cmd);
2572	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
2573
2574	cred = wpa_config_get_cred(wpa_s->conf, id);
2575	return wpas_ctrl_remove_cred(wpa_s, cred);
2576}
2577
2578
2579static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
2580					      char *cmd)
2581{
2582	int id;
2583	struct wpa_cred *cred;
2584	char *name, *value;
2585
2586	/* cmd: "<cred id> <variable name> <value>" */
2587	name = os_strchr(cmd, ' ');
2588	if (name == NULL)
2589		return -1;
2590	*name++ = '\0';
2591
2592	value = os_strchr(name, ' ');
2593	if (value == NULL)
2594		return -1;
2595	*value++ = '\0';
2596
2597	id = atoi(cmd);
2598	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
2599		   id, name);
2600	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2601			      (u8 *) value, os_strlen(value));
2602
2603	cred = wpa_config_get_cred(wpa_s->conf, id);
2604	if (cred == NULL) {
2605		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2606			   id);
2607		return -1;
2608	}
2609
2610	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
2611		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
2612			   "variable '%s'", name);
2613		return -1;
2614	}
2615
2616	return 0;
2617}
2618
2619
2620#ifndef CONFIG_NO_CONFIG_WRITE
2621static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
2622{
2623	int ret;
2624
2625	if (!wpa_s->conf->update_config) {
2626		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
2627			   "to update configuration (update_config=0)");
2628		return -1;
2629	}
2630
2631	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2632	if (ret) {
2633		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
2634			   "update configuration");
2635	} else {
2636		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
2637			   " updated");
2638	}
2639
2640	return ret;
2641}
2642#endif /* CONFIG_NO_CONFIG_WRITE */
2643
2644
2645static int ctrl_iface_get_capability_pairwise(int res, char *strict,
2646					      struct wpa_driver_capa *capa,
2647					      char *buf, size_t buflen)
2648{
2649	int ret, first = 1;
2650	char *pos, *end;
2651	size_t len;
2652
2653	pos = buf;
2654	end = pos + buflen;
2655
2656	if (res < 0) {
2657		if (strict)
2658			return 0;
2659		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
2660		if (len >= buflen)
2661			return -1;
2662		return len;
2663	}
2664
2665	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2666		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2667		if (ret < 0 || ret >= end - pos)
2668			return pos - buf;
2669		pos += ret;
2670		first = 0;
2671	}
2672
2673	if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2674		ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
2675		if (ret < 0 || ret >= end - pos)
2676			return pos - buf;
2677		pos += ret;
2678		first = 0;
2679	}
2680
2681	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2682		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2683		if (ret < 0 || ret >= end - pos)
2684			return pos - buf;
2685		pos += ret;
2686		first = 0;
2687	}
2688
2689	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2690		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
2691		if (ret < 0 || ret >= end - pos)
2692			return pos - buf;
2693		pos += ret;
2694		first = 0;
2695	}
2696
2697	return pos - buf;
2698}
2699
2700
2701static int ctrl_iface_get_capability_group(int res, char *strict,
2702					   struct wpa_driver_capa *capa,
2703					   char *buf, size_t buflen)
2704{
2705	int ret, first = 1;
2706	char *pos, *end;
2707	size_t len;
2708
2709	pos = buf;
2710	end = pos + buflen;
2711
2712	if (res < 0) {
2713		if (strict)
2714			return 0;
2715		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
2716		if (len >= buflen)
2717			return -1;
2718		return len;
2719	}
2720
2721	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2722		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2723		if (ret < 0 || ret >= end - pos)
2724			return pos - buf;
2725		pos += ret;
2726		first = 0;
2727	}
2728
2729	if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2730		ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
2731		if (ret < 0 || ret >= end - pos)
2732			return pos - buf;
2733		pos += ret;
2734		first = 0;
2735	}
2736
2737	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2738		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2739		if (ret < 0 || ret >= end - pos)
2740			return pos - buf;
2741		pos += ret;
2742		first = 0;
2743	}
2744
2745	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2746		ret = os_snprintf(pos, end - pos, "%sWEP104",
2747				  first ? "" : " ");
2748		if (ret < 0 || ret >= end - pos)
2749			return pos - buf;
2750		pos += ret;
2751		first = 0;
2752	}
2753
2754	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2755		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
2756		if (ret < 0 || ret >= end - pos)
2757			return pos - buf;
2758		pos += ret;
2759		first = 0;
2760	}
2761
2762	return pos - buf;
2763}
2764
2765
2766static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
2767					      struct wpa_driver_capa *capa,
2768					      char *buf, size_t buflen)
2769{
2770	int ret;
2771	char *pos, *end;
2772	size_t len;
2773
2774	pos = buf;
2775	end = pos + buflen;
2776
2777	if (res < 0) {
2778		if (strict)
2779			return 0;
2780		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
2781				 "NONE", buflen);
2782		if (len >= buflen)
2783			return -1;
2784		return len;
2785	}
2786
2787	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
2788	if (ret < 0 || ret >= end - pos)
2789		return pos - buf;
2790	pos += ret;
2791
2792	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2793			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2794		ret = os_snprintf(pos, end - pos, " WPA-EAP");
2795		if (ret < 0 || ret >= end - pos)
2796			return pos - buf;
2797		pos += ret;
2798	}
2799
2800	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2801			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2802		ret = os_snprintf(pos, end - pos, " WPA-PSK");
2803		if (ret < 0 || ret >= end - pos)
2804			return pos - buf;
2805		pos += ret;
2806	}
2807
2808	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2809		ret = os_snprintf(pos, end - pos, " WPA-NONE");
2810		if (ret < 0 || ret >= end - pos)
2811			return pos - buf;
2812		pos += ret;
2813	}
2814
2815	return pos - buf;
2816}
2817
2818
2819static int ctrl_iface_get_capability_proto(int res, char *strict,
2820					   struct wpa_driver_capa *capa,
2821					   char *buf, size_t buflen)
2822{
2823	int ret, first = 1;
2824	char *pos, *end;
2825	size_t len;
2826
2827	pos = buf;
2828	end = pos + buflen;
2829
2830	if (res < 0) {
2831		if (strict)
2832			return 0;
2833		len = os_strlcpy(buf, "RSN WPA", buflen);
2834		if (len >= buflen)
2835			return -1;
2836		return len;
2837	}
2838
2839	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2840			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2841		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
2842		if (ret < 0 || ret >= end - pos)
2843			return pos - buf;
2844		pos += ret;
2845		first = 0;
2846	}
2847
2848	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2849			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2850		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
2851		if (ret < 0 || ret >= end - pos)
2852			return pos - buf;
2853		pos += ret;
2854		first = 0;
2855	}
2856
2857	return pos - buf;
2858}
2859
2860
2861static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
2862					      struct wpa_driver_capa *capa,
2863					      char *buf, size_t buflen)
2864{
2865	int ret, first = 1;
2866	char *pos, *end;
2867	size_t len;
2868
2869	pos = buf;
2870	end = pos + buflen;
2871
2872	if (res < 0) {
2873		if (strict)
2874			return 0;
2875		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
2876		if (len >= buflen)
2877			return -1;
2878		return len;
2879	}
2880
2881	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
2882		ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
2883		if (ret < 0 || ret >= end - pos)
2884			return pos - buf;
2885		pos += ret;
2886		first = 0;
2887	}
2888
2889	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
2890		ret = os_snprintf(pos, end - pos, "%sSHARED",
2891				  first ? "" : " ");
2892		if (ret < 0 || ret >= end - pos)
2893			return pos - buf;
2894		pos += ret;
2895		first = 0;
2896	}
2897
2898	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
2899		ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
2900		if (ret < 0 || ret >= end - pos)
2901			return pos - buf;
2902		pos += ret;
2903		first = 0;
2904	}
2905
2906	return pos - buf;
2907}
2908
2909
2910static int ctrl_iface_get_capability_modes(int res, char *strict,
2911					   struct wpa_driver_capa *capa,
2912					   char *buf, size_t buflen)
2913{
2914	int ret, first = 1;
2915	char *pos, *end;
2916	size_t len;
2917
2918	pos = buf;
2919	end = pos + buflen;
2920
2921	if (res < 0) {
2922		if (strict)
2923			return 0;
2924		len = os_strlcpy(buf, "IBSS AP", buflen);
2925		if (len >= buflen)
2926			return -1;
2927		return len;
2928	}
2929
2930	if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
2931		ret = os_snprintf(pos, end - pos, "%sIBSS", first ? "" : " ");
2932		if (ret < 0 || ret >= end - pos)
2933			return pos - buf;
2934		pos += ret;
2935		first = 0;
2936	}
2937
2938	if (capa->flags & WPA_DRIVER_FLAGS_AP) {
2939		ret = os_snprintf(pos, end - pos, "%sAP", first ? "" : " ");
2940		if (ret < 0 || ret >= end - pos)
2941			return pos - buf;
2942		pos += ret;
2943		first = 0;
2944	}
2945
2946	return pos - buf;
2947}
2948
2949
2950static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
2951					      char *buf, size_t buflen)
2952{
2953	struct hostapd_channel_data *chnl;
2954	int ret, i, j;
2955	char *pos, *end, *hmode;
2956
2957	pos = buf;
2958	end = pos + buflen;
2959
2960	for (j = 0; j < wpa_s->hw.num_modes; j++) {
2961		switch (wpa_s->hw.modes[j].mode) {
2962		case HOSTAPD_MODE_IEEE80211B:
2963			hmode = "B";
2964			break;
2965		case HOSTAPD_MODE_IEEE80211G:
2966			hmode = "G";
2967			break;
2968		case HOSTAPD_MODE_IEEE80211A:
2969			hmode = "A";
2970			break;
2971		case HOSTAPD_MODE_IEEE80211AD:
2972			hmode = "AD";
2973			break;
2974		default:
2975			continue;
2976		}
2977		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
2978		if (ret < 0 || ret >= end - pos)
2979			return pos - buf;
2980		pos += ret;
2981		chnl = wpa_s->hw.modes[j].channels;
2982		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
2983			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
2984				continue;
2985			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
2986			if (ret < 0 || ret >= end - pos)
2987				return pos - buf;
2988			pos += ret;
2989		}
2990		ret = os_snprintf(pos, end - pos, "\n");
2991		if (ret < 0 || ret >= end - pos)
2992			return pos - buf;
2993		pos += ret;
2994	}
2995
2996	return pos - buf;
2997}
2998
2999
3000static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
3001					  char *buf, size_t buflen)
3002{
3003	struct hostapd_channel_data *chnl;
3004	int ret, i, j;
3005	char *pos, *end, *hmode;
3006
3007	pos = buf;
3008	end = pos + buflen;
3009
3010	for (j = 0; j < wpa_s->hw.num_modes; j++) {
3011		switch (wpa_s->hw.modes[j].mode) {
3012		case HOSTAPD_MODE_IEEE80211B:
3013			hmode = "B";
3014			break;
3015		case HOSTAPD_MODE_IEEE80211G:
3016			hmode = "G";
3017			break;
3018		case HOSTAPD_MODE_IEEE80211A:
3019			hmode = "A";
3020			break;
3021		case HOSTAPD_MODE_IEEE80211AD:
3022			hmode = "AD";
3023			break;
3024		default:
3025			continue;
3026		}
3027		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
3028				  hmode);
3029		if (ret < 0 || ret >= end - pos)
3030			return pos - buf;
3031		pos += ret;
3032		chnl = wpa_s->hw.modes[j].channels;
3033		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3034			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3035				continue;
3036			ret = os_snprintf(pos, end - pos, " %d = %d MHz%s\n",
3037					  chnl[i].chan, chnl[i].freq,
3038					  chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ?
3039					  " (NO_IBSS)" : "");
3040			if (ret < 0 || ret >= end - pos)
3041				return pos - buf;
3042			pos += ret;
3043		}
3044		ret = os_snprintf(pos, end - pos, "\n");
3045		if (ret < 0 || ret >= end - pos)
3046			return pos - buf;
3047		pos += ret;
3048	}
3049
3050	return pos - buf;
3051}
3052
3053
3054static int wpa_supplicant_ctrl_iface_get_capability(
3055	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
3056	size_t buflen)
3057{
3058	struct wpa_driver_capa capa;
3059	int res;
3060	char *strict;
3061	char field[30];
3062	size_t len;
3063
3064	/* Determine whether or not strict checking was requested */
3065	len = os_strlcpy(field, _field, sizeof(field));
3066	if (len >= sizeof(field))
3067		return -1;
3068	strict = os_strchr(field, ' ');
3069	if (strict != NULL) {
3070		*strict++ = '\0';
3071		if (os_strcmp(strict, "strict") != 0)
3072			return -1;
3073	}
3074
3075	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
3076		field, strict ? strict : "");
3077
3078	if (os_strcmp(field, "eap") == 0) {
3079		return eap_get_names(buf, buflen);
3080	}
3081
3082	res = wpa_drv_get_capa(wpa_s, &capa);
3083
3084	if (os_strcmp(field, "pairwise") == 0)
3085		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
3086							  buf, buflen);
3087
3088	if (os_strcmp(field, "group") == 0)
3089		return ctrl_iface_get_capability_group(res, strict, &capa,
3090						       buf, buflen);
3091
3092	if (os_strcmp(field, "key_mgmt") == 0)
3093		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
3094							  buf, buflen);
3095
3096	if (os_strcmp(field, "proto") == 0)
3097		return ctrl_iface_get_capability_proto(res, strict, &capa,
3098						       buf, buflen);
3099
3100	if (os_strcmp(field, "auth_alg") == 0)
3101		return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
3102							  buf, buflen);
3103
3104	if (os_strcmp(field, "modes") == 0)
3105		return ctrl_iface_get_capability_modes(res, strict, &capa,
3106						       buf, buflen);
3107
3108	if (os_strcmp(field, "channels") == 0)
3109		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
3110
3111	if (os_strcmp(field, "freq") == 0)
3112		return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
3113
3114	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3115		   field);
3116
3117	return -1;
3118}
3119
3120
3121#ifdef CONFIG_INTERWORKING
3122static char * anqp_add_hex(char *pos, char *end, const char *title,
3123			   struct wpabuf *data)
3124{
3125	char *start = pos;
3126	size_t i;
3127	int ret;
3128	const u8 *d;
3129
3130	if (data == NULL)
3131		return start;
3132
3133	ret = os_snprintf(pos, end - pos, "%s=", title);
3134	if (ret < 0 || ret >= end - pos)
3135		return start;
3136	pos += ret;
3137
3138	d = wpabuf_head_u8(data);
3139	for (i = 0; i < wpabuf_len(data); i++) {
3140		ret = os_snprintf(pos, end - pos, "%02x", *d++);
3141		if (ret < 0 || ret >= end - pos)
3142			return start;
3143		pos += ret;
3144	}
3145
3146	ret = os_snprintf(pos, end - pos, "\n");
3147	if (ret < 0 || ret >= end - pos)
3148		return start;
3149	pos += ret;
3150
3151	return pos;
3152}
3153#endif /* CONFIG_INTERWORKING */
3154
3155
3156static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
3157			  unsigned long mask, char *buf, size_t buflen)
3158{
3159	size_t i;
3160	int ret;
3161	char *pos, *end;
3162	const u8 *ie, *ie2;
3163
3164	pos = buf;
3165	end = buf + buflen;
3166
3167	if (mask & WPA_BSS_MASK_ID) {
3168		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
3169		if (ret < 0 || ret >= end - pos)
3170			return 0;
3171		pos += ret;
3172	}
3173
3174	if (mask & WPA_BSS_MASK_BSSID) {
3175		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
3176				  MAC2STR(bss->bssid));
3177		if (ret < 0 || ret >= end - pos)
3178			return 0;
3179		pos += ret;
3180	}
3181
3182	if (mask & WPA_BSS_MASK_FREQ) {
3183		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
3184		if (ret < 0 || ret >= end - pos)
3185			return 0;
3186		pos += ret;
3187	}
3188
3189	if (mask & WPA_BSS_MASK_BEACON_INT) {
3190		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
3191				  bss->beacon_int);
3192		if (ret < 0 || ret >= end - pos)
3193			return 0;
3194		pos += ret;
3195	}
3196
3197	if (mask & WPA_BSS_MASK_CAPABILITIES) {
3198		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
3199				  bss->caps);
3200		if (ret < 0 || ret >= end - pos)
3201			return 0;
3202		pos += ret;
3203	}
3204
3205	if (mask & WPA_BSS_MASK_QUAL) {
3206		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
3207		if (ret < 0 || ret >= end - pos)
3208			return 0;
3209		pos += ret;
3210	}
3211
3212	if (mask & WPA_BSS_MASK_NOISE) {
3213		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
3214		if (ret < 0 || ret >= end - pos)
3215			return 0;
3216		pos += ret;
3217	}
3218
3219	if (mask & WPA_BSS_MASK_LEVEL) {
3220		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
3221		if (ret < 0 || ret >= end - pos)
3222			return 0;
3223		pos += ret;
3224	}
3225
3226	if (mask & WPA_BSS_MASK_TSF) {
3227		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
3228				  (unsigned long long) bss->tsf);
3229		if (ret < 0 || ret >= end - pos)
3230			return 0;
3231		pos += ret;
3232	}
3233
3234	if (mask & WPA_BSS_MASK_AGE) {
3235		struct os_time now;
3236
3237		os_get_time(&now);
3238		ret = os_snprintf(pos, end - pos, "age=%d\n",
3239				  (int) (now.sec - bss->last_update.sec));
3240		if (ret < 0 || ret >= end - pos)
3241			return 0;
3242		pos += ret;
3243	}
3244
3245	if (mask & WPA_BSS_MASK_IE) {
3246		ret = os_snprintf(pos, end - pos, "ie=");
3247		if (ret < 0 || ret >= end - pos)
3248			return 0;
3249		pos += ret;
3250
3251		ie = (const u8 *) (bss + 1);
3252		for (i = 0; i < bss->ie_len; i++) {
3253			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
3254			if (ret < 0 || ret >= end - pos)
3255				return 0;
3256			pos += ret;
3257		}
3258
3259		ret = os_snprintf(pos, end - pos, "\n");
3260		if (ret < 0 || ret >= end - pos)
3261			return 0;
3262		pos += ret;
3263	}
3264
3265	if (mask & WPA_BSS_MASK_FLAGS) {
3266		ret = os_snprintf(pos, end - pos, "flags=");
3267		if (ret < 0 || ret >= end - pos)
3268			return 0;
3269		pos += ret;
3270
3271		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3272		if (ie)
3273			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
3274						    2 + ie[1]);
3275		ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3276		if (ie2)
3277			pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
3278						    2 + ie2[1]);
3279		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3280		if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
3281			ret = os_snprintf(pos, end - pos, "[WEP]");
3282			if (ret < 0 || ret >= end - pos)
3283				return 0;
3284			pos += ret;
3285		}
3286		if (bss->caps & IEEE80211_CAP_IBSS) {
3287			ret = os_snprintf(pos, end - pos, "[IBSS]");
3288			if (ret < 0 || ret >= end - pos)
3289				return 0;
3290			pos += ret;
3291		}
3292		if (bss->caps & IEEE80211_CAP_ESS) {
3293			ret = os_snprintf(pos, end - pos, "[ESS]");
3294			if (ret < 0 || ret >= end - pos)
3295				return 0;
3296			pos += ret;
3297		}
3298		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
3299			ret = os_snprintf(pos, end - pos, "[P2P]");
3300			if (ret < 0 || ret >= end - pos)
3301				return 0;
3302			pos += ret;
3303		}
3304#ifdef CONFIG_HS20
3305		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
3306			ret = os_snprintf(pos, end - pos, "[HS20]");
3307			if (ret < 0 || ret >= end - pos)
3308				return 0;
3309			pos += ret;
3310		}
3311#endif /* CONFIG_HS20 */
3312
3313		ret = os_snprintf(pos, end - pos, "\n");
3314		if (ret < 0 || ret >= end - pos)
3315			return 0;
3316		pos += ret;
3317	}
3318
3319	if (mask & WPA_BSS_MASK_SSID) {
3320		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
3321				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
3322		if (ret < 0 || ret >= end - pos)
3323			return 0;
3324		pos += ret;
3325	}
3326
3327#ifdef CONFIG_WPS
3328	if (mask & WPA_BSS_MASK_WPS_SCAN) {
3329		ie = (const u8 *) (bss + 1);
3330		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
3331		if (ret < 0 || ret >= end - pos)
3332			return 0;
3333		pos += ret;
3334	}
3335#endif /* CONFIG_WPS */
3336
3337#ifdef CONFIG_P2P
3338	if (mask & WPA_BSS_MASK_P2P_SCAN) {
3339		ie = (const u8 *) (bss + 1);
3340		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
3341		if (ret < 0 || ret >= end - pos)
3342			return 0;
3343		pos += ret;
3344	}
3345#endif /* CONFIG_P2P */
3346
3347#ifdef CONFIG_WIFI_DISPLAY
3348	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
3349		struct wpabuf *wfd;
3350		ie = (const u8 *) (bss + 1);
3351		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
3352						  WFD_IE_VENDOR_TYPE);
3353		if (wfd) {
3354			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
3355			if (ret < 0 || ret >= end - pos)
3356				return 0;
3357			pos += ret;
3358
3359			pos += wpa_snprintf_hex(pos, end - pos,
3360						wpabuf_head(wfd),
3361						wpabuf_len(wfd));
3362			wpabuf_free(wfd);
3363
3364			ret = os_snprintf(pos, end - pos, "\n");
3365			if (ret < 0 || ret >= end - pos)
3366				return 0;
3367			pos += ret;
3368		}
3369	}
3370#endif /* CONFIG_WIFI_DISPLAY */
3371
3372#ifdef CONFIG_INTERWORKING
3373	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
3374		struct wpa_bss_anqp *anqp = bss->anqp;
3375		pos = anqp_add_hex(pos, end, "anqp_venue_name",
3376				   anqp->venue_name);
3377		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
3378				   anqp->network_auth_type);
3379		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
3380				   anqp->roaming_consortium);
3381		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
3382				   anqp->ip_addr_type_availability);
3383		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
3384				   anqp->nai_realm);
3385		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
3386		pos = anqp_add_hex(pos, end, "anqp_domain_name",
3387				   anqp->domain_name);
3388#ifdef CONFIG_HS20
3389		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
3390				   anqp->hs20_operator_friendly_name);
3391		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
3392				   anqp->hs20_wan_metrics);
3393		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
3394				   anqp->hs20_connection_capability);
3395#endif /* CONFIG_HS20 */
3396	}
3397#endif /* CONFIG_INTERWORKING */
3398
3399	if (mask & WPA_BSS_MASK_DELIM) {
3400		ret = os_snprintf(pos, end - pos, "====\n");
3401		if (ret < 0 || ret >= end - pos)
3402			return 0;
3403		pos += ret;
3404	}
3405
3406	return pos - buf;
3407}
3408
3409
3410static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
3411					 const char *cmd, char *buf,
3412					 size_t buflen)
3413{
3414	u8 bssid[ETH_ALEN];
3415	size_t i;
3416	struct wpa_bss *bss;
3417	struct wpa_bss *bsslast = NULL;
3418	struct dl_list *next;
3419	int ret = 0;
3420	int len;
3421	char *ctmp;
3422	unsigned long mask = WPA_BSS_MASK_ALL;
3423
3424	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
3425		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
3426			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
3427					    list_id);
3428			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
3429					       list_id);
3430		} else { /* N1-N2 */
3431			unsigned int id1, id2;
3432
3433			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
3434				wpa_printf(MSG_INFO, "Wrong BSS range "
3435					   "format");
3436				return 0;
3437			}
3438
3439			if (*(cmd + 6) == '-')
3440				id1 = 0;
3441			else
3442				id1 = atoi(cmd + 6);
3443			ctmp++;
3444			if (*ctmp >= '0' && *ctmp <= '9')
3445				id2 = atoi(ctmp);
3446			else
3447				id2 = (unsigned int) -1;
3448			bss = wpa_bss_get_id_range(wpa_s, id1, id2);
3449			if (id2 == (unsigned int) -1)
3450				bsslast = dl_list_last(&wpa_s->bss_id,
3451						       struct wpa_bss,
3452						       list_id);
3453			else {
3454				bsslast = wpa_bss_get_id(wpa_s, id2);
3455				if (bsslast == NULL && bss && id2 > id1) {
3456					struct wpa_bss *tmp = bss;
3457					for (;;) {
3458						next = tmp->list_id.next;
3459						if (next == &wpa_s->bss_id)
3460							break;
3461						tmp = dl_list_entry(
3462							next, struct wpa_bss,
3463							list_id);
3464						if (tmp->id > id2)
3465							break;
3466						bsslast = tmp;
3467					}
3468				}
3469			}
3470		}
3471	} else if (os_strncmp(cmd, "FIRST", 5) == 0)
3472		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
3473	else if (os_strncmp(cmd, "LAST", 4) == 0)
3474		bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
3475	else if (os_strncmp(cmd, "ID-", 3) == 0) {
3476		i = atoi(cmd + 3);
3477		bss = wpa_bss_get_id(wpa_s, i);
3478	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
3479		i = atoi(cmd + 5);
3480		bss = wpa_bss_get_id(wpa_s, i);
3481		if (bss) {
3482			next = bss->list_id.next;
3483			if (next == &wpa_s->bss_id)
3484				bss = NULL;
3485			else
3486				bss = dl_list_entry(next, struct wpa_bss,
3487						    list_id);
3488		}
3489#ifdef CONFIG_P2P
3490	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
3491		if (hwaddr_aton(cmd + 13, bssid) == 0)
3492			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
3493		else
3494			bss = NULL;
3495#endif /* CONFIG_P2P */
3496	} else if (hwaddr_aton(cmd, bssid) == 0)
3497		bss = wpa_bss_get_bssid(wpa_s, bssid);
3498	else {
3499		struct wpa_bss *tmp;
3500		i = atoi(cmd);
3501		bss = NULL;
3502		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
3503		{
3504			if (i-- == 0) {
3505				bss = tmp;
3506				break;
3507			}
3508		}
3509	}
3510
3511	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
3512		mask = strtoul(ctmp + 5, NULL, 0x10);
3513		if (mask == 0)
3514			mask = WPA_BSS_MASK_ALL;
3515	}
3516
3517	if (bss == NULL)
3518		return 0;
3519
3520	if (bsslast == NULL)
3521		bsslast = bss;
3522	do {
3523		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
3524		ret += len;
3525		buf += len;
3526		buflen -= len;
3527		if (bss == bsslast) {
3528			if ((mask & WPA_BSS_MASK_DELIM) && len &&
3529			    (bss == dl_list_last(&wpa_s->bss_id,
3530						 struct wpa_bss, list_id)))
3531				os_snprintf(buf - 5, 5, "####\n");
3532			break;
3533		}
3534		next = bss->list_id.next;
3535		if (next == &wpa_s->bss_id)
3536			break;
3537		bss = dl_list_entry(next, struct wpa_bss, list_id);
3538	} while (bss && len);
3539
3540	return ret;
3541}
3542
3543
3544static int wpa_supplicant_ctrl_iface_ap_scan(
3545	struct wpa_supplicant *wpa_s, char *cmd)
3546{
3547	int ap_scan = atoi(cmd);
3548	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
3549}
3550
3551
3552static int wpa_supplicant_ctrl_iface_scan_interval(
3553	struct wpa_supplicant *wpa_s, char *cmd)
3554{
3555	int scan_int = atoi(cmd);
3556	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
3557}
3558
3559
3560static int wpa_supplicant_ctrl_iface_bss_expire_age(
3561	struct wpa_supplicant *wpa_s, char *cmd)
3562{
3563	int expire_age = atoi(cmd);
3564	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
3565}
3566
3567
3568static int wpa_supplicant_ctrl_iface_bss_expire_count(
3569	struct wpa_supplicant *wpa_s, char *cmd)
3570{
3571	int expire_count = atoi(cmd);
3572	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
3573}
3574
3575
3576static int wpa_supplicant_ctrl_iface_bss_flush(
3577	struct wpa_supplicant *wpa_s, char *cmd)
3578{
3579	int flush_age = atoi(cmd);
3580
3581	if (flush_age == 0)
3582		wpa_bss_flush(wpa_s);
3583	else
3584		wpa_bss_flush_by_age(wpa_s, flush_age);
3585	return 0;
3586}
3587
3588
3589static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
3590{
3591	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
3592	/* MLME-DELETEKEYS.request */
3593	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
3594	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
3595	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
3596	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
3597#ifdef CONFIG_IEEE80211W
3598	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
3599	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
3600#endif /* CONFIG_IEEE80211W */
3601
3602	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
3603			0);
3604	/* MLME-SETPROTECTION.request(None) */
3605	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
3606				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
3607				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
3608	wpa_sm_drop_sa(wpa_s->wpa);
3609}
3610
3611
3612static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
3613					  char *addr)
3614{
3615#ifdef CONFIG_NO_SCAN_PROCESSING
3616	return -1;
3617#else /* CONFIG_NO_SCAN_PROCESSING */
3618	u8 bssid[ETH_ALEN];
3619	struct wpa_bss *bss;
3620	struct wpa_ssid *ssid = wpa_s->current_ssid;
3621
3622	if (hwaddr_aton(addr, bssid)) {
3623		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
3624			   "address '%s'", addr);
3625		return -1;
3626	}
3627
3628	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
3629
3630	if (!ssid) {
3631		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
3632			   "configuration known for the target AP");
3633		return -1;
3634	}
3635
3636	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
3637	if (!bss) {
3638		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
3639			   "from BSS table");
3640		return -1;
3641	}
3642
3643	/*
3644	 * TODO: Find best network configuration block from configuration to
3645	 * allow roaming to other networks
3646	 */
3647
3648	wpa_s->reassociate = 1;
3649	wpa_supplicant_connect(wpa_s, bss, ssid);
3650
3651	return 0;
3652#endif /* CONFIG_NO_SCAN_PROCESSING */
3653}
3654
3655
3656#ifdef CONFIG_P2P
3657static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
3658{
3659	unsigned int timeout = atoi(cmd);
3660	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
3661	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
3662	char *pos;
3663	unsigned int search_delay;
3664
3665	if (os_strstr(cmd, "type=social"))
3666		type = P2P_FIND_ONLY_SOCIAL;
3667	else if (os_strstr(cmd, "type=progressive"))
3668		type = P2P_FIND_PROGRESSIVE;
3669
3670	pos = os_strstr(cmd, "dev_id=");
3671	if (pos) {
3672		pos += 7;
3673		if (hwaddr_aton(pos, dev_id))
3674			return -1;
3675		_dev_id = dev_id;
3676	}
3677
3678	pos = os_strstr(cmd, "delay=");
3679	if (pos) {
3680		pos += 6;
3681		search_delay = atoi(pos);
3682	} else
3683		search_delay = wpas_p2p_search_delay(wpa_s);
3684
3685	return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id,
3686			     search_delay);
3687}
3688
3689
3690static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
3691			    char *buf, size_t buflen)
3692{
3693	u8 addr[ETH_ALEN];
3694	char *pos, *pos2;
3695	char *pin = NULL;
3696	enum p2p_wps_method wps_method;
3697	int new_pin;
3698	int ret;
3699	int persistent_group, persistent_id = -1;
3700	int join;
3701	int auth;
3702	int automatic;
3703	int go_intent = -1;
3704	int freq = 0;
3705	int pd;
3706	int ht40;
3707
3708	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
3709	 * [persistent|persistent=<network id>]
3710	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
3711	 * [ht40] */
3712
3713	if (hwaddr_aton(cmd, addr))
3714		return -1;
3715
3716	pos = cmd + 17;
3717	if (*pos != ' ')
3718		return -1;
3719	pos++;
3720
3721	persistent_group = os_strstr(pos, " persistent") != NULL;
3722	pos2 = os_strstr(pos, " persistent=");
3723	if (pos2) {
3724		struct wpa_ssid *ssid;
3725		persistent_id = atoi(pos2 + 12);
3726		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
3727		if (ssid == NULL || ssid->disabled != 2 ||
3728		    ssid->mode != WPAS_MODE_P2P_GO) {
3729			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3730				   "SSID id=%d for persistent P2P group (GO)",
3731				   persistent_id);
3732			return -1;
3733		}
3734	}
3735	join = os_strstr(pos, " join") != NULL;
3736	auth = os_strstr(pos, " auth") != NULL;
3737	automatic = os_strstr(pos, " auto") != NULL;
3738	pd = os_strstr(pos, " provdisc") != NULL;
3739	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
3740
3741	pos2 = os_strstr(pos, " go_intent=");
3742	if (pos2) {
3743		pos2 += 11;
3744		go_intent = atoi(pos2);
3745		if (go_intent < 0 || go_intent > 15)
3746			return -1;
3747	}
3748
3749	pos2 = os_strstr(pos, " freq=");
3750	if (pos2) {
3751		pos2 += 6;
3752		freq = atoi(pos2);
3753		if (freq <= 0)
3754			return -1;
3755	}
3756
3757	if (os_strncmp(pos, "pin", 3) == 0) {
3758		/* Request random PIN (to be displayed) and enable the PIN */
3759		wps_method = WPS_PIN_DISPLAY;
3760	} else if (os_strncmp(pos, "pbc", 3) == 0) {
3761		wps_method = WPS_PBC;
3762	} else {
3763		pin = pos;
3764		pos = os_strchr(pin, ' ');
3765		wps_method = WPS_PIN_KEYPAD;
3766		if (pos) {
3767			*pos++ = '\0';
3768			if (os_strncmp(pos, "display", 7) == 0)
3769				wps_method = WPS_PIN_DISPLAY;
3770		}
3771		if (!wps_pin_str_valid(pin)) {
3772			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
3773			return 17;
3774		}
3775	}
3776
3777	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
3778				   persistent_group, automatic, join,
3779				   auth, go_intent, freq, persistent_id, pd,
3780				   ht40);
3781	if (new_pin == -2) {
3782		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
3783		return 25;
3784	}
3785	if (new_pin == -3) {
3786		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
3787		return 25;
3788	}
3789	if (new_pin < 0)
3790		return -1;
3791	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
3792		ret = os_snprintf(buf, buflen, "%08d", new_pin);
3793		if (ret < 0 || (size_t) ret >= buflen)
3794			return -1;
3795		return ret;
3796	}
3797
3798	os_memcpy(buf, "OK\n", 3);
3799	return 3;
3800}
3801
3802
3803static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
3804{
3805	unsigned int timeout = atoi(cmd);
3806	return wpas_p2p_listen(wpa_s, timeout);
3807}
3808
3809
3810static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
3811{
3812	u8 addr[ETH_ALEN];
3813	char *pos;
3814	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
3815
3816	/* <addr> <config method> [join|auto] */
3817
3818	if (hwaddr_aton(cmd, addr))
3819		return -1;
3820
3821	pos = cmd + 17;
3822	if (*pos != ' ')
3823		return -1;
3824	pos++;
3825
3826	if (os_strstr(pos, " join") != NULL)
3827		use = WPAS_P2P_PD_FOR_JOIN;
3828	else if (os_strstr(pos, " auto") != NULL)
3829		use = WPAS_P2P_PD_AUTO;
3830
3831	return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
3832}
3833
3834
3835static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
3836			      size_t buflen)
3837{
3838	struct wpa_ssid *ssid = wpa_s->current_ssid;
3839
3840	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
3841	    ssid->passphrase == NULL)
3842		return -1;
3843
3844	os_strlcpy(buf, ssid->passphrase, buflen);
3845	return os_strlen(buf);
3846}
3847
3848
3849static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
3850				  char *buf, size_t buflen)
3851{
3852	u64 ref;
3853	int res;
3854	u8 dst_buf[ETH_ALEN], *dst;
3855	struct wpabuf *tlvs;
3856	char *pos;
3857	size_t len;
3858
3859	if (hwaddr_aton(cmd, dst_buf))
3860		return -1;
3861	dst = dst_buf;
3862	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
3863	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
3864		dst = NULL;
3865	pos = cmd + 17;
3866	if (*pos != ' ')
3867		return -1;
3868	pos++;
3869
3870	if (os_strncmp(pos, "upnp ", 5) == 0) {
3871		u8 version;
3872		pos += 5;
3873		if (hexstr2bin(pos, &version, 1) < 0)
3874			return -1;
3875		pos += 2;
3876		if (*pos != ' ')
3877			return -1;
3878		pos++;
3879		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
3880#ifdef CONFIG_WIFI_DISPLAY
3881	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
3882		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
3883#endif /* CONFIG_WIFI_DISPLAY */
3884	} else {
3885		len = os_strlen(pos);
3886		if (len & 1)
3887			return -1;
3888		len /= 2;
3889		tlvs = wpabuf_alloc(len);
3890		if (tlvs == NULL)
3891			return -1;
3892		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
3893			wpabuf_free(tlvs);
3894			return -1;
3895		}
3896
3897		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
3898		wpabuf_free(tlvs);
3899	}
3900	if (ref == 0)
3901		return -1;
3902	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
3903	if (res < 0 || (unsigned) res >= buflen)
3904		return -1;
3905	return res;
3906}
3907
3908
3909static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
3910					 char *cmd)
3911{
3912	long long unsigned val;
3913	u64 req;
3914	if (sscanf(cmd, "%llx", &val) != 1)
3915		return -1;
3916	req = val;
3917	return wpas_p2p_sd_cancel_request(wpa_s, req);
3918}
3919
3920
3921static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
3922{
3923	int freq;
3924	u8 dst[ETH_ALEN];
3925	u8 dialog_token;
3926	struct wpabuf *resp_tlvs;
3927	char *pos, *pos2;
3928	size_t len;
3929
3930	pos = os_strchr(cmd, ' ');
3931	if (pos == NULL)
3932		return -1;
3933	*pos++ = '\0';
3934	freq = atoi(cmd);
3935	if (freq == 0)
3936		return -1;
3937
3938	if (hwaddr_aton(pos, dst))
3939		return -1;
3940	pos += 17;
3941	if (*pos != ' ')
3942		return -1;
3943	pos++;
3944
3945	pos2 = os_strchr(pos, ' ');
3946	if (pos2 == NULL)
3947		return -1;
3948	*pos2++ = '\0';
3949	dialog_token = atoi(pos);
3950
3951	len = os_strlen(pos2);
3952	if (len & 1)
3953		return -1;
3954	len /= 2;
3955	resp_tlvs = wpabuf_alloc(len);
3956	if (resp_tlvs == NULL)
3957		return -1;
3958	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
3959		wpabuf_free(resp_tlvs);
3960		return -1;
3961	}
3962
3963	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
3964	wpabuf_free(resp_tlvs);
3965	return 0;
3966}
3967
3968
3969static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
3970				       char *cmd)
3971{
3972	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
3973		return -1;
3974	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
3975	return 0;
3976}
3977
3978
3979static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
3980					char *cmd)
3981{
3982	char *pos;
3983	size_t len;
3984	struct wpabuf *query, *resp;
3985
3986	pos = os_strchr(cmd, ' ');
3987	if (pos == NULL)
3988		return -1;
3989	*pos++ = '\0';
3990
3991	len = os_strlen(cmd);
3992	if (len & 1)
3993		return -1;
3994	len /= 2;
3995	query = wpabuf_alloc(len);
3996	if (query == NULL)
3997		return -1;
3998	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
3999		wpabuf_free(query);
4000		return -1;
4001	}
4002
4003	len = os_strlen(pos);
4004	if (len & 1) {
4005		wpabuf_free(query);
4006		return -1;
4007	}
4008	len /= 2;
4009	resp = wpabuf_alloc(len);
4010	if (resp == NULL) {
4011		wpabuf_free(query);
4012		return -1;
4013	}
4014	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
4015		wpabuf_free(query);
4016		wpabuf_free(resp);
4017		return -1;
4018	}
4019
4020	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
4021		wpabuf_free(query);
4022		wpabuf_free(resp);
4023		return -1;
4024	}
4025	return 0;
4026}
4027
4028
4029static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4030{
4031	char *pos;
4032	u8 version;
4033
4034	pos = os_strchr(cmd, ' ');
4035	if (pos == NULL)
4036		return -1;
4037	*pos++ = '\0';
4038
4039	if (hexstr2bin(cmd, &version, 1) < 0)
4040		return -1;
4041
4042	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
4043}
4044
4045
4046static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
4047{
4048	char *pos;
4049
4050	pos = os_strchr(cmd, ' ');
4051	if (pos == NULL)
4052		return -1;
4053	*pos++ = '\0';
4054
4055	if (os_strcmp(cmd, "bonjour") == 0)
4056		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
4057	if (os_strcmp(cmd, "upnp") == 0)
4058		return p2p_ctrl_service_add_upnp(wpa_s, pos);
4059	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4060	return -1;
4061}
4062
4063
4064static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
4065					char *cmd)
4066{
4067	size_t len;
4068	struct wpabuf *query;
4069	int ret;
4070
4071	len = os_strlen(cmd);
4072	if (len & 1)
4073		return -1;
4074	len /= 2;
4075	query = wpabuf_alloc(len);
4076	if (query == NULL)
4077		return -1;
4078	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
4079		wpabuf_free(query);
4080		return -1;
4081	}
4082
4083	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
4084	wpabuf_free(query);
4085	return ret;
4086}
4087
4088
4089static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4090{
4091	char *pos;
4092	u8 version;
4093
4094	pos = os_strchr(cmd, ' ');
4095	if (pos == NULL)
4096		return -1;
4097	*pos++ = '\0';
4098
4099	if (hexstr2bin(cmd, &version, 1) < 0)
4100		return -1;
4101
4102	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
4103}
4104
4105
4106static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
4107{
4108	char *pos;
4109
4110	pos = os_strchr(cmd, ' ');
4111	if (pos == NULL)
4112		return -1;
4113	*pos++ = '\0';
4114
4115	if (os_strcmp(cmd, "bonjour") == 0)
4116		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
4117	if (os_strcmp(cmd, "upnp") == 0)
4118		return p2p_ctrl_service_del_upnp(wpa_s, pos);
4119	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4120	return -1;
4121}
4122
4123
4124static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
4125{
4126	u8 addr[ETH_ALEN];
4127
4128	/* <addr> */
4129
4130	if (hwaddr_aton(cmd, addr))
4131		return -1;
4132
4133	return wpas_p2p_reject(wpa_s, addr);
4134}
4135
4136
4137static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
4138{
4139	char *pos;
4140	int id;
4141	struct wpa_ssid *ssid;
4142	u8 *_peer = NULL, peer[ETH_ALEN];
4143	int freq = 0, pref_freq = 0;
4144	int ht40;
4145
4146	id = atoi(cmd);
4147	pos = os_strstr(cmd, " peer=");
4148	if (pos) {
4149		pos += 6;
4150		if (hwaddr_aton(pos, peer))
4151			return -1;
4152		_peer = peer;
4153	}
4154	ssid = wpa_config_get_network(wpa_s->conf, id);
4155	if (ssid == NULL || ssid->disabled != 2) {
4156		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4157			   "for persistent P2P group",
4158			   id);
4159		return -1;
4160	}
4161
4162	pos = os_strstr(cmd, " freq=");
4163	if (pos) {
4164		pos += 6;
4165		freq = atoi(pos);
4166		if (freq <= 0)
4167			return -1;
4168	}
4169
4170	pos = os_strstr(cmd, " pref=");
4171	if (pos) {
4172		pos += 6;
4173		pref_freq = atoi(pos);
4174		if (pref_freq <= 0)
4175			return -1;
4176	}
4177
4178	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
4179
4180	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, pref_freq);
4181}
4182
4183
4184static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
4185{
4186	char *pos;
4187	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
4188
4189	pos = os_strstr(cmd, " peer=");
4190	if (!pos)
4191		return -1;
4192
4193	*pos = '\0';
4194	pos += 6;
4195	if (hwaddr_aton(pos, peer)) {
4196		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
4197		return -1;
4198	}
4199
4200	pos = os_strstr(pos, " go_dev_addr=");
4201	if (pos) {
4202		pos += 13;
4203		if (hwaddr_aton(pos, go_dev_addr)) {
4204			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
4205				   pos);
4206			return -1;
4207		}
4208		go_dev = go_dev_addr;
4209	}
4210
4211	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
4212}
4213
4214
4215static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
4216{
4217	if (os_strncmp(cmd, "persistent=", 11) == 0)
4218		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
4219	if (os_strncmp(cmd, "group=", 6) == 0)
4220		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
4221
4222	return -1;
4223}
4224
4225
4226static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
4227					 char *cmd, int freq, int ht40)
4228{
4229	int id;
4230	struct wpa_ssid *ssid;
4231
4232	id = atoi(cmd);
4233	ssid = wpa_config_get_network(wpa_s->conf, id);
4234	if (ssid == NULL || ssid->disabled != 2) {
4235		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4236			   "for persistent P2P group",
4237			   id);
4238		return -1;
4239	}
4240
4241	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40, NULL);
4242}
4243
4244
4245static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
4246{
4247	int freq = 0, ht40;
4248	char *pos;
4249
4250	pos = os_strstr(cmd, "freq=");
4251	if (pos)
4252		freq = atoi(pos + 5);
4253
4254	ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
4255
4256	if (os_strncmp(cmd, "persistent=", 11) == 0)
4257		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
4258						     ht40);
4259	if (os_strcmp(cmd, "persistent") == 0 ||
4260	    os_strncmp(cmd, "persistent ", 11) == 0)
4261		return wpas_p2p_group_add(wpa_s, 1, freq, ht40);
4262	if (os_strncmp(cmd, "freq=", 5) == 0)
4263		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
4264	if (ht40)
4265		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
4266
4267	wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
4268		   cmd);
4269	return -1;
4270}
4271
4272
4273static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
4274			 char *buf, size_t buflen)
4275{
4276	u8 addr[ETH_ALEN], *addr_ptr;
4277	int next, res;
4278	const struct p2p_peer_info *info;
4279	char *pos, *end;
4280	char devtype[WPS_DEV_TYPE_BUFSIZE];
4281	struct wpa_ssid *ssid;
4282	size_t i;
4283
4284	if (!wpa_s->global->p2p)
4285		return -1;
4286
4287	if (os_strcmp(cmd, "FIRST") == 0) {
4288		addr_ptr = NULL;
4289		next = 0;
4290	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
4291		if (hwaddr_aton(cmd + 5, addr) < 0)
4292			return -1;
4293		addr_ptr = addr;
4294		next = 1;
4295	} else {
4296		if (hwaddr_aton(cmd, addr) < 0)
4297			return -1;
4298		addr_ptr = addr;
4299		next = 0;
4300	}
4301
4302	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
4303	if (info == NULL)
4304		return -1;
4305
4306	pos = buf;
4307	end = buf + buflen;
4308
4309	res = os_snprintf(pos, end - pos, MACSTR "\n"
4310			  "pri_dev_type=%s\n"
4311			  "device_name=%s\n"
4312			  "manufacturer=%s\n"
4313			  "model_name=%s\n"
4314			  "model_number=%s\n"
4315			  "serial_number=%s\n"
4316			  "config_methods=0x%x\n"
4317			  "dev_capab=0x%x\n"
4318			  "group_capab=0x%x\n"
4319			  "level=%d\n",
4320			  MAC2STR(info->p2p_device_addr),
4321			  wps_dev_type_bin2str(info->pri_dev_type,
4322					       devtype, sizeof(devtype)),
4323			  info->device_name,
4324			  info->manufacturer,
4325			  info->model_name,
4326			  info->model_number,
4327			  info->serial_number,
4328			  info->config_methods,
4329			  info->dev_capab,
4330			  info->group_capab,
4331			  info->level);
4332	if (res < 0 || res >= end - pos)
4333		return pos - buf;
4334	pos += res;
4335
4336	for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
4337	{
4338		const u8 *t;
4339		t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
4340		res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
4341				  wps_dev_type_bin2str(t, devtype,
4342						       sizeof(devtype)));
4343		if (res < 0 || res >= end - pos)
4344			return pos - buf;
4345		pos += res;
4346	}
4347
4348	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
4349	if (ssid) {
4350		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
4351		if (res < 0 || res >= end - pos)
4352			return pos - buf;
4353		pos += res;
4354	}
4355
4356	res = p2p_get_peer_info_txt(info, pos, end - pos);
4357	if (res < 0)
4358		return pos - buf;
4359	pos += res;
4360
4361	return pos - buf;
4362}
4363
4364
4365static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
4366				  const char *param)
4367{
4368	struct wpa_freq_range *freq = NULL, *n;
4369	unsigned int count = 0, i;
4370	const char *pos, *pos2, *pos3;
4371
4372	if (wpa_s->global->p2p == NULL)
4373		return -1;
4374
4375	/*
4376	 * param includes comma separated frequency range.
4377	 * For example: 2412-2432,2462,5000-6000
4378	 */
4379	pos = param;
4380	while (pos && pos[0]) {
4381		n = os_realloc_array(freq, count + 1,
4382				     sizeof(struct wpa_freq_range));
4383		if (n == NULL) {
4384			os_free(freq);
4385			return -1;
4386		}
4387		freq = n;
4388		freq[count].min = atoi(pos);
4389		pos2 = os_strchr(pos, '-');
4390		pos3 = os_strchr(pos, ',');
4391		if (pos2 && (!pos3 || pos2 < pos3)) {
4392			pos2++;
4393			freq[count].max = atoi(pos2);
4394		} else
4395			freq[count].max = freq[count].min;
4396		pos = pos3;
4397		if (pos)
4398			pos++;
4399		count++;
4400	}
4401
4402	for (i = 0; i < count; i++) {
4403		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
4404			   freq[i].min, freq[i].max);
4405	}
4406
4407	os_free(wpa_s->global->p2p_disallow_freq);
4408	wpa_s->global->p2p_disallow_freq = freq;
4409	wpa_s->global->num_p2p_disallow_freq = count;
4410	wpas_p2p_update_channel_list(wpa_s);
4411	return 0;
4412}
4413
4414
4415static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
4416{
4417	char *param;
4418
4419	if (wpa_s->global->p2p == NULL)
4420		return -1;
4421
4422	param = os_strchr(cmd, ' ');
4423	if (param == NULL)
4424		return -1;
4425	*param++ = '\0';
4426
4427	if (os_strcmp(cmd, "discoverability") == 0) {
4428		p2p_set_client_discoverability(wpa_s->global->p2p,
4429					       atoi(param));
4430		return 0;
4431	}
4432
4433	if (os_strcmp(cmd, "managed") == 0) {
4434		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
4435		return 0;
4436	}
4437
4438	if (os_strcmp(cmd, "listen_channel") == 0) {
4439		return p2p_set_listen_channel(wpa_s->global->p2p, 81,
4440					      atoi(param));
4441	}
4442
4443	if (os_strcmp(cmd, "ssid_postfix") == 0) {
4444		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
4445					    os_strlen(param));
4446	}
4447
4448	if (os_strcmp(cmd, "noa") == 0) {
4449		char *pos;
4450		int count, start, duration;
4451		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
4452		count = atoi(param);
4453		pos = os_strchr(param, ',');
4454		if (pos == NULL)
4455			return -1;
4456		pos++;
4457		start = atoi(pos);
4458		pos = os_strchr(pos, ',');
4459		if (pos == NULL)
4460			return -1;
4461		pos++;
4462		duration = atoi(pos);
4463		if (count < 0 || count > 255 || start < 0 || duration < 0)
4464			return -1;
4465		if (count == 0 && duration > 0)
4466			return -1;
4467		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
4468			   "start=%d duration=%d", count, start, duration);
4469		return wpas_p2p_set_noa(wpa_s, count, start, duration);
4470	}
4471
4472	if (os_strcmp(cmd, "ps") == 0)
4473		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
4474
4475	if (os_strcmp(cmd, "oppps") == 0)
4476		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
4477
4478	if (os_strcmp(cmd, "ctwindow") == 0)
4479		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
4480
4481	if (os_strcmp(cmd, "disabled") == 0) {
4482		wpa_s->global->p2p_disabled = atoi(param);
4483		wpa_printf(MSG_DEBUG, "P2P functionality %s",
4484			   wpa_s->global->p2p_disabled ?
4485			   "disabled" : "enabled");
4486		if (wpa_s->global->p2p_disabled) {
4487			wpas_p2p_stop_find(wpa_s);
4488			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4489			p2p_flush(wpa_s->global->p2p);
4490		}
4491		return 0;
4492	}
4493
4494	if (os_strcmp(cmd, "conc_pref") == 0) {
4495		if (os_strcmp(param, "sta") == 0)
4496			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
4497		else if (os_strcmp(param, "p2p") == 0)
4498			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
4499		else {
4500			wpa_printf(MSG_INFO, "Invalid conc_pref value");
4501			return -1;
4502		}
4503		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
4504			   "%s", param);
4505		return 0;
4506	}
4507
4508	if (os_strcmp(cmd, "force_long_sd") == 0) {
4509		wpa_s->force_long_sd = atoi(param);
4510		return 0;
4511	}
4512
4513	if (os_strcmp(cmd, "peer_filter") == 0) {
4514		u8 addr[ETH_ALEN];
4515		if (hwaddr_aton(param, addr))
4516			return -1;
4517		p2p_set_peer_filter(wpa_s->global->p2p, addr);
4518		return 0;
4519	}
4520
4521	if (os_strcmp(cmd, "cross_connect") == 0)
4522		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
4523
4524	if (os_strcmp(cmd, "go_apsd") == 0) {
4525		if (os_strcmp(param, "disable") == 0)
4526			wpa_s->set_ap_uapsd = 0;
4527		else {
4528			wpa_s->set_ap_uapsd = 1;
4529			wpa_s->ap_uapsd = atoi(param);
4530		}
4531		return 0;
4532	}
4533
4534	if (os_strcmp(cmd, "client_apsd") == 0) {
4535		if (os_strcmp(param, "disable") == 0)
4536			wpa_s->set_sta_uapsd = 0;
4537		else {
4538			int be, bk, vi, vo;
4539			char *pos;
4540			/* format: BE,BK,VI,VO;max SP Length */
4541			be = atoi(param);
4542			pos = os_strchr(param, ',');
4543			if (pos == NULL)
4544				return -1;
4545			pos++;
4546			bk = atoi(pos);
4547			pos = os_strchr(pos, ',');
4548			if (pos == NULL)
4549				return -1;
4550			pos++;
4551			vi = atoi(pos);
4552			pos = os_strchr(pos, ',');
4553			if (pos == NULL)
4554				return -1;
4555			pos++;
4556			vo = atoi(pos);
4557			/* ignore max SP Length for now */
4558
4559			wpa_s->set_sta_uapsd = 1;
4560			wpa_s->sta_uapsd = 0;
4561			if (be)
4562				wpa_s->sta_uapsd |= BIT(0);
4563			if (bk)
4564				wpa_s->sta_uapsd |= BIT(1);
4565			if (vi)
4566				wpa_s->sta_uapsd |= BIT(2);
4567			if (vo)
4568				wpa_s->sta_uapsd |= BIT(3);
4569		}
4570		return 0;
4571	}
4572
4573	if (os_strcmp(cmd, "disallow_freq") == 0)
4574		return p2p_ctrl_disallow_freq(wpa_s, param);
4575
4576	if (os_strcmp(cmd, "disc_int") == 0) {
4577		int min_disc_int, max_disc_int, max_disc_tu;
4578		char *pos;
4579
4580		pos = param;
4581
4582		min_disc_int = atoi(pos);
4583		pos = os_strchr(pos, ' ');
4584		if (pos == NULL)
4585			return -1;
4586		*pos++ = '\0';
4587
4588		max_disc_int = atoi(pos);
4589		pos = os_strchr(pos, ' ');
4590		if (pos == NULL)
4591			return -1;
4592		*pos++ = '\0';
4593
4594		max_disc_tu = atoi(pos);
4595
4596		return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
4597					max_disc_int, max_disc_tu);
4598	}
4599
4600	if (os_strcmp(cmd, "per_sta_psk") == 0) {
4601		wpa_s->global->p2p_per_sta_psk = !!atoi(param);
4602		return 0;
4603	}
4604
4605	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
4606		   cmd);
4607
4608	return -1;
4609}
4610
4611
4612static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
4613{
4614	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4615	wpa_s->force_long_sd = 0;
4616	if (wpa_s->global->p2p)
4617		p2p_flush(wpa_s->global->p2p);
4618}
4619
4620
4621static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
4622{
4623	char *pos, *pos2;
4624	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
4625
4626	if (cmd[0]) {
4627		pos = os_strchr(cmd, ' ');
4628		if (pos == NULL)
4629			return -1;
4630		*pos++ = '\0';
4631		dur1 = atoi(cmd);
4632
4633		pos2 = os_strchr(pos, ' ');
4634		if (pos2)
4635			*pos2++ = '\0';
4636		int1 = atoi(pos);
4637	} else
4638		pos2 = NULL;
4639
4640	if (pos2) {
4641		pos = os_strchr(pos2, ' ');
4642		if (pos == NULL)
4643			return -1;
4644		*pos++ = '\0';
4645		dur2 = atoi(pos2);
4646		int2 = atoi(pos);
4647	}
4648
4649	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
4650}
4651
4652
4653static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
4654{
4655	char *pos;
4656	unsigned int period = 0, interval = 0;
4657
4658	if (cmd[0]) {
4659		pos = os_strchr(cmd, ' ');
4660		if (pos == NULL)
4661			return -1;
4662		*pos++ = '\0';
4663		period = atoi(cmd);
4664		interval = atoi(pos);
4665	}
4666
4667	return wpas_p2p_ext_listen(wpa_s, period, interval);
4668}
4669
4670
4671static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
4672{
4673	const char *pos;
4674	u8 peer[ETH_ALEN];
4675	int iface_addr = 0;
4676
4677	pos = cmd;
4678	if (os_strncmp(pos, "iface=", 6) == 0) {
4679		iface_addr = 1;
4680		pos += 6;
4681	}
4682	if (hwaddr_aton(pos, peer))
4683		return -1;
4684
4685	wpas_p2p_remove_client(wpa_s, peer, iface_addr);
4686	return 0;
4687}
4688
4689#endif /* CONFIG_P2P */
4690
4691
4692#ifdef CONFIG_INTERWORKING
4693static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
4694{
4695	u8 bssid[ETH_ALEN];
4696	struct wpa_bss *bss;
4697
4698	if (hwaddr_aton(dst, bssid)) {
4699		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
4700		return -1;
4701	}
4702
4703	bss = wpa_bss_get_bssid(wpa_s, bssid);
4704	if (bss == NULL) {
4705		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
4706			   MAC2STR(bssid));
4707		return -1;
4708	}
4709
4710	return interworking_connect(wpa_s, bss);
4711}
4712
4713
4714static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
4715{
4716	u8 dst_addr[ETH_ALEN];
4717	int used;
4718	char *pos;
4719#define MAX_ANQP_INFO_ID 100
4720	u16 id[MAX_ANQP_INFO_ID];
4721	size_t num_id = 0;
4722
4723	used = hwaddr_aton2(dst, dst_addr);
4724	if (used < 0)
4725		return -1;
4726	pos = dst + used;
4727	while (num_id < MAX_ANQP_INFO_ID) {
4728		id[num_id] = atoi(pos);
4729		if (id[num_id])
4730			num_id++;
4731		pos = os_strchr(pos + 1, ',');
4732		if (pos == NULL)
4733			break;
4734		pos++;
4735	}
4736
4737	if (num_id == 0)
4738		return -1;
4739
4740	return anqp_send_req(wpa_s, dst_addr, id, num_id);
4741}
4742
4743
4744static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
4745{
4746	u8 dst_addr[ETH_ALEN];
4747	struct wpabuf *advproto, *query = NULL;
4748	int used, ret = -1;
4749	char *pos, *end;
4750	size_t len;
4751
4752	used = hwaddr_aton2(cmd, dst_addr);
4753	if (used < 0)
4754		return -1;
4755
4756	pos = cmd + used;
4757	while (*pos == ' ')
4758		pos++;
4759
4760	/* Advertisement Protocol ID */
4761	end = os_strchr(pos, ' ');
4762	if (end)
4763		len = end - pos;
4764	else
4765		len = os_strlen(pos);
4766	if (len & 0x01)
4767		return -1;
4768	len /= 2;
4769	if (len == 0)
4770		return -1;
4771	advproto = wpabuf_alloc(len);
4772	if (advproto == NULL)
4773		return -1;
4774	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
4775		goto fail;
4776
4777	if (end) {
4778		/* Optional Query Request */
4779		pos = end + 1;
4780		while (*pos == ' ')
4781			pos++;
4782
4783		len = os_strlen(pos);
4784		if (len) {
4785			if (len & 0x01)
4786				goto fail;
4787			len /= 2;
4788			if (len == 0)
4789				goto fail;
4790			query = wpabuf_alloc(len);
4791			if (query == NULL)
4792				goto fail;
4793			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
4794				goto fail;
4795		}
4796	}
4797
4798	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
4799
4800fail:
4801	wpabuf_free(advproto);
4802	wpabuf_free(query);
4803
4804	return ret;
4805}
4806
4807
4808static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
4809			    size_t buflen)
4810{
4811	u8 addr[ETH_ALEN];
4812	int dialog_token;
4813	int used;
4814	char *pos;
4815	size_t resp_len, start, requested_len;
4816
4817	if (!wpa_s->last_gas_resp)
4818		return -1;
4819
4820	used = hwaddr_aton2(cmd, addr);
4821	if (used < 0)
4822		return -1;
4823
4824	pos = cmd + used;
4825	while (*pos == ' ')
4826		pos++;
4827	dialog_token = atoi(pos);
4828
4829	if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 ||
4830	    dialog_token != wpa_s->last_gas_dialog_token)
4831		return -1;
4832
4833	resp_len = wpabuf_len(wpa_s->last_gas_resp);
4834	start = 0;
4835	requested_len = resp_len;
4836
4837	pos = os_strchr(pos, ' ');
4838	if (pos) {
4839		start = atoi(pos);
4840		if (start > resp_len)
4841			return os_snprintf(buf, buflen, "FAIL-Invalid range");
4842		pos = os_strchr(pos, ',');
4843		if (pos == NULL)
4844			return -1;
4845		pos++;
4846		requested_len = atoi(pos);
4847		if (start + requested_len > resp_len)
4848			return os_snprintf(buf, buflen, "FAIL-Invalid range");
4849	}
4850
4851	if (requested_len * 2 + 1 > buflen)
4852		return os_snprintf(buf, buflen, "FAIL-Too long response");
4853
4854	return wpa_snprintf_hex(buf, buflen,
4855				wpabuf_head_u8(wpa_s->last_gas_resp) + start,
4856				requested_len);
4857}
4858#endif /* CONFIG_INTERWORKING */
4859
4860
4861#ifdef CONFIG_HS20
4862
4863static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
4864{
4865	u8 dst_addr[ETH_ALEN];
4866	int used;
4867	char *pos;
4868	u32 subtypes = 0;
4869
4870	used = hwaddr_aton2(dst, dst_addr);
4871	if (used < 0)
4872		return -1;
4873	pos = dst + used;
4874	for (;;) {
4875		int num = atoi(pos);
4876		if (num <= 0 || num > 31)
4877			return -1;
4878		subtypes |= BIT(num);
4879		pos = os_strchr(pos + 1, ',');
4880		if (pos == NULL)
4881			break;
4882		pos++;
4883	}
4884
4885	if (subtypes == 0)
4886		return -1;
4887
4888	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
4889}
4890
4891
4892static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
4893				    const u8 *addr, const char *realm)
4894{
4895	u8 *buf;
4896	size_t rlen, len;
4897	int ret;
4898
4899	rlen = os_strlen(realm);
4900	len = 3 + rlen;
4901	buf = os_malloc(len);
4902	if (buf == NULL)
4903		return -1;
4904	buf[0] = 1; /* NAI Home Realm Count */
4905	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
4906	buf[2] = rlen;
4907	os_memcpy(buf + 3, realm, rlen);
4908
4909	ret = hs20_anqp_send_req(wpa_s, addr,
4910				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
4911				 buf, len);
4912
4913	os_free(buf);
4914
4915	return ret;
4916}
4917
4918
4919static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
4920					char *dst)
4921{
4922	struct wpa_cred *cred = wpa_s->conf->cred;
4923	u8 dst_addr[ETH_ALEN];
4924	int used;
4925	u8 *buf;
4926	size_t len;
4927	int ret;
4928
4929	used = hwaddr_aton2(dst, dst_addr);
4930	if (used < 0)
4931		return -1;
4932
4933	while (dst[used] == ' ')
4934		used++;
4935	if (os_strncmp(dst + used, "realm=", 6) == 0)
4936		return hs20_nai_home_realm_list(wpa_s, dst_addr,
4937						dst + used + 6);
4938
4939	len = os_strlen(dst + used);
4940
4941	if (len == 0 && cred && cred->realm)
4942		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
4943
4944	if (len % 1)
4945		return -1;
4946	len /= 2;
4947	buf = os_malloc(len);
4948	if (buf == NULL)
4949		return -1;
4950	if (hexstr2bin(dst + used, buf, len) < 0) {
4951		os_free(buf);
4952		return -1;
4953	}
4954
4955	ret = hs20_anqp_send_req(wpa_s, dst_addr,
4956				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
4957				 buf, len);
4958	os_free(buf);
4959
4960	return ret;
4961}
4962
4963#endif /* CONFIG_HS20 */
4964
4965
4966static int wpa_supplicant_ctrl_iface_sta_autoconnect(
4967	struct wpa_supplicant *wpa_s, char *cmd)
4968{
4969	wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
4970	return 0;
4971}
4972
4973
4974#ifdef CONFIG_AUTOSCAN
4975
4976static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
4977					      char *cmd)
4978{
4979	enum wpa_states state = wpa_s->wpa_state;
4980	char *new_params = NULL;
4981
4982	if (os_strlen(cmd) > 0) {
4983		new_params = os_strdup(cmd);
4984		if (new_params == NULL)
4985			return -1;
4986	}
4987
4988	os_free(wpa_s->conf->autoscan);
4989	wpa_s->conf->autoscan = new_params;
4990
4991	if (wpa_s->conf->autoscan == NULL)
4992		autoscan_deinit(wpa_s);
4993	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
4994		autoscan_init(wpa_s, 1);
4995	else if (state == WPA_SCANNING)
4996		wpa_supplicant_reinit_autoscan(wpa_s);
4997
4998	return 0;
4999}
5000
5001#endif /* CONFIG_AUTOSCAN */
5002
5003
5004#ifdef CONFIG_WNM
5005
5006static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
5007{
5008	int enter;
5009	int intval = 0;
5010	char *pos;
5011	int ret;
5012	struct wpabuf *tfs_req = NULL;
5013
5014	if (os_strncmp(cmd, "enter", 5) == 0)
5015		enter = 1;
5016	else if (os_strncmp(cmd, "exit", 4) == 0)
5017		enter = 0;
5018	else
5019		return -1;
5020
5021	pos = os_strstr(cmd, " interval=");
5022	if (pos)
5023		intval = atoi(pos + 10);
5024
5025	pos = os_strstr(cmd, " tfs_req=");
5026	if (pos) {
5027		char *end;
5028		size_t len;
5029		pos += 9;
5030		end = os_strchr(pos, ' ');
5031		if (end)
5032			len = end - pos;
5033		else
5034			len = os_strlen(pos);
5035		if (len & 1)
5036			return -1;
5037		len /= 2;
5038		tfs_req = wpabuf_alloc(len);
5039		if (tfs_req == NULL)
5040			return -1;
5041		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
5042			wpabuf_free(tfs_req);
5043			return -1;
5044		}
5045	}
5046
5047	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
5048					   WNM_SLEEP_MODE_EXIT, intval,
5049					   tfs_req);
5050	wpabuf_free(tfs_req);
5051
5052	return ret;
5053}
5054
5055
5056static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
5057{
5058	int query_reason;
5059
5060	query_reason = atoi(cmd);
5061
5062	wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
5063		   query_reason);
5064
5065	return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
5066}
5067
5068#endif /* CONFIG_WNM */
5069
5070
5071/* Get string representation of channel width */
5072static const char * channel_width_name(enum chan_width width)
5073{
5074	switch (width) {
5075	case CHAN_WIDTH_20_NOHT:
5076		return "20 MHz (no HT)";
5077	case CHAN_WIDTH_20:
5078		return "20 MHz";
5079	case CHAN_WIDTH_40:
5080		return "40 MHz";
5081	case CHAN_WIDTH_80:
5082		return "80 MHz";
5083	case CHAN_WIDTH_80P80:
5084		return "80+80 MHz";
5085	case CHAN_WIDTH_160:
5086		return "160 MHz";
5087	default:
5088		return "unknown";
5089	}
5090}
5091
5092
5093static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
5094				      size_t buflen)
5095{
5096	struct wpa_signal_info si;
5097	int ret;
5098	char *pos, *end;
5099
5100	ret = wpa_drv_signal_poll(wpa_s, &si);
5101	if (ret)
5102		return -1;
5103
5104	pos = buf;
5105	end = buf + buflen;
5106
5107	ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
5108			  "NOISE=%d\nFREQUENCY=%u\n",
5109			  si.current_signal, si.current_txrate / 1000,
5110			  si.current_noise, si.frequency);
5111	if (ret < 0 || ret > end - pos)
5112		return -1;
5113	pos += ret;
5114
5115	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
5116		ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
5117				  channel_width_name(si.chanwidth));
5118		if (ret < 0 || ret > end - pos)
5119			return -1;
5120		pos += ret;
5121	}
5122
5123	if (si.center_frq1 > 0 && si.center_frq2 > 0) {
5124		ret = os_snprintf(pos, end - pos,
5125				  "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
5126				  si.center_frq1, si.center_frq2);
5127		if (ret < 0 || ret > end - pos)
5128			return -1;
5129		pos += ret;
5130	}
5131
5132	if (si.avg_signal) {
5133		ret = os_snprintf(pos, end - pos,
5134				  "AVG_RSSI=%d\n", si.avg_signal);
5135		if (ret < 0 || ret >= end - pos)
5136			return -1;
5137		pos += ret;
5138	}
5139
5140	return pos - buf;
5141}
5142
5143
5144static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
5145				      size_t buflen)
5146{
5147	struct hostap_sta_driver_data sta;
5148	int ret;
5149
5150	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
5151	if (ret)
5152		return -1;
5153
5154	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
5155			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
5156	if (ret < 0 || (size_t) ret > buflen)
5157		return -1;
5158	return ret;
5159}
5160
5161
5162#ifdef ANDROID
5163static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
5164				     char *buf, size_t buflen)
5165{
5166	int ret;
5167
5168	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
5169	if (ret == 0) {
5170		if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
5171			struct p2p_data *p2p = wpa_s->global->p2p;
5172			if (p2p) {
5173				char country[3];
5174				country[0] = cmd[8];
5175				country[1] = cmd[9];
5176				country[2] = 0x04;
5177				p2p_set_country(p2p, country);
5178			}
5179		}
5180		ret = sprintf(buf, "%s\n", "OK");
5181	}
5182	return ret;
5183}
5184#endif
5185
5186
5187static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
5188{
5189	wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
5190
5191#ifdef CONFIG_P2P
5192	wpas_p2p_stop_find(wpa_s);
5193	p2p_ctrl_flush(wpa_s);
5194	wpas_p2p_group_remove(wpa_s, "*");
5195#endif /* CONFIG_P2P */
5196
5197#ifdef CONFIG_WPS_TESTING
5198	wps_version_number = 0x20;
5199	wps_testing_dummy_cred = 0;
5200#endif /* CONFIG_WPS_TESTING */
5201#ifdef CONFIG_WPS
5202	wpas_wps_cancel(wpa_s);
5203#endif /* CONFIG_WPS */
5204
5205#ifdef CONFIG_TDLS_TESTING
5206	extern unsigned int tdls_testing;
5207	tdls_testing = 0;
5208#endif /* CONFIG_TDLS_TESTING */
5209#ifdef CONFIG_TDLS
5210	wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
5211	wpa_tdls_enable(wpa_s->wpa, 1);
5212#endif /* CONFIG_TDLS */
5213
5214	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
5215	wpa_supplicant_stop_countermeasures(wpa_s, NULL);
5216
5217	wpa_s->no_keep_alive = 0;
5218
5219	os_free(wpa_s->disallow_aps_bssid);
5220	wpa_s->disallow_aps_bssid = NULL;
5221	wpa_s->disallow_aps_bssid_count = 0;
5222	os_free(wpa_s->disallow_aps_ssid);
5223	wpa_s->disallow_aps_ssid = NULL;
5224	wpa_s->disallow_aps_ssid_count = 0;
5225
5226	wpa_s->set_sta_uapsd = 0;
5227	wpa_s->sta_uapsd = 0;
5228
5229	wpa_drv_radio_disable(wpa_s, 0);
5230
5231	wpa_bss_flush(wpa_s);
5232	wpa_blacklist_clear(wpa_s);
5233	wpa_s->extra_blacklist_count = 0;
5234	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
5235	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
5236}
5237
5238
5239char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
5240					 char *buf, size_t *resp_len)
5241{
5242	char *reply;
5243	const int reply_size = 4096;
5244	int ctrl_rsp = 0;
5245	int reply_len;
5246
5247	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
5248	    os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
5249	    os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
5250	    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
5251	    os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
5252		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
5253				      (const u8 *) buf, os_strlen(buf));
5254	} else {
5255		int level = MSG_DEBUG;
5256		if (os_strcmp(buf, "PING") == 0)
5257			level = MSG_EXCESSIVE;
5258		wpa_hexdump_ascii(level, "RX ctrl_iface",
5259				  (const u8 *) buf, os_strlen(buf));
5260		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
5261	}
5262
5263	reply = os_malloc(reply_size);
5264	if (reply == NULL) {
5265		*resp_len = 1;
5266		return NULL;
5267	}
5268
5269	os_memcpy(reply, "OK\n", 3);
5270	reply_len = 3;
5271
5272	if (os_strcmp(buf, "PING") == 0) {
5273		os_memcpy(reply, "PONG\n", 5);
5274		reply_len = 5;
5275	} else if (os_strcmp(buf, "IFNAME") == 0) {
5276		reply_len = os_strlen(wpa_s->ifname);
5277		os_memcpy(reply, wpa_s->ifname, reply_len);
5278	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
5279		if (wpa_debug_reopen_file() < 0)
5280			reply_len = -1;
5281	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
5282		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
5283	} else if (os_strcmp(buf, "MIB") == 0) {
5284		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
5285		if (reply_len >= 0) {
5286			int res;
5287			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
5288					       reply_size - reply_len);
5289			if (res < 0)
5290				reply_len = -1;
5291			else
5292				reply_len += res;
5293		}
5294	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
5295		reply_len = wpa_supplicant_ctrl_iface_status(
5296			wpa_s, buf + 6, reply, reply_size);
5297	} else if (os_strcmp(buf, "PMKSA") == 0) {
5298		reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
5299						    reply_size);
5300	} else if (os_strncmp(buf, "SET ", 4) == 0) {
5301		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
5302			reply_len = -1;
5303	} else if (os_strncmp(buf, "GET ", 4) == 0) {
5304		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
5305							  reply, reply_size);
5306	} else if (os_strcmp(buf, "LOGON") == 0) {
5307		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
5308	} else if (os_strcmp(buf, "LOGOFF") == 0) {
5309		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
5310	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
5311		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5312			reply_len = -1;
5313		else
5314			wpas_request_connection(wpa_s);
5315	} else if (os_strcmp(buf, "RECONNECT") == 0) {
5316		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5317			reply_len = -1;
5318		else if (wpa_s->disconnected)
5319			wpas_request_connection(wpa_s);
5320#ifdef IEEE8021X_EAPOL
5321	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
5322		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
5323			reply_len = -1;
5324#endif /* IEEE8021X_EAPOL */
5325#ifdef CONFIG_PEERKEY
5326	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
5327		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
5328			reply_len = -1;
5329#endif /* CONFIG_PEERKEY */
5330#ifdef CONFIG_IEEE80211R
5331	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
5332		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
5333			reply_len = -1;
5334#endif /* CONFIG_IEEE80211R */
5335#ifdef CONFIG_WPS
5336	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
5337		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
5338		if (res == -2) {
5339			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
5340			reply_len = 17;
5341		} else if (res)
5342			reply_len = -1;
5343	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
5344		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
5345		if (res == -2) {
5346			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
5347			reply_len = 17;
5348		} else if (res)
5349			reply_len = -1;
5350	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
5351		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
5352							      reply,
5353							      reply_size);
5354	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
5355		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
5356			wpa_s, buf + 14, reply, reply_size);
5357	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
5358		if (wpas_wps_cancel(wpa_s))
5359			reply_len = -1;
5360#ifdef CONFIG_WPS_NFC
5361	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
5362		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
5363			reply_len = -1;
5364	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
5365		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
5366			reply_len = -1;
5367	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
5368		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
5369			wpa_s, buf + 21, reply, reply_size);
5370	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
5371		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
5372			wpa_s, buf + 14, reply, reply_size);
5373	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
5374		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
5375							       buf + 17))
5376			reply_len = -1;
5377	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
5378		reply_len = wpas_ctrl_nfc_get_handover_req(
5379			wpa_s, buf + 21, reply, reply_size);
5380	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
5381		reply_len = wpas_ctrl_nfc_get_handover_sel(
5382			wpa_s, buf + 21, reply, reply_size);
5383	} else if (os_strncmp(buf, "NFC_RX_HANDOVER_REQ ", 20) == 0) {
5384		reply_len = wpas_ctrl_nfc_rx_handover_req(
5385			wpa_s, buf + 20, reply, reply_size);
5386	} else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) {
5387		if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20))
5388			reply_len = -1;
5389	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
5390		if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
5391			reply_len = -1;
5392#endif /* CONFIG_WPS_NFC */
5393	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
5394		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
5395			reply_len = -1;
5396#ifdef CONFIG_AP
5397	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
5398		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
5399			wpa_s, buf + 11, reply, reply_size);
5400#endif /* CONFIG_AP */
5401#ifdef CONFIG_WPS_ER
5402	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
5403		if (wpas_wps_er_start(wpa_s, NULL))
5404			reply_len = -1;
5405	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
5406		if (wpas_wps_er_start(wpa_s, buf + 13))
5407			reply_len = -1;
5408	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
5409		if (wpas_wps_er_stop(wpa_s))
5410			reply_len = -1;
5411	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
5412		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
5413			reply_len = -1;
5414	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
5415		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
5416		if (ret == -2) {
5417			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
5418			reply_len = 17;
5419		} else if (ret == -3) {
5420			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
5421			reply_len = 18;
5422		} else if (ret == -4) {
5423			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
5424			reply_len = 20;
5425		} else if (ret)
5426			reply_len = -1;
5427	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
5428		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
5429			reply_len = -1;
5430	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
5431		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
5432								buf + 18))
5433			reply_len = -1;
5434	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
5435		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
5436			reply_len = -1;
5437#ifdef CONFIG_WPS_NFC
5438	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
5439		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
5440			wpa_s, buf + 24, reply, reply_size);
5441#endif /* CONFIG_WPS_NFC */
5442#endif /* CONFIG_WPS_ER */
5443#endif /* CONFIG_WPS */
5444#ifdef CONFIG_IBSS_RSN
5445	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
5446		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
5447			reply_len = -1;
5448#endif /* CONFIG_IBSS_RSN */
5449#ifdef CONFIG_P2P
5450	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
5451		if (p2p_ctrl_find(wpa_s, buf + 9))
5452			reply_len = -1;
5453	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
5454		if (p2p_ctrl_find(wpa_s, ""))
5455			reply_len = -1;
5456	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
5457		wpas_p2p_stop_find(wpa_s);
5458	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
5459		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
5460					     reply_size);
5461	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
5462		if (p2p_ctrl_listen(wpa_s, buf + 11))
5463			reply_len = -1;
5464	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
5465		if (p2p_ctrl_listen(wpa_s, ""))
5466			reply_len = -1;
5467	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
5468		if (wpas_p2p_group_remove(wpa_s, buf + 17))
5469			reply_len = -1;
5470	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
5471		if (wpas_p2p_group_add(wpa_s, 0, 0, 0))
5472			reply_len = -1;
5473	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
5474		if (p2p_ctrl_group_add(wpa_s, buf + 14))
5475			reply_len = -1;
5476	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
5477		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
5478			reply_len = -1;
5479	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
5480		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
5481	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
5482		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
5483						   reply_size);
5484	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
5485		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
5486			reply_len = -1;
5487	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
5488		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
5489			reply_len = -1;
5490	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
5491		wpas_p2p_sd_service_update(wpa_s);
5492	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
5493		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
5494			reply_len = -1;
5495	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
5496		wpas_p2p_service_flush(wpa_s);
5497	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
5498		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
5499			reply_len = -1;
5500	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
5501		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
5502			reply_len = -1;
5503	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
5504		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
5505			reply_len = -1;
5506	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
5507		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
5508			reply_len = -1;
5509	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
5510		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
5511					      reply_size);
5512	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
5513		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
5514			reply_len = -1;
5515	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
5516		p2p_ctrl_flush(wpa_s);
5517	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
5518		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
5519			reply_len = -1;
5520	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
5521		if (wpas_p2p_cancel(wpa_s))
5522			reply_len = -1;
5523	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
5524		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
5525			reply_len = -1;
5526	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
5527		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
5528			reply_len = -1;
5529	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
5530		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
5531			reply_len = -1;
5532	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
5533		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
5534			reply_len = -1;
5535	} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
5536		if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
5537			reply_len = -1;
5538#endif /* CONFIG_P2P */
5539#ifdef CONFIG_WIFI_DISPLAY
5540	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
5541		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
5542			reply_len = -1;
5543	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
5544		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
5545						     reply, reply_size);
5546#endif /* CONFIG_WIFI_DISPLAY */
5547#ifdef CONFIG_INTERWORKING
5548	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
5549		if (interworking_fetch_anqp(wpa_s) < 0)
5550			reply_len = -1;
5551	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
5552		interworking_stop_fetch_anqp(wpa_s);
5553	} else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) {
5554		if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") !=
5555					NULL) < 0)
5556			reply_len = -1;
5557	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
5558		if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
5559			reply_len = -1;
5560	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
5561		if (get_anqp(wpa_s, buf + 9) < 0)
5562			reply_len = -1;
5563	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
5564		if (gas_request(wpa_s, buf + 12) < 0)
5565			reply_len = -1;
5566	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
5567		reply_len = gas_response_get(wpa_s, buf + 17, reply,
5568					     reply_size);
5569#endif /* CONFIG_INTERWORKING */
5570#ifdef CONFIG_HS20
5571	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
5572		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
5573			reply_len = -1;
5574	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
5575		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
5576			reply_len = -1;
5577#endif /* CONFIG_HS20 */
5578	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
5579	{
5580		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
5581			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
5582			reply_len = -1;
5583		else
5584			ctrl_rsp = 1;
5585	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
5586		if (wpa_supplicant_reload_configuration(wpa_s))
5587			reply_len = -1;
5588	} else if (os_strcmp(buf, "TERMINATE") == 0) {
5589		wpa_supplicant_terminate_proc(wpa_s->global);
5590	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
5591		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
5592			reply_len = -1;
5593	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
5594		reply_len = wpa_supplicant_ctrl_iface_blacklist(
5595			wpa_s, buf + 9, reply, reply_size);
5596	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
5597		reply_len = wpa_supplicant_ctrl_iface_log_level(
5598			wpa_s, buf + 9, reply, reply_size);
5599	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
5600		reply_len = wpa_supplicant_ctrl_iface_list_networks(
5601			wpa_s, reply, reply_size);
5602	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
5603#ifdef CONFIG_SME
5604		wpa_s->sme.prev_bssid_set = 0;
5605#endif /* CONFIG_SME */
5606		wpa_s->reassociate = 0;
5607		wpa_s->disconnected = 1;
5608		wpa_supplicant_cancel_sched_scan(wpa_s);
5609		wpa_supplicant_cancel_scan(wpa_s);
5610		wpa_supplicant_deauthenticate(wpa_s,
5611					      WLAN_REASON_DEAUTH_LEAVING);
5612	} else if (os_strcmp(buf, "SCAN") == 0 ||
5613		   os_strncmp(buf, "SCAN ", 5) == 0) {
5614		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5615			reply_len = -1;
5616		else {
5617			if (os_strlen(buf) > 4 &&
5618			    os_strncasecmp(buf + 5, "TYPE=ONLY", 9) == 0)
5619				wpa_s->scan_res_handler = scan_only_handler;
5620			if (!wpa_s->sched_scanning && !wpa_s->scanning &&
5621			    ((wpa_s->wpa_state <= WPA_SCANNING) ||
5622			     (wpa_s->wpa_state == WPA_COMPLETED))) {
5623				wpa_s->normal_scans = 0;
5624				wpa_s->scan_req = MANUAL_SCAN_REQ;
5625				wpa_supplicant_req_scan(wpa_s, 0, 0);
5626			} else if (wpa_s->sched_scanning) {
5627				wpa_printf(MSG_DEBUG, "Stop ongoing "
5628					   "sched_scan to allow requested "
5629					   "full scan to proceed");
5630				wpa_supplicant_cancel_sched_scan(wpa_s);
5631				wpa_s->scan_req = MANUAL_SCAN_REQ;
5632				wpa_supplicant_req_scan(wpa_s, 0, 0);
5633			} else {
5634				wpa_printf(MSG_DEBUG, "Ongoing scan action - "
5635					   "reject new request");
5636				reply_len = os_snprintf(reply, reply_size,
5637							"FAIL-BUSY\n");
5638			}
5639		}
5640	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
5641		reply_len = wpa_supplicant_ctrl_iface_scan_results(
5642			wpa_s, reply, reply_size);
5643	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
5644		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
5645			reply_len = -1;
5646	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
5647		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
5648			reply_len = -1;
5649	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
5650		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
5651			reply_len = -1;
5652	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
5653		reply_len = wpa_supplicant_ctrl_iface_add_network(
5654			wpa_s, reply, reply_size);
5655	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
5656		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
5657			reply_len = -1;
5658	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
5659		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
5660			reply_len = -1;
5661	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
5662		reply_len = wpa_supplicant_ctrl_iface_get_network(
5663			wpa_s, buf + 12, reply, reply_size);
5664	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
5665		reply_len = wpa_supplicant_ctrl_iface_list_creds(
5666			wpa_s, reply, reply_size);
5667	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
5668		reply_len = wpa_supplicant_ctrl_iface_add_cred(
5669			wpa_s, reply, reply_size);
5670	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
5671		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
5672			reply_len = -1;
5673	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
5674		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
5675			reply_len = -1;
5676#ifndef CONFIG_NO_CONFIG_WRITE
5677	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
5678		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
5679			reply_len = -1;
5680#endif /* CONFIG_NO_CONFIG_WRITE */
5681	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
5682		reply_len = wpa_supplicant_ctrl_iface_get_capability(
5683			wpa_s, buf + 15, reply, reply_size);
5684	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
5685		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
5686			reply_len = -1;
5687	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
5688		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
5689			reply_len = -1;
5690	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
5691		reply_len = wpa_supplicant_global_iface_list(
5692			wpa_s->global, reply, reply_size);
5693	} else if (os_strcmp(buf, "INTERFACES") == 0) {
5694		reply_len = wpa_supplicant_global_iface_interfaces(
5695			wpa_s->global, reply, reply_size);
5696	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
5697		reply_len = wpa_supplicant_ctrl_iface_bss(
5698			wpa_s, buf + 4, reply, reply_size);
5699#ifdef CONFIG_AP
5700	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
5701		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
5702	} else if (os_strncmp(buf, "STA ", 4) == 0) {
5703		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
5704					      reply_size);
5705	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
5706		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
5707						   reply_size);
5708	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
5709		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
5710			reply_len = -1;
5711	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
5712		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
5713			reply_len = -1;
5714#endif /* CONFIG_AP */
5715	} else if (os_strcmp(buf, "SUSPEND") == 0) {
5716		wpas_notify_suspend(wpa_s->global);
5717	} else if (os_strcmp(buf, "RESUME") == 0) {
5718		wpas_notify_resume(wpa_s->global);
5719	} else if (os_strcmp(buf, "DROP_SA") == 0) {
5720		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
5721	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
5722		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
5723			reply_len = -1;
5724	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
5725		if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
5726			reply_len = -1;
5727	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
5728		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
5729			reply_len = -1;
5730	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
5731		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
5732							       buf + 17))
5733			reply_len = -1;
5734	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
5735		if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10))
5736			reply_len = -1;
5737#ifdef CONFIG_TDLS
5738	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
5739		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
5740			reply_len = -1;
5741	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
5742		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
5743			reply_len = -1;
5744	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
5745		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
5746			reply_len = -1;
5747#endif /* CONFIG_TDLS */
5748	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
5749		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
5750						       reply_size);
5751	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
5752		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
5753						       reply_size);
5754#ifdef CONFIG_AUTOSCAN
5755	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
5756		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
5757			reply_len = -1;
5758#endif /* CONFIG_AUTOSCAN */
5759#ifdef ANDROID
5760	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
5761		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
5762						      reply_size);
5763#endif
5764	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
5765		pmksa_cache_clear_current(wpa_s->wpa);
5766		eapol_sm_request_reauth(wpa_s->eapol);
5767#ifdef CONFIG_WNM
5768	} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
5769		if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
5770			reply_len = -1;
5771	} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 10) == 0) {
5772		if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 10))
5773				reply_len = -1;
5774#endif /* CONFIG_WNM */
5775	} else if (os_strcmp(buf, "FLUSH") == 0) {
5776		wpa_supplicant_ctrl_iface_flush(wpa_s);
5777	} else {
5778		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
5779		reply_len = 16;
5780	}
5781
5782	if (reply_len < 0) {
5783		os_memcpy(reply, "FAIL\n", 5);
5784		reply_len = 5;
5785	}
5786
5787	if (ctrl_rsp)
5788		eapol_sm_notify_ctrl_response(wpa_s->eapol);
5789
5790	*resp_len = reply_len;
5791	return reply;
5792}
5793
5794
5795static int wpa_supplicant_global_iface_add(struct wpa_global *global,
5796					   char *cmd)
5797{
5798	struct wpa_interface iface;
5799	char *pos;
5800
5801	/*
5802	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
5803	 * TAB<bridge_ifname>
5804	 */
5805	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
5806
5807	os_memset(&iface, 0, sizeof(iface));
5808
5809	do {
5810		iface.ifname = pos = cmd;
5811		pos = os_strchr(pos, '\t');
5812		if (pos)
5813			*pos++ = '\0';
5814		if (iface.ifname[0] == '\0')
5815			return -1;
5816		if (pos == NULL)
5817			break;
5818
5819		iface.confname = pos;
5820		pos = os_strchr(pos, '\t');
5821		if (pos)
5822			*pos++ = '\0';
5823		if (iface.confname[0] == '\0')
5824			iface.confname = NULL;
5825		if (pos == NULL)
5826			break;
5827
5828		iface.driver = pos;
5829		pos = os_strchr(pos, '\t');
5830		if (pos)
5831			*pos++ = '\0';
5832		if (iface.driver[0] == '\0')
5833			iface.driver = NULL;
5834		if (pos == NULL)
5835			break;
5836
5837		iface.ctrl_interface = pos;
5838		pos = os_strchr(pos, '\t');
5839		if (pos)
5840			*pos++ = '\0';
5841		if (iface.ctrl_interface[0] == '\0')
5842			iface.ctrl_interface = NULL;
5843		if (pos == NULL)
5844			break;
5845
5846		iface.driver_param = pos;
5847		pos = os_strchr(pos, '\t');
5848		if (pos)
5849			*pos++ = '\0';
5850		if (iface.driver_param[0] == '\0')
5851			iface.driver_param = NULL;
5852		if (pos == NULL)
5853			break;
5854
5855		iface.bridge_ifname = pos;
5856		pos = os_strchr(pos, '\t');
5857		if (pos)
5858			*pos++ = '\0';
5859		if (iface.bridge_ifname[0] == '\0')
5860			iface.bridge_ifname = NULL;
5861		if (pos == NULL)
5862			break;
5863	} while (0);
5864
5865	if (wpa_supplicant_get_iface(global, iface.ifname))
5866		return -1;
5867
5868	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
5869}
5870
5871
5872static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
5873					      char *cmd)
5874{
5875	struct wpa_supplicant *wpa_s;
5876
5877	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
5878
5879	wpa_s = wpa_supplicant_get_iface(global, cmd);
5880	if (wpa_s == NULL)
5881		return -1;
5882	return wpa_supplicant_remove_iface(global, wpa_s, 0);
5883}
5884
5885
5886static void wpa_free_iface_info(struct wpa_interface_info *iface)
5887{
5888	struct wpa_interface_info *prev;
5889
5890	while (iface) {
5891		prev = iface;
5892		iface = iface->next;
5893
5894		os_free(prev->ifname);
5895		os_free(prev->desc);
5896		os_free(prev);
5897	}
5898}
5899
5900
5901static int wpa_supplicant_global_iface_list(struct wpa_global *global,
5902					    char *buf, int len)
5903{
5904	int i, res;
5905	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
5906	char *pos, *end;
5907
5908	for (i = 0; wpa_drivers[i]; i++) {
5909		struct wpa_driver_ops *drv = wpa_drivers[i];
5910		if (drv->get_interfaces == NULL)
5911			continue;
5912		tmp = drv->get_interfaces(global->drv_priv[i]);
5913		if (tmp == NULL)
5914			continue;
5915
5916		if (last == NULL)
5917			iface = last = tmp;
5918		else
5919			last->next = tmp;
5920		while (last->next)
5921			last = last->next;
5922	}
5923
5924	pos = buf;
5925	end = buf + len;
5926	for (tmp = iface; tmp; tmp = tmp->next) {
5927		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
5928				  tmp->drv_name, tmp->ifname,
5929				  tmp->desc ? tmp->desc : "");
5930		if (res < 0 || res >= end - pos) {
5931			*pos = '\0';
5932			break;
5933		}
5934		pos += res;
5935	}
5936
5937	wpa_free_iface_info(iface);
5938
5939	return pos - buf;
5940}
5941
5942
5943static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
5944						  char *buf, int len)
5945{
5946	int res;
5947	char *pos, *end;
5948	struct wpa_supplicant *wpa_s;
5949
5950	wpa_s = global->ifaces;
5951	pos = buf;
5952	end = buf + len;
5953
5954	while (wpa_s) {
5955		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
5956		if (res < 0 || res >= end - pos) {
5957			*pos = '\0';
5958			break;
5959		}
5960		pos += res;
5961		wpa_s = wpa_s->next;
5962	}
5963	return pos - buf;
5964}
5965
5966
5967static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
5968					    const char *ifname,
5969					    char *cmd, size_t *resp_len)
5970{
5971	struct wpa_supplicant *wpa_s;
5972
5973	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5974		if (os_strcmp(ifname, wpa_s->ifname) == 0)
5975			break;
5976	}
5977
5978	if (wpa_s == NULL) {
5979		char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
5980		if (resp)
5981			*resp_len = os_strlen(resp);
5982		else
5983			*resp_len = 1;
5984		return resp;
5985	}
5986
5987	return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
5988}
5989
5990
5991static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
5992					       char *buf, size_t *resp_len)
5993{
5994#ifdef CONFIG_P2P
5995	static const char * cmd[] = {
5996#ifdef ANDROID_P2P
5997		"LIST_NETWORKS",
5998		"SAVE_CONFIG",
5999#endif
6000		"P2P_FIND",
6001		"P2P_STOP_FIND",
6002		"P2P_LISTEN",
6003		"P2P_GROUP_ADD",
6004		"P2P_GET_PASSPHRASE",
6005		"P2P_SERVICE_UPDATE",
6006		"P2P_SERVICE_FLUSH",
6007		"P2P_FLUSH",
6008		"P2P_CANCEL",
6009		"P2P_PRESENCE_REQ",
6010		"P2P_EXT_LISTEN",
6011		NULL
6012	};
6013	static const char * prefix[] = {
6014#ifdef ANDROID_P2P
6015		"DRIVER ",
6016		"GET_NETWORK ",
6017		"REMOVE_NETWORK ",
6018		"SET ",
6019#endif
6020		"P2P_FIND ",
6021		"P2P_CONNECT ",
6022		"P2P_LISTEN ",
6023		"P2P_GROUP_REMOVE ",
6024		"P2P_GROUP_ADD ",
6025		"P2P_PROV_DISC ",
6026		"P2P_SERV_DISC_REQ ",
6027		"P2P_SERV_DISC_CANCEL_REQ ",
6028		"P2P_SERV_DISC_RESP ",
6029		"P2P_SERV_DISC_EXTERNAL ",
6030		"P2P_SERVICE_ADD ",
6031		"P2P_SERVICE_DEL ",
6032		"P2P_REJECT ",
6033		"P2P_INVITE ",
6034		"P2P_PEER ",
6035		"P2P_SET ",
6036		"P2P_UNAUTHORIZE ",
6037		"P2P_PRESENCE_REQ ",
6038		"P2P_EXT_LISTEN ",
6039		"P2P_REMOVE_CLIENT ",
6040		NULL
6041	};
6042	int found = 0;
6043	int i;
6044
6045	if (global->p2p_init_wpa_s == NULL)
6046		return NULL;
6047
6048	for (i = 0; !found && cmd[i]; i++) {
6049		if (os_strcmp(buf, cmd[i]) == 0)
6050			found = 1;
6051	}
6052
6053	for (i = 0; !found && prefix[i]; i++) {
6054		if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
6055			found = 1;
6056	}
6057
6058	if (found)
6059		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6060							 buf, resp_len);
6061#endif /* CONFIG_P2P */
6062	return NULL;
6063}
6064
6065
6066static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
6067					       char *buf, size_t *resp_len)
6068{
6069#ifdef CONFIG_WIFI_DISPLAY
6070	if (global->p2p_init_wpa_s == NULL)
6071		return NULL;
6072	if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
6073	    os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
6074		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6075							 buf, resp_len);
6076#endif /* CONFIG_WIFI_DISPLAY */
6077	return NULL;
6078}
6079
6080
6081static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
6082					   char *buf, size_t *resp_len)
6083{
6084	char *ret;
6085
6086	ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
6087	if (ret)
6088		return ret;
6089
6090	ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
6091	if (ret)
6092		return ret;
6093
6094	return NULL;
6095}
6096
6097
6098static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
6099{
6100	char *value;
6101
6102	value = os_strchr(cmd, ' ');
6103	if (value == NULL)
6104		return -1;
6105	*value++ = '\0';
6106
6107	wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
6108
6109#ifdef CONFIG_WIFI_DISPLAY
6110	if (os_strcasecmp(cmd, "wifi_display") == 0) {
6111		wifi_display_enable(global, !!atoi(value));
6112		return 0;
6113	}
6114#endif /* CONFIG_WIFI_DISPLAY */
6115
6116	return -1;
6117}
6118
6119
6120#ifndef CONFIG_NO_CONFIG_WRITE
6121static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
6122{
6123	int ret = 0;
6124	struct wpa_supplicant *wpa_s;
6125
6126	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6127		if (!wpa_s->conf->update_config) {
6128			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
6129			continue;
6130		}
6131
6132		if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
6133			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
6134			ret = 1;
6135		} else {
6136			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
6137		}
6138	}
6139
6140	return ret;
6141}
6142#endif /* CONFIG_NO_CONFIG_WRITE */
6143
6144
6145static int wpas_global_ctrl_iface_status(struct wpa_global *global,
6146					 char *buf, size_t buflen)
6147{
6148	char *pos, *end;
6149	int ret;
6150	struct wpa_supplicant *wpa_s;
6151
6152	pos = buf;
6153	end = buf + buflen;
6154
6155#ifdef CONFIG_P2P
6156	if (global->p2p && !global->p2p_disabled) {
6157		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
6158				  "\n"
6159				  "p2p_state=%s\n",
6160				  MAC2STR(global->p2p_dev_addr),
6161				  p2p_get_state_txt(global->p2p));
6162		if (ret < 0 || ret >= end - pos)
6163			return pos - buf;
6164		pos += ret;
6165	} else if (global->p2p) {
6166		ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
6167		if (ret < 0 || ret >= end - pos)
6168			return pos - buf;
6169		pos += ret;
6170	}
6171#endif /* CONFIG_P2P */
6172
6173#ifdef CONFIG_WIFI_DISPLAY
6174	ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
6175			  !!global->wifi_display);
6176	if (ret < 0 || ret >= end - pos)
6177		return pos - buf;
6178	pos += ret;
6179#endif /* CONFIG_WIFI_DISPLAY */
6180
6181	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6182		ret = os_snprintf(pos, end - pos, "ifname=%s\n"
6183				  "address=" MACSTR "\n",
6184				  wpa_s->ifname, MAC2STR(wpa_s->own_addr));
6185		if (ret < 0 || ret >= end - pos)
6186			return pos - buf;
6187		pos += ret;
6188	}
6189
6190	return pos - buf;
6191}
6192
6193
6194char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
6195						char *buf, size_t *resp_len)
6196{
6197	char *reply;
6198	const int reply_size = 2048;
6199	int reply_len;
6200	int level = MSG_DEBUG;
6201
6202	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
6203		char *pos = os_strchr(buf + 7, ' ');
6204		if (pos) {
6205			*pos++ = '\0';
6206			return wpas_global_ctrl_iface_ifname(global,
6207							     buf + 7, pos,
6208							     resp_len);
6209		}
6210	}
6211
6212	reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
6213	if (reply)
6214		return reply;
6215
6216	if (os_strcmp(buf, "PING") == 0)
6217		level = MSG_EXCESSIVE;
6218	wpa_hexdump_ascii(level, "RX global ctrl_iface",
6219			  (const u8 *) buf, os_strlen(buf));
6220
6221	reply = os_malloc(reply_size);
6222	if (reply == NULL) {
6223		*resp_len = 1;
6224		return NULL;
6225	}
6226
6227	os_memcpy(reply, "OK\n", 3);
6228	reply_len = 3;
6229
6230	if (os_strcmp(buf, "PING") == 0) {
6231		os_memcpy(reply, "PONG\n", 5);
6232		reply_len = 5;
6233	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
6234		if (wpa_supplicant_global_iface_add(global, buf + 14))
6235			reply_len = -1;
6236	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
6237		if (wpa_supplicant_global_iface_remove(global, buf + 17))
6238			reply_len = -1;
6239	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
6240		reply_len = wpa_supplicant_global_iface_list(
6241			global, reply, reply_size);
6242	} else if (os_strcmp(buf, "INTERFACES") == 0) {
6243		reply_len = wpa_supplicant_global_iface_interfaces(
6244			global, reply, reply_size);
6245	} else if (os_strcmp(buf, "TERMINATE") == 0) {
6246		wpa_supplicant_terminate_proc(global);
6247	} else if (os_strcmp(buf, "SUSPEND") == 0) {
6248		wpas_notify_suspend(global);
6249	} else if (os_strcmp(buf, "RESUME") == 0) {
6250		wpas_notify_resume(global);
6251	} else if (os_strncmp(buf, "SET ", 4) == 0) {
6252		if (wpas_global_ctrl_iface_set(global, buf + 4))
6253			reply_len = -1;
6254#ifndef CONFIG_NO_CONFIG_WRITE
6255	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
6256		if (wpas_global_ctrl_iface_save_config(global))
6257			reply_len = -1;
6258#endif /* CONFIG_NO_CONFIG_WRITE */
6259	} else if (os_strcmp(buf, "STATUS") == 0) {
6260		reply_len = wpas_global_ctrl_iface_status(global, reply,
6261							  reply_size);
6262	} else {
6263		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
6264		reply_len = 16;
6265	}
6266
6267	if (reply_len < 0) {
6268		os_memcpy(reply, "FAIL\n", 5);
6269		reply_len = 5;
6270	}
6271
6272	*resp_len = reply_len;
6273	return reply;
6274}
6275