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