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