ctrl_iface.c revision 281806
168651Skris/*
268651Skris * WPA Supplicant / Control interface (shared code for all backends)
368651Skris * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
468651Skris *
568651Skris * This software may be distributed under the terms of the BSD license.
668651Skris * See README for more details.
768651Skris */
868651Skris
968651Skris#include "utils/includes.h"
1068651Skris#ifdef CONFIG_TESTING_OPTIONS
1168651Skris#include <net/ethernet.h>
1268651Skris#include <netinet/ip.h>
1368651Skris#endif /* CONFIG_TESTING_OPTIONS */
1468651Skris
1568651Skris#include "utils/common.h"
1668651Skris#include "utils/eloop.h"
1768651Skris#include "utils/uuid.h"
1868651Skris#include "common/version.h"
1968651Skris#include "common/ieee802_11_defs.h"
2079998Skris#include "common/ieee802_11_common.h"
2179998Skris#include "common/wpa_ctrl.h"
2289837Skris#include "crypto/tls.h"
2379998Skris#include "ap/hostapd.h"
2479998Skris#include "eap_peer/eap.h"
2579998Skris#include "eapol_supp/eapol_supp_sm.h"
2668651Skris#include "rsn_supp/wpa.h"
2768651Skris#include "rsn_supp/preauth.h"
2868651Skris#include "rsn_supp/pmksa_cache.h"
2968651Skris#include "l2_packet/l2_packet.h"
3068651Skris#include "wps/wps.h"
3168651Skris#include "config.h"
3276866Skris#include "wpa_supplicant_i.h"
3368651Skris#include "driver_i.h"
3468651Skris#include "wps_supplicant.h"
3568651Skris#include "ibss_rsn.h"
3668651Skris#include "ap.h"
3768651Skris#include "p2p_supplicant.h"
3868651Skris#include "p2p/p2p.h"
3968651Skris#include "hs20_supplicant.h"
4068651Skris#include "wifi_display.h"
4168651Skris#include "notify.h"
4268651Skris#include "bss.h"
4368651Skris#include "scan.h"
4468651Skris#include "ctrl_iface.h"
4568651Skris#include "interworking.h"
4668651Skris#include "blacklist.h"
4768651Skris#include "autoscan.h"
4868651Skris#include "wnm_sta.h"
4968651Skris#include "offchannel.h"
5068651Skris#include "drivers/driver.h"
5168651Skris#include "mesh.h"
5279998Skris
5379998Skrisstatic int wpa_supplicant_global_iface_list(struct wpa_global *global,
5468651Skris					    char *buf, int len);
5568651Skrisstatic int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
56						  char *buf, int len);
57static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
58					char *val);
59
60static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
61{
62	char *pos;
63	u8 addr[ETH_ALEN], *filter = NULL, *n;
64	size_t count = 0;
65
66	pos = val;
67	while (pos) {
68		if (*pos == '\0')
69			break;
70		if (hwaddr_aton(pos, addr)) {
71			os_free(filter);
72			return -1;
73		}
74		n = os_realloc_array(filter, count + 1, ETH_ALEN);
75		if (n == NULL) {
76			os_free(filter);
77			return -1;
78		}
79		filter = n;
80		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
81		count++;
82
83		pos = os_strchr(pos, ' ');
84		if (pos)
85			pos++;
86	}
87
88	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
89	os_free(wpa_s->bssid_filter);
90	wpa_s->bssid_filter = filter;
91	wpa_s->bssid_filter_count = count;
92
93	return 0;
94}
95
96
97static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
98{
99	char *pos;
100	u8 addr[ETH_ALEN], *bssid = NULL, *n;
101	struct wpa_ssid_value *ssid = NULL, *ns;
102	size_t count = 0, ssid_count = 0;
103	struct wpa_ssid *c;
104
105	/*
106	 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
107	 * SSID_SPEC ::= ssid <SSID_HEX>
108	 * BSSID_SPEC ::= bssid <BSSID_HEX>
109	 */
110
111	pos = val;
112	while (pos) {
113		if (*pos == '\0')
114			break;
115		if (os_strncmp(pos, "bssid ", 6) == 0) {
116			int res;
117			pos += 6;
118			res = hwaddr_aton2(pos, addr);
119			if (res < 0) {
120				os_free(ssid);
121				os_free(bssid);
122				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
123					   "BSSID value '%s'", pos);
124				return -1;
125			}
126			pos += res;
127			n = os_realloc_array(bssid, count + 1, ETH_ALEN);
128			if (n == NULL) {
129				os_free(ssid);
130				os_free(bssid);
131				return -1;
132			}
133			bssid = n;
134			os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
135			count++;
136		} else if (os_strncmp(pos, "ssid ", 5) == 0) {
137			char *end;
138			pos += 5;
139
140			end = pos;
141			while (*end) {
142				if (*end == '\0' || *end == ' ')
143					break;
144				end++;
145			}
146
147			ns = os_realloc_array(ssid, ssid_count + 1,
148					      sizeof(struct wpa_ssid_value));
149			if (ns == NULL) {
150				os_free(ssid);
151				os_free(bssid);
152				return -1;
153			}
154			ssid = ns;
155
156			if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
157			    hexstr2bin(pos, ssid[ssid_count].ssid,
158				       (end - pos) / 2) < 0) {
159				os_free(ssid);
160				os_free(bssid);
161				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
162					   "SSID value '%s'", pos);
163				return -1;
164			}
165			ssid[ssid_count].ssid_len = (end - pos) / 2;
166			wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
167					  ssid[ssid_count].ssid,
168					  ssid[ssid_count].ssid_len);
169			ssid_count++;
170			pos = end;
171		} else {
172			wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
173				   "'%s'", pos);
174			os_free(ssid);
175			os_free(bssid);
176			return -1;
177		}
178
179		pos = os_strchr(pos, ' ');
180		if (pos)
181			pos++;
182	}
183
184	wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
185	os_free(wpa_s->disallow_aps_bssid);
186	wpa_s->disallow_aps_bssid = bssid;
187	wpa_s->disallow_aps_bssid_count = count;
188
189	wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
190	os_free(wpa_s->disallow_aps_ssid);
191	wpa_s->disallow_aps_ssid = ssid;
192	wpa_s->disallow_aps_ssid_count = ssid_count;
193
194	if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
195		return 0;
196
197	c = wpa_s->current_ssid;
198	if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
199		return 0;
200
201	if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
202	    !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
203		return 0;
204
205	wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
206		   "because current AP was marked disallowed");
207
208#ifdef CONFIG_SME
209	wpa_s->sme.prev_bssid_set = 0;
210#endif /* CONFIG_SME */
211	wpa_s->reassociate = 1;
212	wpa_s->own_disconnect_req = 1;
213	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
214	wpa_supplicant_req_scan(wpa_s, 0, 0);
215
216	return 0;
217}
218
219
220#ifndef CONFIG_NO_CONFIG_BLOBS
221static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
222{
223	char *name = pos;
224	struct wpa_config_blob *blob;
225	size_t len;
226
227	pos = os_strchr(pos, ' ');
228	if (pos == NULL)
229		return -1;
230	*pos++ = '\0';
231	len = os_strlen(pos);
232	if (len & 1)
233		return -1;
234
235	wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
236	blob = os_zalloc(sizeof(*blob));
237	if (blob == NULL)
238		return -1;
239	blob->name = os_strdup(name);
240	blob->data = os_malloc(len / 2);
241	if (blob->name == NULL || blob->data == NULL) {
242		wpa_config_free_blob(blob);
243		return -1;
244	}
245
246	if (hexstr2bin(pos, blob->data, len / 2) < 0) {
247		wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
248		wpa_config_free_blob(blob);
249		return -1;
250	}
251	blob->len = len / 2;
252
253	wpa_config_set_blob(wpa_s->conf, blob);
254
255	return 0;
256}
257#endif /* CONFIG_NO_CONFIG_BLOBS */
258
259
260static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
261{
262	char *params;
263	char *pos;
264	int *freqs = NULL;
265	int ret;
266
267	if (atoi(cmd)) {
268		params = os_strchr(cmd, ' ');
269		os_free(wpa_s->manual_sched_scan_freqs);
270		if (params) {
271			params++;
272			pos = os_strstr(params, "freq=");
273			if (pos)
274				freqs = freq_range_to_channel_list(wpa_s,
275								   pos + 5);
276		}
277		wpa_s->manual_sched_scan_freqs = freqs;
278		ret = wpas_start_pno(wpa_s);
279	} else {
280		ret = wpas_stop_pno(wpa_s);
281	}
282	return ret;
283}
284
285
286static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
287					 char *cmd)
288{
289	char *value;
290	int ret = 0;
291
292	value = os_strchr(cmd, ' ');
293	if (value == NULL)
294		return -1;
295	*value++ = '\0';
296
297	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
298	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
299		eapol_sm_configure(wpa_s->eapol,
300				   atoi(value), -1, -1, -1);
301	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
302		eapol_sm_configure(wpa_s->eapol,
303				   -1, atoi(value), -1, -1);
304	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
305		eapol_sm_configure(wpa_s->eapol,
306				   -1, -1, atoi(value), -1);
307	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
308		eapol_sm_configure(wpa_s->eapol,
309				   -1, -1, -1, atoi(value));
310	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
311		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
312				     atoi(value)))
313			ret = -1;
314	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
315		   0) {
316		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
317				     atoi(value)))
318			ret = -1;
319	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
320		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
321			ret = -1;
322	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
323		wpa_s->wps_fragment_size = atoi(value);
324#ifdef CONFIG_WPS_TESTING
325	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
326		long int val;
327		val = strtol(value, NULL, 0);
328		if (val < 0 || val > 0xff) {
329			ret = -1;
330			wpa_printf(MSG_DEBUG, "WPS: Invalid "
331				   "wps_version_number %ld", val);
332		} else {
333			wps_version_number = val;
334			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
335				   "version %u.%u",
336				   (wps_version_number & 0xf0) >> 4,
337				   wps_version_number & 0x0f);
338		}
339	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
340		wps_testing_dummy_cred = atoi(value);
341		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
342			   wps_testing_dummy_cred);
343	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
344		wps_corrupt_pkhash = atoi(value);
345		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
346			   wps_corrupt_pkhash);
347#endif /* CONFIG_WPS_TESTING */
348	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
349		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
350			ret = -1;
351#ifdef CONFIG_TDLS
352#ifdef CONFIG_TDLS_TESTING
353	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
354		extern unsigned int tdls_testing;
355		tdls_testing = strtol(value, NULL, 0);
356		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
357#endif /* CONFIG_TDLS_TESTING */
358	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
359		int disabled = atoi(value);
360		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
361		if (disabled) {
362			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
363				ret = -1;
364		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
365			ret = -1;
366		wpa_tdls_enable(wpa_s->wpa, !disabled);
367#endif /* CONFIG_TDLS */
368	} else if (os_strcasecmp(cmd, "pno") == 0) {
369		ret = wpas_ctrl_pno(wpa_s, value);
370	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
371		int disabled = atoi(value);
372		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
373			ret = -1;
374		else if (disabled)
375			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
376	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
377		if (os_strcmp(value, "disable") == 0)
378			wpa_s->set_sta_uapsd = 0;
379		else {
380			int be, bk, vi, vo;
381			char *pos;
382			/* format: BE,BK,VI,VO;max SP Length */
383			be = atoi(value);
384			pos = os_strchr(value, ',');
385			if (pos == NULL)
386				return -1;
387			pos++;
388			bk = atoi(pos);
389			pos = os_strchr(pos, ',');
390			if (pos == NULL)
391				return -1;
392			pos++;
393			vi = atoi(pos);
394			pos = os_strchr(pos, ',');
395			if (pos == NULL)
396				return -1;
397			pos++;
398			vo = atoi(pos);
399			/* ignore max SP Length for now */
400
401			wpa_s->set_sta_uapsd = 1;
402			wpa_s->sta_uapsd = 0;
403			if (be)
404				wpa_s->sta_uapsd |= BIT(0);
405			if (bk)
406				wpa_s->sta_uapsd |= BIT(1);
407			if (vi)
408				wpa_s->sta_uapsd |= BIT(2);
409			if (vo)
410				wpa_s->sta_uapsd |= BIT(3);
411		}
412	} else if (os_strcasecmp(cmd, "ps") == 0) {
413		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
414#ifdef CONFIG_WIFI_DISPLAY
415	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
416		int enabled = !!atoi(value);
417		if (enabled && !wpa_s->global->p2p)
418			ret = -1;
419		else
420			wifi_display_enable(wpa_s->global, enabled);
421#endif /* CONFIG_WIFI_DISPLAY */
422	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
423		ret = set_bssid_filter(wpa_s, value);
424	} else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
425		ret = set_disallow_aps(wpa_s, value);
426	} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
427		wpa_s->no_keep_alive = !!atoi(value);
428#ifdef CONFIG_TESTING_OPTIONS
429	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
430		wpa_s->ext_mgmt_frame_handling = !!atoi(value);
431	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
432		wpa_s->ext_eapol_frame_io = !!atoi(value);
433#ifdef CONFIG_AP
434		if (wpa_s->ap_iface) {
435			wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
436				wpa_s->ext_eapol_frame_io;
437		}
438#endif /* CONFIG_AP */
439	} else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
440		wpa_s->extra_roc_dur = atoi(value);
441	} else if (os_strcasecmp(cmd, "test_failure") == 0) {
442		wpa_s->test_failure = atoi(value);
443#endif /* CONFIG_TESTING_OPTIONS */
444#ifndef CONFIG_NO_CONFIG_BLOBS
445	} else if (os_strcmp(cmd, "blob") == 0) {
446		ret = wpas_ctrl_set_blob(wpa_s, value);
447#endif /* CONFIG_NO_CONFIG_BLOBS */
448	} else if (os_strcasecmp(cmd, "setband") == 0) {
449		if (os_strcmp(value, "AUTO") == 0)
450			wpa_s->setband = WPA_SETBAND_AUTO;
451		else if (os_strcmp(value, "5G") == 0)
452			wpa_s->setband = WPA_SETBAND_5G;
453		else if (os_strcmp(value, "2G") == 0)
454			wpa_s->setband = WPA_SETBAND_2G;
455		else
456			ret = -1;
457	} else {
458		value[-1] = '=';
459		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
460		if (ret == 0)
461			wpa_supplicant_update_config(wpa_s);
462	}
463
464	return ret;
465}
466
467
468static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
469					 char *cmd, char *buf, size_t buflen)
470{
471	int res = -1;
472
473	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
474
475	if (os_strcmp(cmd, "version") == 0) {
476		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
477	} else if (os_strcasecmp(cmd, "country") == 0) {
478		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
479			res = os_snprintf(buf, buflen, "%c%c",
480					  wpa_s->conf->country[0],
481					  wpa_s->conf->country[1]);
482#ifdef CONFIG_WIFI_DISPLAY
483	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
484		int enabled;
485		if (wpa_s->global->p2p == NULL ||
486		    wpa_s->global->p2p_disabled)
487			enabled = 0;
488		else
489			enabled = wpa_s->global->wifi_display;
490		res = os_snprintf(buf, buflen, "%d", enabled);
491#endif /* CONFIG_WIFI_DISPLAY */
492#ifdef CONFIG_TESTING_GET_GTK
493	} else if (os_strcmp(cmd, "gtk") == 0) {
494		if (wpa_s->last_gtk_len == 0)
495			return -1;
496		res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
497				       wpa_s->last_gtk_len);
498		return res;
499#endif /* CONFIG_TESTING_GET_GTK */
500	} else if (os_strcmp(cmd, "tls_library") == 0) {
501		res = tls_get_library_version(buf, buflen);
502	} else {
503		res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
504	}
505
506	if (os_snprintf_error(buflen, res))
507		return -1;
508	return res;
509}
510
511
512#ifdef IEEE8021X_EAPOL
513static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
514					     char *addr)
515{
516	u8 bssid[ETH_ALEN];
517	struct wpa_ssid *ssid = wpa_s->current_ssid;
518
519	if (hwaddr_aton(addr, bssid)) {
520		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
521			   "'%s'", addr);
522		return -1;
523	}
524
525	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
526	rsn_preauth_deinit(wpa_s->wpa);
527	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
528		return -1;
529
530	return 0;
531}
532#endif /* IEEE8021X_EAPOL */
533
534
535#ifdef CONFIG_PEERKEY
536/* MLME-STKSTART.request(peer) */
537static int wpa_supplicant_ctrl_iface_stkstart(
538	struct wpa_supplicant *wpa_s, char *addr)
539{
540	u8 peer[ETH_ALEN];
541
542	if (hwaddr_aton(addr, peer)) {
543		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
544			   "address '%s'", addr);
545		return -1;
546	}
547
548	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
549		   MAC2STR(peer));
550
551	return wpa_sm_stkstart(wpa_s->wpa, peer);
552}
553#endif /* CONFIG_PEERKEY */
554
555
556#ifdef CONFIG_TDLS
557
558static int wpa_supplicant_ctrl_iface_tdls_discover(
559	struct wpa_supplicant *wpa_s, char *addr)
560{
561	u8 peer[ETH_ALEN];
562	int ret;
563
564	if (hwaddr_aton(addr, peer)) {
565		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
566			   "address '%s'", addr);
567		return -1;
568	}
569
570	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
571		   MAC2STR(peer));
572
573	if (wpa_tdls_is_external_setup(wpa_s->wpa))
574		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
575	else
576		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
577
578	return ret;
579}
580
581
582static int wpa_supplicant_ctrl_iface_tdls_setup(
583	struct wpa_supplicant *wpa_s, char *addr)
584{
585	u8 peer[ETH_ALEN];
586	int ret;
587
588	if (hwaddr_aton(addr, peer)) {
589		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
590			   "address '%s'", addr);
591		return -1;
592	}
593
594	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
595		   MAC2STR(peer));
596
597	if ((wpa_s->conf->tdls_external_control) &&
598	    wpa_tdls_is_external_setup(wpa_s->wpa))
599		return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
600
601	wpa_tdls_remove(wpa_s->wpa, peer);
602
603	if (wpa_tdls_is_external_setup(wpa_s->wpa))
604		ret = wpa_tdls_start(wpa_s->wpa, peer);
605	else
606		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
607
608	return ret;
609}
610
611
612static int wpa_supplicant_ctrl_iface_tdls_teardown(
613	struct wpa_supplicant *wpa_s, char *addr)
614{
615	u8 peer[ETH_ALEN];
616	int ret;
617
618	if (os_strcmp(addr, "*") == 0) {
619		/* remove everyone */
620		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
621		wpa_tdls_teardown_peers(wpa_s->wpa);
622		return 0;
623	}
624
625	if (hwaddr_aton(addr, peer)) {
626		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
627			   "address '%s'", addr);
628		return -1;
629	}
630
631	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
632		   MAC2STR(peer));
633
634	if ((wpa_s->conf->tdls_external_control) &&
635	    wpa_tdls_is_external_setup(wpa_s->wpa))
636		return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
637
638	if (wpa_tdls_is_external_setup(wpa_s->wpa))
639		ret = wpa_tdls_teardown_link(
640			wpa_s->wpa, peer,
641			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
642	else
643		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
644
645	return ret;
646}
647
648
649static int ctrl_iface_get_capability_tdls(
650	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
651{
652	int ret;
653
654	ret = os_snprintf(buf, buflen, "%s\n",
655			  wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
656			  (wpa_s->drv_flags &
657			   WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
658			   "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
659	if (os_snprintf_error(buflen, ret))
660		return -1;
661	return ret;
662}
663
664
665static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
666	struct wpa_supplicant *wpa_s, char *cmd)
667{
668	u8 peer[ETH_ALEN];
669	struct hostapd_freq_params freq_params;
670	u8 oper_class;
671	char *pos, *end;
672
673	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
674		wpa_printf(MSG_INFO,
675			   "tdls_chanswitch: Only supported with external setup");
676		return -1;
677	}
678
679	os_memset(&freq_params, 0, sizeof(freq_params));
680
681	pos = os_strchr(cmd, ' ');
682	if (pos == NULL)
683		return -1;
684	*pos++ = '\0';
685
686	oper_class = strtol(pos, &end, 10);
687	if (pos == end) {
688		wpa_printf(MSG_INFO,
689			   "tdls_chanswitch: Invalid op class provided");
690		return -1;
691	}
692
693	pos = end;
694	freq_params.freq = atoi(pos);
695	if (freq_params.freq == 0) {
696		wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
697		return -1;
698	}
699
700#define SET_FREQ_SETTING(str) \
701	do { \
702		const char *pos2 = os_strstr(pos, " " #str "="); \
703		if (pos2) { \
704			pos2 += sizeof(" " #str "=") - 1; \
705			freq_params.str = atoi(pos2); \
706		} \
707	} while (0)
708
709	SET_FREQ_SETTING(center_freq1);
710	SET_FREQ_SETTING(center_freq2);
711	SET_FREQ_SETTING(bandwidth);
712	SET_FREQ_SETTING(sec_channel_offset);
713#undef SET_FREQ_SETTING
714
715	freq_params.ht_enabled = !!os_strstr(pos, " ht");
716	freq_params.vht_enabled = !!os_strstr(pos, " vht");
717
718	if (hwaddr_aton(cmd, peer)) {
719		wpa_printf(MSG_DEBUG,
720			   "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
721			   cmd);
722		return -1;
723	}
724
725	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
726		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
727		   MAC2STR(peer), oper_class, freq_params.freq,
728		   freq_params.center_freq1, freq_params.center_freq2,
729		   freq_params.bandwidth, freq_params.sec_channel_offset,
730		   freq_params.ht_enabled ? " HT" : "",
731		   freq_params.vht_enabled ? " VHT" : "");
732
733	return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
734					   &freq_params);
735}
736
737
738static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
739	struct wpa_supplicant *wpa_s, char *cmd)
740{
741	u8 peer[ETH_ALEN];
742
743	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
744		wpa_printf(MSG_INFO,
745			   "tdls_chanswitch: Only supported with external setup");
746		return -1;
747	}
748
749	if (hwaddr_aton(cmd, peer)) {
750		wpa_printf(MSG_DEBUG,
751			   "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
752			   cmd);
753		return -1;
754	}
755
756	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
757		   MAC2STR(peer));
758
759	return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
760}
761
762#endif /* CONFIG_TDLS */
763
764
765static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
766{
767	char *token, *context = NULL;
768	struct wmm_ac_ts_setup_params params = {
769		.tsid = 0xff,
770		.direction = 0xff,
771	};
772
773	while ((token = str_token(cmd, " ", &context))) {
774		if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
775		    sscanf(token, "up=%i", &params.user_priority) == 1 ||
776		    sscanf(token, "nominal_msdu_size=%i",
777			   &params.nominal_msdu_size) == 1 ||
778		    sscanf(token, "mean_data_rate=%i",
779			   &params.mean_data_rate) == 1 ||
780		    sscanf(token, "min_phy_rate=%i",
781			   &params.minimum_phy_rate) == 1 ||
782		    sscanf(token, "sba=%i",
783			   &params.surplus_bandwidth_allowance) == 1)
784			continue;
785
786		if (os_strcasecmp(token, "downlink") == 0) {
787			params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
788		} else if (os_strcasecmp(token, "uplink") == 0) {
789			params.direction = WMM_TSPEC_DIRECTION_UPLINK;
790		} else if (os_strcasecmp(token, "bidi") == 0) {
791			params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
792		} else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
793			params.fixed_nominal_msdu = 1;
794		} else {
795			wpa_printf(MSG_DEBUG,
796				   "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
797				   token);
798			return -1;
799		}
800
801	}
802
803	return wpas_wmm_ac_addts(wpa_s, &params);
804}
805
806
807static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
808{
809	u8 tsid = atoi(cmd);
810
811	return wpas_wmm_ac_delts(wpa_s, tsid);
812}
813
814
815#ifdef CONFIG_IEEE80211R
816static int wpa_supplicant_ctrl_iface_ft_ds(
817	struct wpa_supplicant *wpa_s, char *addr)
818{
819	u8 target_ap[ETH_ALEN];
820	struct wpa_bss *bss;
821	const u8 *mdie;
822
823	if (hwaddr_aton(addr, target_ap)) {
824		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
825			   "address '%s'", addr);
826		return -1;
827	}
828
829	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
830
831	bss = wpa_bss_get_bssid(wpa_s, target_ap);
832	if (bss)
833		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
834	else
835		mdie = NULL;
836
837	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
838}
839#endif /* CONFIG_IEEE80211R */
840
841
842#ifdef CONFIG_WPS
843static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
844					     char *cmd)
845{
846	u8 bssid[ETH_ALEN], *_bssid = bssid;
847#ifdef CONFIG_P2P
848	u8 p2p_dev_addr[ETH_ALEN];
849#endif /* CONFIG_P2P */
850#ifdef CONFIG_AP
851	u8 *_p2p_dev_addr = NULL;
852#endif /* CONFIG_AP */
853
854	if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
855		_bssid = NULL;
856#ifdef CONFIG_P2P
857	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
858		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
859			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
860				   "P2P Device Address '%s'",
861				   cmd + 13);
862			return -1;
863		}
864		_p2p_dev_addr = p2p_dev_addr;
865#endif /* CONFIG_P2P */
866	} else if (hwaddr_aton(cmd, bssid)) {
867		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
868			   cmd);
869		return -1;
870	}
871
872#ifdef CONFIG_AP
873	if (wpa_s->ap_iface)
874		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
875#endif /* CONFIG_AP */
876
877	return wpas_wps_start_pbc(wpa_s, _bssid, 0);
878}
879
880
881static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
882					     char *cmd, char *buf,
883					     size_t buflen)
884{
885	u8 bssid[ETH_ALEN], *_bssid = bssid;
886	char *pin;
887	int ret;
888
889	pin = os_strchr(cmd, ' ');
890	if (pin)
891		*pin++ = '\0';
892
893	if (os_strcmp(cmd, "any") == 0)
894		_bssid = NULL;
895	else if (os_strcmp(cmd, "get") == 0) {
896		ret = wps_generate_pin();
897		goto done;
898	} else if (hwaddr_aton(cmd, bssid)) {
899		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
900			   cmd);
901		return -1;
902	}
903
904#ifdef CONFIG_AP
905	if (wpa_s->ap_iface) {
906		int timeout = 0;
907		char *pos;
908
909		if (pin) {
910			pos = os_strchr(pin, ' ');
911			if (pos) {
912				*pos++ = '\0';
913				timeout = atoi(pos);
914			}
915		}
916
917		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
918						 buf, buflen, timeout);
919	}
920#endif /* CONFIG_AP */
921
922	if (pin) {
923		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
924					 DEV_PW_DEFAULT);
925		if (ret < 0)
926			return -1;
927		ret = os_snprintf(buf, buflen, "%s", pin);
928		if (os_snprintf_error(buflen, ret))
929			return -1;
930		return ret;
931	}
932
933	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
934	if (ret < 0)
935		return -1;
936
937done:
938	/* Return the generated PIN */
939	ret = os_snprintf(buf, buflen, "%08d", ret);
940	if (os_snprintf_error(buflen, ret))
941		return -1;
942	return ret;
943}
944
945
946static int wpa_supplicant_ctrl_iface_wps_check_pin(
947	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
948{
949	char pin[9];
950	size_t len;
951	char *pos;
952	int ret;
953
954	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
955			      (u8 *) cmd, os_strlen(cmd));
956	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
957		if (*pos < '0' || *pos > '9')
958			continue;
959		pin[len++] = *pos;
960		if (len == 9) {
961			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
962			return -1;
963		}
964	}
965	if (len != 4 && len != 8) {
966		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
967		return -1;
968	}
969	pin[len] = '\0';
970
971	if (len == 8) {
972		unsigned int pin_val;
973		pin_val = atoi(pin);
974		if (!wps_pin_valid(pin_val)) {
975			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
976			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
977			if (os_snprintf_error(buflen, ret))
978				return -1;
979			return ret;
980		}
981	}
982
983	ret = os_snprintf(buf, buflen, "%s", pin);
984	if (os_snprintf_error(buflen, ret))
985		return -1;
986
987	return ret;
988}
989
990
991#ifdef CONFIG_WPS_NFC
992
993static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
994					     char *cmd)
995{
996	u8 bssid[ETH_ALEN], *_bssid = bssid;
997
998	if (cmd == NULL || cmd[0] == '\0')
999		_bssid = NULL;
1000	else if (hwaddr_aton(cmd, bssid))
1001		return -1;
1002
1003	return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1004				  0, 0);
1005}
1006
1007
1008static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1009	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1010{
1011	int ndef;
1012	struct wpabuf *buf;
1013	int res;
1014	char *pos;
1015
1016	pos = os_strchr(cmd, ' ');
1017	if (pos)
1018		*pos++ = '\0';
1019	if (os_strcmp(cmd, "WPS") == 0)
1020		ndef = 0;
1021	else if (os_strcmp(cmd, "NDEF") == 0)
1022		ndef = 1;
1023	else
1024		return -1;
1025
1026	buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
1027	if (buf == NULL)
1028		return -1;
1029
1030	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1031					 wpabuf_len(buf));
1032	reply[res++] = '\n';
1033	reply[res] = '\0';
1034
1035	wpabuf_free(buf);
1036
1037	return res;
1038}
1039
1040
1041static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1042	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1043{
1044	int ndef;
1045	struct wpabuf *buf;
1046	int res;
1047
1048	if (os_strcmp(cmd, "WPS") == 0)
1049		ndef = 0;
1050	else if (os_strcmp(cmd, "NDEF") == 0)
1051		ndef = 1;
1052	else
1053		return -1;
1054
1055	buf = wpas_wps_nfc_token(wpa_s, ndef);
1056	if (buf == NULL)
1057		return -1;
1058
1059	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1060					 wpabuf_len(buf));
1061	reply[res++] = '\n';
1062	reply[res] = '\0';
1063
1064	wpabuf_free(buf);
1065
1066	return res;
1067}
1068
1069
1070static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1071	struct wpa_supplicant *wpa_s, char *pos)
1072{
1073	size_t len;
1074	struct wpabuf *buf;
1075	int ret;
1076	char *freq;
1077	int forced_freq = 0;
1078
1079	freq = strstr(pos, " freq=");
1080	if (freq) {
1081		*freq = '\0';
1082		freq += 6;
1083		forced_freq = atoi(freq);
1084	}
1085
1086	len = os_strlen(pos);
1087	if (len & 0x01)
1088		return -1;
1089	len /= 2;
1090
1091	buf = wpabuf_alloc(len);
1092	if (buf == NULL)
1093		return -1;
1094	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1095		wpabuf_free(buf);
1096		return -1;
1097	}
1098
1099	ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
1100	wpabuf_free(buf);
1101
1102	return ret;
1103}
1104
1105
1106static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
1107					      char *reply, size_t max_len,
1108					      int ndef)
1109{
1110	struct wpabuf *buf;
1111	int res;
1112
1113	buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
1114	if (buf == NULL)
1115		return -1;
1116
1117	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1118					 wpabuf_len(buf));
1119	reply[res++] = '\n';
1120	reply[res] = '\0';
1121
1122	wpabuf_free(buf);
1123
1124	return res;
1125}
1126
1127
1128#ifdef CONFIG_P2P
1129static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1130					      char *reply, size_t max_len,
1131					      int ndef)
1132{
1133	struct wpabuf *buf;
1134	int res;
1135
1136	buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1137	if (buf == NULL) {
1138		wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1139		return -1;
1140	}
1141
1142	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1143					 wpabuf_len(buf));
1144	reply[res++] = '\n';
1145	reply[res] = '\0';
1146
1147	wpabuf_free(buf);
1148
1149	return res;
1150}
1151#endif /* CONFIG_P2P */
1152
1153
1154static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1155					  char *cmd, char *reply,
1156					  size_t max_len)
1157{
1158	char *pos;
1159	int ndef;
1160
1161	pos = os_strchr(cmd, ' ');
1162	if (pos == NULL)
1163		return -1;
1164	*pos++ = '\0';
1165
1166	if (os_strcmp(cmd, "WPS") == 0)
1167		ndef = 0;
1168	else if (os_strcmp(cmd, "NDEF") == 0)
1169		ndef = 1;
1170	else
1171		return -1;
1172
1173	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1174		if (!ndef)
1175			return -1;
1176		return wpas_ctrl_nfc_get_handover_req_wps(
1177			wpa_s, reply, max_len, ndef);
1178	}
1179
1180#ifdef CONFIG_P2P
1181	if (os_strcmp(pos, "P2P-CR") == 0) {
1182		return wpas_ctrl_nfc_get_handover_req_p2p(
1183			wpa_s, reply, max_len, ndef);
1184	}
1185#endif /* CONFIG_P2P */
1186
1187	return -1;
1188}
1189
1190
1191static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1192					      char *reply, size_t max_len,
1193					      int ndef, int cr, char *uuid)
1194{
1195	struct wpabuf *buf;
1196	int res;
1197
1198	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1199	if (buf == NULL)
1200		return -1;
1201
1202	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1203					 wpabuf_len(buf));
1204	reply[res++] = '\n';
1205	reply[res] = '\0';
1206
1207	wpabuf_free(buf);
1208
1209	return res;
1210}
1211
1212
1213#ifdef CONFIG_P2P
1214static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1215					      char *reply, size_t max_len,
1216					      int ndef, int tag)
1217{
1218	struct wpabuf *buf;
1219	int res;
1220
1221	buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1222	if (buf == NULL)
1223		return -1;
1224
1225	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1226					 wpabuf_len(buf));
1227	reply[res++] = '\n';
1228	reply[res] = '\0';
1229
1230	wpabuf_free(buf);
1231
1232	return res;
1233}
1234#endif /* CONFIG_P2P */
1235
1236
1237static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1238					  char *cmd, char *reply,
1239					  size_t max_len)
1240{
1241	char *pos, *pos2;
1242	int ndef;
1243
1244	pos = os_strchr(cmd, ' ');
1245	if (pos == NULL)
1246		return -1;
1247	*pos++ = '\0';
1248
1249	if (os_strcmp(cmd, "WPS") == 0)
1250		ndef = 0;
1251	else if (os_strcmp(cmd, "NDEF") == 0)
1252		ndef = 1;
1253	else
1254		return -1;
1255
1256	pos2 = os_strchr(pos, ' ');
1257	if (pos2)
1258		*pos2++ = '\0';
1259	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1260		if (!ndef)
1261			return -1;
1262		return wpas_ctrl_nfc_get_handover_sel_wps(
1263			wpa_s, reply, max_len, ndef,
1264			os_strcmp(pos, "WPS-CR") == 0, pos2);
1265	}
1266
1267#ifdef CONFIG_P2P
1268	if (os_strcmp(pos, "P2P-CR") == 0) {
1269		return wpas_ctrl_nfc_get_handover_sel_p2p(
1270			wpa_s, reply, max_len, ndef, 0);
1271	}
1272
1273	if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1274		return wpas_ctrl_nfc_get_handover_sel_p2p(
1275			wpa_s, reply, max_len, ndef, 1);
1276	}
1277#endif /* CONFIG_P2P */
1278
1279	return -1;
1280}
1281
1282
1283static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1284					 char *cmd)
1285{
1286	size_t len;
1287	struct wpabuf *req, *sel;
1288	int ret;
1289	char *pos, *role, *type, *pos2;
1290#ifdef CONFIG_P2P
1291	char *freq;
1292	int forced_freq = 0;
1293
1294	freq = strstr(cmd, " freq=");
1295	if (freq) {
1296		*freq = '\0';
1297		freq += 6;
1298		forced_freq = atoi(freq);
1299	}
1300#endif /* CONFIG_P2P */
1301
1302	role = cmd;
1303	pos = os_strchr(role, ' ');
1304	if (pos == NULL) {
1305		wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1306		return -1;
1307	}
1308	*pos++ = '\0';
1309
1310	type = pos;
1311	pos = os_strchr(type, ' ');
1312	if (pos == NULL) {
1313		wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1314		return -1;
1315	}
1316	*pos++ = '\0';
1317
1318	pos2 = os_strchr(pos, ' ');
1319	if (pos2 == NULL) {
1320		wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1321		return -1;
1322	}
1323	*pos2++ = '\0';
1324
1325	len = os_strlen(pos);
1326	if (len & 0x01) {
1327		wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1328		return -1;
1329	}
1330	len /= 2;
1331
1332	req = wpabuf_alloc(len);
1333	if (req == NULL) {
1334		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1335		return -1;
1336	}
1337	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1338		wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1339		wpabuf_free(req);
1340		return -1;
1341	}
1342
1343	len = os_strlen(pos2);
1344	if (len & 0x01) {
1345		wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1346		wpabuf_free(req);
1347		return -1;
1348	}
1349	len /= 2;
1350
1351	sel = wpabuf_alloc(len);
1352	if (sel == NULL) {
1353		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1354		wpabuf_free(req);
1355		return -1;
1356	}
1357	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1358		wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1359		wpabuf_free(req);
1360		wpabuf_free(sel);
1361		return -1;
1362	}
1363
1364	wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1365		   role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1366
1367	if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1368		ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1369#ifdef CONFIG_AP
1370	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1371	{
1372		ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1373		if (ret < 0)
1374			ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1375#endif /* CONFIG_AP */
1376#ifdef CONFIG_P2P
1377	} else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1378	{
1379		ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1380	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1381	{
1382		ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1383						   forced_freq);
1384#endif /* CONFIG_P2P */
1385	} else {
1386		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1387			   "reported: role=%s type=%s", role, type);
1388		ret = -1;
1389	}
1390	wpabuf_free(req);
1391	wpabuf_free(sel);
1392
1393	if (ret)
1394		wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1395
1396	return ret;
1397}
1398
1399#endif /* CONFIG_WPS_NFC */
1400
1401
1402static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1403					     char *cmd)
1404{
1405	u8 bssid[ETH_ALEN];
1406	char *pin;
1407	char *new_ssid;
1408	char *new_auth;
1409	char *new_encr;
1410	char *new_key;
1411	struct wps_new_ap_settings ap;
1412
1413	pin = os_strchr(cmd, ' ');
1414	if (pin == NULL)
1415		return -1;
1416	*pin++ = '\0';
1417
1418	if (hwaddr_aton(cmd, bssid)) {
1419		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1420			   cmd);
1421		return -1;
1422	}
1423
1424	new_ssid = os_strchr(pin, ' ');
1425	if (new_ssid == NULL)
1426		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1427	*new_ssid++ = '\0';
1428
1429	new_auth = os_strchr(new_ssid, ' ');
1430	if (new_auth == NULL)
1431		return -1;
1432	*new_auth++ = '\0';
1433
1434	new_encr = os_strchr(new_auth, ' ');
1435	if (new_encr == NULL)
1436		return -1;
1437	*new_encr++ = '\0';
1438
1439	new_key = os_strchr(new_encr, ' ');
1440	if (new_key == NULL)
1441		return -1;
1442	*new_key++ = '\0';
1443
1444	os_memset(&ap, 0, sizeof(ap));
1445	ap.ssid_hex = new_ssid;
1446	ap.auth = new_auth;
1447	ap.encr = new_encr;
1448	ap.key_hex = new_key;
1449	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1450}
1451
1452
1453#ifdef CONFIG_AP
1454static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1455						char *cmd, char *buf,
1456						size_t buflen)
1457{
1458	int timeout = 300;
1459	char *pos;
1460	const char *pin_txt;
1461
1462	if (!wpa_s->ap_iface)
1463		return -1;
1464
1465	pos = os_strchr(cmd, ' ');
1466	if (pos)
1467		*pos++ = '\0';
1468
1469	if (os_strcmp(cmd, "disable") == 0) {
1470		wpas_wps_ap_pin_disable(wpa_s);
1471		return os_snprintf(buf, buflen, "OK\n");
1472	}
1473
1474	if (os_strcmp(cmd, "random") == 0) {
1475		if (pos)
1476			timeout = atoi(pos);
1477		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1478		if (pin_txt == NULL)
1479			return -1;
1480		return os_snprintf(buf, buflen, "%s", pin_txt);
1481	}
1482
1483	if (os_strcmp(cmd, "get") == 0) {
1484		pin_txt = wpas_wps_ap_pin_get(wpa_s);
1485		if (pin_txt == NULL)
1486			return -1;
1487		return os_snprintf(buf, buflen, "%s", pin_txt);
1488	}
1489
1490	if (os_strcmp(cmd, "set") == 0) {
1491		char *pin;
1492		if (pos == NULL)
1493			return -1;
1494		pin = pos;
1495		pos = os_strchr(pos, ' ');
1496		if (pos) {
1497			*pos++ = '\0';
1498			timeout = atoi(pos);
1499		}
1500		if (os_strlen(pin) > buflen)
1501			return -1;
1502		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1503			return -1;
1504		return os_snprintf(buf, buflen, "%s", pin);
1505	}
1506
1507	return -1;
1508}
1509#endif /* CONFIG_AP */
1510
1511
1512#ifdef CONFIG_WPS_ER
1513static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1514						char *cmd)
1515{
1516	char *uuid = cmd, *pin, *pos;
1517	u8 addr_buf[ETH_ALEN], *addr = NULL;
1518	pin = os_strchr(uuid, ' ');
1519	if (pin == NULL)
1520		return -1;
1521	*pin++ = '\0';
1522	pos = os_strchr(pin, ' ');
1523	if (pos) {
1524		*pos++ = '\0';
1525		if (hwaddr_aton(pos, addr_buf) == 0)
1526			addr = addr_buf;
1527	}
1528	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
1529}
1530
1531
1532static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
1533						  char *cmd)
1534{
1535	char *uuid = cmd, *pin;
1536	pin = os_strchr(uuid, ' ');
1537	if (pin == NULL)
1538		return -1;
1539	*pin++ = '\0';
1540	return wpas_wps_er_learn(wpa_s, uuid, pin);
1541}
1542
1543
1544static int wpa_supplicant_ctrl_iface_wps_er_set_config(
1545	struct wpa_supplicant *wpa_s, char *cmd)
1546{
1547	char *uuid = cmd, *id;
1548	id = os_strchr(uuid, ' ');
1549	if (id == NULL)
1550		return -1;
1551	*id++ = '\0';
1552	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
1553}
1554
1555
1556static int wpa_supplicant_ctrl_iface_wps_er_config(
1557	struct wpa_supplicant *wpa_s, char *cmd)
1558{
1559	char *pin;
1560	char *new_ssid;
1561	char *new_auth;
1562	char *new_encr;
1563	char *new_key;
1564	struct wps_new_ap_settings ap;
1565
1566	pin = os_strchr(cmd, ' ');
1567	if (pin == NULL)
1568		return -1;
1569	*pin++ = '\0';
1570
1571	new_ssid = os_strchr(pin, ' ');
1572	if (new_ssid == NULL)
1573		return -1;
1574	*new_ssid++ = '\0';
1575
1576	new_auth = os_strchr(new_ssid, ' ');
1577	if (new_auth == NULL)
1578		return -1;
1579	*new_auth++ = '\0';
1580
1581	new_encr = os_strchr(new_auth, ' ');
1582	if (new_encr == NULL)
1583		return -1;
1584	*new_encr++ = '\0';
1585
1586	new_key = os_strchr(new_encr, ' ');
1587	if (new_key == NULL)
1588		return -1;
1589	*new_key++ = '\0';
1590
1591	os_memset(&ap, 0, sizeof(ap));
1592	ap.ssid_hex = new_ssid;
1593	ap.auth = new_auth;
1594	ap.encr = new_encr;
1595	ap.key_hex = new_key;
1596	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
1597}
1598
1599
1600#ifdef CONFIG_WPS_NFC
1601static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
1602	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1603{
1604	int ndef;
1605	struct wpabuf *buf;
1606	int res;
1607	char *uuid;
1608
1609	uuid = os_strchr(cmd, ' ');
1610	if (uuid == NULL)
1611		return -1;
1612	*uuid++ = '\0';
1613
1614	if (os_strcmp(cmd, "WPS") == 0)
1615		ndef = 0;
1616	else if (os_strcmp(cmd, "NDEF") == 0)
1617		ndef = 1;
1618	else
1619		return -1;
1620
1621	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
1622	if (buf == NULL)
1623		return -1;
1624
1625	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1626					 wpabuf_len(buf));
1627	reply[res++] = '\n';
1628	reply[res] = '\0';
1629
1630	wpabuf_free(buf);
1631
1632	return res;
1633}
1634#endif /* CONFIG_WPS_NFC */
1635#endif /* CONFIG_WPS_ER */
1636
1637#endif /* CONFIG_WPS */
1638
1639
1640#ifdef CONFIG_IBSS_RSN
1641static int wpa_supplicant_ctrl_iface_ibss_rsn(
1642	struct wpa_supplicant *wpa_s, char *addr)
1643{
1644	u8 peer[ETH_ALEN];
1645
1646	if (hwaddr_aton(addr, peer)) {
1647		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
1648			   "address '%s'", addr);
1649		return -1;
1650	}
1651
1652	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
1653		   MAC2STR(peer));
1654
1655	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
1656}
1657#endif /* CONFIG_IBSS_RSN */
1658
1659
1660static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
1661					      char *rsp)
1662{
1663#ifdef IEEE8021X_EAPOL
1664	char *pos, *id_pos;
1665	int id;
1666	struct wpa_ssid *ssid;
1667
1668	pos = os_strchr(rsp, '-');
1669	if (pos == NULL)
1670		return -1;
1671	*pos++ = '\0';
1672	id_pos = pos;
1673	pos = os_strchr(pos, ':');
1674	if (pos == NULL)
1675		return -1;
1676	*pos++ = '\0';
1677	id = atoi(id_pos);
1678	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
1679	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1680			      (u8 *) pos, os_strlen(pos));
1681
1682	ssid = wpa_config_get_network(wpa_s->conf, id);
1683	if (ssid == NULL) {
1684		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1685			   "to update", id);
1686		return -1;
1687	}
1688
1689	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
1690							 pos);
1691#else /* IEEE8021X_EAPOL */
1692	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1693	return -1;
1694#endif /* IEEE8021X_EAPOL */
1695}
1696
1697
1698static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
1699					    const char *params,
1700					    char *buf, size_t buflen)
1701{
1702	char *pos, *end, tmp[30];
1703	int res, verbose, wps, ret;
1704#ifdef CONFIG_HS20
1705	const u8 *hs20;
1706#endif /* CONFIG_HS20 */
1707	const u8 *sess_id;
1708	size_t sess_id_len;
1709
1710	if (os_strcmp(params, "-DRIVER") == 0)
1711		return wpa_drv_status(wpa_s, buf, buflen);
1712	verbose = os_strcmp(params, "-VERBOSE") == 0;
1713	wps = os_strcmp(params, "-WPS") == 0;
1714	pos = buf;
1715	end = buf + buflen;
1716	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1717		struct wpa_ssid *ssid = wpa_s->current_ssid;
1718		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1719				  MAC2STR(wpa_s->bssid));
1720		if (os_snprintf_error(end - pos, ret))
1721			return pos - buf;
1722		pos += ret;
1723		ret = os_snprintf(pos, end - pos, "freq=%u\n",
1724				  wpa_s->assoc_freq);
1725		if (os_snprintf_error(end - pos, ret))
1726			return pos - buf;
1727		pos += ret;
1728		if (ssid) {
1729			u8 *_ssid = ssid->ssid;
1730			size_t ssid_len = ssid->ssid_len;
1731			u8 ssid_buf[MAX_SSID_LEN];
1732			if (ssid_len == 0) {
1733				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1734				if (_res < 0)
1735					ssid_len = 0;
1736				else
1737					ssid_len = _res;
1738				_ssid = ssid_buf;
1739			}
1740			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1741					  wpa_ssid_txt(_ssid, ssid_len),
1742					  ssid->id);
1743			if (os_snprintf_error(end - pos, ret))
1744				return pos - buf;
1745			pos += ret;
1746
1747			if (wps && ssid->passphrase &&
1748			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1749			    (ssid->mode == WPAS_MODE_AP ||
1750			     ssid->mode == WPAS_MODE_P2P_GO)) {
1751				ret = os_snprintf(pos, end - pos,
1752						  "passphrase=%s\n",
1753						  ssid->passphrase);
1754				if (os_snprintf_error(end - pos, ret))
1755					return pos - buf;
1756				pos += ret;
1757			}
1758			if (ssid->id_str) {
1759				ret = os_snprintf(pos, end - pos,
1760						  "id_str=%s\n",
1761						  ssid->id_str);
1762				if (os_snprintf_error(end - pos, ret))
1763					return pos - buf;
1764				pos += ret;
1765			}
1766
1767			switch (ssid->mode) {
1768			case WPAS_MODE_INFRA:
1769				ret = os_snprintf(pos, end - pos,
1770						  "mode=station\n");
1771				break;
1772			case WPAS_MODE_IBSS:
1773				ret = os_snprintf(pos, end - pos,
1774						  "mode=IBSS\n");
1775				break;
1776			case WPAS_MODE_AP:
1777				ret = os_snprintf(pos, end - pos,
1778						  "mode=AP\n");
1779				break;
1780			case WPAS_MODE_P2P_GO:
1781				ret = os_snprintf(pos, end - pos,
1782						  "mode=P2P GO\n");
1783				break;
1784			case WPAS_MODE_P2P_GROUP_FORMATION:
1785				ret = os_snprintf(pos, end - pos,
1786						  "mode=P2P GO - group "
1787						  "formation\n");
1788				break;
1789			default:
1790				ret = 0;
1791				break;
1792			}
1793			if (os_snprintf_error(end - pos, ret))
1794				return pos - buf;
1795			pos += ret;
1796		}
1797
1798#ifdef CONFIG_AP
1799		if (wpa_s->ap_iface) {
1800			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1801							    end - pos,
1802							    verbose);
1803		} else
1804#endif /* CONFIG_AP */
1805		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1806	}
1807#ifdef CONFIG_SAE
1808	if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
1809#ifdef CONFIG_AP
1810	    !wpa_s->ap_iface &&
1811#endif /* CONFIG_AP */
1812	    wpa_s->sme.sae.state == SAE_ACCEPTED) {
1813		ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
1814				  wpa_s->sme.sae.group);
1815		if (os_snprintf_error(end - pos, ret))
1816			return pos - buf;
1817		pos += ret;
1818	}
1819#endif /* CONFIG_SAE */
1820	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1821			  wpa_supplicant_state_txt(wpa_s->wpa_state));
1822	if (os_snprintf_error(end - pos, ret))
1823		return pos - buf;
1824	pos += ret;
1825
1826	if (wpa_s->l2 &&
1827	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1828		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1829		if (os_snprintf_error(end - pos, ret))
1830			return pos - buf;
1831		pos += ret;
1832	}
1833
1834#ifdef CONFIG_P2P
1835	if (wpa_s->global->p2p) {
1836		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1837				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1838		if (os_snprintf_error(end - pos, ret))
1839			return pos - buf;
1840		pos += ret;
1841	}
1842#endif /* CONFIG_P2P */
1843
1844	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1845			  MAC2STR(wpa_s->own_addr));
1846	if (os_snprintf_error(end - pos, ret))
1847		return pos - buf;
1848	pos += ret;
1849
1850#ifdef CONFIG_HS20
1851	if (wpa_s->current_bss &&
1852	    (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
1853					  HS20_IE_VENDOR_TYPE)) &&
1854	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
1855	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
1856		int release = 1;
1857		if (hs20[1] >= 5) {
1858			u8 rel_num = (hs20[6] & 0xf0) >> 4;
1859			release = rel_num + 1;
1860		}
1861		ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
1862		if (os_snprintf_error(end - pos, ret))
1863			return pos - buf;
1864		pos += ret;
1865	}
1866
1867	if (wpa_s->current_ssid) {
1868		struct wpa_cred *cred;
1869		char *type;
1870
1871		for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1872			size_t i;
1873
1874			if (wpa_s->current_ssid->parent_cred != cred)
1875				continue;
1876
1877			if (cred->provisioning_sp) {
1878				ret = os_snprintf(pos, end - pos,
1879						  "provisioning_sp=%s\n",
1880						  cred->provisioning_sp);
1881				if (os_snprintf_error(end - pos, ret))
1882					return pos - buf;
1883				pos += ret;
1884			}
1885
1886			if (!cred->domain)
1887				goto no_domain;
1888
1889			i = 0;
1890			if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
1891				struct wpabuf *names =
1892					wpa_s->current_bss->anqp->domain_name;
1893				for (i = 0; names && i < cred->num_domain; i++)
1894				{
1895					if (domain_name_list_contains(
1896						    names, cred->domain[i], 1))
1897						break;
1898				}
1899				if (i == cred->num_domain)
1900					i = 0; /* show first entry by default */
1901			}
1902			ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
1903					  cred->domain[i]);
1904			if (os_snprintf_error(end - pos, ret))
1905				return pos - buf;
1906			pos += ret;
1907
1908		no_domain:
1909			if (wpa_s->current_bss == NULL ||
1910			    wpa_s->current_bss->anqp == NULL)
1911				res = -1;
1912			else
1913				res = interworking_home_sp_cred(
1914					wpa_s, cred,
1915					wpa_s->current_bss->anqp->domain_name);
1916			if (res > 0)
1917				type = "home";
1918			else if (res == 0)
1919				type = "roaming";
1920			else
1921				type = "unknown";
1922
1923			ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
1924			if (os_snprintf_error(end - pos, ret))
1925				return pos - buf;
1926			pos += ret;
1927
1928			break;
1929		}
1930	}
1931#endif /* CONFIG_HS20 */
1932
1933	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1934	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1935		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1936					  verbose);
1937		if (res >= 0)
1938			pos += res;
1939	}
1940
1941	sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
1942	if (sess_id) {
1943		char *start = pos;
1944
1945		ret = os_snprintf(pos, end - pos, "eap_session_id=");
1946		if (os_snprintf_error(end - pos, ret))
1947			return start - buf;
1948		pos += ret;
1949		ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
1950		if (ret <= 0)
1951			return start - buf;
1952		pos += ret;
1953		ret = os_snprintf(pos, end - pos, "\n");
1954		if (os_snprintf_error(end - pos, ret))
1955			return start - buf;
1956		pos += ret;
1957	}
1958
1959	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1960	if (res >= 0)
1961		pos += res;
1962
1963#ifdef CONFIG_WPS
1964	{
1965		char uuid_str[100];
1966		uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
1967		ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
1968		if (os_snprintf_error(end - pos, ret))
1969			return pos - buf;
1970		pos += ret;
1971	}
1972#endif /* CONFIG_WPS */
1973
1974#ifdef ANDROID
1975	/*
1976	 * Allow using the STATUS command with default behavior, say for debug,
1977	 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
1978	 * events with STATUS-NO_EVENTS.
1979	 */
1980	if (os_strcmp(params, "-NO_EVENTS")) {
1981		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
1982			     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
1983			     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
1984			     wpa_s->wpa_state,
1985			     MAC2STR(wpa_s->bssid),
1986			     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
1987			     wpa_ssid_txt(wpa_s->current_ssid->ssid,
1988					  wpa_s->current_ssid->ssid_len) : "");
1989		if (wpa_s->wpa_state == WPA_COMPLETED) {
1990			struct wpa_ssid *ssid = wpa_s->current_ssid;
1991			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
1992				     "- connection to " MACSTR
1993				     " completed %s [id=%d id_str=%s]",
1994				     MAC2STR(wpa_s->bssid), "(auth)",
1995				     ssid ? ssid->id : -1,
1996				     ssid && ssid->id_str ? ssid->id_str : "");
1997		}
1998	}
1999#endif /* ANDROID */
2000
2001	return pos - buf;
2002}
2003
2004
2005static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2006					   char *cmd)
2007{
2008	char *pos;
2009	int id;
2010	struct wpa_ssid *ssid;
2011	u8 bssid[ETH_ALEN];
2012
2013	/* cmd: "<network id> <BSSID>" */
2014	pos = os_strchr(cmd, ' ');
2015	if (pos == NULL)
2016		return -1;
2017	*pos++ = '\0';
2018	id = atoi(cmd);
2019	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2020	if (hwaddr_aton(pos, bssid)) {
2021		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2022		return -1;
2023	}
2024
2025	ssid = wpa_config_get_network(wpa_s->conf, id);
2026	if (ssid == NULL) {
2027		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2028			   "to update", id);
2029		return -1;
2030	}
2031
2032	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2033	ssid->bssid_set = !is_zero_ether_addr(bssid);
2034
2035	return 0;
2036}
2037
2038
2039static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
2040					       char *cmd, char *buf,
2041					       size_t buflen)
2042{
2043	u8 bssid[ETH_ALEN];
2044	struct wpa_blacklist *e;
2045	char *pos, *end;
2046	int ret;
2047
2048	/* cmd: "BLACKLIST [<BSSID>]" */
2049	if (*cmd == '\0') {
2050		pos = buf;
2051		end = buf + buflen;
2052		e = wpa_s->blacklist;
2053		while (e) {
2054			ret = os_snprintf(pos, end - pos, MACSTR "\n",
2055					  MAC2STR(e->bssid));
2056			if (os_snprintf_error(end - pos, ret))
2057				return pos - buf;
2058			pos += ret;
2059			e = e->next;
2060		}
2061		return pos - buf;
2062	}
2063
2064	cmd++;
2065	if (os_strncmp(cmd, "clear", 5) == 0) {
2066		wpa_blacklist_clear(wpa_s);
2067		os_memcpy(buf, "OK\n", 3);
2068		return 3;
2069	}
2070
2071	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
2072	if (hwaddr_aton(cmd, bssid)) {
2073		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
2074		return -1;
2075	}
2076
2077	/*
2078	 * Add the BSSID twice, so its count will be 2, causing it to be
2079	 * skipped when processing scan results.
2080	 */
2081	ret = wpa_blacklist_add(wpa_s, bssid);
2082	if (ret < 0)
2083		return -1;
2084	ret = wpa_blacklist_add(wpa_s, bssid);
2085	if (ret < 0)
2086		return -1;
2087	os_memcpy(buf, "OK\n", 3);
2088	return 3;
2089}
2090
2091
2092static const char * debug_level_str(int level)
2093{
2094	switch (level) {
2095	case MSG_EXCESSIVE:
2096		return "EXCESSIVE";
2097	case MSG_MSGDUMP:
2098		return "MSGDUMP";
2099	case MSG_DEBUG:
2100		return "DEBUG";
2101	case MSG_INFO:
2102		return "INFO";
2103	case MSG_WARNING:
2104		return "WARNING";
2105	case MSG_ERROR:
2106		return "ERROR";
2107	default:
2108		return "?";
2109	}
2110}
2111
2112
2113static int str_to_debug_level(const char *s)
2114{
2115	if (os_strcasecmp(s, "EXCESSIVE") == 0)
2116		return MSG_EXCESSIVE;
2117	if (os_strcasecmp(s, "MSGDUMP") == 0)
2118		return MSG_MSGDUMP;
2119	if (os_strcasecmp(s, "DEBUG") == 0)
2120		return MSG_DEBUG;
2121	if (os_strcasecmp(s, "INFO") == 0)
2122		return MSG_INFO;
2123	if (os_strcasecmp(s, "WARNING") == 0)
2124		return MSG_WARNING;
2125	if (os_strcasecmp(s, "ERROR") == 0)
2126		return MSG_ERROR;
2127	return -1;
2128}
2129
2130
2131static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2132					       char *cmd, char *buf,
2133					       size_t buflen)
2134{
2135	char *pos, *end, *stamp;
2136	int ret;
2137
2138	/* cmd: "LOG_LEVEL [<level>]" */
2139	if (*cmd == '\0') {
2140		pos = buf;
2141		end = buf + buflen;
2142		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2143				  "Timestamp: %d\n",
2144				  debug_level_str(wpa_debug_level),
2145				  wpa_debug_timestamp);
2146		if (os_snprintf_error(end - pos, ret))
2147			ret = 0;
2148
2149		return ret;
2150	}
2151
2152	while (*cmd == ' ')
2153		cmd++;
2154
2155	stamp = os_strchr(cmd, ' ');
2156	if (stamp) {
2157		*stamp++ = '\0';
2158		while (*stamp == ' ') {
2159			stamp++;
2160		}
2161	}
2162
2163	if (cmd && os_strlen(cmd)) {
2164		int level = str_to_debug_level(cmd);
2165		if (level < 0)
2166			return -1;
2167		wpa_debug_level = level;
2168	}
2169
2170	if (stamp && os_strlen(stamp))
2171		wpa_debug_timestamp = atoi(stamp);
2172
2173	os_memcpy(buf, "OK\n", 3);
2174	return 3;
2175}
2176
2177
2178static int wpa_supplicant_ctrl_iface_list_networks(
2179	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2180{
2181	char *pos, *end, *prev;
2182	struct wpa_ssid *ssid;
2183	int ret;
2184
2185	pos = buf;
2186	end = buf + buflen;
2187	ret = os_snprintf(pos, end - pos,
2188			  "network id / ssid / bssid / flags\n");
2189	if (os_snprintf_error(end - pos, ret))
2190		return pos - buf;
2191	pos += ret;
2192
2193	ssid = wpa_s->conf->ssid;
2194
2195	/* skip over ssids until we find next one */
2196	if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2197		int last_id = atoi(cmd + 8);
2198		if (last_id != -1) {
2199			while (ssid != NULL && ssid->id <= last_id) {
2200				ssid = ssid->next;
2201			}
2202		}
2203	}
2204
2205	while (ssid) {
2206		prev = pos;
2207		ret = os_snprintf(pos, end - pos, "%d\t%s",
2208				  ssid->id,
2209				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2210		if (os_snprintf_error(end - pos, ret))
2211			return prev - buf;
2212		pos += ret;
2213		if (ssid->bssid_set) {
2214			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2215					  MAC2STR(ssid->bssid));
2216		} else {
2217			ret = os_snprintf(pos, end - pos, "\tany");
2218		}
2219		if (os_snprintf_error(end - pos, ret))
2220			return prev - buf;
2221		pos += ret;
2222		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2223				  ssid == wpa_s->current_ssid ?
2224				  "[CURRENT]" : "",
2225				  ssid->disabled ? "[DISABLED]" : "",
2226				  ssid->disabled_until.sec ?
2227				  "[TEMP-DISABLED]" : "",
2228				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2229				  "");
2230		if (os_snprintf_error(end - pos, ret))
2231			return prev - buf;
2232		pos += ret;
2233		ret = os_snprintf(pos, end - pos, "\n");
2234		if (os_snprintf_error(end - pos, ret))
2235			return prev - buf;
2236		pos += ret;
2237
2238		ssid = ssid->next;
2239	}
2240
2241	return pos - buf;
2242}
2243
2244
2245static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2246{
2247	int ret;
2248	ret = os_snprintf(pos, end - pos, "-");
2249	if (os_snprintf_error(end - pos, ret))
2250		return pos;
2251	pos += ret;
2252	ret = wpa_write_ciphers(pos, end, cipher, "+");
2253	if (ret < 0)
2254		return pos;
2255	pos += ret;
2256	return pos;
2257}
2258
2259
2260static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2261				    const u8 *ie, size_t ie_len)
2262{
2263	struct wpa_ie_data data;
2264	char *start;
2265	int ret;
2266
2267	ret = os_snprintf(pos, end - pos, "[%s-", proto);
2268	if (os_snprintf_error(end - pos, ret))
2269		return pos;
2270	pos += ret;
2271
2272	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2273		ret = os_snprintf(pos, end - pos, "?]");
2274		if (os_snprintf_error(end - pos, ret))
2275			return pos;
2276		pos += ret;
2277		return pos;
2278	}
2279
2280	start = pos;
2281	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2282		ret = os_snprintf(pos, end - pos, "%sEAP",
2283				  pos == start ? "" : "+");
2284		if (os_snprintf_error(end - pos, ret))
2285			return pos;
2286		pos += ret;
2287	}
2288	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2289		ret = os_snprintf(pos, end - pos, "%sPSK",
2290				  pos == start ? "" : "+");
2291		if (os_snprintf_error(end - pos, ret))
2292			return pos;
2293		pos += ret;
2294	}
2295	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2296		ret = os_snprintf(pos, end - pos, "%sNone",
2297				  pos == start ? "" : "+");
2298		if (os_snprintf_error(end - pos, ret))
2299			return pos;
2300		pos += ret;
2301	}
2302	if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2303		ret = os_snprintf(pos, end - pos, "%sSAE",
2304				  pos == start ? "" : "+");
2305		if (os_snprintf_error(end - pos, ret))
2306			return pos;
2307		pos += ret;
2308	}
2309#ifdef CONFIG_IEEE80211R
2310	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2311		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2312				  pos == start ? "" : "+");
2313		if (os_snprintf_error(end - pos, ret))
2314			return pos;
2315		pos += ret;
2316	}
2317	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2318		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2319				  pos == start ? "" : "+");
2320		if (os_snprintf_error(end - pos, ret))
2321			return pos;
2322		pos += ret;
2323	}
2324	if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2325		ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2326				  pos == start ? "" : "+");
2327		if (os_snprintf_error(end - pos, ret))
2328			return pos;
2329		pos += ret;
2330	}
2331#endif /* CONFIG_IEEE80211R */
2332#ifdef CONFIG_IEEE80211W
2333	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2334		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2335				  pos == start ? "" : "+");
2336		if (os_snprintf_error(end - pos, ret))
2337			return pos;
2338		pos += ret;
2339	}
2340	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2341		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2342				  pos == start ? "" : "+");
2343		if (os_snprintf_error(end - pos, ret))
2344			return pos;
2345		pos += ret;
2346	}
2347#endif /* CONFIG_IEEE80211W */
2348
2349#ifdef CONFIG_SUITEB
2350	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2351		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2352				  pos == start ? "" : "+");
2353		if (os_snprintf_error(end - pos, ret))
2354			return pos;
2355		pos += ret;
2356	}
2357#endif /* CONFIG_SUITEB */
2358
2359#ifdef CONFIG_SUITEB192
2360	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2361		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2362				  pos == start ? "" : "+");
2363		if (os_snprintf_error(end - pos, ret))
2364			return pos;
2365		pos += ret;
2366	}
2367#endif /* CONFIG_SUITEB192 */
2368
2369	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
2370
2371	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
2372		ret = os_snprintf(pos, end - pos, "-preauth");
2373		if (os_snprintf_error(end - pos, ret))
2374			return pos;
2375		pos += ret;
2376	}
2377
2378	ret = os_snprintf(pos, end - pos, "]");
2379	if (os_snprintf_error(end - pos, ret))
2380		return pos;
2381	pos += ret;
2382
2383	return pos;
2384}
2385
2386
2387#ifdef CONFIG_WPS
2388static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
2389					    char *pos, char *end,
2390					    struct wpabuf *wps_ie)
2391{
2392	int ret;
2393	const char *txt;
2394
2395	if (wps_ie == NULL)
2396		return pos;
2397	if (wps_is_selected_pbc_registrar(wps_ie))
2398		txt = "[WPS-PBC]";
2399	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2400		txt = "[WPS-AUTH]";
2401	else if (wps_is_selected_pin_registrar(wps_ie))
2402		txt = "[WPS-PIN]";
2403	else
2404		txt = "[WPS]";
2405
2406	ret = os_snprintf(pos, end - pos, "%s", txt);
2407	if (!os_snprintf_error(end - pos, ret))
2408		pos += ret;
2409	wpabuf_free(wps_ie);
2410	return pos;
2411}
2412#endif /* CONFIG_WPS */
2413
2414
2415static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2416					char *pos, char *end,
2417					const struct wpa_bss *bss)
2418{
2419#ifdef CONFIG_WPS
2420	struct wpabuf *wps_ie;
2421	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2422	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2423#else /* CONFIG_WPS */
2424	return pos;
2425#endif /* CONFIG_WPS */
2426}
2427
2428
2429/* Format one result on one text line into a buffer. */
2430static int wpa_supplicant_ctrl_iface_scan_result(
2431	struct wpa_supplicant *wpa_s,
2432	const struct wpa_bss *bss, char *buf, size_t buflen)
2433{
2434	char *pos, *end;
2435	int ret;
2436	const u8 *ie, *ie2, *p2p, *mesh;
2437
2438	mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
2439	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2440	if (!p2p)
2441		p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
2442	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2443	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2444	    0)
2445		return 0; /* Do not show P2P listen discovery results here */
2446
2447	pos = buf;
2448	end = buf + buflen;
2449
2450	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2451			  MAC2STR(bss->bssid), bss->freq, bss->level);
2452	if (os_snprintf_error(end - pos, ret))
2453		return -1;
2454	pos += ret;
2455	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2456	if (ie)
2457		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2458	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2459	if (ie2) {
2460		pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
2461					    ie2, 2 + ie2[1]);
2462	}
2463	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2464	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2465		ret = os_snprintf(pos, end - pos, "[WEP]");
2466		if (os_snprintf_error(end - pos, ret))
2467			return -1;
2468		pos += ret;
2469	}
2470	if (mesh) {
2471		ret = os_snprintf(pos, end - pos, "[MESH]");
2472		if (os_snprintf_error(end - pos, ret))
2473			return -1;
2474		pos += ret;
2475	}
2476	if (bss_is_dmg(bss)) {
2477		const char *s;
2478		ret = os_snprintf(pos, end - pos, "[DMG]");
2479		if (os_snprintf_error(end - pos, ret))
2480			return -1;
2481		pos += ret;
2482		switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
2483		case IEEE80211_CAP_DMG_IBSS:
2484			s = "[IBSS]";
2485			break;
2486		case IEEE80211_CAP_DMG_AP:
2487			s = "[ESS]";
2488			break;
2489		case IEEE80211_CAP_DMG_PBSS:
2490			s = "[PBSS]";
2491			break;
2492		default:
2493			s = "";
2494			break;
2495		}
2496		ret = os_snprintf(pos, end - pos, "%s", s);
2497		if (os_snprintf_error(end - pos, ret))
2498			return -1;
2499		pos += ret;
2500	} else {
2501		if (bss->caps & IEEE80211_CAP_IBSS) {
2502			ret = os_snprintf(pos, end - pos, "[IBSS]");
2503			if (os_snprintf_error(end - pos, ret))
2504				return -1;
2505			pos += ret;
2506		}
2507		if (bss->caps & IEEE80211_CAP_ESS) {
2508			ret = os_snprintf(pos, end - pos, "[ESS]");
2509			if (os_snprintf_error(end - pos, ret))
2510				return -1;
2511			pos += ret;
2512		}
2513	}
2514	if (p2p) {
2515		ret = os_snprintf(pos, end - pos, "[P2P]");
2516		if (os_snprintf_error(end - pos, ret))
2517			return -1;
2518		pos += ret;
2519	}
2520#ifdef CONFIG_HS20
2521	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2522		ret = os_snprintf(pos, end - pos, "[HS20]");
2523		if (os_snprintf_error(end - pos, ret))
2524			return -1;
2525		pos += ret;
2526	}
2527#endif /* CONFIG_HS20 */
2528
2529	ret = os_snprintf(pos, end - pos, "\t%s",
2530			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
2531	if (os_snprintf_error(end - pos, ret))
2532		return -1;
2533	pos += ret;
2534
2535	ret = os_snprintf(pos, end - pos, "\n");
2536	if (os_snprintf_error(end - pos, ret))
2537		return -1;
2538	pos += ret;
2539
2540	return pos - buf;
2541}
2542
2543
2544static int wpa_supplicant_ctrl_iface_scan_results(
2545	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2546{
2547	char *pos, *end;
2548	struct wpa_bss *bss;
2549	int ret;
2550
2551	pos = buf;
2552	end = buf + buflen;
2553	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2554			  "flags / ssid\n");
2555	if (os_snprintf_error(end - pos, ret))
2556		return pos - buf;
2557	pos += ret;
2558
2559	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2560		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2561							    end - pos);
2562		if (ret < 0 || ret >= end - pos)
2563			return pos - buf;
2564		pos += ret;
2565	}
2566
2567	return pos - buf;
2568}
2569
2570
2571#ifdef CONFIG_MESH
2572
2573static int wpa_supplicant_ctrl_iface_mesh_interface_add(
2574	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2575{
2576	char *pos, ifname[IFNAMSIZ + 1];
2577
2578	ifname[0] = '\0';
2579
2580	pos = os_strstr(cmd, "ifname=");
2581	if (pos) {
2582		pos += 7;
2583		os_strlcpy(ifname, pos, sizeof(ifname));
2584	}
2585
2586	if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
2587		return -1;
2588
2589	os_strlcpy(reply, ifname, max_len);
2590	return os_strlen(ifname);
2591}
2592
2593
2594static int wpa_supplicant_ctrl_iface_mesh_group_add(
2595	struct wpa_supplicant *wpa_s, char *cmd)
2596{
2597	int id;
2598	struct wpa_ssid *ssid;
2599
2600	id = atoi(cmd);
2601	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
2602
2603	ssid = wpa_config_get_network(wpa_s->conf, id);
2604	if (ssid == NULL) {
2605		wpa_printf(MSG_DEBUG,
2606			   "CTRL_IFACE: Could not find network id=%d", id);
2607		return -1;
2608	}
2609	if (ssid->mode != WPAS_MODE_MESH) {
2610		wpa_printf(MSG_DEBUG,
2611			   "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
2612		return -1;
2613	}
2614	if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
2615	    ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
2616		wpa_printf(MSG_ERROR,
2617			   "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
2618		return -1;
2619	}
2620
2621	/*
2622	 * TODO: If necessary write our own group_add function,
2623	 * for now we can reuse select_network
2624	 */
2625	wpa_supplicant_select_network(wpa_s, ssid);
2626
2627	return 0;
2628}
2629
2630
2631static int wpa_supplicant_ctrl_iface_mesh_group_remove(
2632	struct wpa_supplicant *wpa_s, char *cmd)
2633{
2634	struct wpa_supplicant *orig;
2635	struct wpa_global *global;
2636	int found = 0;
2637
2638	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
2639
2640	global = wpa_s->global;
2641	orig = wpa_s;
2642
2643	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
2644		if (os_strcmp(wpa_s->ifname, cmd) == 0) {
2645			found = 1;
2646			break;
2647		}
2648	}
2649	if (!found) {
2650		wpa_printf(MSG_ERROR,
2651			   "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
2652			   cmd);
2653		return -1;
2654	}
2655	if (wpa_s->mesh_if_created && wpa_s == orig) {
2656		wpa_printf(MSG_ERROR,
2657			   "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
2658		return -1;
2659	}
2660
2661	wpa_s->reassociate = 0;
2662	wpa_s->disconnected = 1;
2663	wpa_supplicant_cancel_sched_scan(wpa_s);
2664	wpa_supplicant_cancel_scan(wpa_s);
2665
2666	/*
2667	 * TODO: If necessary write our own group_remove function,
2668	 * for now we can reuse deauthenticate
2669	 */
2670	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2671
2672	if (wpa_s->mesh_if_created)
2673		wpa_supplicant_remove_iface(global, wpa_s, 0);
2674
2675	return 0;
2676}
2677
2678#endif /* CONFIG_MESH */
2679
2680
2681static int wpa_supplicant_ctrl_iface_select_network(
2682	struct wpa_supplicant *wpa_s, char *cmd)
2683{
2684	int id;
2685	struct wpa_ssid *ssid;
2686	char *pos;
2687
2688	/* cmd: "<network id>" or "any" */
2689	if (os_strncmp(cmd, "any", 3) == 0) {
2690		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
2691		ssid = NULL;
2692	} else {
2693		id = atoi(cmd);
2694		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
2695
2696		ssid = wpa_config_get_network(wpa_s->conf, id);
2697		if (ssid == NULL) {
2698			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2699				   "network id=%d", id);
2700			return -1;
2701		}
2702		if (ssid->disabled == 2) {
2703			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2704				   "SELECT_NETWORK with persistent P2P group");
2705			return -1;
2706		}
2707	}
2708
2709	pos = os_strstr(cmd, " freq=");
2710	if (pos) {
2711		int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
2712		if (freqs) {
2713			wpa_s->scan_req = MANUAL_SCAN_REQ;
2714			os_free(wpa_s->manual_scan_freqs);
2715			wpa_s->manual_scan_freqs = freqs;
2716		}
2717	}
2718
2719	wpa_supplicant_select_network(wpa_s, ssid);
2720
2721	return 0;
2722}
2723
2724
2725static int wpa_supplicant_ctrl_iface_enable_network(
2726	struct wpa_supplicant *wpa_s, char *cmd)
2727{
2728	int id;
2729	struct wpa_ssid *ssid;
2730
2731	/* cmd: "<network id>" or "all" */
2732	if (os_strcmp(cmd, "all") == 0) {
2733		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
2734		ssid = NULL;
2735	} else {
2736		id = atoi(cmd);
2737		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
2738
2739		ssid = wpa_config_get_network(wpa_s->conf, id);
2740		if (ssid == NULL) {
2741			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2742				   "network id=%d", id);
2743			return -1;
2744		}
2745		if (ssid->disabled == 2) {
2746			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2747				   "ENABLE_NETWORK with persistent P2P group");
2748			return -1;
2749		}
2750
2751		if (os_strstr(cmd, " no-connect")) {
2752			ssid->disabled = 0;
2753			return 0;
2754		}
2755	}
2756	wpa_supplicant_enable_network(wpa_s, ssid);
2757
2758	return 0;
2759}
2760
2761
2762static int wpa_supplicant_ctrl_iface_disable_network(
2763	struct wpa_supplicant *wpa_s, char *cmd)
2764{
2765	int id;
2766	struct wpa_ssid *ssid;
2767
2768	/* cmd: "<network id>" or "all" */
2769	if (os_strcmp(cmd, "all") == 0) {
2770		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
2771		ssid = NULL;
2772	} else {
2773		id = atoi(cmd);
2774		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
2775
2776		ssid = wpa_config_get_network(wpa_s->conf, id);
2777		if (ssid == NULL) {
2778			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2779				   "network id=%d", id);
2780			return -1;
2781		}
2782		if (ssid->disabled == 2) {
2783			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2784				   "DISABLE_NETWORK with persistent P2P "
2785				   "group");
2786			return -1;
2787		}
2788	}
2789	wpa_supplicant_disable_network(wpa_s, ssid);
2790
2791	return 0;
2792}
2793
2794
2795static int wpa_supplicant_ctrl_iface_add_network(
2796	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2797{
2798	struct wpa_ssid *ssid;
2799	int ret;
2800
2801	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
2802
2803	ssid = wpa_config_add_network(wpa_s->conf);
2804	if (ssid == NULL)
2805		return -1;
2806
2807	wpas_notify_network_added(wpa_s, ssid);
2808
2809	ssid->disabled = 1;
2810	wpa_config_set_network_defaults(ssid);
2811
2812	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
2813	if (os_snprintf_error(buflen, ret))
2814		return -1;
2815	return ret;
2816}
2817
2818
2819static int wpa_supplicant_ctrl_iface_remove_network(
2820	struct wpa_supplicant *wpa_s, char *cmd)
2821{
2822	int id;
2823	struct wpa_ssid *ssid;
2824	int was_disabled;
2825
2826	/* cmd: "<network id>" or "all" */
2827	if (os_strcmp(cmd, "all") == 0) {
2828		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
2829		if (wpa_s->sched_scanning)
2830			wpa_supplicant_cancel_sched_scan(wpa_s);
2831
2832		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2833		if (wpa_s->current_ssid) {
2834#ifdef CONFIG_SME
2835			wpa_s->sme.prev_bssid_set = 0;
2836#endif /* CONFIG_SME */
2837			wpa_sm_set_config(wpa_s->wpa, NULL);
2838			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2839			wpa_s->own_disconnect_req = 1;
2840			wpa_supplicant_deauthenticate(
2841				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2842		}
2843		ssid = wpa_s->conf->ssid;
2844		while (ssid) {
2845			struct wpa_ssid *remove_ssid = ssid;
2846			id = ssid->id;
2847			ssid = ssid->next;
2848			if (wpa_s->last_ssid == remove_ssid)
2849				wpa_s->last_ssid = NULL;
2850			wpas_notify_network_removed(wpa_s, remove_ssid);
2851			wpa_config_remove_network(wpa_s->conf, id);
2852		}
2853		return 0;
2854	}
2855
2856	id = atoi(cmd);
2857	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
2858
2859	ssid = wpa_config_get_network(wpa_s->conf, id);
2860	if (ssid)
2861		wpas_notify_network_removed(wpa_s, ssid);
2862	if (ssid == NULL) {
2863		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2864			   "id=%d", id);
2865		return -1;
2866	}
2867
2868	if (wpa_s->last_ssid == ssid)
2869		wpa_s->last_ssid = NULL;
2870
2871	if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2872#ifdef CONFIG_SME
2873		wpa_s->sme.prev_bssid_set = 0;
2874#endif /* CONFIG_SME */
2875		/*
2876		 * Invalidate the EAP session cache if the current or
2877		 * previously used network is removed.
2878		 */
2879		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2880	}
2881
2882	if (ssid == wpa_s->current_ssid) {
2883		wpa_sm_set_config(wpa_s->wpa, NULL);
2884		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2885
2886		wpa_s->own_disconnect_req = 1;
2887		wpa_supplicant_deauthenticate(wpa_s,
2888					      WLAN_REASON_DEAUTH_LEAVING);
2889	}
2890
2891	was_disabled = ssid->disabled;
2892
2893	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2894		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
2895			   "network id=%d", id);
2896		return -1;
2897	}
2898
2899	if (!was_disabled && wpa_s->sched_scanning) {
2900		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2901			   "network from filters");
2902		wpa_supplicant_cancel_sched_scan(wpa_s);
2903		wpa_supplicant_req_scan(wpa_s, 0, 0);
2904	}
2905
2906	return 0;
2907}
2908
2909
2910static int wpa_supplicant_ctrl_iface_update_network(
2911	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2912	char *name, char *value)
2913{
2914	if (wpa_config_set(ssid, name, value, 0) < 0) {
2915		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
2916			   "variable '%s'", name);
2917		return -1;
2918	}
2919
2920	if (os_strcmp(name, "bssid") != 0 &&
2921	    os_strcmp(name, "priority") != 0)
2922		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2923
2924	if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
2925		/*
2926		 * Invalidate the EAP session cache if anything in the current
2927		 * or previously used configuration changes.
2928		 */
2929		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2930	}
2931
2932	if ((os_strcmp(name, "psk") == 0 &&
2933	     value[0] == '"' && ssid->ssid_len) ||
2934	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
2935		wpa_config_update_psk(ssid);
2936	else if (os_strcmp(name, "priority") == 0)
2937		wpa_config_update_prio_list(wpa_s->conf);
2938
2939	return 0;
2940}
2941
2942
2943static int wpa_supplicant_ctrl_iface_set_network(
2944	struct wpa_supplicant *wpa_s, char *cmd)
2945{
2946	int id, ret, prev_bssid_set, prev_disabled;
2947	struct wpa_ssid *ssid;
2948	char *name, *value;
2949	u8 prev_bssid[ETH_ALEN];
2950
2951	/* cmd: "<network id> <variable name> <value>" */
2952	name = os_strchr(cmd, ' ');
2953	if (name == NULL)
2954		return -1;
2955	*name++ = '\0';
2956
2957	value = os_strchr(name, ' ');
2958	if (value == NULL)
2959		return -1;
2960	*value++ = '\0';
2961
2962	id = atoi(cmd);
2963	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
2964		   id, name);
2965	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2966			      (u8 *) value, os_strlen(value));
2967
2968	ssid = wpa_config_get_network(wpa_s->conf, id);
2969	if (ssid == NULL) {
2970		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2971			   "id=%d", id);
2972		return -1;
2973	}
2974
2975	prev_bssid_set = ssid->bssid_set;
2976	prev_disabled = ssid->disabled;
2977	os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
2978	ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
2979						       value);
2980	if (ret == 0 &&
2981	    (ssid->bssid_set != prev_bssid_set ||
2982	     os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
2983		wpas_notify_network_bssid_set_changed(wpa_s, ssid);
2984
2985	if (prev_disabled != ssid->disabled &&
2986	    (prev_disabled == 2 || ssid->disabled == 2))
2987		wpas_notify_network_type_changed(wpa_s, ssid);
2988
2989	return ret;
2990}
2991
2992
2993static int wpa_supplicant_ctrl_iface_get_network(
2994	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2995{
2996	int id;
2997	size_t res;
2998	struct wpa_ssid *ssid;
2999	char *name, *value;
3000
3001	/* cmd: "<network id> <variable name>" */
3002	name = os_strchr(cmd, ' ');
3003	if (name == NULL || buflen == 0)
3004		return -1;
3005	*name++ = '\0';
3006
3007	id = atoi(cmd);
3008	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
3009		   id, name);
3010
3011	ssid = wpa_config_get_network(wpa_s->conf, id);
3012	if (ssid == NULL) {
3013		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3014			   "id=%d", id);
3015		return -1;
3016	}
3017
3018	value = wpa_config_get_no_key(ssid, name);
3019	if (value == NULL) {
3020		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3021			   "variable '%s'", name);
3022		return -1;
3023	}
3024
3025	res = os_strlcpy(buf, value, buflen);
3026	if (res >= buflen) {
3027		os_free(value);
3028		return -1;
3029	}
3030
3031	os_free(value);
3032
3033	return res;
3034}
3035
3036
3037static int wpa_supplicant_ctrl_iface_dup_network(
3038	struct wpa_supplicant *wpa_s, char *cmd)
3039{
3040	struct wpa_ssid *ssid_s, *ssid_d;
3041	char *name, *id, *value;
3042	int id_s, id_d, ret;
3043
3044	/* cmd: "<src network id> <dst network id> <variable name>" */
3045	id = os_strchr(cmd, ' ');
3046	if (id == NULL)
3047		return -1;
3048	*id++ = '\0';
3049
3050	name = os_strchr(id, ' ');
3051	if (name == NULL)
3052		return -1;
3053	*name++ = '\0';
3054
3055	id_s = atoi(cmd);
3056	id_d = atoi(id);
3057	wpa_printf(MSG_DEBUG, "CTRL_IFACE: DUP_NETWORK id=%d -> %d name='%s'",
3058		   id_s, id_d, name);
3059
3060	ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3061	if (ssid_s == NULL) {
3062		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3063			   "network id=%d", id_s);
3064		return -1;
3065	}
3066
3067	ssid_d = wpa_config_get_network(wpa_s->conf, id_d);
3068	if (ssid_d == NULL) {
3069		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3070			   "network id=%d", id_d);
3071		return -1;
3072	}
3073
3074	value = wpa_config_get(ssid_s, name);
3075	if (value == NULL) {
3076		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3077			   "variable '%s'", name);
3078		return -1;
3079	}
3080
3081	ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid_d, name,
3082						       value);
3083
3084	os_free(value);
3085
3086	return ret;
3087}
3088
3089
3090static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3091						char *buf, size_t buflen)
3092{
3093	char *pos, *end;
3094	struct wpa_cred *cred;
3095	int ret;
3096
3097	pos = buf;
3098	end = buf + buflen;
3099	ret = os_snprintf(pos, end - pos,
3100			  "cred id / realm / username / domain / imsi\n");
3101	if (os_snprintf_error(end - pos, ret))
3102		return pos - buf;
3103	pos += ret;
3104
3105	cred = wpa_s->conf->cred;
3106	while (cred) {
3107		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3108				  cred->id, cred->realm ? cred->realm : "",
3109				  cred->username ? cred->username : "",
3110				  cred->domain ? cred->domain[0] : "",
3111				  cred->imsi ? cred->imsi : "");
3112		if (os_snprintf_error(end - pos, ret))
3113			return pos - buf;
3114		pos += ret;
3115
3116		cred = cred->next;
3117	}
3118
3119	return pos - buf;
3120}
3121
3122
3123static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3124					      char *buf, size_t buflen)
3125{
3126	struct wpa_cred *cred;
3127	int ret;
3128
3129	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3130
3131	cred = wpa_config_add_cred(wpa_s->conf);
3132	if (cred == NULL)
3133		return -1;
3134
3135	wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3136
3137	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
3138	if (os_snprintf_error(buflen, ret))
3139		return -1;
3140	return ret;
3141}
3142
3143
3144static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
3145				 struct wpa_cred *cred)
3146{
3147	struct wpa_ssid *ssid;
3148	char str[20];
3149	int id;
3150
3151	if (cred == NULL) {
3152		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3153		return -1;
3154	}
3155
3156	id = cred->id;
3157	if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
3158		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3159		return -1;
3160	}
3161
3162	wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
3163
3164	/* Remove any network entry created based on the removed credential */
3165	ssid = wpa_s->conf->ssid;
3166	while (ssid) {
3167		if (ssid->parent_cred == cred) {
3168			int res;
3169
3170			wpa_printf(MSG_DEBUG, "Remove network id %d since it "
3171				   "used the removed credential", ssid->id);
3172			res = os_snprintf(str, sizeof(str), "%d", ssid->id);
3173			if (os_snprintf_error(sizeof(str), res))
3174				str[sizeof(str) - 1] = '\0';
3175			ssid = ssid->next;
3176			wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
3177		} else
3178			ssid = ssid->next;
3179	}
3180
3181	return 0;
3182}
3183
3184
3185static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3186						 char *cmd)
3187{
3188	int id;
3189	struct wpa_cred *cred, *prev;
3190
3191	/* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3192	 * "provisioning_sp=<FQDN> */
3193	if (os_strcmp(cmd, "all") == 0) {
3194		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
3195		cred = wpa_s->conf->cred;
3196		while (cred) {
3197			prev = cred;
3198			cred = cred->next;
3199			wpas_ctrl_remove_cred(wpa_s, prev);
3200		}
3201		return 0;
3202	}
3203
3204	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3205		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3206			   cmd + 8);
3207		cred = wpa_s->conf->cred;
3208		while (cred) {
3209			prev = cred;
3210			cred = cred->next;
3211			if (prev->domain) {
3212				size_t i;
3213				for (i = 0; i < prev->num_domain; i++) {
3214					if (os_strcmp(prev->domain[i], cmd + 8)
3215					    != 0)
3216						continue;
3217					wpas_ctrl_remove_cred(wpa_s, prev);
3218					break;
3219				}
3220			}
3221		}
3222		return 0;
3223	}
3224
3225	if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3226		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3227			   cmd + 16);
3228		cred = wpa_s->conf->cred;
3229		while (cred) {
3230			prev = cred;
3231			cred = cred->next;
3232			if (prev->provisioning_sp &&
3233			    os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
3234				wpas_ctrl_remove_cred(wpa_s, prev);
3235		}
3236		return 0;
3237	}
3238
3239	id = atoi(cmd);
3240	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3241
3242	cred = wpa_config_get_cred(wpa_s->conf, id);
3243	return wpas_ctrl_remove_cred(wpa_s, cred);
3244}
3245
3246
3247static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3248					      char *cmd)
3249{
3250	int id;
3251	struct wpa_cred *cred;
3252	char *name, *value;
3253
3254	/* cmd: "<cred id> <variable name> <value>" */
3255	name = os_strchr(cmd, ' ');
3256	if (name == NULL)
3257		return -1;
3258	*name++ = '\0';
3259
3260	value = os_strchr(name, ' ');
3261	if (value == NULL)
3262		return -1;
3263	*value++ = '\0';
3264
3265	id = atoi(cmd);
3266	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3267		   id, name);
3268	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3269			      (u8 *) value, os_strlen(value));
3270
3271	cred = wpa_config_get_cred(wpa_s->conf, id);
3272	if (cred == NULL) {
3273		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3274			   id);
3275		return -1;
3276	}
3277
3278	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3279		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3280			   "variable '%s'", name);
3281		return -1;
3282	}
3283
3284	wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3285
3286	return 0;
3287}
3288
3289
3290static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
3291					      char *cmd, char *buf,
3292					      size_t buflen)
3293{
3294	int id;
3295	size_t res;
3296	struct wpa_cred *cred;
3297	char *name, *value;
3298
3299	/* cmd: "<cred id> <variable name>" */
3300	name = os_strchr(cmd, ' ');
3301	if (name == NULL)
3302		return -1;
3303	*name++ = '\0';
3304
3305	id = atoi(cmd);
3306	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
3307		   id, name);
3308
3309	cred = wpa_config_get_cred(wpa_s->conf, id);
3310	if (cred == NULL) {
3311		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3312			   id);
3313		return -1;
3314	}
3315
3316	value = wpa_config_get_cred_no_key(cred, name);
3317	if (value == NULL) {
3318		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
3319			   name);
3320		return -1;
3321	}
3322
3323	res = os_strlcpy(buf, value, buflen);
3324	if (res >= buflen) {
3325		os_free(value);
3326		return -1;
3327	}
3328
3329	os_free(value);
3330
3331	return res;
3332}
3333
3334
3335#ifndef CONFIG_NO_CONFIG_WRITE
3336static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
3337{
3338	int ret;
3339
3340	if (!wpa_s->conf->update_config) {
3341		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
3342			   "to update configuration (update_config=0)");
3343		return -1;
3344	}
3345
3346	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
3347	if (ret) {
3348		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
3349			   "update configuration");
3350	} else {
3351		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
3352			   " updated");
3353	}
3354
3355	return ret;
3356}
3357#endif /* CONFIG_NO_CONFIG_WRITE */
3358
3359
3360struct cipher_info {
3361	unsigned int capa;
3362	const char *name;
3363	int group_only;
3364};
3365
3366static const struct cipher_info ciphers[] = {
3367	{ WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
3368	{ WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
3369	{ WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
3370	{ WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
3371	{ WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
3372	{ WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
3373	{ WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
3374	{ WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
3375};
3376
3377static const struct cipher_info ciphers_group_mgmt[] = {
3378	{ WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
3379	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
3380	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
3381	{ WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
3382};
3383
3384
3385static int ctrl_iface_get_capability_pairwise(int res, char *strict,
3386					      struct wpa_driver_capa *capa,
3387					      char *buf, size_t buflen)
3388{
3389	int ret;
3390	char *pos, *end;
3391	size_t len;
3392	unsigned int i;
3393
3394	pos = buf;
3395	end = pos + buflen;
3396
3397	if (res < 0) {
3398		if (strict)
3399			return 0;
3400		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
3401		if (len >= buflen)
3402			return -1;
3403		return len;
3404	}
3405
3406	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
3407		if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
3408			ret = os_snprintf(pos, end - pos, "%s%s",
3409					  pos == buf ? "" : " ",
3410					  ciphers[i].name);
3411			if (os_snprintf_error(end - pos, ret))
3412				return pos - buf;
3413			pos += ret;
3414		}
3415	}
3416
3417	return pos - buf;
3418}
3419
3420
3421static int ctrl_iface_get_capability_group(int res, char *strict,
3422					   struct wpa_driver_capa *capa,
3423					   char *buf, size_t buflen)
3424{
3425	int ret;
3426	char *pos, *end;
3427	size_t len;
3428	unsigned int i;
3429
3430	pos = buf;
3431	end = pos + buflen;
3432
3433	if (res < 0) {
3434		if (strict)
3435			return 0;
3436		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
3437		if (len >= buflen)
3438			return -1;
3439		return len;
3440	}
3441
3442	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
3443		if (capa->enc & ciphers[i].capa) {
3444			ret = os_snprintf(pos, end - pos, "%s%s",
3445					  pos == buf ? "" : " ",
3446					  ciphers[i].name);
3447			if (os_snprintf_error(end - pos, ret))
3448				return pos - buf;
3449			pos += ret;
3450		}
3451	}
3452
3453	return pos - buf;
3454}
3455
3456
3457static int ctrl_iface_get_capability_group_mgmt(int res, char *strict,
3458						struct wpa_driver_capa *capa,
3459						char *buf, size_t buflen)
3460{
3461	int ret;
3462	char *pos, *end;
3463	unsigned int i;
3464
3465	pos = buf;
3466	end = pos + buflen;
3467
3468	if (res < 0)
3469		return 0;
3470
3471	for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
3472		if (capa->enc & ciphers_group_mgmt[i].capa) {
3473			ret = os_snprintf(pos, end - pos, "%s%s",
3474					  pos == buf ? "" : " ",
3475					  ciphers_group_mgmt[i].name);
3476			if (os_snprintf_error(end - pos, ret))
3477				return pos - buf;
3478			pos += ret;
3479		}
3480	}
3481
3482	return pos - buf;
3483}
3484
3485
3486static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
3487					      struct wpa_driver_capa *capa,
3488					      char *buf, size_t buflen)
3489{
3490	int ret;
3491	char *pos, *end;
3492	size_t len;
3493
3494	pos = buf;
3495	end = pos + buflen;
3496
3497	if (res < 0) {
3498		if (strict)
3499			return 0;
3500		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
3501				 "NONE", buflen);
3502		if (len >= buflen)
3503			return -1;
3504		return len;
3505	}
3506
3507	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
3508	if (os_snprintf_error(end - pos, ret))
3509		return pos - buf;
3510	pos += ret;
3511
3512	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3513			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
3514		ret = os_snprintf(pos, end - pos, " WPA-EAP");
3515		if (os_snprintf_error(end - pos, ret))
3516			return pos - buf;
3517		pos += ret;
3518	}
3519
3520	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3521			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3522		ret = os_snprintf(pos, end - pos, " WPA-PSK");
3523		if (os_snprintf_error(end - pos, ret))
3524			return pos - buf;
3525		pos += ret;
3526	}
3527
3528	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
3529		ret = os_snprintf(pos, end - pos, " WPA-NONE");
3530		if (os_snprintf_error(end - pos, ret))
3531			return pos - buf;
3532		pos += ret;
3533	}
3534
3535#ifdef CONFIG_SUITEB
3536	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
3537		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
3538		if (os_snprintf_error(end - pos, ret))
3539			return pos - buf;
3540		pos += ret;
3541	}
3542#endif /* CONFIG_SUITEB */
3543#ifdef CONFIG_SUITEB192
3544	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
3545		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
3546		if (os_snprintf_error(end - pos, ret))
3547			return pos - buf;
3548		pos += ret;
3549	}
3550#endif /* CONFIG_SUITEB192 */
3551
3552	return pos - buf;
3553}
3554
3555
3556static int ctrl_iface_get_capability_proto(int res, char *strict,
3557					   struct wpa_driver_capa *capa,
3558					   char *buf, size_t buflen)
3559{
3560	int ret;
3561	char *pos, *end;
3562	size_t len;
3563
3564	pos = buf;
3565	end = pos + buflen;
3566
3567	if (res < 0) {
3568		if (strict)
3569			return 0;
3570		len = os_strlcpy(buf, "RSN WPA", buflen);
3571		if (len >= buflen)
3572			return -1;
3573		return len;
3574	}
3575
3576	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
3577			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3578		ret = os_snprintf(pos, end - pos, "%sRSN",
3579				  pos == buf ? "" : " ");
3580		if (os_snprintf_error(end - pos, ret))
3581			return pos - buf;
3582		pos += ret;
3583	}
3584
3585	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3586			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
3587		ret = os_snprintf(pos, end - pos, "%sWPA",
3588				  pos == buf ? "" : " ");
3589		if (os_snprintf_error(end - pos, ret))
3590			return pos - buf;
3591		pos += ret;
3592	}
3593
3594	return pos - buf;
3595}
3596
3597
3598static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
3599					      int res, char *strict,
3600					      struct wpa_driver_capa *capa,
3601					      char *buf, size_t buflen)
3602{
3603	int ret;
3604	char *pos, *end;
3605	size_t len;
3606
3607	pos = buf;
3608	end = pos + buflen;
3609
3610	if (res < 0) {
3611		if (strict)
3612			return 0;
3613		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
3614		if (len >= buflen)
3615			return -1;
3616		return len;
3617	}
3618
3619	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
3620		ret = os_snprintf(pos, end - pos, "%sOPEN",
3621				  pos == buf ? "" : " ");
3622		if (os_snprintf_error(end - pos, ret))
3623			return pos - buf;
3624		pos += ret;
3625	}
3626
3627	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
3628		ret = os_snprintf(pos, end - pos, "%sSHARED",
3629				  pos == buf ? "" : " ");
3630		if (os_snprintf_error(end - pos, ret))
3631			return pos - buf;
3632		pos += ret;
3633	}
3634
3635	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
3636		ret = os_snprintf(pos, end - pos, "%sLEAP",
3637				  pos == buf ? "" : " ");
3638		if (os_snprintf_error(end - pos, ret))
3639			return pos - buf;
3640		pos += ret;
3641	}
3642
3643#ifdef CONFIG_SAE
3644	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
3645		ret = os_snprintf(pos, end - pos, "%sSAE",
3646				  pos == buf ? "" : " ");
3647		if (os_snprintf_error(end - pos, ret))
3648			return pos - buf;
3649		pos += ret;
3650	}
3651#endif /* CONFIG_SAE */
3652
3653	return pos - buf;
3654}
3655
3656
3657static int ctrl_iface_get_capability_modes(int res, char *strict,
3658					   struct wpa_driver_capa *capa,
3659					   char *buf, size_t buflen)
3660{
3661	int ret;
3662	char *pos, *end;
3663	size_t len;
3664
3665	pos = buf;
3666	end = pos + buflen;
3667
3668	if (res < 0) {
3669		if (strict)
3670			return 0;
3671		len = os_strlcpy(buf, "IBSS AP", buflen);
3672		if (len >= buflen)
3673			return -1;
3674		return len;
3675	}
3676
3677	if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
3678		ret = os_snprintf(pos, end - pos, "%sIBSS",
3679				  pos == buf ? "" : " ");
3680		if (os_snprintf_error(end - pos, ret))
3681			return pos - buf;
3682		pos += ret;
3683	}
3684
3685	if (capa->flags & WPA_DRIVER_FLAGS_AP) {
3686		ret = os_snprintf(pos, end - pos, "%sAP",
3687				  pos == buf ? "" : " ");
3688		if (os_snprintf_error(end - pos, ret))
3689			return pos - buf;
3690		pos += ret;
3691	}
3692
3693#ifdef CONFIG_MESH
3694	if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
3695		ret = os_snprintf(pos, end - pos, "%sMESH",
3696				  pos == buf ? "" : " ");
3697		if (os_snprintf_error(end - pos, ret))
3698			return pos - buf;
3699		pos += ret;
3700	}
3701#endif /* CONFIG_MESH */
3702
3703	return pos - buf;
3704}
3705
3706
3707static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
3708					      char *buf, size_t buflen)
3709{
3710	struct hostapd_channel_data *chnl;
3711	int ret, i, j;
3712	char *pos, *end, *hmode;
3713
3714	pos = buf;
3715	end = pos + buflen;
3716
3717	for (j = 0; j < wpa_s->hw.num_modes; j++) {
3718		switch (wpa_s->hw.modes[j].mode) {
3719		case HOSTAPD_MODE_IEEE80211B:
3720			hmode = "B";
3721			break;
3722		case HOSTAPD_MODE_IEEE80211G:
3723			hmode = "G";
3724			break;
3725		case HOSTAPD_MODE_IEEE80211A:
3726			hmode = "A";
3727			break;
3728		case HOSTAPD_MODE_IEEE80211AD:
3729			hmode = "AD";
3730			break;
3731		default:
3732			continue;
3733		}
3734		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
3735		if (os_snprintf_error(end - pos, ret))
3736			return pos - buf;
3737		pos += ret;
3738		chnl = wpa_s->hw.modes[j].channels;
3739		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3740			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3741				continue;
3742			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
3743			if (os_snprintf_error(end - pos, ret))
3744				return pos - buf;
3745			pos += ret;
3746		}
3747		ret = os_snprintf(pos, end - pos, "\n");
3748		if (os_snprintf_error(end - pos, ret))
3749			return pos - buf;
3750		pos += ret;
3751	}
3752
3753	return pos - buf;
3754}
3755
3756
3757static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
3758					  char *buf, size_t buflen)
3759{
3760	struct hostapd_channel_data *chnl;
3761	int ret, i, j;
3762	char *pos, *end, *hmode;
3763
3764	pos = buf;
3765	end = pos + buflen;
3766
3767	for (j = 0; j < wpa_s->hw.num_modes; j++) {
3768		switch (wpa_s->hw.modes[j].mode) {
3769		case HOSTAPD_MODE_IEEE80211B:
3770			hmode = "B";
3771			break;
3772		case HOSTAPD_MODE_IEEE80211G:
3773			hmode = "G";
3774			break;
3775		case HOSTAPD_MODE_IEEE80211A:
3776			hmode = "A";
3777			break;
3778		case HOSTAPD_MODE_IEEE80211AD:
3779			hmode = "AD";
3780			break;
3781		default:
3782			continue;
3783		}
3784		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
3785				  hmode);
3786		if (os_snprintf_error(end - pos, ret))
3787			return pos - buf;
3788		pos += ret;
3789		chnl = wpa_s->hw.modes[j].channels;
3790		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3791			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3792				continue;
3793			ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
3794					  chnl[i].chan, chnl[i].freq,
3795					  chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
3796					  " (NO_IR)" : "",
3797					  chnl[i].flag & HOSTAPD_CHAN_RADAR ?
3798					  " (DFS)" : "");
3799
3800			if (os_snprintf_error(end - pos, ret))
3801				return pos - buf;
3802			pos += ret;
3803		}
3804		ret = os_snprintf(pos, end - pos, "\n");
3805		if (os_snprintf_error(end - pos, ret))
3806			return pos - buf;
3807		pos += ret;
3808	}
3809
3810	return pos - buf;
3811}
3812
3813
3814static int wpa_supplicant_ctrl_iface_get_capability(
3815	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
3816	size_t buflen)
3817{
3818	struct wpa_driver_capa capa;
3819	int res;
3820	char *strict;
3821	char field[30];
3822	size_t len;
3823
3824	/* Determine whether or not strict checking was requested */
3825	len = os_strlcpy(field, _field, sizeof(field));
3826	if (len >= sizeof(field))
3827		return -1;
3828	strict = os_strchr(field, ' ');
3829	if (strict != NULL) {
3830		*strict++ = '\0';
3831		if (os_strcmp(strict, "strict") != 0)
3832			return -1;
3833	}
3834
3835	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
3836		field, strict ? strict : "");
3837
3838	if (os_strcmp(field, "eap") == 0) {
3839		return eap_get_names(buf, buflen);
3840	}
3841
3842	res = wpa_drv_get_capa(wpa_s, &capa);
3843
3844	if (os_strcmp(field, "pairwise") == 0)
3845		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
3846							  buf, buflen);
3847
3848	if (os_strcmp(field, "group") == 0)
3849		return ctrl_iface_get_capability_group(res, strict, &capa,
3850						       buf, buflen);
3851
3852	if (os_strcmp(field, "group_mgmt") == 0)
3853		return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
3854							    buf, buflen);
3855
3856	if (os_strcmp(field, "key_mgmt") == 0)
3857		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
3858							  buf, buflen);
3859
3860	if (os_strcmp(field, "proto") == 0)
3861		return ctrl_iface_get_capability_proto(res, strict, &capa,
3862						       buf, buflen);
3863
3864	if (os_strcmp(field, "auth_alg") == 0)
3865		return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
3866							  &capa, buf, buflen);
3867
3868	if (os_strcmp(field, "modes") == 0)
3869		return ctrl_iface_get_capability_modes(res, strict, &capa,
3870						       buf, buflen);
3871
3872	if (os_strcmp(field, "channels") == 0)
3873		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
3874
3875	if (os_strcmp(field, "freq") == 0)
3876		return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
3877
3878#ifdef CONFIG_TDLS
3879	if (os_strcmp(field, "tdls") == 0)
3880		return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
3881#endif /* CONFIG_TDLS */
3882
3883#ifdef CONFIG_ERP
3884	if (os_strcmp(field, "erp") == 0) {
3885		res = os_snprintf(buf, buflen, "ERP");
3886		if (os_snprintf_error(buflen, res))
3887			return -1;
3888		return res;
3889	}
3890#endif /* CONFIG_EPR */
3891
3892	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3893		   field);
3894
3895	return -1;
3896}
3897
3898
3899#ifdef CONFIG_INTERWORKING
3900static char * anqp_add_hex(char *pos, char *end, const char *title,
3901			   struct wpabuf *data)
3902{
3903	char *start = pos;
3904	size_t i;
3905	int ret;
3906	const u8 *d;
3907
3908	if (data == NULL)
3909		return start;
3910
3911	ret = os_snprintf(pos, end - pos, "%s=", title);
3912	if (os_snprintf_error(end - pos, ret))
3913		return start;
3914	pos += ret;
3915
3916	d = wpabuf_head_u8(data);
3917	for (i = 0; i < wpabuf_len(data); i++) {
3918		ret = os_snprintf(pos, end - pos, "%02x", *d++);
3919		if (os_snprintf_error(end - pos, ret))
3920			return start;
3921		pos += ret;
3922	}
3923
3924	ret = os_snprintf(pos, end - pos, "\n");
3925	if (os_snprintf_error(end - pos, ret))
3926		return start;
3927	pos += ret;
3928
3929	return pos;
3930}
3931#endif /* CONFIG_INTERWORKING */
3932
3933
3934static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
3935			  unsigned long mask, char *buf, size_t buflen)
3936{
3937	size_t i;
3938	int ret;
3939	char *pos, *end;
3940	const u8 *ie, *ie2;
3941
3942	pos = buf;
3943	end = buf + buflen;
3944
3945	if (mask & WPA_BSS_MASK_ID) {
3946		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
3947		if (os_snprintf_error(end - pos, ret))
3948			return 0;
3949		pos += ret;
3950	}
3951
3952	if (mask & WPA_BSS_MASK_BSSID) {
3953		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
3954				  MAC2STR(bss->bssid));
3955		if (os_snprintf_error(end - pos, ret))
3956			return 0;
3957		pos += ret;
3958	}
3959
3960	if (mask & WPA_BSS_MASK_FREQ) {
3961		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
3962		if (os_snprintf_error(end - pos, ret))
3963			return 0;
3964		pos += ret;
3965	}
3966
3967	if (mask & WPA_BSS_MASK_BEACON_INT) {
3968		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
3969				  bss->beacon_int);
3970		if (os_snprintf_error(end - pos, ret))
3971			return 0;
3972		pos += ret;
3973	}
3974
3975	if (mask & WPA_BSS_MASK_CAPABILITIES) {
3976		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
3977				  bss->caps);
3978		if (os_snprintf_error(end - pos, ret))
3979			return 0;
3980		pos += ret;
3981	}
3982
3983	if (mask & WPA_BSS_MASK_QUAL) {
3984		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
3985		if (os_snprintf_error(end - pos, ret))
3986			return 0;
3987		pos += ret;
3988	}
3989
3990	if (mask & WPA_BSS_MASK_NOISE) {
3991		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
3992		if (os_snprintf_error(end - pos, ret))
3993			return 0;
3994		pos += ret;
3995	}
3996
3997	if (mask & WPA_BSS_MASK_LEVEL) {
3998		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
3999		if (os_snprintf_error(end - pos, ret))
4000			return 0;
4001		pos += ret;
4002	}
4003
4004	if (mask & WPA_BSS_MASK_TSF) {
4005		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
4006				  (unsigned long long) bss->tsf);
4007		if (os_snprintf_error(end - pos, ret))
4008			return 0;
4009		pos += ret;
4010	}
4011
4012	if (mask & WPA_BSS_MASK_AGE) {
4013		struct os_reltime now;
4014
4015		os_get_reltime(&now);
4016		ret = os_snprintf(pos, end - pos, "age=%d\n",
4017				  (int) (now.sec - bss->last_update.sec));
4018		if (os_snprintf_error(end - pos, ret))
4019			return 0;
4020		pos += ret;
4021	}
4022
4023	if (mask & WPA_BSS_MASK_IE) {
4024		ret = os_snprintf(pos, end - pos, "ie=");
4025		if (os_snprintf_error(end - pos, ret))
4026			return 0;
4027		pos += ret;
4028
4029		ie = (const u8 *) (bss + 1);
4030		for (i = 0; i < bss->ie_len; i++) {
4031			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
4032			if (os_snprintf_error(end - pos, ret))
4033				return 0;
4034			pos += ret;
4035		}
4036
4037		ret = os_snprintf(pos, end - pos, "\n");
4038		if (os_snprintf_error(end - pos, ret))
4039			return 0;
4040		pos += ret;
4041	}
4042
4043	if (mask & WPA_BSS_MASK_FLAGS) {
4044		ret = os_snprintf(pos, end - pos, "flags=");
4045		if (os_snprintf_error(end - pos, ret))
4046			return 0;
4047		pos += ret;
4048
4049		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
4050		if (ie)
4051			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
4052						    2 + ie[1]);
4053		ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4054		if (ie2)
4055			pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
4056						    2 + ie2[1]);
4057		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
4058		if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
4059			ret = os_snprintf(pos, end - pos, "[WEP]");
4060			if (os_snprintf_error(end - pos, ret))
4061				return 0;
4062			pos += ret;
4063		}
4064		if (bss_is_dmg(bss)) {
4065			const char *s;
4066			ret = os_snprintf(pos, end - pos, "[DMG]");
4067			if (os_snprintf_error(end - pos, ret))
4068				return 0;
4069			pos += ret;
4070			switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
4071			case IEEE80211_CAP_DMG_IBSS:
4072				s = "[IBSS]";
4073				break;
4074			case IEEE80211_CAP_DMG_AP:
4075				s = "[ESS]";
4076				break;
4077			case IEEE80211_CAP_DMG_PBSS:
4078				s = "[PBSS]";
4079				break;
4080			default:
4081				s = "";
4082				break;
4083			}
4084			ret = os_snprintf(pos, end - pos, "%s", s);
4085			if (os_snprintf_error(end - pos, ret))
4086				return 0;
4087			pos += ret;
4088		} else {
4089			if (bss->caps & IEEE80211_CAP_IBSS) {
4090				ret = os_snprintf(pos, end - pos, "[IBSS]");
4091				if (os_snprintf_error(end - pos, ret))
4092					return 0;
4093				pos += ret;
4094			}
4095			if (bss->caps & IEEE80211_CAP_ESS) {
4096				ret = os_snprintf(pos, end - pos, "[ESS]");
4097				if (os_snprintf_error(end - pos, ret))
4098					return 0;
4099				pos += ret;
4100			}
4101		}
4102		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
4103		    wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
4104			ret = os_snprintf(pos, end - pos, "[P2P]");
4105			if (os_snprintf_error(end - pos, ret))
4106				return 0;
4107			pos += ret;
4108		}
4109#ifdef CONFIG_HS20
4110		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
4111			ret = os_snprintf(pos, end - pos, "[HS20]");
4112			if (os_snprintf_error(end - pos, ret))
4113				return 0;
4114			pos += ret;
4115		}
4116#endif /* CONFIG_HS20 */
4117
4118		ret = os_snprintf(pos, end - pos, "\n");
4119		if (os_snprintf_error(end - pos, ret))
4120			return 0;
4121		pos += ret;
4122	}
4123
4124	if (mask & WPA_BSS_MASK_SSID) {
4125		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
4126				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
4127		if (os_snprintf_error(end - pos, ret))
4128			return 0;
4129		pos += ret;
4130	}
4131
4132#ifdef CONFIG_WPS
4133	if (mask & WPA_BSS_MASK_WPS_SCAN) {
4134		ie = (const u8 *) (bss + 1);
4135		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
4136		if (ret < 0 || ret >= end - pos)
4137			return 0;
4138		pos += ret;
4139	}
4140#endif /* CONFIG_WPS */
4141
4142#ifdef CONFIG_P2P
4143	if (mask & WPA_BSS_MASK_P2P_SCAN) {
4144		ie = (const u8 *) (bss + 1);
4145		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
4146		if (ret < 0 || ret >= end - pos)
4147			return 0;
4148		pos += ret;
4149	}
4150#endif /* CONFIG_P2P */
4151
4152#ifdef CONFIG_WIFI_DISPLAY
4153	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
4154		struct wpabuf *wfd;
4155		ie = (const u8 *) (bss + 1);
4156		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
4157						  WFD_IE_VENDOR_TYPE);
4158		if (wfd) {
4159			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
4160			if (os_snprintf_error(end - pos, ret)) {
4161				wpabuf_free(wfd);
4162				return 0;
4163			}
4164			pos += ret;
4165
4166			pos += wpa_snprintf_hex(pos, end - pos,
4167						wpabuf_head(wfd),
4168						wpabuf_len(wfd));
4169			wpabuf_free(wfd);
4170
4171			ret = os_snprintf(pos, end - pos, "\n");
4172			if (os_snprintf_error(end - pos, ret))
4173				return 0;
4174			pos += ret;
4175		}
4176	}
4177#endif /* CONFIG_WIFI_DISPLAY */
4178
4179#ifdef CONFIG_INTERWORKING
4180	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
4181		struct wpa_bss_anqp *anqp = bss->anqp;
4182		pos = anqp_add_hex(pos, end, "anqp_capability_list",
4183				   anqp->capability_list);
4184		pos = anqp_add_hex(pos, end, "anqp_venue_name",
4185				   anqp->venue_name);
4186		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
4187				   anqp->network_auth_type);
4188		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
4189				   anqp->roaming_consortium);
4190		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
4191				   anqp->ip_addr_type_availability);
4192		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
4193				   anqp->nai_realm);
4194		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
4195		pos = anqp_add_hex(pos, end, "anqp_domain_name",
4196				   anqp->domain_name);
4197#ifdef CONFIG_HS20
4198		pos = anqp_add_hex(pos, end, "hs20_capability_list",
4199				   anqp->hs20_capability_list);
4200		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
4201				   anqp->hs20_operator_friendly_name);
4202		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
4203				   anqp->hs20_wan_metrics);
4204		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
4205				   anqp->hs20_connection_capability);
4206		pos = anqp_add_hex(pos, end, "hs20_operating_class",
4207				   anqp->hs20_operating_class);
4208		pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
4209				   anqp->hs20_osu_providers_list);
4210#endif /* CONFIG_HS20 */
4211	}
4212#endif /* CONFIG_INTERWORKING */
4213
4214#ifdef CONFIG_MESH
4215	if (mask & WPA_BSS_MASK_MESH_SCAN) {
4216		ie = (const u8 *) (bss + 1);
4217		ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
4218		if (ret < 0 || ret >= end - pos)
4219			return 0;
4220		pos += ret;
4221	}
4222#endif /* CONFIG_MESH */
4223
4224	if (mask & WPA_BSS_MASK_SNR) {
4225		ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
4226		if (os_snprintf_error(end - pos, ret))
4227			return 0;
4228		pos += ret;
4229	}
4230
4231	if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
4232		ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
4233				  bss->est_throughput);
4234		if (os_snprintf_error(end - pos, ret))
4235			return 0;
4236		pos += ret;
4237	}
4238
4239	if (mask & WPA_BSS_MASK_DELIM) {
4240		ret = os_snprintf(pos, end - pos, "====\n");
4241		if (os_snprintf_error(end - pos, ret))
4242			return 0;
4243		pos += ret;
4244	}
4245
4246	return pos - buf;
4247}
4248
4249
4250static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
4251					 const char *cmd, char *buf,
4252					 size_t buflen)
4253{
4254	u8 bssid[ETH_ALEN];
4255	size_t i;
4256	struct wpa_bss *bss;
4257	struct wpa_bss *bsslast = NULL;
4258	struct dl_list *next;
4259	int ret = 0;
4260	int len;
4261	char *ctmp, *end = buf + buflen;
4262	unsigned long mask = WPA_BSS_MASK_ALL;
4263
4264	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
4265		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
4266			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
4267					    list_id);
4268			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
4269					       list_id);
4270		} else { /* N1-N2 */
4271			unsigned int id1, id2;
4272
4273			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
4274				wpa_printf(MSG_INFO, "Wrong BSS range "
4275					   "format");
4276				return 0;
4277			}
4278
4279			if (*(cmd + 6) == '-')
4280				id1 = 0;
4281			else
4282				id1 = atoi(cmd + 6);
4283			ctmp++;
4284			if (*ctmp >= '0' && *ctmp <= '9')
4285				id2 = atoi(ctmp);
4286			else
4287				id2 = (unsigned int) -1;
4288			bss = wpa_bss_get_id_range(wpa_s, id1, id2);
4289			if (id2 == (unsigned int) -1)
4290				bsslast = dl_list_last(&wpa_s->bss_id,
4291						       struct wpa_bss,
4292						       list_id);
4293			else {
4294				bsslast = wpa_bss_get_id(wpa_s, id2);
4295				if (bsslast == NULL && bss && id2 > id1) {
4296					struct wpa_bss *tmp = bss;
4297					for (;;) {
4298						next = tmp->list_id.next;
4299						if (next == &wpa_s->bss_id)
4300							break;
4301						tmp = dl_list_entry(
4302							next, struct wpa_bss,
4303							list_id);
4304						if (tmp->id > id2)
4305							break;
4306						bsslast = tmp;
4307					}
4308				}
4309			}
4310		}
4311	} else if (os_strncmp(cmd, "FIRST", 5) == 0)
4312		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
4313	else if (os_strncmp(cmd, "LAST", 4) == 0)
4314		bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
4315	else if (os_strncmp(cmd, "ID-", 3) == 0) {
4316		i = atoi(cmd + 3);
4317		bss = wpa_bss_get_id(wpa_s, i);
4318	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
4319		i = atoi(cmd + 5);
4320		bss = wpa_bss_get_id(wpa_s, i);
4321		if (bss) {
4322			next = bss->list_id.next;
4323			if (next == &wpa_s->bss_id)
4324				bss = NULL;
4325			else
4326				bss = dl_list_entry(next, struct wpa_bss,
4327						    list_id);
4328		}
4329#ifdef CONFIG_P2P
4330	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
4331		if (hwaddr_aton(cmd + 13, bssid) == 0)
4332			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
4333		else
4334			bss = NULL;
4335#endif /* CONFIG_P2P */
4336	} else if (hwaddr_aton(cmd, bssid) == 0)
4337		bss = wpa_bss_get_bssid(wpa_s, bssid);
4338	else {
4339		struct wpa_bss *tmp;
4340		i = atoi(cmd);
4341		bss = NULL;
4342		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
4343		{
4344			if (i-- == 0) {
4345				bss = tmp;
4346				break;
4347			}
4348		}
4349	}
4350
4351	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
4352		mask = strtoul(ctmp + 5, NULL, 0x10);
4353		if (mask == 0)
4354			mask = WPA_BSS_MASK_ALL;
4355	}
4356
4357	if (bss == NULL)
4358		return 0;
4359
4360	if (bsslast == NULL)
4361		bsslast = bss;
4362	do {
4363		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
4364		ret += len;
4365		buf += len;
4366		buflen -= len;
4367		if (bss == bsslast) {
4368			if ((mask & WPA_BSS_MASK_DELIM) && len &&
4369			    (bss == dl_list_last(&wpa_s->bss_id,
4370						 struct wpa_bss, list_id))) {
4371				int res;
4372
4373				res = os_snprintf(buf - 5, end - buf + 5,
4374						  "####\n");
4375				if (os_snprintf_error(end - buf + 5, res)) {
4376					wpa_printf(MSG_DEBUG,
4377						   "Could not add end delim");
4378				}
4379			}
4380			break;
4381		}
4382		next = bss->list_id.next;
4383		if (next == &wpa_s->bss_id)
4384			break;
4385		bss = dl_list_entry(next, struct wpa_bss, list_id);
4386	} while (bss && len);
4387
4388	return ret;
4389}
4390
4391
4392static int wpa_supplicant_ctrl_iface_ap_scan(
4393	struct wpa_supplicant *wpa_s, char *cmd)
4394{
4395	int ap_scan = atoi(cmd);
4396	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
4397}
4398
4399
4400static int wpa_supplicant_ctrl_iface_scan_interval(
4401	struct wpa_supplicant *wpa_s, char *cmd)
4402{
4403	int scan_int = atoi(cmd);
4404	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
4405}
4406
4407
4408static int wpa_supplicant_ctrl_iface_bss_expire_age(
4409	struct wpa_supplicant *wpa_s, char *cmd)
4410{
4411	int expire_age = atoi(cmd);
4412	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
4413}
4414
4415
4416static int wpa_supplicant_ctrl_iface_bss_expire_count(
4417	struct wpa_supplicant *wpa_s, char *cmd)
4418{
4419	int expire_count = atoi(cmd);
4420	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
4421}
4422
4423
4424static void wpa_supplicant_ctrl_iface_bss_flush(
4425	struct wpa_supplicant *wpa_s, char *cmd)
4426{
4427	int flush_age = atoi(cmd);
4428
4429	if (flush_age == 0)
4430		wpa_bss_flush(wpa_s);
4431	else
4432		wpa_bss_flush_by_age(wpa_s, flush_age);
4433}
4434
4435
4436#ifdef CONFIG_TESTING_OPTIONS
4437static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
4438{
4439	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
4440	/* MLME-DELETEKEYS.request */
4441	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
4442	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
4443	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
4444	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
4445#ifdef CONFIG_IEEE80211W
4446	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
4447	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
4448#endif /* CONFIG_IEEE80211W */
4449
4450	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
4451			0);
4452	/* MLME-SETPROTECTION.request(None) */
4453	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
4454				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
4455				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
4456	wpa_sm_drop_sa(wpa_s->wpa);
4457}
4458#endif /* CONFIG_TESTING_OPTIONS */
4459
4460
4461static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
4462					  char *addr)
4463{
4464#ifdef CONFIG_NO_SCAN_PROCESSING
4465	return -1;
4466#else /* CONFIG_NO_SCAN_PROCESSING */
4467	u8 bssid[ETH_ALEN];
4468	struct wpa_bss *bss;
4469	struct wpa_ssid *ssid = wpa_s->current_ssid;
4470
4471	if (hwaddr_aton(addr, bssid)) {
4472		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
4473			   "address '%s'", addr);
4474		return -1;
4475	}
4476
4477	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
4478
4479	if (!ssid) {
4480		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
4481			   "configuration known for the target AP");
4482		return -1;
4483	}
4484
4485	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
4486	if (!bss) {
4487		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
4488			   "from BSS table");
4489		return -1;
4490	}
4491
4492	/*
4493	 * TODO: Find best network configuration block from configuration to
4494	 * allow roaming to other networks
4495	 */
4496
4497	wpa_s->reassociate = 1;
4498	wpa_supplicant_connect(wpa_s, bss, ssid);
4499
4500	return 0;
4501#endif /* CONFIG_NO_SCAN_PROCESSING */
4502}
4503
4504
4505#ifdef CONFIG_P2P
4506static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
4507{
4508	unsigned int timeout = atoi(cmd);
4509	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
4510	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
4511	u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
4512	char *pos;
4513	unsigned int search_delay;
4514	const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
4515	u8 seek_count = 0;
4516	int freq = 0;
4517
4518	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4519		wpa_dbg(wpa_s, MSG_INFO,
4520			"Reject P2P_FIND since interface is disabled");
4521		return -1;
4522	}
4523	if (os_strstr(cmd, "type=social"))
4524		type = P2P_FIND_ONLY_SOCIAL;
4525	else if (os_strstr(cmd, "type=progressive"))
4526		type = P2P_FIND_PROGRESSIVE;
4527
4528	pos = os_strstr(cmd, "dev_id=");
4529	if (pos) {
4530		pos += 7;
4531		if (hwaddr_aton(pos, dev_id))
4532			return -1;
4533		_dev_id = dev_id;
4534	}
4535
4536	pos = os_strstr(cmd, "dev_type=");
4537	if (pos) {
4538		pos += 9;
4539		if (wps_dev_type_str2bin(pos, dev_type) < 0)
4540			return -1;
4541		_dev_type = dev_type;
4542	}
4543
4544	pos = os_strstr(cmd, "delay=");
4545	if (pos) {
4546		pos += 6;
4547		search_delay = atoi(pos);
4548	} else
4549		search_delay = wpas_p2p_search_delay(wpa_s);
4550
4551	/* Must be searched for last, because it adds nul termination */
4552	pos = os_strstr(cmd, " seek=");
4553	while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
4554		char *term;
4555
4556		term = os_strchr(pos + 1, ' ');
4557		_seek[seek_count++] = pos + 6;
4558		seek = _seek;
4559		pos = os_strstr(pos + 6, " seek=");
4560
4561		if (term)
4562			*term = '\0';
4563	}
4564	if (seek_count > P2P_MAX_QUERY_HASH) {
4565		seek[0] = NULL;
4566		seek_count = 1;
4567	}
4568
4569	pos = os_strstr(cmd, "freq=");
4570	if (pos) {
4571		pos += 5;
4572		freq = atoi(pos);
4573		if (freq <= 0)
4574			return -1;
4575	}
4576
4577	return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
4578			     _dev_id, search_delay, seek_count, seek, freq);
4579}
4580
4581
4582static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
4583{
4584	struct p2ps_provision *p2ps_prov;
4585	char *pos;
4586	size_t info_len = 0;
4587	char *info = NULL;
4588	u8 role = P2PS_SETUP_NONE;
4589	long long unsigned val;
4590
4591	pos = os_strstr(cmd, "info=");
4592	if (pos) {
4593		pos += 5;
4594		info_len = os_strlen(pos);
4595
4596		if (info_len) {
4597			info = os_malloc(info_len + 1);
4598			if (info) {
4599				info_len = utf8_unescape(pos, info_len,
4600							 info, info_len + 1);
4601			} else
4602				info_len = 0;
4603		}
4604	}
4605
4606	p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
4607	if (p2ps_prov == NULL) {
4608		os_free(info);
4609		return NULL;
4610	}
4611
4612	if (info) {
4613		os_memcpy(p2ps_prov->info, info, info_len);
4614		p2ps_prov->info[info_len] = '\0';
4615		os_free(info);
4616	}
4617
4618	pos = os_strstr(cmd, "status=");
4619	if (pos)
4620		p2ps_prov->status = atoi(pos + 7);
4621	else
4622		p2ps_prov->status = -1;
4623
4624	pos = os_strstr(cmd, "adv_id=");
4625	if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
4626		goto invalid_args;
4627	p2ps_prov->adv_id = val;
4628
4629	pos = os_strstr(cmd, "method=");
4630	if (pos)
4631		p2ps_prov->method = strtol(pos + 7, NULL, 16);
4632	else
4633		p2ps_prov->method = 0;
4634
4635	pos = os_strstr(cmd, "session=");
4636	if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
4637		goto invalid_args;
4638	p2ps_prov->session_id = val;
4639
4640	pos = os_strstr(cmd, "adv_mac=");
4641	if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
4642		goto invalid_args;
4643
4644	pos = os_strstr(cmd, "session_mac=");
4645	if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
4646		goto invalid_args;
4647
4648	/* force conncap with tstCap (no sanity checks) */
4649	pos = os_strstr(cmd, "tstCap=");
4650	if (pos) {
4651		role = strtol(pos + 7, NULL, 16);
4652	} else {
4653		pos = os_strstr(cmd, "role=");
4654		if (pos) {
4655			role = strtol(pos + 5, NULL, 16);
4656			if (role != P2PS_SETUP_CLIENT &&
4657			    role != P2PS_SETUP_GROUP_OWNER)
4658				role = P2PS_SETUP_NONE;
4659		}
4660	}
4661	p2ps_prov->role = role;
4662
4663	return p2ps_prov;
4664
4665invalid_args:
4666	os_free(p2ps_prov);
4667	return NULL;
4668}
4669
4670
4671static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
4672{
4673	u8 addr[ETH_ALEN];
4674	struct p2ps_provision *p2ps_prov;
4675	char *pos;
4676
4677	/* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
4678
4679	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
4680
4681	if (hwaddr_aton(cmd, addr))
4682		return -1;
4683
4684	pos = cmd + 17;
4685	if (*pos != ' ')
4686		return -1;
4687
4688	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
4689	if (!p2ps_prov)
4690		return -1;
4691
4692	if (p2ps_prov->status < 0) {
4693		os_free(p2ps_prov);
4694		return -1;
4695	}
4696
4697	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
4698				  p2ps_prov);
4699}
4700
4701
4702static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
4703{
4704	u8 addr[ETH_ALEN];
4705	struct p2ps_provision *p2ps_prov;
4706	char *pos;
4707
4708	/* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
4709	 *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
4710	 */
4711
4712	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
4713	if (hwaddr_aton(cmd, addr))
4714		return -1;
4715
4716	pos = cmd + 17;
4717	if (*pos != ' ')
4718		return -1;
4719
4720	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
4721	if (!p2ps_prov)
4722		return -1;
4723
4724	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
4725				  p2ps_prov);
4726}
4727
4728
4729static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
4730			    char *buf, size_t buflen)
4731{
4732	u8 addr[ETH_ALEN];
4733	char *pos, *pos2;
4734	char *pin = NULL;
4735	enum p2p_wps_method wps_method;
4736	int new_pin;
4737	int ret;
4738	int persistent_group, persistent_id = -1;
4739	int join;
4740	int auth;
4741	int automatic;
4742	int go_intent = -1;
4743	int freq = 0;
4744	int pd;
4745	int ht40, vht;
4746
4747	if (!wpa_s->global->p2p_init_wpa_s)
4748		return -1;
4749	if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
4750		wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
4751			wpa_s->global->p2p_init_wpa_s->ifname);
4752		wpa_s = wpa_s->global->p2p_init_wpa_s;
4753	}
4754
4755	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
4756	 * [persistent|persistent=<network id>]
4757	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
4758	 * [ht40] [vht] [auto] */
4759
4760	if (hwaddr_aton(cmd, addr))
4761		return -1;
4762
4763	pos = cmd + 17;
4764	if (*pos != ' ')
4765		return -1;
4766	pos++;
4767
4768	persistent_group = os_strstr(pos, " persistent") != NULL;
4769	pos2 = os_strstr(pos, " persistent=");
4770	if (pos2) {
4771		struct wpa_ssid *ssid;
4772		persistent_id = atoi(pos2 + 12);
4773		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
4774		if (ssid == NULL || ssid->disabled != 2 ||
4775		    ssid->mode != WPAS_MODE_P2P_GO) {
4776			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
4777				   "SSID id=%d for persistent P2P group (GO)",
4778				   persistent_id);
4779			return -1;
4780		}
4781	}
4782	join = os_strstr(pos, " join") != NULL;
4783	auth = os_strstr(pos, " auth") != NULL;
4784	automatic = os_strstr(pos, " auto") != NULL;
4785	pd = os_strstr(pos, " provdisc") != NULL;
4786	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
4787	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4788		vht;
4789
4790	pos2 = os_strstr(pos, " go_intent=");
4791	if (pos2) {
4792		pos2 += 11;
4793		go_intent = atoi(pos2);
4794		if (go_intent < 0 || go_intent > 15)
4795			return -1;
4796	}
4797
4798	pos2 = os_strstr(pos, " freq=");
4799	if (pos2) {
4800		pos2 += 6;
4801		freq = atoi(pos2);
4802		if (freq <= 0)
4803			return -1;
4804	}
4805
4806	if (os_strncmp(pos, "pin", 3) == 0) {
4807		/* Request random PIN (to be displayed) and enable the PIN */
4808		wps_method = WPS_PIN_DISPLAY;
4809	} else if (os_strncmp(pos, "pbc", 3) == 0) {
4810		wps_method = WPS_PBC;
4811	} else {
4812		pin = pos;
4813		pos = os_strchr(pin, ' ');
4814		wps_method = WPS_PIN_KEYPAD;
4815		if (pos) {
4816			*pos++ = '\0';
4817			if (os_strncmp(pos, "display", 7) == 0)
4818				wps_method = WPS_PIN_DISPLAY;
4819			else if (os_strncmp(pos, "p2ps", 4) == 0)
4820				wps_method = WPS_P2PS;
4821		}
4822		if (!wps_pin_str_valid(pin)) {
4823			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
4824			return 17;
4825		}
4826	}
4827
4828	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
4829				   persistent_group, automatic, join,
4830				   auth, go_intent, freq, persistent_id, pd,
4831				   ht40, vht);
4832	if (new_pin == -2) {
4833		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
4834		return 25;
4835	}
4836	if (new_pin == -3) {
4837		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
4838		return 25;
4839	}
4840	if (new_pin < 0)
4841		return -1;
4842	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
4843		ret = os_snprintf(buf, buflen, "%08d", new_pin);
4844		if (os_snprintf_error(buflen, ret))
4845			return -1;
4846		return ret;
4847	}
4848
4849	os_memcpy(buf, "OK\n", 3);
4850	return 3;
4851}
4852
4853
4854static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
4855{
4856	unsigned int timeout = atoi(cmd);
4857	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4858		wpa_dbg(wpa_s, MSG_INFO,
4859			"Reject P2P_LISTEN since interface is disabled");
4860		return -1;
4861	}
4862	return wpas_p2p_listen(wpa_s, timeout);
4863}
4864
4865
4866static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
4867{
4868	u8 addr[ETH_ALEN];
4869	char *pos;
4870	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
4871
4872	/* <addr> <config method> [join|auto] */
4873
4874	if (hwaddr_aton(cmd, addr))
4875		return -1;
4876
4877	pos = cmd + 17;
4878	if (*pos != ' ')
4879		return -1;
4880	pos++;
4881
4882	if (os_strstr(pos, " join") != NULL)
4883		use = WPAS_P2P_PD_FOR_JOIN;
4884	else if (os_strstr(pos, " auto") != NULL)
4885		use = WPAS_P2P_PD_AUTO;
4886
4887	return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
4888}
4889
4890
4891static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
4892			      size_t buflen)
4893{
4894	struct wpa_ssid *ssid = wpa_s->current_ssid;
4895
4896	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
4897	    ssid->passphrase == NULL)
4898		return -1;
4899
4900	os_strlcpy(buf, ssid->passphrase, buflen);
4901	return os_strlen(buf);
4902}
4903
4904
4905static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
4906				  char *buf, size_t buflen)
4907{
4908	u64 ref;
4909	int res;
4910	u8 dst_buf[ETH_ALEN], *dst;
4911	struct wpabuf *tlvs;
4912	char *pos;
4913	size_t len;
4914
4915	if (hwaddr_aton(cmd, dst_buf))
4916		return -1;
4917	dst = dst_buf;
4918	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
4919	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
4920		dst = NULL;
4921	pos = cmd + 17;
4922	if (*pos != ' ')
4923		return -1;
4924	pos++;
4925
4926	if (os_strncmp(pos, "upnp ", 5) == 0) {
4927		u8 version;
4928		pos += 5;
4929		if (hexstr2bin(pos, &version, 1) < 0)
4930			return -1;
4931		pos += 2;
4932		if (*pos != ' ')
4933			return -1;
4934		pos++;
4935		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
4936#ifdef CONFIG_WIFI_DISPLAY
4937	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
4938		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
4939#endif /* CONFIG_WIFI_DISPLAY */
4940	} else if (os_strncmp(pos, "asp ", 4) == 0) {
4941		char *svc_str;
4942		char *svc_info = NULL;
4943		u32 id;
4944
4945		pos += 4;
4946		if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
4947			return -1;
4948
4949		pos = os_strchr(pos, ' ');
4950		if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
4951			return -1;
4952
4953		svc_str = pos + 1;
4954
4955		pos = os_strchr(svc_str, ' ');
4956
4957		if (pos)
4958			*pos++ = '\0';
4959
4960		/* All remaining data is the svc_info string */
4961		if (pos && pos[0] && pos[0] != ' ') {
4962			len = os_strlen(pos);
4963
4964			/* Unescape in place */
4965			len = utf8_unescape(pos, len, pos, len);
4966			if (len > 0xff)
4967				return -1;
4968
4969			svc_info = pos;
4970		}
4971
4972		ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
4973					      svc_str, svc_info);
4974	} else {
4975		len = os_strlen(pos);
4976		if (len & 1)
4977			return -1;
4978		len /= 2;
4979		tlvs = wpabuf_alloc(len);
4980		if (tlvs == NULL)
4981			return -1;
4982		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
4983			wpabuf_free(tlvs);
4984			return -1;
4985		}
4986
4987		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
4988		wpabuf_free(tlvs);
4989	}
4990	if (ref == 0)
4991		return -1;
4992	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
4993	if (os_snprintf_error(buflen, res))
4994		return -1;
4995	return res;
4996}
4997
4998
4999static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
5000					 char *cmd)
5001{
5002	long long unsigned val;
5003	u64 req;
5004	if (sscanf(cmd, "%llx", &val) != 1)
5005		return -1;
5006	req = val;
5007	return wpas_p2p_sd_cancel_request(wpa_s, req);
5008}
5009
5010
5011static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
5012{
5013	int freq;
5014	u8 dst[ETH_ALEN];
5015	u8 dialog_token;
5016	struct wpabuf *resp_tlvs;
5017	char *pos, *pos2;
5018	size_t len;
5019
5020	pos = os_strchr(cmd, ' ');
5021	if (pos == NULL)
5022		return -1;
5023	*pos++ = '\0';
5024	freq = atoi(cmd);
5025	if (freq == 0)
5026		return -1;
5027
5028	if (hwaddr_aton(pos, dst))
5029		return -1;
5030	pos += 17;
5031	if (*pos != ' ')
5032		return -1;
5033	pos++;
5034
5035	pos2 = os_strchr(pos, ' ');
5036	if (pos2 == NULL)
5037		return -1;
5038	*pos2++ = '\0';
5039	dialog_token = atoi(pos);
5040
5041	len = os_strlen(pos2);
5042	if (len & 1)
5043		return -1;
5044	len /= 2;
5045	resp_tlvs = wpabuf_alloc(len);
5046	if (resp_tlvs == NULL)
5047		return -1;
5048	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
5049		wpabuf_free(resp_tlvs);
5050		return -1;
5051	}
5052
5053	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
5054	wpabuf_free(resp_tlvs);
5055	return 0;
5056}
5057
5058
5059static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
5060				       char *cmd)
5061{
5062	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
5063		return -1;
5064	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
5065	return 0;
5066}
5067
5068
5069static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
5070					char *cmd)
5071{
5072	char *pos;
5073	size_t len;
5074	struct wpabuf *query, *resp;
5075
5076	pos = os_strchr(cmd, ' ');
5077	if (pos == NULL)
5078		return -1;
5079	*pos++ = '\0';
5080
5081	len = os_strlen(cmd);
5082	if (len & 1)
5083		return -1;
5084	len /= 2;
5085	query = wpabuf_alloc(len);
5086	if (query == NULL)
5087		return -1;
5088	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
5089		wpabuf_free(query);
5090		return -1;
5091	}
5092
5093	len = os_strlen(pos);
5094	if (len & 1) {
5095		wpabuf_free(query);
5096		return -1;
5097	}
5098	len /= 2;
5099	resp = wpabuf_alloc(len);
5100	if (resp == NULL) {
5101		wpabuf_free(query);
5102		return -1;
5103	}
5104	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
5105		wpabuf_free(query);
5106		wpabuf_free(resp);
5107		return -1;
5108	}
5109
5110	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
5111		wpabuf_free(query);
5112		wpabuf_free(resp);
5113		return -1;
5114	}
5115	return 0;
5116}
5117
5118
5119static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
5120{
5121	char *pos;
5122	u8 version;
5123
5124	pos = os_strchr(cmd, ' ');
5125	if (pos == NULL)
5126		return -1;
5127	*pos++ = '\0';
5128
5129	if (hexstr2bin(cmd, &version, 1) < 0)
5130		return -1;
5131
5132	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
5133}
5134
5135
5136static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
5137				    u8 replace, char *cmd)
5138{
5139	char *pos;
5140	char *adv_str;
5141	u32 auto_accept, adv_id, svc_state, config_methods;
5142	char *svc_info = NULL;
5143
5144	pos = os_strchr(cmd, ' ');
5145	if (pos == NULL)
5146		return -1;
5147	*pos++ = '\0';
5148
5149	/* Auto-Accept value is mandatory, and must be one of the
5150	 * single values (0, 1, 2, 4) */
5151	auto_accept = atoi(cmd);
5152	switch (auto_accept) {
5153	case P2PS_SETUP_NONE: /* No auto-accept */
5154	case P2PS_SETUP_NEW:
5155	case P2PS_SETUP_CLIENT:
5156	case P2PS_SETUP_GROUP_OWNER:
5157		break;
5158	default:
5159		return -1;
5160	}
5161
5162	/* Advertisement ID is mandatory */
5163	cmd = pos;
5164	pos = os_strchr(cmd, ' ');
5165	if (pos == NULL)
5166		return -1;
5167	*pos++ = '\0';
5168
5169	/* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
5170	if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
5171		return -1;
5172
5173	/* Only allow replacements if exist, and adds if not */
5174	if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
5175		if (!replace)
5176			return -1;
5177	} else {
5178		if (replace)
5179			return -1;
5180	}
5181
5182	/* svc_state between 0 - 0xff is mandatory */
5183	if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
5184		return -1;
5185
5186	pos = os_strchr(pos, ' ');
5187	if (pos == NULL)
5188		return -1;
5189
5190	/* config_methods is mandatory */
5191	pos++;
5192	if (sscanf(pos, "%x", &config_methods) != 1)
5193		return -1;
5194
5195	if (!(config_methods &
5196	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
5197		return -1;
5198
5199	pos = os_strchr(pos, ' ');
5200	if (pos == NULL)
5201		return -1;
5202
5203	pos++;
5204	adv_str = pos;
5205
5206	/* Advertisement string is mandatory */
5207	if (!pos[0] || pos[0] == ' ')
5208		return -1;
5209
5210	/* Terminate svc string */
5211	pos = os_strchr(pos, ' ');
5212	if (pos != NULL)
5213		*pos++ = '\0';
5214
5215	/* Service and Response Information are optional */
5216	if (pos && pos[0]) {
5217		size_t len;
5218
5219		/* Note the bare ' included, which cannot exist legally
5220		 * in unescaped string. */
5221		svc_info = os_strstr(pos, "svc_info='");
5222
5223		if (svc_info) {
5224			svc_info += 9;
5225			len = os_strlen(svc_info);
5226			utf8_unescape(svc_info, len, svc_info, len);
5227		}
5228	}
5229
5230	return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
5231					(u8) svc_state, (u16) config_methods,
5232					svc_info);
5233}
5234
5235
5236static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
5237{
5238	char *pos;
5239
5240	pos = os_strchr(cmd, ' ');
5241	if (pos == NULL)
5242		return -1;
5243	*pos++ = '\0';
5244
5245	if (os_strcmp(cmd, "bonjour") == 0)
5246		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
5247	if (os_strcmp(cmd, "upnp") == 0)
5248		return p2p_ctrl_service_add_upnp(wpa_s, pos);
5249	if (os_strcmp(cmd, "asp") == 0)
5250		return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
5251	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
5252	return -1;
5253}
5254
5255
5256static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
5257					char *cmd)
5258{
5259	size_t len;
5260	struct wpabuf *query;
5261	int ret;
5262
5263	len = os_strlen(cmd);
5264	if (len & 1)
5265		return -1;
5266	len /= 2;
5267	query = wpabuf_alloc(len);
5268	if (query == NULL)
5269		return -1;
5270	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
5271		wpabuf_free(query);
5272		return -1;
5273	}
5274
5275	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
5276	wpabuf_free(query);
5277	return ret;
5278}
5279
5280
5281static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
5282{
5283	char *pos;
5284	u8 version;
5285
5286	pos = os_strchr(cmd, ' ');
5287	if (pos == NULL)
5288		return -1;
5289	*pos++ = '\0';
5290
5291	if (hexstr2bin(cmd, &version, 1) < 0)
5292		return -1;
5293
5294	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
5295}
5296
5297
5298static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
5299{
5300	u32 adv_id;
5301
5302	if (sscanf(cmd, "%x", &adv_id) != 1)
5303		return -1;
5304
5305	return wpas_p2p_service_del_asp(wpa_s, adv_id);
5306}
5307
5308
5309static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
5310{
5311	char *pos;
5312
5313	pos = os_strchr(cmd, ' ');
5314	if (pos == NULL)
5315		return -1;
5316	*pos++ = '\0';
5317
5318	if (os_strcmp(cmd, "bonjour") == 0)
5319		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
5320	if (os_strcmp(cmd, "upnp") == 0)
5321		return p2p_ctrl_service_del_upnp(wpa_s, pos);
5322	if (os_strcmp(cmd, "asp") == 0)
5323		return p2p_ctrl_service_del_asp(wpa_s, pos);
5324	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
5325	return -1;
5326}
5327
5328
5329static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
5330{
5331	char *pos;
5332
5333	pos = os_strchr(cmd, ' ');
5334	if (pos == NULL)
5335		return -1;
5336	*pos++ = '\0';
5337
5338	if (os_strcmp(cmd, "asp") == 0)
5339		return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
5340
5341	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
5342	return -1;
5343}
5344
5345
5346static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
5347{
5348	u8 addr[ETH_ALEN];
5349
5350	/* <addr> */
5351
5352	if (hwaddr_aton(cmd, addr))
5353		return -1;
5354
5355	return wpas_p2p_reject(wpa_s, addr);
5356}
5357
5358
5359static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
5360{
5361	char *pos;
5362	int id;
5363	struct wpa_ssid *ssid;
5364	u8 *_peer = NULL, peer[ETH_ALEN];
5365	int freq = 0, pref_freq = 0;
5366	int ht40, vht;
5367
5368	id = atoi(cmd);
5369	pos = os_strstr(cmd, " peer=");
5370	if (pos) {
5371		pos += 6;
5372		if (hwaddr_aton(pos, peer))
5373			return -1;
5374		_peer = peer;
5375	}
5376	ssid = wpa_config_get_network(wpa_s->conf, id);
5377	if (ssid == NULL || ssid->disabled != 2) {
5378		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
5379			   "for persistent P2P group",
5380			   id);
5381		return -1;
5382	}
5383
5384	pos = os_strstr(cmd, " freq=");
5385	if (pos) {
5386		pos += 6;
5387		freq = atoi(pos);
5388		if (freq <= 0)
5389			return -1;
5390	}
5391
5392	pos = os_strstr(cmd, " pref=");
5393	if (pos) {
5394		pos += 6;
5395		pref_freq = atoi(pos);
5396		if (pref_freq <= 0)
5397			return -1;
5398	}
5399
5400	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
5401	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
5402		vht;
5403
5404	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
5405			       pref_freq);
5406}
5407
5408
5409static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
5410{
5411	char *pos;
5412	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
5413
5414	pos = os_strstr(cmd, " peer=");
5415	if (!pos)
5416		return -1;
5417
5418	*pos = '\0';
5419	pos += 6;
5420	if (hwaddr_aton(pos, peer)) {
5421		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
5422		return -1;
5423	}
5424
5425	pos = os_strstr(pos, " go_dev_addr=");
5426	if (pos) {
5427		pos += 13;
5428		if (hwaddr_aton(pos, go_dev_addr)) {
5429			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
5430				   pos);
5431			return -1;
5432		}
5433		go_dev = go_dev_addr;
5434	}
5435
5436	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
5437}
5438
5439
5440static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
5441{
5442	if (os_strncmp(cmd, "persistent=", 11) == 0)
5443		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
5444	if (os_strncmp(cmd, "group=", 6) == 0)
5445		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
5446
5447	return -1;
5448}
5449
5450
5451static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
5452					 char *cmd, int freq, int ht40,
5453					 int vht)
5454{
5455	int id;
5456	struct wpa_ssid *ssid;
5457
5458	id = atoi(cmd);
5459	ssid = wpa_config_get_network(wpa_s->conf, id);
5460	if (ssid == NULL || ssid->disabled != 2) {
5461		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
5462			   "for persistent P2P group",
5463			   id);
5464		return -1;
5465	}
5466
5467	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
5468					     NULL, 0);
5469}
5470
5471
5472static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
5473{
5474	int freq = 0, ht40, vht;
5475	char *pos;
5476
5477	pos = os_strstr(cmd, "freq=");
5478	if (pos)
5479		freq = atoi(pos + 5);
5480
5481	vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht;
5482	ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
5483		vht;
5484
5485	if (os_strncmp(cmd, "persistent=", 11) == 0)
5486		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
5487						     ht40, vht);
5488	if (os_strcmp(cmd, "persistent") == 0 ||
5489	    os_strncmp(cmd, "persistent ", 11) == 0)
5490		return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht);
5491	if (os_strncmp(cmd, "freq=", 5) == 0)
5492		return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
5493	if (ht40)
5494		return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
5495
5496	wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
5497		   cmd);
5498	return -1;
5499}
5500
5501
5502static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
5503			 char *buf, size_t buflen)
5504{
5505	u8 addr[ETH_ALEN], *addr_ptr;
5506	int next, res;
5507	const struct p2p_peer_info *info;
5508	char *pos, *end;
5509	char devtype[WPS_DEV_TYPE_BUFSIZE];
5510	struct wpa_ssid *ssid;
5511	size_t i;
5512
5513	if (!wpa_s->global->p2p)
5514		return -1;
5515
5516	if (os_strcmp(cmd, "FIRST") == 0) {
5517		addr_ptr = NULL;
5518		next = 0;
5519	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5520		if (hwaddr_aton(cmd + 5, addr) < 0)
5521			return -1;
5522		addr_ptr = addr;
5523		next = 1;
5524	} else {
5525		if (hwaddr_aton(cmd, addr) < 0)
5526			return -1;
5527		addr_ptr = addr;
5528		next = 0;
5529	}
5530
5531	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
5532	if (info == NULL)
5533		return -1;
5534
5535	pos = buf;
5536	end = buf + buflen;
5537
5538	res = os_snprintf(pos, end - pos, MACSTR "\n"
5539			  "pri_dev_type=%s\n"
5540			  "device_name=%s\n"
5541			  "manufacturer=%s\n"
5542			  "model_name=%s\n"
5543			  "model_number=%s\n"
5544			  "serial_number=%s\n"
5545			  "config_methods=0x%x\n"
5546			  "dev_capab=0x%x\n"
5547			  "group_capab=0x%x\n"
5548			  "level=%d\n",
5549			  MAC2STR(info->p2p_device_addr),
5550			  wps_dev_type_bin2str(info->pri_dev_type,
5551					       devtype, sizeof(devtype)),
5552			  info->device_name,
5553			  info->manufacturer,
5554			  info->model_name,
5555			  info->model_number,
5556			  info->serial_number,
5557			  info->config_methods,
5558			  info->dev_capab,
5559			  info->group_capab,
5560			  info->level);
5561	if (os_snprintf_error(end - pos, res))
5562		return pos - buf;
5563	pos += res;
5564
5565	for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
5566	{
5567		const u8 *t;
5568		t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
5569		res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
5570				  wps_dev_type_bin2str(t, devtype,
5571						       sizeof(devtype)));
5572		if (os_snprintf_error(end - pos, res))
5573			return pos - buf;
5574		pos += res;
5575	}
5576
5577	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
5578	if (ssid) {
5579		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
5580		if (os_snprintf_error(end - pos, res))
5581			return pos - buf;
5582		pos += res;
5583	}
5584
5585	res = p2p_get_peer_info_txt(info, pos, end - pos);
5586	if (res < 0)
5587		return pos - buf;
5588	pos += res;
5589
5590	if (info->vendor_elems) {
5591		res = os_snprintf(pos, end - pos, "vendor_elems=");
5592		if (os_snprintf_error(end - pos, res))
5593			return pos - buf;
5594		pos += res;
5595
5596		pos += wpa_snprintf_hex(pos, end - pos,
5597					wpabuf_head(info->vendor_elems),
5598					wpabuf_len(info->vendor_elems));
5599
5600		res = os_snprintf(pos, end - pos, "\n");
5601		if (os_snprintf_error(end - pos, res))
5602			return pos - buf;
5603		pos += res;
5604	}
5605
5606	return pos - buf;
5607}
5608
5609
5610static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
5611				  const char *param)
5612{
5613	unsigned int i;
5614
5615	if (wpa_s->global->p2p == NULL)
5616		return -1;
5617
5618	if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
5619		return -1;
5620
5621	for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
5622		struct wpa_freq_range *freq;
5623		freq = &wpa_s->global->p2p_disallow_freq.range[i];
5624		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
5625			   freq->min, freq->max);
5626	}
5627
5628	wpas_p2p_update_channel_list(wpa_s);
5629	return 0;
5630}
5631
5632
5633static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
5634{
5635	char *param;
5636
5637	if (wpa_s->global->p2p == NULL)
5638		return -1;
5639
5640	param = os_strchr(cmd, ' ');
5641	if (param == NULL)
5642		return -1;
5643	*param++ = '\0';
5644
5645	if (os_strcmp(cmd, "discoverability") == 0) {
5646		p2p_set_client_discoverability(wpa_s->global->p2p,
5647					       atoi(param));
5648		return 0;
5649	}
5650
5651	if (os_strcmp(cmd, "managed") == 0) {
5652		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
5653		return 0;
5654	}
5655
5656	if (os_strcmp(cmd, "listen_channel") == 0) {
5657		return p2p_set_listen_channel(wpa_s->global->p2p, 81,
5658					      atoi(param), 1);
5659	}
5660
5661	if (os_strcmp(cmd, "ssid_postfix") == 0) {
5662		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
5663					    os_strlen(param));
5664	}
5665
5666	if (os_strcmp(cmd, "noa") == 0) {
5667		char *pos;
5668		int count, start, duration;
5669		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
5670		count = atoi(param);
5671		pos = os_strchr(param, ',');
5672		if (pos == NULL)
5673			return -1;
5674		pos++;
5675		start = atoi(pos);
5676		pos = os_strchr(pos, ',');
5677		if (pos == NULL)
5678			return -1;
5679		pos++;
5680		duration = atoi(pos);
5681		if (count < 0 || count > 255 || start < 0 || duration < 0)
5682			return -1;
5683		if (count == 0 && duration > 0)
5684			return -1;
5685		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
5686			   "start=%d duration=%d", count, start, duration);
5687		return wpas_p2p_set_noa(wpa_s, count, start, duration);
5688	}
5689
5690	if (os_strcmp(cmd, "ps") == 0)
5691		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
5692
5693	if (os_strcmp(cmd, "oppps") == 0)
5694		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
5695
5696	if (os_strcmp(cmd, "ctwindow") == 0)
5697		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
5698
5699	if (os_strcmp(cmd, "disabled") == 0) {
5700		wpa_s->global->p2p_disabled = atoi(param);
5701		wpa_printf(MSG_DEBUG, "P2P functionality %s",
5702			   wpa_s->global->p2p_disabled ?
5703			   "disabled" : "enabled");
5704		if (wpa_s->global->p2p_disabled) {
5705			wpas_p2p_stop_find(wpa_s);
5706			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
5707			p2p_flush(wpa_s->global->p2p);
5708		}
5709		return 0;
5710	}
5711
5712	if (os_strcmp(cmd, "conc_pref") == 0) {
5713		if (os_strcmp(param, "sta") == 0)
5714			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
5715		else if (os_strcmp(param, "p2p") == 0)
5716			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
5717		else {
5718			wpa_printf(MSG_INFO, "Invalid conc_pref value");
5719			return -1;
5720		}
5721		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
5722			   "%s", param);
5723		return 0;
5724	}
5725
5726	if (os_strcmp(cmd, "force_long_sd") == 0) {
5727		wpa_s->force_long_sd = atoi(param);
5728		return 0;
5729	}
5730
5731	if (os_strcmp(cmd, "peer_filter") == 0) {
5732		u8 addr[ETH_ALEN];
5733		if (hwaddr_aton(param, addr))
5734			return -1;
5735		p2p_set_peer_filter(wpa_s->global->p2p, addr);
5736		return 0;
5737	}
5738
5739	if (os_strcmp(cmd, "cross_connect") == 0)
5740		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
5741
5742	if (os_strcmp(cmd, "go_apsd") == 0) {
5743		if (os_strcmp(param, "disable") == 0)
5744			wpa_s->set_ap_uapsd = 0;
5745		else {
5746			wpa_s->set_ap_uapsd = 1;
5747			wpa_s->ap_uapsd = atoi(param);
5748		}
5749		return 0;
5750	}
5751
5752	if (os_strcmp(cmd, "client_apsd") == 0) {
5753		if (os_strcmp(param, "disable") == 0)
5754			wpa_s->set_sta_uapsd = 0;
5755		else {
5756			int be, bk, vi, vo;
5757			char *pos;
5758			/* format: BE,BK,VI,VO;max SP Length */
5759			be = atoi(param);
5760			pos = os_strchr(param, ',');
5761			if (pos == NULL)
5762				return -1;
5763			pos++;
5764			bk = atoi(pos);
5765			pos = os_strchr(pos, ',');
5766			if (pos == NULL)
5767				return -1;
5768			pos++;
5769			vi = atoi(pos);
5770			pos = os_strchr(pos, ',');
5771			if (pos == NULL)
5772				return -1;
5773			pos++;
5774			vo = atoi(pos);
5775			/* ignore max SP Length for now */
5776
5777			wpa_s->set_sta_uapsd = 1;
5778			wpa_s->sta_uapsd = 0;
5779			if (be)
5780				wpa_s->sta_uapsd |= BIT(0);
5781			if (bk)
5782				wpa_s->sta_uapsd |= BIT(1);
5783			if (vi)
5784				wpa_s->sta_uapsd |= BIT(2);
5785			if (vo)
5786				wpa_s->sta_uapsd |= BIT(3);
5787		}
5788		return 0;
5789	}
5790
5791	if (os_strcmp(cmd, "disallow_freq") == 0)
5792		return p2p_ctrl_disallow_freq(wpa_s, param);
5793
5794	if (os_strcmp(cmd, "disc_int") == 0) {
5795		int min_disc_int, max_disc_int, max_disc_tu;
5796		char *pos;
5797
5798		pos = param;
5799
5800		min_disc_int = atoi(pos);
5801		pos = os_strchr(pos, ' ');
5802		if (pos == NULL)
5803			return -1;
5804		*pos++ = '\0';
5805
5806		max_disc_int = atoi(pos);
5807		pos = os_strchr(pos, ' ');
5808		if (pos == NULL)
5809			return -1;
5810		*pos++ = '\0';
5811
5812		max_disc_tu = atoi(pos);
5813
5814		return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
5815					max_disc_int, max_disc_tu);
5816	}
5817
5818	if (os_strcmp(cmd, "per_sta_psk") == 0) {
5819		wpa_s->global->p2p_per_sta_psk = !!atoi(param);
5820		return 0;
5821	}
5822
5823#ifdef CONFIG_WPS_NFC
5824	if (os_strcmp(cmd, "nfc_tag") == 0)
5825		return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
5826#endif /* CONFIG_WPS_NFC */
5827
5828	if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
5829		wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
5830		return 0;
5831	}
5832
5833	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
5834		   cmd);
5835
5836	return -1;
5837}
5838
5839
5840static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
5841{
5842	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
5843	wpa_s->force_long_sd = 0;
5844	wpas_p2p_stop_find(wpa_s);
5845	if (wpa_s->global->p2p)
5846		p2p_flush(wpa_s->global->p2p);
5847}
5848
5849
5850static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
5851{
5852	char *pos, *pos2;
5853	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
5854
5855	if (cmd[0]) {
5856		pos = os_strchr(cmd, ' ');
5857		if (pos == NULL)
5858			return -1;
5859		*pos++ = '\0';
5860		dur1 = atoi(cmd);
5861
5862		pos2 = os_strchr(pos, ' ');
5863		if (pos2)
5864			*pos2++ = '\0';
5865		int1 = atoi(pos);
5866	} else
5867		pos2 = NULL;
5868
5869	if (pos2) {
5870		pos = os_strchr(pos2, ' ');
5871		if (pos == NULL)
5872			return -1;
5873		*pos++ = '\0';
5874		dur2 = atoi(pos2);
5875		int2 = atoi(pos);
5876	}
5877
5878	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
5879}
5880
5881
5882static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
5883{
5884	char *pos;
5885	unsigned int period = 0, interval = 0;
5886
5887	if (cmd[0]) {
5888		pos = os_strchr(cmd, ' ');
5889		if (pos == NULL)
5890			return -1;
5891		*pos++ = '\0';
5892		period = atoi(cmd);
5893		interval = atoi(pos);
5894	}
5895
5896	return wpas_p2p_ext_listen(wpa_s, period, interval);
5897}
5898
5899
5900static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
5901{
5902	const char *pos;
5903	u8 peer[ETH_ALEN];
5904	int iface_addr = 0;
5905
5906	pos = cmd;
5907	if (os_strncmp(pos, "iface=", 6) == 0) {
5908		iface_addr = 1;
5909		pos += 6;
5910	}
5911	if (hwaddr_aton(pos, peer))
5912		return -1;
5913
5914	wpas_p2p_remove_client(wpa_s, peer, iface_addr);
5915	return 0;
5916}
5917
5918#endif /* CONFIG_P2P */
5919
5920
5921static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
5922{
5923	struct wpa_freq_range_list ranges;
5924	int *freqs = NULL;
5925	struct hostapd_hw_modes *mode;
5926	u16 i;
5927
5928	if (wpa_s->hw.modes == NULL)
5929		return NULL;
5930
5931	os_memset(&ranges, 0, sizeof(ranges));
5932	if (freq_range_list_parse(&ranges, val) < 0)
5933		return NULL;
5934
5935	for (i = 0; i < wpa_s->hw.num_modes; i++) {
5936		int j;
5937
5938		mode = &wpa_s->hw.modes[i];
5939		for (j = 0; j < mode->num_channels; j++) {
5940			unsigned int freq;
5941
5942			if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
5943				continue;
5944
5945			freq = mode->channels[j].freq;
5946			if (!freq_range_list_includes(&ranges, freq))
5947				continue;
5948
5949			int_array_add_unique(&freqs, freq);
5950		}
5951	}
5952
5953	os_free(ranges.range);
5954	return freqs;
5955}
5956
5957
5958#ifdef CONFIG_INTERWORKING
5959
5960static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
5961{
5962	int auto_sel = 0;
5963	int *freqs = NULL;
5964
5965	if (param) {
5966		char *pos;
5967
5968		auto_sel = os_strstr(param, "auto") != NULL;
5969
5970		pos = os_strstr(param, "freq=");
5971		if (pos) {
5972			freqs = freq_range_to_channel_list(wpa_s, pos + 5);
5973			if (freqs == NULL)
5974				return -1;
5975		}
5976
5977	}
5978
5979	return interworking_select(wpa_s, auto_sel, freqs);
5980}
5981
5982
5983static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
5984				     int only_add)
5985{
5986	u8 bssid[ETH_ALEN];
5987	struct wpa_bss *bss;
5988
5989	if (hwaddr_aton(dst, bssid)) {
5990		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
5991		return -1;
5992	}
5993
5994	bss = wpa_bss_get_bssid(wpa_s, bssid);
5995	if (bss == NULL) {
5996		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
5997			   MAC2STR(bssid));
5998		return -1;
5999	}
6000
6001	if (bss->ssid_len == 0) {
6002		int found = 0;
6003
6004		wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
6005			   " does not have SSID information", MAC2STR(bssid));
6006
6007		dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
6008					 list) {
6009			if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
6010			    bss->ssid_len > 0) {
6011				found = 1;
6012				break;
6013			}
6014		}
6015
6016		if (!found)
6017			return -1;
6018		wpa_printf(MSG_DEBUG,
6019			   "Found another matching BSS entry with SSID");
6020	}
6021
6022	return interworking_connect(wpa_s, bss, only_add);
6023}
6024
6025
6026static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
6027{
6028	u8 dst_addr[ETH_ALEN];
6029	int used;
6030	char *pos;
6031#define MAX_ANQP_INFO_ID 100
6032	u16 id[MAX_ANQP_INFO_ID];
6033	size_t num_id = 0;
6034	u32 subtypes = 0;
6035
6036	used = hwaddr_aton2(dst, dst_addr);
6037	if (used < 0)
6038		return -1;
6039	pos = dst + used;
6040	if (*pos == ' ')
6041		pos++;
6042	while (num_id < MAX_ANQP_INFO_ID) {
6043		if (os_strncmp(pos, "hs20:", 5) == 0) {
6044#ifdef CONFIG_HS20
6045			int num = atoi(pos + 5);
6046			if (num <= 0 || num > 31)
6047				return -1;
6048			subtypes |= BIT(num);
6049#else /* CONFIG_HS20 */
6050			return -1;
6051#endif /* CONFIG_HS20 */
6052		} else {
6053			id[num_id] = atoi(pos);
6054			if (id[num_id])
6055				num_id++;
6056		}
6057		pos = os_strchr(pos + 1, ',');
6058		if (pos == NULL)
6059			break;
6060		pos++;
6061	}
6062
6063	if (num_id == 0)
6064		return -1;
6065
6066	return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
6067}
6068
6069
6070static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
6071{
6072	u8 dst_addr[ETH_ALEN];
6073	struct wpabuf *advproto, *query = NULL;
6074	int used, ret = -1;
6075	char *pos, *end;
6076	size_t len;
6077
6078	used = hwaddr_aton2(cmd, dst_addr);
6079	if (used < 0)
6080		return -1;
6081
6082	pos = cmd + used;
6083	while (*pos == ' ')
6084		pos++;
6085
6086	/* Advertisement Protocol ID */
6087	end = os_strchr(pos, ' ');
6088	if (end)
6089		len = end - pos;
6090	else
6091		len = os_strlen(pos);
6092	if (len & 0x01)
6093		return -1;
6094	len /= 2;
6095	if (len == 0)
6096		return -1;
6097	advproto = wpabuf_alloc(len);
6098	if (advproto == NULL)
6099		return -1;
6100	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
6101		goto fail;
6102
6103	if (end) {
6104		/* Optional Query Request */
6105		pos = end + 1;
6106		while (*pos == ' ')
6107			pos++;
6108
6109		len = os_strlen(pos);
6110		if (len) {
6111			if (len & 0x01)
6112				goto fail;
6113			len /= 2;
6114			if (len == 0)
6115				goto fail;
6116			query = wpabuf_alloc(len);
6117			if (query == NULL)
6118				goto fail;
6119			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
6120				goto fail;
6121		}
6122	}
6123
6124	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
6125
6126fail:
6127	wpabuf_free(advproto);
6128	wpabuf_free(query);
6129
6130	return ret;
6131}
6132
6133
6134static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
6135			    size_t buflen)
6136{
6137	u8 addr[ETH_ALEN];
6138	int dialog_token;
6139	int used;
6140	char *pos;
6141	size_t resp_len, start, requested_len;
6142	struct wpabuf *resp;
6143	int ret;
6144
6145	used = hwaddr_aton2(cmd, addr);
6146	if (used < 0)
6147		return -1;
6148
6149	pos = cmd + used;
6150	while (*pos == ' ')
6151		pos++;
6152	dialog_token = atoi(pos);
6153
6154	if (wpa_s->last_gas_resp &&
6155	    os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
6156	    dialog_token == wpa_s->last_gas_dialog_token)
6157		resp = wpa_s->last_gas_resp;
6158	else if (wpa_s->prev_gas_resp &&
6159		 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
6160		 dialog_token == wpa_s->prev_gas_dialog_token)
6161		resp = wpa_s->prev_gas_resp;
6162	else
6163		return -1;
6164
6165	resp_len = wpabuf_len(resp);
6166	start = 0;
6167	requested_len = resp_len;
6168
6169	pos = os_strchr(pos, ' ');
6170	if (pos) {
6171		start = atoi(pos);
6172		if (start > resp_len)
6173			return os_snprintf(buf, buflen, "FAIL-Invalid range");
6174		pos = os_strchr(pos, ',');
6175		if (pos == NULL)
6176			return -1;
6177		pos++;
6178		requested_len = atoi(pos);
6179		if (start + requested_len > resp_len)
6180			return os_snprintf(buf, buflen, "FAIL-Invalid range");
6181	}
6182
6183	if (requested_len * 2 + 1 > buflen)
6184		return os_snprintf(buf, buflen, "FAIL-Too long response");
6185
6186	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
6187			       requested_len);
6188
6189	if (start + requested_len == resp_len) {
6190		/*
6191		 * Free memory by dropping the response after it has been
6192		 * fetched.
6193		 */
6194		if (resp == wpa_s->prev_gas_resp) {
6195			wpabuf_free(wpa_s->prev_gas_resp);
6196			wpa_s->prev_gas_resp = NULL;
6197		} else {
6198			wpabuf_free(wpa_s->last_gas_resp);
6199			wpa_s->last_gas_resp = NULL;
6200		}
6201	}
6202
6203	return ret;
6204}
6205#endif /* CONFIG_INTERWORKING */
6206
6207
6208#ifdef CONFIG_HS20
6209
6210static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
6211{
6212	u8 dst_addr[ETH_ALEN];
6213	int used;
6214	char *pos;
6215	u32 subtypes = 0;
6216
6217	used = hwaddr_aton2(dst, dst_addr);
6218	if (used < 0)
6219		return -1;
6220	pos = dst + used;
6221	if (*pos == ' ')
6222		pos++;
6223	for (;;) {
6224		int num = atoi(pos);
6225		if (num <= 0 || num > 31)
6226			return -1;
6227		subtypes |= BIT(num);
6228		pos = os_strchr(pos + 1, ',');
6229		if (pos == NULL)
6230			break;
6231		pos++;
6232	}
6233
6234	if (subtypes == 0)
6235		return -1;
6236
6237	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
6238}
6239
6240
6241static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
6242				    const u8 *addr, const char *realm)
6243{
6244	u8 *buf;
6245	size_t rlen, len;
6246	int ret;
6247
6248	rlen = os_strlen(realm);
6249	len = 3 + rlen;
6250	buf = os_malloc(len);
6251	if (buf == NULL)
6252		return -1;
6253	buf[0] = 1; /* NAI Home Realm Count */
6254	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
6255	buf[2] = rlen;
6256	os_memcpy(buf + 3, realm, rlen);
6257
6258	ret = hs20_anqp_send_req(wpa_s, addr,
6259				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
6260				 buf, len);
6261
6262	os_free(buf);
6263
6264	return ret;
6265}
6266
6267
6268static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
6269					char *dst)
6270{
6271	struct wpa_cred *cred = wpa_s->conf->cred;
6272	u8 dst_addr[ETH_ALEN];
6273	int used;
6274	u8 *buf;
6275	size_t len;
6276	int ret;
6277
6278	used = hwaddr_aton2(dst, dst_addr);
6279	if (used < 0)
6280		return -1;
6281
6282	while (dst[used] == ' ')
6283		used++;
6284	if (os_strncmp(dst + used, "realm=", 6) == 0)
6285		return hs20_nai_home_realm_list(wpa_s, dst_addr,
6286						dst + used + 6);
6287
6288	len = os_strlen(dst + used);
6289
6290	if (len == 0 && cred && cred->realm)
6291		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
6292
6293	if (len & 1)
6294		return -1;
6295	len /= 2;
6296	buf = os_malloc(len);
6297	if (buf == NULL)
6298		return -1;
6299	if (hexstr2bin(dst + used, buf, len) < 0) {
6300		os_free(buf);
6301		return -1;
6302	}
6303
6304	ret = hs20_anqp_send_req(wpa_s, dst_addr,
6305				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
6306				 buf, len);
6307	os_free(buf);
6308
6309	return ret;
6310}
6311
6312
6313static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
6314{
6315	u8 dst_addr[ETH_ALEN];
6316	int used;
6317	char *icon;
6318
6319	used = hwaddr_aton2(cmd, dst_addr);
6320	if (used < 0)
6321		return -1;
6322
6323	while (cmd[used] == ' ')
6324		used++;
6325	icon = &cmd[used];
6326
6327	wpa_s->fetch_osu_icon_in_progress = 0;
6328	return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
6329				  (u8 *) icon, os_strlen(icon));
6330}
6331
6332#endif /* CONFIG_HS20 */
6333
6334
6335#ifdef CONFIG_AUTOSCAN
6336
6337static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
6338					      char *cmd)
6339{
6340	enum wpa_states state = wpa_s->wpa_state;
6341	char *new_params = NULL;
6342
6343	if (os_strlen(cmd) > 0) {
6344		new_params = os_strdup(cmd);
6345		if (new_params == NULL)
6346			return -1;
6347	}
6348
6349	os_free(wpa_s->conf->autoscan);
6350	wpa_s->conf->autoscan = new_params;
6351
6352	if (wpa_s->conf->autoscan == NULL)
6353		autoscan_deinit(wpa_s);
6354	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
6355		autoscan_init(wpa_s, 1);
6356	else if (state == WPA_SCANNING)
6357		wpa_supplicant_reinit_autoscan(wpa_s);
6358
6359	return 0;
6360}
6361
6362#endif /* CONFIG_AUTOSCAN */
6363
6364
6365#ifdef CONFIG_WNM
6366
6367static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
6368{
6369	int enter;
6370	int intval = 0;
6371	char *pos;
6372	int ret;
6373	struct wpabuf *tfs_req = NULL;
6374
6375	if (os_strncmp(cmd, "enter", 5) == 0)
6376		enter = 1;
6377	else if (os_strncmp(cmd, "exit", 4) == 0)
6378		enter = 0;
6379	else
6380		return -1;
6381
6382	pos = os_strstr(cmd, " interval=");
6383	if (pos)
6384		intval = atoi(pos + 10);
6385
6386	pos = os_strstr(cmd, " tfs_req=");
6387	if (pos) {
6388		char *end;
6389		size_t len;
6390		pos += 9;
6391		end = os_strchr(pos, ' ');
6392		if (end)
6393			len = end - pos;
6394		else
6395			len = os_strlen(pos);
6396		if (len & 1)
6397			return -1;
6398		len /= 2;
6399		tfs_req = wpabuf_alloc(len);
6400		if (tfs_req == NULL)
6401			return -1;
6402		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
6403			wpabuf_free(tfs_req);
6404			return -1;
6405		}
6406	}
6407
6408	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
6409					   WNM_SLEEP_MODE_EXIT, intval,
6410					   tfs_req);
6411	wpabuf_free(tfs_req);
6412
6413	return ret;
6414}
6415
6416
6417static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
6418{
6419	int query_reason;
6420
6421	query_reason = atoi(cmd);
6422
6423	wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
6424		   query_reason);
6425
6426	return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
6427}
6428
6429#endif /* CONFIG_WNM */
6430
6431
6432static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
6433				      size_t buflen)
6434{
6435	struct wpa_signal_info si;
6436	int ret;
6437	char *pos, *end;
6438
6439	ret = wpa_drv_signal_poll(wpa_s, &si);
6440	if (ret)
6441		return -1;
6442
6443	pos = buf;
6444	end = buf + buflen;
6445
6446	ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
6447			  "NOISE=%d\nFREQUENCY=%u\n",
6448			  si.current_signal, si.current_txrate / 1000,
6449			  si.current_noise, si.frequency);
6450	if (os_snprintf_error(end - pos, ret))
6451		return -1;
6452	pos += ret;
6453
6454	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
6455		ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
6456				  channel_width_to_string(si.chanwidth));
6457		if (os_snprintf_error(end - pos, ret))
6458			return -1;
6459		pos += ret;
6460	}
6461
6462	if (si.center_frq1 > 0 && si.center_frq2 > 0) {
6463		ret = os_snprintf(pos, end - pos,
6464				  "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
6465				  si.center_frq1, si.center_frq2);
6466		if (os_snprintf_error(end - pos, ret))
6467			return -1;
6468		pos += ret;
6469	}
6470
6471	if (si.avg_signal) {
6472		ret = os_snprintf(pos, end - pos,
6473				  "AVG_RSSI=%d\n", si.avg_signal);
6474		if (os_snprintf_error(end - pos, ret))
6475			return -1;
6476		pos += ret;
6477	}
6478
6479	return pos - buf;
6480}
6481
6482
6483static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
6484				      size_t buflen)
6485{
6486	struct hostap_sta_driver_data sta;
6487	int ret;
6488
6489	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
6490	if (ret)
6491		return -1;
6492
6493	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
6494			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
6495	if (os_snprintf_error(buflen, ret))
6496		return -1;
6497	return ret;
6498}
6499
6500
6501#ifdef ANDROID
6502static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
6503				     char *buf, size_t buflen)
6504{
6505	int ret;
6506
6507	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
6508	if (ret == 0) {
6509		if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
6510			struct p2p_data *p2p = wpa_s->global->p2p;
6511			if (p2p) {
6512				char country[3];
6513				country[0] = cmd[8];
6514				country[1] = cmd[9];
6515				country[2] = 0x04;
6516				p2p_set_country(p2p, country);
6517			}
6518		}
6519		ret = os_snprintf(buf, buflen, "%s\n", "OK");
6520		if (os_snprintf_error(buflen, ret))
6521			ret = -1;
6522	}
6523	return ret;
6524}
6525#endif /* ANDROID */
6526
6527
6528static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
6529				     char *buf, size_t buflen)
6530{
6531	int ret;
6532	char *pos;
6533	u8 *data = NULL;
6534	unsigned int vendor_id, subcmd;
6535	struct wpabuf *reply;
6536	size_t data_len = 0;
6537
6538	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
6539	vendor_id = strtoul(cmd, &pos, 16);
6540	if (!isblank(*pos))
6541		return -EINVAL;
6542
6543	subcmd = strtoul(pos, &pos, 10);
6544
6545	if (*pos != '\0') {
6546		if (!isblank(*pos++))
6547			return -EINVAL;
6548		data_len = os_strlen(pos);
6549	}
6550
6551	if (data_len) {
6552		data_len /= 2;
6553		data = os_malloc(data_len);
6554		if (!data)
6555			return -1;
6556
6557		if (hexstr2bin(pos, data, data_len)) {
6558			wpa_printf(MSG_DEBUG,
6559				   "Vendor command: wrong parameter format");
6560			os_free(data);
6561			return -EINVAL;
6562		}
6563	}
6564
6565	reply = wpabuf_alloc((buflen - 1) / 2);
6566	if (!reply) {
6567		os_free(data);
6568		return -1;
6569	}
6570
6571	ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
6572				 reply);
6573
6574	if (ret == 0)
6575		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
6576				       wpabuf_len(reply));
6577
6578	wpabuf_free(reply);
6579	os_free(data);
6580
6581	return ret;
6582}
6583
6584
6585static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
6586{
6587#ifdef CONFIG_P2P
6588	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
6589		wpa_s->global->p2p_init_wpa_s : wpa_s;
6590#endif /* CONFIG_P2P */
6591
6592	wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
6593
6594#ifdef CONFIG_P2P
6595	wpas_p2p_cancel(p2p_wpa_s);
6596	p2p_ctrl_flush(p2p_wpa_s);
6597	wpas_p2p_group_remove(p2p_wpa_s, "*");
6598	wpas_p2p_service_flush(p2p_wpa_s);
6599	p2p_wpa_s->global->p2p_disabled = 0;
6600	p2p_wpa_s->global->p2p_per_sta_psk = 0;
6601	p2p_wpa_s->conf->num_sec_device_types = 0;
6602	p2p_wpa_s->p2p_disable_ip_addr_req = 0;
6603	os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
6604	p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
6605	p2p_wpa_s->global->pending_p2ps_group = 0;
6606#endif /* CONFIG_P2P */
6607
6608#ifdef CONFIG_WPS_TESTING
6609	wps_version_number = 0x20;
6610	wps_testing_dummy_cred = 0;
6611	wps_corrupt_pkhash = 0;
6612#endif /* CONFIG_WPS_TESTING */
6613#ifdef CONFIG_WPS
6614	wpa_s->wps_fragment_size = 0;
6615	wpas_wps_cancel(wpa_s);
6616	wps_registrar_flush(wpa_s->wps->registrar);
6617#endif /* CONFIG_WPS */
6618	wpa_s->after_wps = 0;
6619	wpa_s->known_wps_freq = 0;
6620
6621#ifdef CONFIG_TDLS
6622#ifdef CONFIG_TDLS_TESTING
6623	extern unsigned int tdls_testing;
6624	tdls_testing = 0;
6625#endif /* CONFIG_TDLS_TESTING */
6626	wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
6627	wpa_tdls_enable(wpa_s->wpa, 1);
6628#endif /* CONFIG_TDLS */
6629
6630	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
6631	wpa_supplicant_stop_countermeasures(wpa_s, NULL);
6632
6633	wpa_s->no_keep_alive = 0;
6634	wpa_s->own_disconnect_req = 0;
6635
6636	os_free(wpa_s->disallow_aps_bssid);
6637	wpa_s->disallow_aps_bssid = NULL;
6638	wpa_s->disallow_aps_bssid_count = 0;
6639	os_free(wpa_s->disallow_aps_ssid);
6640	wpa_s->disallow_aps_ssid = NULL;
6641	wpa_s->disallow_aps_ssid_count = 0;
6642
6643	wpa_s->set_sta_uapsd = 0;
6644	wpa_s->sta_uapsd = 0;
6645
6646	wpa_drv_radio_disable(wpa_s, 0);
6647	wpa_blacklist_clear(wpa_s);
6648	wpa_s->extra_blacklist_count = 0;
6649	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
6650	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
6651	wpa_config_flush_blobs(wpa_s->conf);
6652	wpa_s->conf->auto_interworking = 0;
6653	wpa_s->conf->okc = 0;
6654
6655	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
6656	rsn_preauth_deinit(wpa_s->wpa);
6657
6658	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
6659	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
6660	wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
6661	eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
6662
6663	radio_remove_works(wpa_s, NULL, 1);
6664	wpa_s->ext_work_in_progress = 0;
6665
6666	wpa_s->next_ssid = NULL;
6667
6668#ifdef CONFIG_INTERWORKING
6669	hs20_cancel_fetch_osu(wpa_s);
6670#endif /* CONFIG_INTERWORKING */
6671
6672	wpa_s->ext_mgmt_frame_handling = 0;
6673	wpa_s->ext_eapol_frame_io = 0;
6674#ifdef CONFIG_TESTING_OPTIONS
6675	wpa_s->extra_roc_dur = 0;
6676	wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
6677#endif /* CONFIG_TESTING_OPTIONS */
6678
6679	wpa_s->disconnected = 0;
6680	os_free(wpa_s->next_scan_freqs);
6681	wpa_s->next_scan_freqs = NULL;
6682
6683	wpa_bss_flush(wpa_s);
6684	if (!dl_list_empty(&wpa_s->bss)) {
6685		wpa_printf(MSG_DEBUG,
6686			   "BSS table not empty after flush: %u entries, current_bss=%p bssid="
6687			   MACSTR " pending_bssid=" MACSTR,
6688			   dl_list_len(&wpa_s->bss), wpa_s->current_bss,
6689			   MAC2STR(wpa_s->bssid),
6690			   MAC2STR(wpa_s->pending_bssid));
6691	}
6692}
6693
6694
6695static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
6696				     char *buf, size_t buflen)
6697{
6698	struct wpa_radio_work *work;
6699	char *pos, *end;
6700	struct os_reltime now, diff;
6701
6702	pos = buf;
6703	end = buf + buflen;
6704
6705	os_get_reltime(&now);
6706
6707	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
6708	{
6709		int ret;
6710
6711		os_reltime_sub(&now, &work->time, &diff);
6712		ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
6713				  work->type, work->wpa_s->ifname, work->freq,
6714				  work->started, diff.sec, diff.usec);
6715		if (os_snprintf_error(end - pos, ret))
6716			break;
6717		pos += ret;
6718	}
6719
6720	return pos - buf;
6721}
6722
6723
6724static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
6725{
6726	struct wpa_radio_work *work = eloop_ctx;
6727	struct wpa_external_work *ework = work->ctx;
6728
6729	wpa_dbg(work->wpa_s, MSG_DEBUG,
6730		"Timing out external radio work %u (%s)",
6731		ework->id, work->type);
6732	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
6733	work->wpa_s->ext_work_in_progress = 0;
6734	radio_work_done(work);
6735	os_free(ework);
6736}
6737
6738
6739static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
6740{
6741	struct wpa_external_work *ework = work->ctx;
6742
6743	if (deinit) {
6744		if (work->started)
6745			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
6746					     work, NULL);
6747
6748		os_free(ework);
6749		return;
6750	}
6751
6752	wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
6753		ework->id, ework->type);
6754	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
6755	work->wpa_s->ext_work_in_progress = 1;
6756	if (!ework->timeout)
6757		ework->timeout = 10;
6758	eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
6759			       work, NULL);
6760}
6761
6762
6763static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
6764				    char *buf, size_t buflen)
6765{
6766	struct wpa_external_work *ework;
6767	char *pos, *pos2;
6768	size_t type_len;
6769	int ret;
6770	unsigned int freq = 0;
6771
6772	/* format: <name> [freq=<MHz>] [timeout=<seconds>] */
6773
6774	ework = os_zalloc(sizeof(*ework));
6775	if (ework == NULL)
6776		return -1;
6777
6778	pos = os_strchr(cmd, ' ');
6779	if (pos) {
6780		type_len = pos - cmd;
6781		pos++;
6782
6783		pos2 = os_strstr(pos, "freq=");
6784		if (pos2)
6785			freq = atoi(pos2 + 5);
6786
6787		pos2 = os_strstr(pos, "timeout=");
6788		if (pos2)
6789			ework->timeout = atoi(pos2 + 8);
6790	} else {
6791		type_len = os_strlen(cmd);
6792	}
6793	if (4 + type_len >= sizeof(ework->type))
6794		type_len = sizeof(ework->type) - 4 - 1;
6795	os_strlcpy(ework->type, "ext:", sizeof(ework->type));
6796	os_memcpy(ework->type + 4, cmd, type_len);
6797	ework->type[4 + type_len] = '\0';
6798
6799	wpa_s->ext_work_id++;
6800	if (wpa_s->ext_work_id == 0)
6801		wpa_s->ext_work_id++;
6802	ework->id = wpa_s->ext_work_id;
6803
6804	if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
6805			   ework) < 0) {
6806		os_free(ework);
6807		return -1;
6808	}
6809
6810	ret = os_snprintf(buf, buflen, "%u", ework->id);
6811	if (os_snprintf_error(buflen, ret))
6812		return -1;
6813	return ret;
6814}
6815
6816
6817static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
6818{
6819	struct wpa_radio_work *work;
6820	unsigned int id = atoi(cmd);
6821
6822	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
6823	{
6824		struct wpa_external_work *ework;
6825
6826		if (os_strncmp(work->type, "ext:", 4) != 0)
6827			continue;
6828		ework = work->ctx;
6829		if (id && ework->id != id)
6830			continue;
6831		wpa_dbg(wpa_s, MSG_DEBUG,
6832			"Completed external radio work %u (%s)",
6833			ework->id, ework->type);
6834		eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
6835		wpa_s->ext_work_in_progress = 0;
6836		radio_work_done(work);
6837		os_free(ework);
6838		return 3; /* "OK\n" */
6839	}
6840
6841	return -1;
6842}
6843
6844
6845static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
6846				char *buf, size_t buflen)
6847{
6848	if (os_strcmp(cmd, "show") == 0)
6849		return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
6850	if (os_strncmp(cmd, "add ", 4) == 0)
6851		return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
6852	if (os_strncmp(cmd, "done ", 5) == 0)
6853		return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
6854	return -1;
6855}
6856
6857
6858void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
6859{
6860	struct wpa_radio_work *work, *tmp;
6861
6862	if (!wpa_s || !wpa_s->radio)
6863		return;
6864
6865	dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
6866			      struct wpa_radio_work, list) {
6867		struct wpa_external_work *ework;
6868
6869		if (os_strncmp(work->type, "ext:", 4) != 0)
6870			continue;
6871		ework = work->ctx;
6872		wpa_dbg(wpa_s, MSG_DEBUG,
6873			"Flushing%s external radio work %u (%s)",
6874			work->started ? " started" : "", ework->id,
6875			ework->type);
6876		if (work->started)
6877			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
6878					     work, NULL);
6879		radio_work_done(work);
6880		os_free(ework);
6881	}
6882}
6883
6884
6885static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
6886{
6887	struct wpa_supplicant *wpa_s = eloop_ctx;
6888	eapol_sm_notify_ctrl_response(wpa_s->eapol);
6889}
6890
6891
6892static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
6893			      unsigned int *scan_id_count, int scan_id[])
6894{
6895	const char *pos = value;
6896
6897	while (pos) {
6898		if (*pos == ' ' || *pos == '\0')
6899			break;
6900		if (*scan_id_count == MAX_SCAN_ID)
6901			return -1;
6902		scan_id[(*scan_id_count)++] = atoi(pos);
6903		pos = os_strchr(pos, ',');
6904		if (pos)
6905			pos++;
6906	}
6907
6908	return 0;
6909}
6910
6911
6912static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
6913			   char *reply, int reply_size, int *reply_len)
6914{
6915	char *pos;
6916	unsigned int manual_scan_passive = 0;
6917	unsigned int manual_scan_use_id = 0;
6918	unsigned int manual_scan_only_new = 0;
6919	unsigned int scan_only = 0;
6920	unsigned int scan_id_count = 0;
6921	int scan_id[MAX_SCAN_ID];
6922	void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
6923				 struct wpa_scan_results *scan_res);
6924	int *manual_scan_freqs = NULL;
6925
6926	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6927		*reply_len = -1;
6928		return;
6929	}
6930
6931	if (radio_work_pending(wpa_s, "scan")) {
6932		wpa_printf(MSG_DEBUG,
6933			   "Pending scan scheduled - reject new request");
6934		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
6935		return;
6936	}
6937
6938	if (params) {
6939		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
6940			scan_only = 1;
6941
6942		pos = os_strstr(params, "freq=");
6943		if (pos) {
6944			manual_scan_freqs = freq_range_to_channel_list(wpa_s,
6945								       pos + 5);
6946			if (manual_scan_freqs == NULL) {
6947				*reply_len = -1;
6948				goto done;
6949			}
6950		}
6951
6952		pos = os_strstr(params, "passive=");
6953		if (pos)
6954			manual_scan_passive = !!atoi(pos + 8);
6955
6956		pos = os_strstr(params, "use_id=");
6957		if (pos)
6958			manual_scan_use_id = atoi(pos + 7);
6959
6960		pos = os_strstr(params, "only_new=1");
6961		if (pos)
6962			manual_scan_only_new = 1;
6963
6964		pos = os_strstr(params, "scan_id=");
6965		if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
6966					      scan_id) < 0) {
6967			*reply_len = -1;
6968			goto done;
6969		}
6970	}
6971
6972	if (scan_only)
6973		scan_res_handler = scan_only_handler;
6974	else if (wpa_s->scan_res_handler == scan_only_handler)
6975		scan_res_handler = NULL;
6976	else
6977		scan_res_handler = wpa_s->scan_res_handler;
6978
6979	if (!wpa_s->sched_scanning && !wpa_s->scanning &&
6980	    ((wpa_s->wpa_state <= WPA_SCANNING) ||
6981	     (wpa_s->wpa_state == WPA_COMPLETED))) {
6982		wpa_s->manual_scan_passive = manual_scan_passive;
6983		wpa_s->manual_scan_use_id = manual_scan_use_id;
6984		wpa_s->manual_scan_only_new = manual_scan_only_new;
6985		wpa_s->scan_id_count = scan_id_count;
6986		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
6987		wpa_s->scan_res_handler = scan_res_handler;
6988		os_free(wpa_s->manual_scan_freqs);
6989		wpa_s->manual_scan_freqs = manual_scan_freqs;
6990		manual_scan_freqs = NULL;
6991
6992		wpa_s->normal_scans = 0;
6993		wpa_s->scan_req = MANUAL_SCAN_REQ;
6994		wpa_s->after_wps = 0;
6995		wpa_s->known_wps_freq = 0;
6996		wpa_supplicant_req_scan(wpa_s, 0, 0);
6997		if (wpa_s->manual_scan_use_id) {
6998			wpa_s->manual_scan_id++;
6999			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
7000				wpa_s->manual_scan_id);
7001			*reply_len = os_snprintf(reply, reply_size, "%u\n",
7002						 wpa_s->manual_scan_id);
7003		}
7004	} else if (wpa_s->sched_scanning) {
7005		wpa_s->manual_scan_passive = manual_scan_passive;
7006		wpa_s->manual_scan_use_id = manual_scan_use_id;
7007		wpa_s->manual_scan_only_new = manual_scan_only_new;
7008		wpa_s->scan_id_count = scan_id_count;
7009		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
7010		wpa_s->scan_res_handler = scan_res_handler;
7011		os_free(wpa_s->manual_scan_freqs);
7012		wpa_s->manual_scan_freqs = manual_scan_freqs;
7013		manual_scan_freqs = NULL;
7014
7015		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
7016		wpa_supplicant_cancel_sched_scan(wpa_s);
7017		wpa_s->scan_req = MANUAL_SCAN_REQ;
7018		wpa_supplicant_req_scan(wpa_s, 0, 0);
7019		if (wpa_s->manual_scan_use_id) {
7020			wpa_s->manual_scan_id++;
7021			*reply_len = os_snprintf(reply, reply_size, "%u\n",
7022						 wpa_s->manual_scan_id);
7023			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
7024				wpa_s->manual_scan_id);
7025		}
7026	} else {
7027		wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
7028		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
7029	}
7030
7031done:
7032	os_free(manual_scan_freqs);
7033}
7034
7035
7036#ifdef CONFIG_TESTING_OPTIONS
7037
7038static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
7039				       unsigned int freq, const u8 *dst,
7040				       const u8 *src, const u8 *bssid,
7041				       const u8 *data, size_t data_len,
7042				       enum offchannel_send_action_result
7043				       result)
7044{
7045	wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
7046		" src=" MACSTR " bssid=" MACSTR " result=%s",
7047		freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
7048		result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
7049		"SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
7050			     "NO_ACK" : "FAILED"));
7051}
7052
7053
7054static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
7055{
7056	char *pos, *param;
7057	size_t len;
7058	u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
7059	int res, used;
7060	int freq = 0, no_cck = 0, wait_time = 0;
7061
7062	/* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
7063	 *    <action=Action frame payload> */
7064
7065	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
7066
7067	pos = cmd;
7068	used = hwaddr_aton2(pos, da);
7069	if (used < 0)
7070		return -1;
7071	pos += used;
7072	while (*pos == ' ')
7073		pos++;
7074	used = hwaddr_aton2(pos, bssid);
7075	if (used < 0)
7076		return -1;
7077	pos += used;
7078
7079	param = os_strstr(pos, " freq=");
7080	if (param) {
7081		param += 6;
7082		freq = atoi(param);
7083	}
7084
7085	param = os_strstr(pos, " no_cck=");
7086	if (param) {
7087		param += 8;
7088		no_cck = atoi(param);
7089	}
7090
7091	param = os_strstr(pos, " wait_time=");
7092	if (param) {
7093		param += 11;
7094		wait_time = atoi(param);
7095	}
7096
7097	param = os_strstr(pos, " action=");
7098	if (param == NULL)
7099		return -1;
7100	param += 8;
7101
7102	len = os_strlen(param);
7103	if (len & 1)
7104		return -1;
7105	len /= 2;
7106
7107	buf = os_malloc(len);
7108	if (buf == NULL)
7109		return -1;
7110
7111	if (hexstr2bin(param, buf, len) < 0) {
7112		os_free(buf);
7113		return -1;
7114	}
7115
7116	res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
7117				     buf, len, wait_time,
7118				     wpas_ctrl_iface_mgmt_tx_cb, no_cck);
7119	os_free(buf);
7120	return res;
7121}
7122
7123
7124static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
7125{
7126	wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
7127	offchannel_send_action_done(wpa_s);
7128}
7129
7130
7131static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
7132{
7133	char *pos, *param;
7134	union wpa_event_data event;
7135	enum wpa_event_type ev;
7136
7137	/* <event name> [parameters..] */
7138
7139	wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
7140
7141	pos = cmd;
7142	param = os_strchr(pos, ' ');
7143	if (param)
7144		*param++ = '\0';
7145
7146	os_memset(&event, 0, sizeof(event));
7147
7148	if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
7149		ev = EVENT_INTERFACE_ENABLED;
7150	} else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
7151		ev = EVENT_INTERFACE_DISABLED;
7152	} else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
7153		ev = EVENT_AVOID_FREQUENCIES;
7154		if (param == NULL)
7155			param = "";
7156		if (freq_range_list_parse(&event.freq_range, param) < 0)
7157			return -1;
7158		wpa_supplicant_event(wpa_s, ev, &event);
7159		os_free(event.freq_range.range);
7160		return 0;
7161	} else {
7162		wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
7163			cmd);
7164		return -1;
7165	}
7166
7167	wpa_supplicant_event(wpa_s, ev, &event);
7168
7169	return 0;
7170}
7171
7172
7173static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
7174{
7175	char *pos;
7176	u8 src[ETH_ALEN], *buf;
7177	int used;
7178	size_t len;
7179
7180	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
7181
7182	pos = cmd;
7183	used = hwaddr_aton2(pos, src);
7184	if (used < 0)
7185		return -1;
7186	pos += used;
7187	while (*pos == ' ')
7188		pos++;
7189
7190	len = os_strlen(pos);
7191	if (len & 1)
7192		return -1;
7193	len /= 2;
7194
7195	buf = os_malloc(len);
7196	if (buf == NULL)
7197		return -1;
7198
7199	if (hexstr2bin(pos, buf, len) < 0) {
7200		os_free(buf);
7201		return -1;
7202	}
7203
7204	wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
7205	os_free(buf);
7206
7207	return 0;
7208}
7209
7210
7211static u16 ipv4_hdr_checksum(const void *buf, size_t len)
7212{
7213	size_t i;
7214	u32 sum = 0;
7215	const u16 *pos = buf;
7216
7217	for (i = 0; i < len / 2; i++)
7218		sum += *pos++;
7219
7220	while (sum >> 16)
7221		sum = (sum & 0xffff) + (sum >> 16);
7222
7223	return sum ^ 0xffff;
7224}
7225
7226
7227#define HWSIM_PACKETLEN 1500
7228#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
7229
7230void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
7231{
7232	struct wpa_supplicant *wpa_s = ctx;
7233	const struct ether_header *eth;
7234	const struct iphdr *ip;
7235	const u8 *pos;
7236	unsigned int i;
7237
7238	if (len != HWSIM_PACKETLEN)
7239		return;
7240
7241	eth = (const struct ether_header *) buf;
7242	ip = (const struct iphdr *) (eth + 1);
7243	pos = (const u8 *) (ip + 1);
7244
7245	if (ip->ihl != 5 || ip->version != 4 ||
7246	    ntohs(ip->tot_len) != HWSIM_IP_LEN)
7247		return;
7248
7249	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) {
7250		if (*pos != (u8) i)
7251			return;
7252		pos++;
7253	}
7254
7255	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
7256		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
7257}
7258
7259
7260static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
7261					    char *cmd)
7262{
7263	int enabled = atoi(cmd);
7264
7265	if (!enabled) {
7266		if (wpa_s->l2_test) {
7267			l2_packet_deinit(wpa_s->l2_test);
7268			wpa_s->l2_test = NULL;
7269			wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
7270		}
7271		return 0;
7272	}
7273
7274	if (wpa_s->l2_test)
7275		return 0;
7276
7277	wpa_s->l2_test = l2_packet_init(wpa_s->ifname, wpa_s->own_addr,
7278					ETHERTYPE_IP, wpas_data_test_rx,
7279					wpa_s, 1);
7280	if (wpa_s->l2_test == NULL)
7281		return -1;
7282
7283	wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
7284
7285	return 0;
7286}
7287
7288
7289static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
7290{
7291	u8 dst[ETH_ALEN], src[ETH_ALEN];
7292	char *pos;
7293	int used;
7294	long int val;
7295	u8 tos;
7296	u8 buf[HWSIM_PACKETLEN];
7297	struct ether_header *eth;
7298	struct iphdr *ip;
7299	u8 *dpos;
7300	unsigned int i;
7301
7302	if (wpa_s->l2_test == NULL)
7303		return -1;
7304
7305	/* format: <dst> <src> <tos> */
7306
7307	pos = cmd;
7308	used = hwaddr_aton2(pos, dst);
7309	if (used < 0)
7310		return -1;
7311	pos += used;
7312	while (*pos == ' ')
7313		pos++;
7314	used = hwaddr_aton2(pos, src);
7315	if (used < 0)
7316		return -1;
7317	pos += used;
7318
7319	val = strtol(pos, NULL, 0);
7320	if (val < 0 || val > 0xff)
7321		return -1;
7322	tos = val;
7323
7324	eth = (struct ether_header *) buf;
7325	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
7326	os_memcpy(eth->ether_shost, src, ETH_ALEN);
7327	eth->ether_type = htons(ETHERTYPE_IP);
7328	ip = (struct iphdr *) (eth + 1);
7329	os_memset(ip, 0, sizeof(*ip));
7330	ip->ihl = 5;
7331	ip->version = 4;
7332	ip->ttl = 64;
7333	ip->tos = tos;
7334	ip->tot_len = htons(HWSIM_IP_LEN);
7335	ip->protocol = 1;
7336	ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1);
7337	ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2);
7338	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
7339	dpos = (u8 *) (ip + 1);
7340	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
7341		*dpos++ = i;
7342
7343	if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, buf,
7344			   HWSIM_PACKETLEN) < 0)
7345		return -1;
7346
7347	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
7348		" tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
7349
7350	return 0;
7351}
7352
7353
7354static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
7355					   char *cmd)
7356{
7357	u8 *buf;
7358	struct ether_header *eth;
7359	struct l2_packet_data *l2 = NULL;
7360	size_t len;
7361	u16 ethertype;
7362	int res = -1;
7363
7364	len = os_strlen(cmd);
7365	if (len & 1 || len < ETH_HLEN * 2)
7366		return -1;
7367	len /= 2;
7368
7369	buf = os_malloc(len);
7370	if (buf == NULL)
7371		return -1;
7372
7373	if (hexstr2bin(cmd, buf, len) < 0)
7374		goto done;
7375
7376	eth = (struct ether_header *) buf;
7377	ethertype = ntohs(eth->ether_type);
7378
7379	l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
7380			    wpas_data_test_rx, wpa_s, 1);
7381	if (l2 == NULL)
7382		goto done;
7383
7384	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
7385	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
7386done:
7387	if (l2)
7388		l2_packet_deinit(l2);
7389	os_free(buf);
7390
7391	return res < 0 ? -1 : 0;
7392}
7393
7394
7395static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
7396{
7397#ifdef WPA_TRACE_BFD
7398	extern char wpa_trace_fail_func[256];
7399	extern unsigned int wpa_trace_fail_after;
7400	char *pos;
7401
7402	wpa_trace_fail_after = atoi(cmd);
7403	pos = os_strchr(cmd, ':');
7404	if (pos) {
7405		pos++;
7406		os_strlcpy(wpa_trace_fail_func, pos,
7407			   sizeof(wpa_trace_fail_func));
7408	} else {
7409		wpa_trace_fail_after = 0;
7410	}
7411	return 0;
7412#else /* WPA_TRACE_BFD */
7413	return -1;
7414#endif /* WPA_TRACE_BFD */
7415}
7416
7417
7418static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
7419				    char *buf, size_t buflen)
7420{
7421#ifdef WPA_TRACE_BFD
7422	extern char wpa_trace_fail_func[256];
7423	extern unsigned int wpa_trace_fail_after;
7424
7425	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
7426			   wpa_trace_fail_func);
7427#else /* WPA_TRACE_BFD */
7428	return -1;
7429#endif /* WPA_TRACE_BFD */
7430}
7431
7432#endif /* CONFIG_TESTING_OPTIONS */
7433
7434
7435static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
7436{
7437	unsigned int i;
7438	char buf[30];
7439
7440	wpa_printf(MSG_DEBUG, "Update vendor elements");
7441
7442	for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7443		if (wpa_s->vendor_elem[i]) {
7444			int res;
7445
7446			res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7447			if (!os_snprintf_error(sizeof(buf), res)) {
7448				wpa_hexdump_buf(MSG_DEBUG, buf,
7449						wpa_s->vendor_elem[i]);
7450			}
7451		}
7452	}
7453
7454#ifdef CONFIG_P2P
7455	if (wpa_s->parent == wpa_s &&
7456	    wpa_s->global->p2p &&
7457	    !wpa_s->global->p2p_disabled)
7458		p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7459#endif /* CONFIG_P2P */
7460}
7461
7462
7463static struct wpa_supplicant *
7464wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
7465			    enum wpa_vendor_elem_frame frame)
7466{
7467	switch (frame) {
7468#ifdef CONFIG_P2P
7469	case VENDOR_ELEM_PROBE_REQ_P2P:
7470	case VENDOR_ELEM_PROBE_RESP_P2P:
7471	case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7472	case VENDOR_ELEM_BEACON_P2P_GO:
7473	case VENDOR_ELEM_P2P_PD_REQ:
7474	case VENDOR_ELEM_P2P_PD_RESP:
7475	case VENDOR_ELEM_P2P_GO_NEG_REQ:
7476	case VENDOR_ELEM_P2P_GO_NEG_RESP:
7477	case VENDOR_ELEM_P2P_GO_NEG_CONF:
7478	case VENDOR_ELEM_P2P_INV_REQ:
7479	case VENDOR_ELEM_P2P_INV_RESP:
7480	case VENDOR_ELEM_P2P_ASSOC_REQ:
7481		return wpa_s->parent;
7482#endif /* CONFIG_P2P */
7483	default:
7484		return wpa_s;
7485	}
7486}
7487
7488
7489static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
7490{
7491	char *pos = cmd;
7492	int frame;
7493	size_t len;
7494	struct wpabuf *buf;
7495	struct ieee802_11_elems elems;
7496
7497	frame = atoi(pos);
7498	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
7499		return -1;
7500	wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
7501
7502	pos = os_strchr(pos, ' ');
7503	if (pos == NULL)
7504		return -1;
7505	pos++;
7506
7507	len = os_strlen(pos);
7508	if (len == 0)
7509		return 0;
7510	if (len & 1)
7511		return -1;
7512	len /= 2;
7513
7514	buf = wpabuf_alloc(len);
7515	if (buf == NULL)
7516		return -1;
7517
7518	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
7519		wpabuf_free(buf);
7520		return -1;
7521	}
7522
7523	if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
7524	    ParseFailed) {
7525		wpabuf_free(buf);
7526		return -1;
7527	}
7528
7529	if (wpa_s->vendor_elem[frame] == NULL) {
7530		wpa_s->vendor_elem[frame] = buf;
7531		wpas_ctrl_vendor_elem_update(wpa_s);
7532		return 0;
7533	}
7534
7535	if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
7536		wpabuf_free(buf);
7537		return -1;
7538	}
7539
7540	wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
7541	wpabuf_free(buf);
7542	wpas_ctrl_vendor_elem_update(wpa_s);
7543
7544	return 0;
7545}
7546
7547
7548static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
7549				     char *buf, size_t buflen)
7550{
7551	int frame = atoi(cmd);
7552
7553	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
7554		return -1;
7555	wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
7556
7557	if (wpa_s->vendor_elem[frame] == NULL)
7558		return 0;
7559
7560	return wpa_snprintf_hex(buf, buflen,
7561				wpabuf_head_u8(wpa_s->vendor_elem[frame]),
7562				wpabuf_len(wpa_s->vendor_elem[frame]));
7563}
7564
7565
7566static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
7567{
7568	char *pos = cmd;
7569	int frame;
7570	size_t len;
7571	u8 *buf;
7572	struct ieee802_11_elems elems;
7573	u8 *ie, *end;
7574
7575	frame = atoi(pos);
7576	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
7577		return -1;
7578	wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
7579
7580	pos = os_strchr(pos, ' ');
7581	if (pos == NULL)
7582		return -1;
7583	pos++;
7584
7585	if (*pos == '*') {
7586		wpabuf_free(wpa_s->vendor_elem[frame]);
7587		wpa_s->vendor_elem[frame] = NULL;
7588		wpas_ctrl_vendor_elem_update(wpa_s);
7589		return 0;
7590	}
7591
7592	if (wpa_s->vendor_elem[frame] == NULL)
7593		return -1;
7594
7595	len = os_strlen(pos);
7596	if (len == 0)
7597		return 0;
7598	if (len & 1)
7599		return -1;
7600	len /= 2;
7601
7602	buf = os_malloc(len);
7603	if (buf == NULL)
7604		return -1;
7605
7606	if (hexstr2bin(pos, buf, len) < 0) {
7607		os_free(buf);
7608		return -1;
7609	}
7610
7611	if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
7612		os_free(buf);
7613		return -1;
7614	}
7615
7616	ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7617	end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7618
7619	for (; ie + 1 < end; ie += 2 + ie[1]) {
7620		if (ie + len > end)
7621			break;
7622		if (os_memcmp(ie, buf, len) != 0)
7623			continue;
7624
7625		if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7626			wpabuf_free(wpa_s->vendor_elem[frame]);
7627			wpa_s->vendor_elem[frame] = NULL;
7628		} else {
7629			os_memmove(ie, ie + len,
7630				   end - (ie + len));
7631			wpa_s->vendor_elem[frame]->used -= len;
7632		}
7633		os_free(buf);
7634		wpas_ctrl_vendor_elem_update(wpa_s);
7635		return 0;
7636	}
7637
7638	os_free(buf);
7639
7640	return -1;
7641}
7642
7643
7644static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
7645{
7646	struct wpa_supplicant *wpa_s = ctx;
7647
7648	if (neighbor_rep) {
7649		wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
7650			     "length=%u",
7651			     (unsigned int) wpabuf_len(neighbor_rep));
7652		wpabuf_free(neighbor_rep);
7653	} else {
7654		wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
7655	}
7656}
7657
7658
7659static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s,
7660					    char *cmd)
7661{
7662	struct wpa_ssid ssid;
7663	struct wpa_ssid *ssid_p = NULL;
7664	int ret = 0;
7665
7666	if (os_strncmp(cmd, " ssid=", 6) == 0) {
7667		ssid.ssid_len = os_strlen(cmd + 6);
7668		if (ssid.ssid_len > 32)
7669			return -1;
7670		ssid.ssid = (u8 *) (cmd + 6);
7671		ssid_p = &ssid;
7672	}
7673
7674	ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p,
7675						 wpas_ctrl_neighbor_rep_cb,
7676						 wpa_s);
7677
7678	return ret;
7679}
7680
7681
7682static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
7683{
7684	eapol_sm_erp_flush(wpa_s->eapol);
7685	return 0;
7686}
7687
7688
7689static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
7690					 char *cmd)
7691{
7692	char *token, *context = NULL;
7693	unsigned int enable = ~0, type = 0;
7694	u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
7695	u8 *addr = NULL, *mask = NULL;
7696
7697	while ((token = str_token(cmd, " ", &context))) {
7698		if (os_strcasecmp(token, "scan") == 0) {
7699			type |= MAC_ADDR_RAND_SCAN;
7700		} else if (os_strcasecmp(token, "sched") == 0) {
7701			type |= MAC_ADDR_RAND_SCHED_SCAN;
7702		} else if (os_strcasecmp(token, "pno") == 0) {
7703			type |= MAC_ADDR_RAND_PNO;
7704		} else if (os_strcasecmp(token, "all") == 0) {
7705			type = wpa_s->mac_addr_rand_supported;
7706		} else if (os_strncasecmp(token, "enable=", 7) == 0) {
7707			enable = atoi(token + 7);
7708		} else if (os_strncasecmp(token, "addr=", 5) == 0) {
7709			addr = _addr;
7710			if (hwaddr_aton(token + 5, addr)) {
7711				wpa_printf(MSG_INFO,
7712					   "CTRL: Invalid MAC address: %s",
7713					   token);
7714				return -1;
7715			}
7716		} else if (os_strncasecmp(token, "mask=", 5) == 0) {
7717			mask = _mask;
7718			if (hwaddr_aton(token + 5, mask)) {
7719				wpa_printf(MSG_INFO,
7720					   "CTRL: Invalid MAC address mask: %s",
7721					   token);
7722				return -1;
7723			}
7724		} else {
7725			wpa_printf(MSG_INFO,
7726				   "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
7727				   token);
7728			return -1;
7729		}
7730	}
7731
7732	if (!type) {
7733		wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
7734		return -1;
7735	}
7736
7737	if ((wpa_s->mac_addr_rand_supported & type) != type) {
7738		wpa_printf(MSG_INFO,
7739			   "CTRL: MAC_RAND_SCAN types=%u != supported=%u",
7740			   type, wpa_s->mac_addr_rand_supported);
7741		return -1;
7742	}
7743
7744	if (enable > 1) {
7745		wpa_printf(MSG_INFO,
7746			   "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
7747		return -1;
7748	}
7749
7750	if (!enable) {
7751		wpas_mac_addr_rand_scan_clear(wpa_s, type);
7752		if (wpa_s->pno) {
7753			if (type & MAC_ADDR_RAND_PNO) {
7754				wpas_stop_pno(wpa_s);
7755				wpas_start_pno(wpa_s);
7756			}
7757		} else if (wpa_s->sched_scanning &&
7758			   (type & MAC_ADDR_RAND_SCHED_SCAN)) {
7759			/* simulate timeout to restart the sched scan */
7760			wpa_s->sched_scan_timed_out = 1;
7761			wpa_s->prev_sched_ssid = NULL;
7762			wpa_supplicant_cancel_sched_scan(wpa_s);
7763		}
7764		return 0;
7765	}
7766
7767	if ((addr && !mask) || (!addr && mask)) {
7768		wpa_printf(MSG_INFO,
7769			   "CTRL: MAC_RAND_SCAN invalid addr/mask combination");
7770		return -1;
7771	}
7772
7773	if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
7774		wpa_printf(MSG_INFO,
7775			   "CTRL: MAC_RAND_SCAN cannot allow multicast address");
7776		return -1;
7777	}
7778
7779	if (type & MAC_ADDR_RAND_SCAN) {
7780		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
7781					    addr, mask);
7782	}
7783
7784	if (type & MAC_ADDR_RAND_SCHED_SCAN) {
7785		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
7786					    addr, mask);
7787
7788		if (wpa_s->sched_scanning && !wpa_s->pno) {
7789			/* simulate timeout to restart the sched scan */
7790			wpa_s->sched_scan_timed_out = 1;
7791			wpa_s->prev_sched_ssid = NULL;
7792			wpa_supplicant_cancel_sched_scan(wpa_s);
7793		}
7794	}
7795
7796	if (type & MAC_ADDR_RAND_PNO) {
7797		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
7798					    addr, mask);
7799		if (wpa_s->pno) {
7800			wpas_stop_pno(wpa_s);
7801			wpas_start_pno(wpa_s);
7802		}
7803	}
7804
7805	return 0;
7806}
7807
7808
7809char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
7810					 char *buf, size_t *resp_len)
7811{
7812	char *reply;
7813	const int reply_size = 4096;
7814	int reply_len;
7815
7816	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
7817	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
7818		if (wpa_debug_show_keys)
7819			wpa_dbg(wpa_s, MSG_DEBUG,
7820				"Control interface command '%s'", buf);
7821		else
7822			wpa_dbg(wpa_s, MSG_DEBUG,
7823				"Control interface command '%s [REMOVED]'",
7824				os_strncmp(buf, WPA_CTRL_RSP,
7825					   os_strlen(WPA_CTRL_RSP)) == 0 ?
7826				WPA_CTRL_RSP : "SET_NETWORK");
7827	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
7828		   os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
7829		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
7830				      (const u8 *) buf, os_strlen(buf));
7831	} else {
7832		int level = MSG_DEBUG;
7833		if (os_strcmp(buf, "PING") == 0)
7834			level = MSG_EXCESSIVE;
7835		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
7836	}
7837
7838	reply = os_malloc(reply_size);
7839	if (reply == NULL) {
7840		*resp_len = 1;
7841		return NULL;
7842	}
7843
7844	os_memcpy(reply, "OK\n", 3);
7845	reply_len = 3;
7846
7847	if (os_strcmp(buf, "PING") == 0) {
7848		os_memcpy(reply, "PONG\n", 5);
7849		reply_len = 5;
7850	} else if (os_strcmp(buf, "IFNAME") == 0) {
7851		reply_len = os_strlen(wpa_s->ifname);
7852		os_memcpy(reply, wpa_s->ifname, reply_len);
7853	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
7854		if (wpa_debug_reopen_file() < 0)
7855			reply_len = -1;
7856	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
7857		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
7858	} else if (os_strcmp(buf, "MIB") == 0) {
7859		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
7860		if (reply_len >= 0) {
7861			reply_len += eapol_sm_get_mib(wpa_s->eapol,
7862						      reply + reply_len,
7863						      reply_size - reply_len);
7864		}
7865	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
7866		reply_len = wpa_supplicant_ctrl_iface_status(
7867			wpa_s, buf + 6, reply, reply_size);
7868	} else if (os_strcmp(buf, "PMKSA") == 0) {
7869		reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
7870						    reply_size);
7871	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
7872		wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
7873	} else if (os_strncmp(buf, "SET ", 4) == 0) {
7874		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
7875			reply_len = -1;
7876	} else if (os_strncmp(buf, "DUMP", 4) == 0) {
7877		reply_len = wpa_config_dump_values(wpa_s->conf,
7878						   reply, reply_size);
7879	} else if (os_strncmp(buf, "GET ", 4) == 0) {
7880		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
7881							  reply, reply_size);
7882	} else if (os_strcmp(buf, "LOGON") == 0) {
7883		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
7884	} else if (os_strcmp(buf, "LOGOFF") == 0) {
7885		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
7886	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
7887		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
7888			reply_len = -1;
7889		else
7890			wpas_request_connection(wpa_s);
7891	} else if (os_strcmp(buf, "REATTACH") == 0) {
7892		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
7893		    !wpa_s->current_ssid)
7894			reply_len = -1;
7895		else {
7896			wpa_s->reattach = 1;
7897			wpas_request_connection(wpa_s);
7898		}
7899	} else if (os_strcmp(buf, "RECONNECT") == 0) {
7900		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
7901			reply_len = -1;
7902		else if (wpa_s->disconnected)
7903			wpas_request_connection(wpa_s);
7904#ifdef IEEE8021X_EAPOL
7905	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
7906		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
7907			reply_len = -1;
7908#endif /* IEEE8021X_EAPOL */
7909#ifdef CONFIG_PEERKEY
7910	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
7911		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
7912			reply_len = -1;
7913#endif /* CONFIG_PEERKEY */
7914#ifdef CONFIG_IEEE80211R
7915	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
7916		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
7917			reply_len = -1;
7918#endif /* CONFIG_IEEE80211R */
7919#ifdef CONFIG_WPS
7920	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
7921		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
7922		if (res == -2) {
7923			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
7924			reply_len = 17;
7925		} else if (res)
7926			reply_len = -1;
7927	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
7928		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
7929		if (res == -2) {
7930			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
7931			reply_len = 17;
7932		} else if (res)
7933			reply_len = -1;
7934	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
7935		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
7936							      reply,
7937							      reply_size);
7938	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
7939		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
7940			wpa_s, buf + 14, reply, reply_size);
7941	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
7942		if (wpas_wps_cancel(wpa_s))
7943			reply_len = -1;
7944#ifdef CONFIG_WPS_NFC
7945	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
7946		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
7947			reply_len = -1;
7948	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
7949		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
7950			reply_len = -1;
7951	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
7952		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
7953			wpa_s, buf + 21, reply, reply_size);
7954	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
7955		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
7956			wpa_s, buf + 14, reply, reply_size);
7957	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
7958		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
7959							       buf + 17))
7960			reply_len = -1;
7961	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
7962		reply_len = wpas_ctrl_nfc_get_handover_req(
7963			wpa_s, buf + 21, reply, reply_size);
7964	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
7965		reply_len = wpas_ctrl_nfc_get_handover_sel(
7966			wpa_s, buf + 21, reply, reply_size);
7967	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
7968		if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
7969			reply_len = -1;
7970#endif /* CONFIG_WPS_NFC */
7971	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
7972		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
7973			reply_len = -1;
7974#ifdef CONFIG_AP
7975	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
7976		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
7977			wpa_s, buf + 11, reply, reply_size);
7978#endif /* CONFIG_AP */
7979#ifdef CONFIG_WPS_ER
7980	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
7981		if (wpas_wps_er_start(wpa_s, NULL))
7982			reply_len = -1;
7983	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
7984		if (wpas_wps_er_start(wpa_s, buf + 13))
7985			reply_len = -1;
7986	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
7987		wpas_wps_er_stop(wpa_s);
7988	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
7989		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
7990			reply_len = -1;
7991	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
7992		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
7993		if (ret == -2) {
7994			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
7995			reply_len = 17;
7996		} else if (ret == -3) {
7997			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
7998			reply_len = 18;
7999		} else if (ret == -4) {
8000			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
8001			reply_len = 20;
8002		} else if (ret)
8003			reply_len = -1;
8004	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
8005		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
8006			reply_len = -1;
8007	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
8008		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
8009								buf + 18))
8010			reply_len = -1;
8011	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
8012		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
8013			reply_len = -1;
8014#ifdef CONFIG_WPS_NFC
8015	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
8016		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
8017			wpa_s, buf + 24, reply, reply_size);
8018#endif /* CONFIG_WPS_NFC */
8019#endif /* CONFIG_WPS_ER */
8020#endif /* CONFIG_WPS */
8021#ifdef CONFIG_IBSS_RSN
8022	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
8023		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
8024			reply_len = -1;
8025#endif /* CONFIG_IBSS_RSN */
8026#ifdef CONFIG_MESH
8027	} else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
8028		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
8029			wpa_s, buf + 19, reply, reply_size);
8030	} else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
8031		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
8032			wpa_s, "", reply, reply_size);
8033	} else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
8034		if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
8035			reply_len = -1;
8036	} else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
8037		if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
8038								buf + 18))
8039			reply_len = -1;
8040#endif /* CONFIG_MESH */
8041#ifdef CONFIG_P2P
8042	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
8043		if (p2p_ctrl_find(wpa_s, buf + 8))
8044			reply_len = -1;
8045	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
8046		if (p2p_ctrl_find(wpa_s, ""))
8047			reply_len = -1;
8048	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
8049		wpas_p2p_stop_find(wpa_s);
8050	} else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
8051		if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
8052			reply_len = -1;
8053	} else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
8054		if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
8055			reply_len = -1;
8056	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
8057		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
8058					     reply_size);
8059	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
8060		if (p2p_ctrl_listen(wpa_s, buf + 11))
8061			reply_len = -1;
8062	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
8063		if (p2p_ctrl_listen(wpa_s, ""))
8064			reply_len = -1;
8065	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
8066		if (wpas_p2p_group_remove(wpa_s, buf + 17))
8067			reply_len = -1;
8068	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
8069		if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0))
8070			reply_len = -1;
8071	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
8072		if (p2p_ctrl_group_add(wpa_s, buf + 14))
8073			reply_len = -1;
8074	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
8075		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
8076			reply_len = -1;
8077	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
8078		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
8079	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
8080		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
8081						   reply_size);
8082	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
8083		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
8084			reply_len = -1;
8085	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
8086		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
8087			reply_len = -1;
8088	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
8089		wpas_p2p_sd_service_update(wpa_s);
8090	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
8091		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
8092			reply_len = -1;
8093	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
8094		wpas_p2p_service_flush(wpa_s);
8095	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
8096		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
8097			reply_len = -1;
8098	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
8099		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
8100			reply_len = -1;
8101	} else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
8102		if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
8103			reply_len = -1;
8104	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
8105		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
8106			reply_len = -1;
8107	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
8108		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
8109			reply_len = -1;
8110	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
8111		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
8112					      reply_size);
8113	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
8114		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
8115			reply_len = -1;
8116	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
8117		p2p_ctrl_flush(wpa_s);
8118	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
8119		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
8120			reply_len = -1;
8121	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
8122		if (wpas_p2p_cancel(wpa_s))
8123			reply_len = -1;
8124	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
8125		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
8126			reply_len = -1;
8127	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
8128		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
8129			reply_len = -1;
8130	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
8131		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
8132			reply_len = -1;
8133	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
8134		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
8135			reply_len = -1;
8136	} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
8137		if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
8138			reply_len = -1;
8139#endif /* CONFIG_P2P */
8140#ifdef CONFIG_WIFI_DISPLAY
8141	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
8142		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
8143			reply_len = -1;
8144	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
8145		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
8146						     reply, reply_size);
8147#endif /* CONFIG_WIFI_DISPLAY */
8148#ifdef CONFIG_INTERWORKING
8149	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
8150		if (interworking_fetch_anqp(wpa_s) < 0)
8151			reply_len = -1;
8152	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
8153		interworking_stop_fetch_anqp(wpa_s);
8154	} else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
8155		if (ctrl_interworking_select(wpa_s, NULL) < 0)
8156			reply_len = -1;
8157	} else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
8158		if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
8159			reply_len = -1;
8160	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
8161		if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
8162			reply_len = -1;
8163	} else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
8164		int id;
8165
8166		id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
8167		if (id < 0)
8168			reply_len = -1;
8169		else {
8170			reply_len = os_snprintf(reply, reply_size, "%d\n", id);
8171			if (os_snprintf_error(reply_size, reply_len))
8172				reply_len = -1;
8173		}
8174	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
8175		if (get_anqp(wpa_s, buf + 9) < 0)
8176			reply_len = -1;
8177	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
8178		if (gas_request(wpa_s, buf + 12) < 0)
8179			reply_len = -1;
8180	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
8181		reply_len = gas_response_get(wpa_s, buf + 17, reply,
8182					     reply_size);
8183#endif /* CONFIG_INTERWORKING */
8184#ifdef CONFIG_HS20
8185	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
8186		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
8187			reply_len = -1;
8188	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
8189		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
8190			reply_len = -1;
8191	} else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
8192		if (hs20_icon_request(wpa_s, buf + 18) < 0)
8193			reply_len = -1;
8194	} else if (os_strcmp(buf, "FETCH_OSU") == 0) {
8195		if (hs20_fetch_osu(wpa_s) < 0)
8196			reply_len = -1;
8197	} else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
8198		hs20_cancel_fetch_osu(wpa_s);
8199#endif /* CONFIG_HS20 */
8200	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
8201	{
8202		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
8203			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
8204			reply_len = -1;
8205		else {
8206			/*
8207			 * Notify response from timeout to allow the control
8208			 * interface response to be sent first.
8209			 */
8210			eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
8211					       wpa_s, NULL);
8212		}
8213	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
8214		if (wpa_supplicant_reload_configuration(wpa_s))
8215			reply_len = -1;
8216	} else if (os_strcmp(buf, "TERMINATE") == 0) {
8217		wpa_supplicant_terminate_proc(wpa_s->global);
8218	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
8219		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
8220			reply_len = -1;
8221	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
8222		reply_len = wpa_supplicant_ctrl_iface_blacklist(
8223			wpa_s, buf + 9, reply, reply_size);
8224	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
8225		reply_len = wpa_supplicant_ctrl_iface_log_level(
8226			wpa_s, buf + 9, reply, reply_size);
8227	} else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
8228		reply_len = wpa_supplicant_ctrl_iface_list_networks(
8229			wpa_s, buf + 14, reply, reply_size);
8230	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
8231		reply_len = wpa_supplicant_ctrl_iface_list_networks(
8232			wpa_s, NULL, reply, reply_size);
8233	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
8234#ifdef CONFIG_SME
8235		wpa_s->sme.prev_bssid_set = 0;
8236#endif /* CONFIG_SME */
8237		wpa_s->reassociate = 0;
8238		wpa_s->disconnected = 1;
8239		wpa_supplicant_cancel_sched_scan(wpa_s);
8240		wpa_supplicant_cancel_scan(wpa_s);
8241		wpa_supplicant_deauthenticate(wpa_s,
8242					      WLAN_REASON_DEAUTH_LEAVING);
8243	} else if (os_strcmp(buf, "SCAN") == 0) {
8244		wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
8245	} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
8246		wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
8247	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
8248		reply_len = wpa_supplicant_ctrl_iface_scan_results(
8249			wpa_s, reply, reply_size);
8250	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
8251		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
8252			reply_len = -1;
8253	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
8254		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
8255			reply_len = -1;
8256	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
8257		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
8258			reply_len = -1;
8259	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
8260		reply_len = wpa_supplicant_ctrl_iface_add_network(
8261			wpa_s, reply, reply_size);
8262	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
8263		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
8264			reply_len = -1;
8265	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
8266		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
8267			reply_len = -1;
8268	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
8269		reply_len = wpa_supplicant_ctrl_iface_get_network(
8270			wpa_s, buf + 12, reply, reply_size);
8271	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
8272		if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12))
8273			reply_len = -1;
8274	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
8275		reply_len = wpa_supplicant_ctrl_iface_list_creds(
8276			wpa_s, reply, reply_size);
8277	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
8278		reply_len = wpa_supplicant_ctrl_iface_add_cred(
8279			wpa_s, reply, reply_size);
8280	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
8281		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
8282			reply_len = -1;
8283	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
8284		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
8285			reply_len = -1;
8286	} else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
8287		reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
8288							       reply,
8289							       reply_size);
8290#ifndef CONFIG_NO_CONFIG_WRITE
8291	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
8292		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
8293			reply_len = -1;
8294#endif /* CONFIG_NO_CONFIG_WRITE */
8295	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
8296		reply_len = wpa_supplicant_ctrl_iface_get_capability(
8297			wpa_s, buf + 15, reply, reply_size);
8298	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
8299		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
8300			reply_len = -1;
8301	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
8302		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
8303			reply_len = -1;
8304	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
8305		reply_len = wpa_supplicant_global_iface_list(
8306			wpa_s->global, reply, reply_size);
8307	} else if (os_strcmp(buf, "INTERFACES") == 0) {
8308		reply_len = wpa_supplicant_global_iface_interfaces(
8309			wpa_s->global, reply, reply_size);
8310	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
8311		reply_len = wpa_supplicant_ctrl_iface_bss(
8312			wpa_s, buf + 4, reply, reply_size);
8313#ifdef CONFIG_AP
8314	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
8315		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
8316	} else if (os_strncmp(buf, "STA ", 4) == 0) {
8317		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
8318					      reply_size);
8319	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
8320		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
8321						   reply_size);
8322	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
8323		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
8324			reply_len = -1;
8325	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
8326		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
8327			reply_len = -1;
8328	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
8329		if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
8330			reply_len = -1;
8331	} else if (os_strcmp(buf, "STOP_AP") == 0) {
8332		if (wpas_ap_stop_ap(wpa_s))
8333			reply_len = -1;
8334#endif /* CONFIG_AP */
8335	} else if (os_strcmp(buf, "SUSPEND") == 0) {
8336		wpas_notify_suspend(wpa_s->global);
8337	} else if (os_strcmp(buf, "RESUME") == 0) {
8338		wpas_notify_resume(wpa_s->global);
8339#ifdef CONFIG_TESTING_OPTIONS
8340	} else if (os_strcmp(buf, "DROP_SA") == 0) {
8341		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
8342#endif /* CONFIG_TESTING_OPTIONS */
8343	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
8344		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
8345			reply_len = -1;
8346	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
8347		wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
8348	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
8349		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
8350			reply_len = -1;
8351	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
8352		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
8353							       buf + 17))
8354			reply_len = -1;
8355	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
8356		wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
8357#ifdef CONFIG_TDLS
8358	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
8359		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
8360			reply_len = -1;
8361	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
8362		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
8363			reply_len = -1;
8364	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
8365		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
8366			reply_len = -1;
8367	} else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
8368		if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
8369							       buf + 17))
8370			reply_len = -1;
8371	} else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
8372		if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
8373								      buf + 24))
8374			reply_len = -1;
8375#endif /* CONFIG_TDLS */
8376	} else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
8377		reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
8378	} else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
8379		if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
8380			reply_len = -1;
8381	} else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
8382		if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
8383			reply_len = -1;
8384	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
8385		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
8386						       reply_size);
8387	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
8388		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
8389						       reply_size);
8390#ifdef CONFIG_AUTOSCAN
8391	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
8392		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
8393			reply_len = -1;
8394#endif /* CONFIG_AUTOSCAN */
8395#ifdef ANDROID
8396	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
8397		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
8398						      reply_size);
8399#endif /* ANDROID */
8400	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
8401		reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
8402						      reply_size);
8403	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
8404		pmksa_cache_clear_current(wpa_s->wpa);
8405		eapol_sm_request_reauth(wpa_s->eapol);
8406#ifdef CONFIG_WNM
8407	} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
8408		if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
8409			reply_len = -1;
8410	} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
8411		if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
8412				reply_len = -1;
8413#endif /* CONFIG_WNM */
8414	} else if (os_strcmp(buf, "FLUSH") == 0) {
8415		wpa_supplicant_ctrl_iface_flush(wpa_s);
8416	} else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
8417		reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
8418						 reply_size);
8419#ifdef CONFIG_TESTING_OPTIONS
8420	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
8421		if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
8422			reply_len = -1;
8423	} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
8424		wpas_ctrl_iface_mgmt_tx_done(wpa_s);
8425	} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
8426		if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
8427			reply_len = -1;
8428	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
8429		if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
8430			reply_len = -1;
8431	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
8432		if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
8433			reply_len = -1;
8434	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
8435		if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
8436			reply_len = -1;
8437	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
8438		if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
8439			reply_len = -1;
8440	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
8441		if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
8442			reply_len = -1;
8443	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
8444		reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
8445#endif /* CONFIG_TESTING_OPTIONS */
8446	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
8447		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
8448			reply_len = -1;
8449	} else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
8450		reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
8451						      reply_size);
8452	} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
8453		if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
8454			reply_len = -1;
8455	} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
8456		if (wpas_ctrl_iface_send_neigbor_rep(wpa_s, buf + 20))
8457			reply_len = -1;
8458	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
8459		wpas_ctrl_iface_erp_flush(wpa_s);
8460	} else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
8461		if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
8462			reply_len = -1;
8463	} else {
8464		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
8465		reply_len = 16;
8466	}
8467
8468	if (reply_len < 0) {
8469		os_memcpy(reply, "FAIL\n", 5);
8470		reply_len = 5;
8471	}
8472
8473	*resp_len = reply_len;
8474	return reply;
8475}
8476
8477
8478static int wpa_supplicant_global_iface_add(struct wpa_global *global,
8479					   char *cmd)
8480{
8481	struct wpa_interface iface;
8482	char *pos;
8483
8484	/*
8485	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
8486	 * TAB<bridge_ifname>
8487	 */
8488	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
8489
8490	os_memset(&iface, 0, sizeof(iface));
8491
8492	do {
8493		iface.ifname = pos = cmd;
8494		pos = os_strchr(pos, '\t');
8495		if (pos)
8496			*pos++ = '\0';
8497		if (iface.ifname[0] == '\0')
8498			return -1;
8499		if (pos == NULL)
8500			break;
8501
8502		iface.confname = pos;
8503		pos = os_strchr(pos, '\t');
8504		if (pos)
8505			*pos++ = '\0';
8506		if (iface.confname[0] == '\0')
8507			iface.confname = NULL;
8508		if (pos == NULL)
8509			break;
8510
8511		iface.driver = pos;
8512		pos = os_strchr(pos, '\t');
8513		if (pos)
8514			*pos++ = '\0';
8515		if (iface.driver[0] == '\0')
8516			iface.driver = NULL;
8517		if (pos == NULL)
8518			break;
8519
8520		iface.ctrl_interface = pos;
8521		pos = os_strchr(pos, '\t');
8522		if (pos)
8523			*pos++ = '\0';
8524		if (iface.ctrl_interface[0] == '\0')
8525			iface.ctrl_interface = NULL;
8526		if (pos == NULL)
8527			break;
8528
8529		iface.driver_param = pos;
8530		pos = os_strchr(pos, '\t');
8531		if (pos)
8532			*pos++ = '\0';
8533		if (iface.driver_param[0] == '\0')
8534			iface.driver_param = NULL;
8535		if (pos == NULL)
8536			break;
8537
8538		iface.bridge_ifname = pos;
8539		pos = os_strchr(pos, '\t');
8540		if (pos)
8541			*pos++ = '\0';
8542		if (iface.bridge_ifname[0] == '\0')
8543			iface.bridge_ifname = NULL;
8544		if (pos == NULL)
8545			break;
8546	} while (0);
8547
8548	if (wpa_supplicant_get_iface(global, iface.ifname))
8549		return -1;
8550
8551	return wpa_supplicant_add_iface(global, &iface, NULL) ? 0 : -1;
8552}
8553
8554
8555static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
8556					      char *cmd)
8557{
8558	struct wpa_supplicant *wpa_s;
8559
8560	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
8561
8562	wpa_s = wpa_supplicant_get_iface(global, cmd);
8563	if (wpa_s == NULL)
8564		return -1;
8565	return wpa_supplicant_remove_iface(global, wpa_s, 0);
8566}
8567
8568
8569static void wpa_free_iface_info(struct wpa_interface_info *iface)
8570{
8571	struct wpa_interface_info *prev;
8572
8573	while (iface) {
8574		prev = iface;
8575		iface = iface->next;
8576
8577		os_free(prev->ifname);
8578		os_free(prev->desc);
8579		os_free(prev);
8580	}
8581}
8582
8583
8584static int wpa_supplicant_global_iface_list(struct wpa_global *global,
8585					    char *buf, int len)
8586{
8587	int i, res;
8588	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
8589	char *pos, *end;
8590
8591	for (i = 0; wpa_drivers[i]; i++) {
8592		struct wpa_driver_ops *drv = wpa_drivers[i];
8593		if (drv->get_interfaces == NULL)
8594			continue;
8595		tmp = drv->get_interfaces(global->drv_priv[i]);
8596		if (tmp == NULL)
8597			continue;
8598
8599		if (last == NULL)
8600			iface = last = tmp;
8601		else
8602			last->next = tmp;
8603		while (last->next)
8604			last = last->next;
8605	}
8606
8607	pos = buf;
8608	end = buf + len;
8609	for (tmp = iface; tmp; tmp = tmp->next) {
8610		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
8611				  tmp->drv_name, tmp->ifname,
8612				  tmp->desc ? tmp->desc : "");
8613		if (os_snprintf_error(end - pos, res)) {
8614			*pos = '\0';
8615			break;
8616		}
8617		pos += res;
8618	}
8619
8620	wpa_free_iface_info(iface);
8621
8622	return pos - buf;
8623}
8624
8625
8626static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
8627						  char *buf, int len)
8628{
8629	int res;
8630	char *pos, *end;
8631	struct wpa_supplicant *wpa_s;
8632
8633	wpa_s = global->ifaces;
8634	pos = buf;
8635	end = buf + len;
8636
8637	while (wpa_s) {
8638		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
8639		if (os_snprintf_error(end - pos, res)) {
8640			*pos = '\0';
8641			break;
8642		}
8643		pos += res;
8644		wpa_s = wpa_s->next;
8645	}
8646	return pos - buf;
8647}
8648
8649
8650static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
8651					    const char *ifname,
8652					    char *cmd, size_t *resp_len)
8653{
8654	struct wpa_supplicant *wpa_s;
8655
8656	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8657		if (os_strcmp(ifname, wpa_s->ifname) == 0)
8658			break;
8659	}
8660
8661	if (wpa_s == NULL) {
8662		char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
8663		if (resp)
8664			*resp_len = os_strlen(resp);
8665		else
8666			*resp_len = 1;
8667		return resp;
8668	}
8669
8670	return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
8671}
8672
8673
8674static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
8675					       char *buf, size_t *resp_len)
8676{
8677#ifdef CONFIG_P2P
8678	static const char * cmd[] = {
8679		"LIST_NETWORKS",
8680		"P2P_FIND",
8681		"P2P_STOP_FIND",
8682		"P2P_LISTEN",
8683		"P2P_GROUP_ADD",
8684		"P2P_GET_PASSPHRASE",
8685		"P2P_SERVICE_UPDATE",
8686		"P2P_SERVICE_FLUSH",
8687		"P2P_FLUSH",
8688		"P2P_CANCEL",
8689		"P2P_PRESENCE_REQ",
8690		"P2P_EXT_LISTEN",
8691		NULL
8692	};
8693	static const char * prefix[] = {
8694#ifdef ANDROID
8695		"DRIVER ",
8696#endif /* ANDROID */
8697		"GET_NETWORK ",
8698		"REMOVE_NETWORK ",
8699		"P2P_FIND ",
8700		"P2P_CONNECT ",
8701		"P2P_LISTEN ",
8702		"P2P_GROUP_REMOVE ",
8703		"P2P_GROUP_ADD ",
8704		"P2P_PROV_DISC ",
8705		"P2P_SERV_DISC_REQ ",
8706		"P2P_SERV_DISC_CANCEL_REQ ",
8707		"P2P_SERV_DISC_RESP ",
8708		"P2P_SERV_DISC_EXTERNAL ",
8709		"P2P_SERVICE_ADD ",
8710		"P2P_SERVICE_DEL ",
8711		"P2P_SERVICE_REP ",
8712		"P2P_REJECT ",
8713		"P2P_INVITE ",
8714		"P2P_PEER ",
8715		"P2P_SET ",
8716		"P2P_UNAUTHORIZE ",
8717		"P2P_PRESENCE_REQ ",
8718		"P2P_EXT_LISTEN ",
8719		"P2P_REMOVE_CLIENT ",
8720		"WPS_NFC_TOKEN ",
8721		"WPS_NFC_TAG_READ ",
8722		"NFC_GET_HANDOVER_SEL ",
8723		"NFC_GET_HANDOVER_REQ ",
8724		"NFC_REPORT_HANDOVER ",
8725		"P2P_ASP_PROVISION ",
8726		"P2P_ASP_PROVISION_RESP ",
8727		NULL
8728	};
8729	int found = 0;
8730	int i;
8731
8732	if (global->p2p_init_wpa_s == NULL)
8733		return NULL;
8734
8735	for (i = 0; !found && cmd[i]; i++) {
8736		if (os_strcmp(buf, cmd[i]) == 0)
8737			found = 1;
8738	}
8739
8740	for (i = 0; !found && prefix[i]; i++) {
8741		if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
8742			found = 1;
8743	}
8744
8745	if (found)
8746		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
8747							 buf, resp_len);
8748#endif /* CONFIG_P2P */
8749	return NULL;
8750}
8751
8752
8753static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
8754					       char *buf, size_t *resp_len)
8755{
8756#ifdef CONFIG_WIFI_DISPLAY
8757	if (global->p2p_init_wpa_s == NULL)
8758		return NULL;
8759	if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
8760	    os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
8761		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
8762							 buf, resp_len);
8763#endif /* CONFIG_WIFI_DISPLAY */
8764	return NULL;
8765}
8766
8767
8768static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
8769					   char *buf, size_t *resp_len)
8770{
8771	char *ret;
8772
8773	ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
8774	if (ret)
8775		return ret;
8776
8777	ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
8778	if (ret)
8779		return ret;
8780
8781	return NULL;
8782}
8783
8784
8785static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
8786{
8787	char *value;
8788
8789	value = os_strchr(cmd, ' ');
8790	if (value == NULL)
8791		return -1;
8792	*value++ = '\0';
8793
8794	wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
8795
8796#ifdef CONFIG_WIFI_DISPLAY
8797	if (os_strcasecmp(cmd, "wifi_display") == 0) {
8798		wifi_display_enable(global, !!atoi(value));
8799		return 0;
8800	}
8801#endif /* CONFIG_WIFI_DISPLAY */
8802
8803	/* Restore cmd to its original value to allow redirection */
8804	value[-1] = ' ';
8805
8806	return -1;
8807}
8808
8809
8810#ifndef CONFIG_NO_CONFIG_WRITE
8811static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
8812{
8813	int ret = 0, saved = 0;
8814	struct wpa_supplicant *wpa_s;
8815
8816	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8817		if (!wpa_s->conf->update_config) {
8818			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
8819			continue;
8820		}
8821
8822		if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
8823			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
8824			ret = 1;
8825		} else {
8826			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
8827			saved++;
8828		}
8829	}
8830
8831	if (!saved && !ret) {
8832		wpa_dbg(wpa_s, MSG_DEBUG,
8833			"CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
8834		ret = 1;
8835	}
8836
8837	return ret;
8838}
8839#endif /* CONFIG_NO_CONFIG_WRITE */
8840
8841
8842static int wpas_global_ctrl_iface_status(struct wpa_global *global,
8843					 char *buf, size_t buflen)
8844{
8845	char *pos, *end;
8846	int ret;
8847	struct wpa_supplicant *wpa_s;
8848
8849	pos = buf;
8850	end = buf + buflen;
8851
8852#ifdef CONFIG_P2P
8853	if (global->p2p && !global->p2p_disabled) {
8854		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
8855				  "\n"
8856				  "p2p_state=%s\n",
8857				  MAC2STR(global->p2p_dev_addr),
8858				  p2p_get_state_txt(global->p2p));
8859		if (os_snprintf_error(end - pos, ret))
8860			return pos - buf;
8861		pos += ret;
8862	} else if (global->p2p) {
8863		ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
8864		if (os_snprintf_error(end - pos, ret))
8865			return pos - buf;
8866		pos += ret;
8867	}
8868#endif /* CONFIG_P2P */
8869
8870#ifdef CONFIG_WIFI_DISPLAY
8871	ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
8872			  !!global->wifi_display);
8873	if (os_snprintf_error(end - pos, ret))
8874		return pos - buf;
8875	pos += ret;
8876#endif /* CONFIG_WIFI_DISPLAY */
8877
8878	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8879		ret = os_snprintf(pos, end - pos, "ifname=%s\n"
8880				  "address=" MACSTR "\n",
8881				  wpa_s->ifname, MAC2STR(wpa_s->own_addr));
8882		if (os_snprintf_error(end - pos, ret))
8883			return pos - buf;
8884		pos += ret;
8885	}
8886
8887	return pos - buf;
8888}
8889
8890
8891char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
8892						char *buf, size_t *resp_len)
8893{
8894	char *reply;
8895	const int reply_size = 2048;
8896	int reply_len;
8897	int level = MSG_DEBUG;
8898
8899	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
8900		char *pos = os_strchr(buf + 7, ' ');
8901		if (pos) {
8902			*pos++ = '\0';
8903			return wpas_global_ctrl_iface_ifname(global,
8904							     buf + 7, pos,
8905							     resp_len);
8906		}
8907	}
8908
8909	reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
8910	if (reply)
8911		return reply;
8912
8913	if (os_strcmp(buf, "PING") == 0)
8914		level = MSG_EXCESSIVE;
8915	wpa_hexdump_ascii(level, "RX global ctrl_iface",
8916			  (const u8 *) buf, os_strlen(buf));
8917
8918	reply = os_malloc(reply_size);
8919	if (reply == NULL) {
8920		*resp_len = 1;
8921		return NULL;
8922	}
8923
8924	os_memcpy(reply, "OK\n", 3);
8925	reply_len = 3;
8926
8927	if (os_strcmp(buf, "PING") == 0) {
8928		os_memcpy(reply, "PONG\n", 5);
8929		reply_len = 5;
8930	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
8931		if (wpa_supplicant_global_iface_add(global, buf + 14))
8932			reply_len = -1;
8933	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
8934		if (wpa_supplicant_global_iface_remove(global, buf + 17))
8935			reply_len = -1;
8936	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
8937		reply_len = wpa_supplicant_global_iface_list(
8938			global, reply, reply_size);
8939	} else if (os_strcmp(buf, "INTERFACES") == 0) {
8940		reply_len = wpa_supplicant_global_iface_interfaces(
8941			global, reply, reply_size);
8942	} else if (os_strcmp(buf, "TERMINATE") == 0) {
8943		wpa_supplicant_terminate_proc(global);
8944	} else if (os_strcmp(buf, "SUSPEND") == 0) {
8945		wpas_notify_suspend(global);
8946	} else if (os_strcmp(buf, "RESUME") == 0) {
8947		wpas_notify_resume(global);
8948	} else if (os_strncmp(buf, "SET ", 4) == 0) {
8949		if (wpas_global_ctrl_iface_set(global, buf + 4)) {
8950#ifdef CONFIG_P2P
8951			if (global->p2p_init_wpa_s) {
8952				os_free(reply);
8953				/* Check if P2P redirection would work for this
8954				 * command. */
8955				return wpa_supplicant_ctrl_iface_process(
8956					global->p2p_init_wpa_s,
8957					buf, resp_len);
8958			}
8959#endif /* CONFIG_P2P */
8960			reply_len = -1;
8961		}
8962#ifndef CONFIG_NO_CONFIG_WRITE
8963	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
8964		if (wpas_global_ctrl_iface_save_config(global))
8965			reply_len = -1;
8966#endif /* CONFIG_NO_CONFIG_WRITE */
8967	} else if (os_strcmp(buf, "STATUS") == 0) {
8968		reply_len = wpas_global_ctrl_iface_status(global, reply,
8969							  reply_size);
8970#ifdef CONFIG_MODULE_TESTS
8971	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
8972		int wpas_module_tests(void);
8973		if (wpas_module_tests() < 0)
8974			reply_len = -1;
8975#endif /* CONFIG_MODULE_TESTS */
8976	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
8977		if (wpa_debug_reopen_file() < 0)
8978			reply_len = -1;
8979	} else {
8980		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
8981		reply_len = 16;
8982	}
8983
8984	if (reply_len < 0) {
8985		os_memcpy(reply, "FAIL\n", 5);
8986		reply_len = 5;
8987	}
8988
8989	*resp_len = reply_len;
8990	return reply;
8991}
8992