1/*
2 * WPA Supplicant / Control interface (shared code for all backends)
3 * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10#ifdef CONFIG_TESTING_OPTIONS
11#include <netinet/ip.h>
12#endif /* CONFIG_TESTING_OPTIONS */
13
14#ifndef __NetBSD__
15#include <net/ethernet.h>
16#endif
17#include "utils/common.h"
18#include "utils/eloop.h"
19#include "utils/uuid.h"
20#include "utils/module_tests.h"
21#include "common/version.h"
22#include "common/ieee802_11_defs.h"
23#include "common/ieee802_11_common.h"
24#include "common/wpa_ctrl.h"
25#ifdef CONFIG_DPP
26#include "common/dpp.h"
27#endif /* CONFIG_DPP */
28#include "crypto/tls.h"
29#include "ap/hostapd.h"
30#include "eap_peer/eap.h"
31#include "eapol_supp/eapol_supp_sm.h"
32#include "rsn_supp/wpa.h"
33#include "rsn_supp/preauth.h"
34#include "rsn_supp/pmksa_cache.h"
35#include "l2_packet/l2_packet.h"
36#include "wps/wps.h"
37#include "fst/fst.h"
38#include "fst/fst_ctrl_iface.h"
39#include "config.h"
40#include "wpa_supplicant_i.h"
41#include "driver_i.h"
42#include "wps_supplicant.h"
43#include "ibss_rsn.h"
44#include "ap.h"
45#include "p2p_supplicant.h"
46#include "p2p/p2p.h"
47#include "hs20_supplicant.h"
48#include "wifi_display.h"
49#include "notify.h"
50#include "bss.h"
51#include "scan.h"
52#include "ctrl_iface.h"
53#include "interworking.h"
54#include "blacklist.h"
55#include "autoscan.h"
56#include "wnm_sta.h"
57#include "offchannel.h"
58#include "drivers/driver.h"
59#include "mesh.h"
60#include "dpp_supplicant.h"
61#include "sme.h"
62
63static int wpa_supplicant_global_iface_list(struct wpa_global *global,
64					    char *buf, int len);
65static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
66						  const char *input,
67						  char *buf, int len);
68static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
69					char *val);
70
71
72static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
73{
74	char *pos;
75	u8 addr[ETH_ALEN], *filter = NULL, *n;
76	size_t count = 0;
77
78	pos = val;
79	while (pos) {
80		if (*pos == '\0')
81			break;
82		if (hwaddr_aton(pos, addr)) {
83			os_free(filter);
84			return -1;
85		}
86		n = os_realloc_array(filter, count + 1, ETH_ALEN);
87		if (n == NULL) {
88			os_free(filter);
89			return -1;
90		}
91		filter = n;
92		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
93		count++;
94
95		pos = os_strchr(pos, ' ');
96		if (pos)
97			pos++;
98	}
99
100	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
101	os_free(wpa_s->bssid_filter);
102	wpa_s->bssid_filter = filter;
103	wpa_s->bssid_filter_count = count;
104
105	return 0;
106}
107
108
109static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
110{
111	char *pos;
112	u8 addr[ETH_ALEN], *bssid = NULL, *n;
113	struct wpa_ssid_value *ssid = NULL, *ns;
114	size_t count = 0, ssid_count = 0;
115	struct wpa_ssid *c;
116
117	/*
118	 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
119	 * SSID_SPEC ::= ssid <SSID_HEX>
120	 * BSSID_SPEC ::= bssid <BSSID_HEX>
121	 */
122
123	pos = val;
124	while (pos) {
125		if (*pos == '\0')
126			break;
127		if (os_strncmp(pos, "bssid ", 6) == 0) {
128			int res;
129			pos += 6;
130			res = hwaddr_aton2(pos, addr);
131			if (res < 0) {
132				os_free(ssid);
133				os_free(bssid);
134				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
135					   "BSSID value '%s'", pos);
136				return -1;
137			}
138			pos += res;
139			n = os_realloc_array(bssid, count + 1, ETH_ALEN);
140			if (n == NULL) {
141				os_free(ssid);
142				os_free(bssid);
143				return -1;
144			}
145			bssid = n;
146			os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
147			count++;
148		} else if (os_strncmp(pos, "ssid ", 5) == 0) {
149			char *end;
150			pos += 5;
151
152			end = pos;
153			while (*end) {
154				if (*end == '\0' || *end == ' ')
155					break;
156				end++;
157			}
158
159			ns = os_realloc_array(ssid, ssid_count + 1,
160					      sizeof(struct wpa_ssid_value));
161			if (ns == NULL) {
162				os_free(ssid);
163				os_free(bssid);
164				return -1;
165			}
166			ssid = ns;
167
168			if ((end - pos) & 0x01 ||
169			    end - pos > 2 * SSID_MAX_LEN ||
170			    hexstr2bin(pos, ssid[ssid_count].ssid,
171				       (end - pos) / 2) < 0) {
172				os_free(ssid);
173				os_free(bssid);
174				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
175					   "SSID value '%s'", pos);
176				return -1;
177			}
178			ssid[ssid_count].ssid_len = (end - pos) / 2;
179			wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
180					  ssid[ssid_count].ssid,
181					  ssid[ssid_count].ssid_len);
182			ssid_count++;
183			pos = end;
184		} else {
185			wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
186				   "'%s'", pos);
187			os_free(ssid);
188			os_free(bssid);
189			return -1;
190		}
191
192		pos = os_strchr(pos, ' ');
193		if (pos)
194			pos++;
195	}
196
197	wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
198	os_free(wpa_s->disallow_aps_bssid);
199	wpa_s->disallow_aps_bssid = bssid;
200	wpa_s->disallow_aps_bssid_count = count;
201
202	wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
203	os_free(wpa_s->disallow_aps_ssid);
204	wpa_s->disallow_aps_ssid = ssid;
205	wpa_s->disallow_aps_ssid_count = ssid_count;
206
207	if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
208		return 0;
209
210	c = wpa_s->current_ssid;
211	if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
212		return 0;
213
214	if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
215	    !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
216		return 0;
217
218	wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
219		   "because current AP was marked disallowed");
220
221#ifdef CONFIG_SME
222	wpa_s->sme.prev_bssid_set = 0;
223#endif /* CONFIG_SME */
224	wpa_s->reassociate = 1;
225	wpa_s->own_disconnect_req = 1;
226	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
227	wpa_supplicant_req_scan(wpa_s, 0, 0);
228
229	return 0;
230}
231
232
233#ifndef CONFIG_NO_CONFIG_BLOBS
234static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
235{
236	char *name = pos;
237	struct wpa_config_blob *blob;
238	size_t len;
239
240	pos = os_strchr(pos, ' ');
241	if (pos == NULL)
242		return -1;
243	*pos++ = '\0';
244	len = os_strlen(pos);
245	if (len & 1)
246		return -1;
247
248	wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
249	blob = os_zalloc(sizeof(*blob));
250	if (blob == NULL)
251		return -1;
252	blob->name = os_strdup(name);
253	blob->data = os_malloc(len / 2);
254	if (blob->name == NULL || blob->data == NULL) {
255		wpa_config_free_blob(blob);
256		return -1;
257	}
258
259	if (hexstr2bin(pos, blob->data, len / 2) < 0) {
260		wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
261		wpa_config_free_blob(blob);
262		return -1;
263	}
264	blob->len = len / 2;
265
266	wpa_config_set_blob(wpa_s->conf, blob);
267
268	return 0;
269}
270#endif /* CONFIG_NO_CONFIG_BLOBS */
271
272
273static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
274{
275	char *params;
276	char *pos;
277	int *freqs = NULL;
278	int ret;
279
280	if (atoi(cmd)) {
281		params = os_strchr(cmd, ' ');
282		os_free(wpa_s->manual_sched_scan_freqs);
283		if (params) {
284			params++;
285			pos = os_strstr(params, "freq=");
286			if (pos)
287				freqs = freq_range_to_channel_list(wpa_s,
288								   pos + 5);
289		}
290		wpa_s->manual_sched_scan_freqs = freqs;
291		ret = wpas_start_pno(wpa_s);
292	} else {
293		ret = wpas_stop_pno(wpa_s);
294	}
295	return ret;
296}
297
298
299static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
300{
301	union wpa_event_data event;
302
303	if (os_strcmp(band, "AUTO") == 0)
304		wpa_s->setband = WPA_SETBAND_AUTO;
305	else if (os_strcmp(band, "5G") == 0)
306		wpa_s->setband = WPA_SETBAND_5G;
307	else if (os_strcmp(band, "2G") == 0)
308		wpa_s->setband = WPA_SETBAND_2G;
309	else
310		return -1;
311
312	if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
313		os_memset(&event, 0, sizeof(event));
314		event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
315		event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
316		wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
317	}
318
319	return 0;
320}
321
322
323static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
324				   const char *cmd)
325{
326	struct wpabuf *lci;
327
328	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
329		wpabuf_free(wpa_s->lci);
330		wpa_s->lci = NULL;
331		return 0;
332	}
333
334	lci = wpabuf_parse_bin(cmd);
335	if (!lci)
336		return -1;
337
338	if (os_get_reltime(&wpa_s->lci_time)) {
339		wpabuf_free(lci);
340		return -1;
341	}
342
343	wpabuf_free(wpa_s->lci);
344	wpa_s->lci = lci;
345
346	return 0;
347}
348
349
350static int
351wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
352{
353	int relative_rssi;
354
355	if (os_strcmp(cmd, "disable") == 0) {
356		wpa_s->srp.relative_rssi_set = 0;
357		return 0;
358	}
359
360	relative_rssi = atoi(cmd);
361	if (relative_rssi < 0 || relative_rssi > 100)
362		return -1;
363	wpa_s->srp.relative_rssi = relative_rssi;
364	wpa_s->srp.relative_rssi_set = 1;
365	return 0;
366}
367
368
369static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
370					      const char *cmd)
371{
372	char *pos;
373	int adjust_rssi;
374
375	/* <band>:adjust_value */
376	pos = os_strchr(cmd, ':');
377	if (!pos)
378		return -1;
379	pos++;
380	adjust_rssi = atoi(pos);
381	if (adjust_rssi < -100 || adjust_rssi > 100)
382		return -1;
383
384	if (os_strncmp(cmd, "2G", 2) == 0)
385		wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
386	else if (os_strncmp(cmd, "5G", 2) == 0)
387		wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
388	else
389		return -1;
390
391	wpa_s->srp.relative_adjust_rssi = adjust_rssi;
392
393	return 0;
394}
395
396
397static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
398				   const char *cmd)
399{
400	struct wpabuf *ric_ies;
401
402	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
403		wpabuf_free(wpa_s->ric_ies);
404		wpa_s->ric_ies = NULL;
405		return 0;
406	}
407
408	ric_ies = wpabuf_parse_bin(cmd);
409	if (!ric_ies)
410		return -1;
411
412	wpabuf_free(wpa_s->ric_ies);
413	wpa_s->ric_ies = ric_ies;
414
415	return 0;
416}
417
418
419static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
420					 char *cmd)
421{
422	char *value;
423	int ret = 0;
424
425	value = os_strchr(cmd, ' ');
426	if (value == NULL)
427		return -1;
428	*value++ = '\0';
429
430	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
431	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
432		eapol_sm_configure(wpa_s->eapol,
433				   atoi(value), -1, -1, -1);
434	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
435		eapol_sm_configure(wpa_s->eapol,
436				   -1, atoi(value), -1, -1);
437	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
438		eapol_sm_configure(wpa_s->eapol,
439				   -1, -1, atoi(value), -1);
440	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
441		eapol_sm_configure(wpa_s->eapol,
442				   -1, -1, -1, atoi(value));
443	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
444		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
445				     atoi(value))) {
446			ret = -1;
447		} else {
448			value[-1] = '=';
449			wpa_config_process_global(wpa_s->conf, cmd, -1);
450		}
451	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
452		   0) {
453		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
454				     atoi(value))) {
455			ret = -1;
456		} else {
457			value[-1] = '=';
458			wpa_config_process_global(wpa_s->conf, cmd, -1);
459		}
460	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
461		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
462				     atoi(value))) {
463			ret = -1;
464		} else {
465			value[-1] = '=';
466			wpa_config_process_global(wpa_s->conf, cmd, -1);
467		}
468	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
469		wpa_s->wps_fragment_size = atoi(value);
470#ifdef CONFIG_WPS_TESTING
471	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
472		long int val;
473		val = strtol(value, NULL, 0);
474		if (val < 0 || val > 0xff) {
475			ret = -1;
476			wpa_printf(MSG_DEBUG, "WPS: Invalid "
477				   "wps_version_number %ld", val);
478		} else {
479			wps_version_number = val;
480			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
481				   "version %u.%u",
482				   (wps_version_number & 0xf0) >> 4,
483				   wps_version_number & 0x0f);
484		}
485	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
486		wps_testing_dummy_cred = atoi(value);
487		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
488			   wps_testing_dummy_cred);
489	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
490		wps_corrupt_pkhash = atoi(value);
491		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
492			   wps_corrupt_pkhash);
493	} else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
494		if (value[0] == '\0') {
495			wps_force_auth_types_in_use = 0;
496		} else {
497			wps_force_auth_types = strtol(value, NULL, 0);
498			wps_force_auth_types_in_use = 1;
499		}
500	} else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
501		if (value[0] == '\0') {
502			wps_force_encr_types_in_use = 0;
503		} else {
504			wps_force_encr_types = strtol(value, NULL, 0);
505			wps_force_encr_types_in_use = 1;
506		}
507#endif /* CONFIG_WPS_TESTING */
508	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
509		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
510			ret = -1;
511#ifdef CONFIG_TDLS
512#ifdef CONFIG_TDLS_TESTING
513	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
514		tdls_testing = strtol(value, NULL, 0);
515		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
516#endif /* CONFIG_TDLS_TESTING */
517	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
518		int disabled = atoi(value);
519		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
520		if (disabled) {
521			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
522				ret = -1;
523		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
524			ret = -1;
525		wpa_tdls_enable(wpa_s->wpa, !disabled);
526#endif /* CONFIG_TDLS */
527	} else if (os_strcasecmp(cmd, "pno") == 0) {
528		ret = wpas_ctrl_pno(wpa_s, value);
529	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
530		int disabled = atoi(value);
531		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
532			ret = -1;
533		else if (disabled)
534			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
535	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
536		if (os_strcmp(value, "disable") == 0)
537			wpa_s->set_sta_uapsd = 0;
538		else {
539			int be, bk, vi, vo;
540			char *pos;
541			/* format: BE,BK,VI,VO;max SP Length */
542			be = atoi(value);
543			pos = os_strchr(value, ',');
544			if (pos == NULL)
545				return -1;
546			pos++;
547			bk = atoi(pos);
548			pos = os_strchr(pos, ',');
549			if (pos == NULL)
550				return -1;
551			pos++;
552			vi = atoi(pos);
553			pos = os_strchr(pos, ',');
554			if (pos == NULL)
555				return -1;
556			pos++;
557			vo = atoi(pos);
558			/* ignore max SP Length for now */
559
560			wpa_s->set_sta_uapsd = 1;
561			wpa_s->sta_uapsd = 0;
562			if (be)
563				wpa_s->sta_uapsd |= BIT(0);
564			if (bk)
565				wpa_s->sta_uapsd |= BIT(1);
566			if (vi)
567				wpa_s->sta_uapsd |= BIT(2);
568			if (vo)
569				wpa_s->sta_uapsd |= BIT(3);
570		}
571	} else if (os_strcasecmp(cmd, "ps") == 0) {
572		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
573#ifdef CONFIG_WIFI_DISPLAY
574	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
575		int enabled = !!atoi(value);
576		if (enabled && !wpa_s->global->p2p)
577			ret = -1;
578		else
579			wifi_display_enable(wpa_s->global, enabled);
580#endif /* CONFIG_WIFI_DISPLAY */
581	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
582		ret = set_bssid_filter(wpa_s, value);
583	} else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
584		ret = set_disallow_aps(wpa_s, value);
585	} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
586		wpa_s->no_keep_alive = !!atoi(value);
587#ifdef CONFIG_DPP
588	} else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
589		os_free(wpa_s->dpp_configurator_params);
590		wpa_s->dpp_configurator_params = os_strdup(value);
591	} else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
592		wpa_s->dpp_init_max_tries = atoi(value);
593	} else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
594		wpa_s->dpp_init_retry_time = atoi(value);
595	} else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
596		wpa_s->dpp_resp_wait_time = atoi(value);
597	} else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
598		wpa_s->dpp_resp_max_tries = atoi(value);
599	} else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
600		wpa_s->dpp_resp_retry_time = atoi(value);
601#ifdef CONFIG_TESTING_OPTIONS
602	} else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
603		if (hwaddr_aton(value, dpp_pkex_own_mac_override))
604			ret = -1;
605	} else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
606		if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
607			ret = -1;
608	} else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
609		size_t hex_len = os_strlen(value);
610
611		if (hex_len >
612		    2 * sizeof(dpp_pkex_ephemeral_key_override))
613			ret = -1;
614		else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
615				    hex_len / 2))
616			ret = -1;
617		else
618			dpp_pkex_ephemeral_key_override_len = hex_len / 2;
619	} else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
620		size_t hex_len = os_strlen(value);
621
622		if (hex_len > 2 * sizeof(dpp_protocol_key_override))
623			ret = -1;
624		else if (hexstr2bin(value, dpp_protocol_key_override,
625				    hex_len / 2))
626			ret = -1;
627		else
628			dpp_protocol_key_override_len = hex_len / 2;
629	} else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
630		size_t hex_len = os_strlen(value);
631
632		if (hex_len > 2 * sizeof(dpp_nonce_override))
633			ret = -1;
634		else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
635			ret = -1;
636		else
637			dpp_nonce_override_len = hex_len / 2;
638#endif /* CONFIG_TESTING_OPTIONS */
639#endif /* CONFIG_DPP */
640#ifdef CONFIG_TESTING_OPTIONS
641	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
642		wpa_s->ext_mgmt_frame_handling = !!atoi(value);
643	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
644		wpa_s->ext_eapol_frame_io = !!atoi(value);
645#ifdef CONFIG_AP
646		if (wpa_s->ap_iface) {
647			wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
648				wpa_s->ext_eapol_frame_io;
649		}
650#endif /* CONFIG_AP */
651	} else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
652		wpa_s->extra_roc_dur = atoi(value);
653	} else if (os_strcasecmp(cmd, "test_failure") == 0) {
654		wpa_s->test_failure = atoi(value);
655	} else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
656		wpa_s->p2p_go_csa_on_inv = !!atoi(value);
657	} else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
658		wpa_s->ignore_auth_resp = !!atoi(value);
659	} else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
660		wpa_s->ignore_assoc_disallow = !!atoi(value);
661		wpa_drv_ignore_assoc_disallow(wpa_s,
662					      wpa_s->ignore_assoc_disallow);
663	} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
664		wpa_s->reject_btm_req_reason = atoi(value);
665	} else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
666		os_free(wpa_s->get_pref_freq_list_override);
667		if (!value[0])
668			wpa_s->get_pref_freq_list_override = NULL;
669		else
670			wpa_s->get_pref_freq_list_override = os_strdup(value);
671	} else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
672		wpabuf_free(wpa_s->sae_commit_override);
673		if (value[0] == '\0')
674			wpa_s->sae_commit_override = NULL;
675		else
676			wpa_s->sae_commit_override = wpabuf_parse_bin(value);
677#ifdef CONFIG_DPP
678	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
679		os_free(wpa_s->dpp_config_obj_override);
680		if (value[0] == '\0')
681			wpa_s->dpp_config_obj_override = NULL;
682		else
683			wpa_s->dpp_config_obj_override = os_strdup(value);
684	} else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
685		os_free(wpa_s->dpp_discovery_override);
686		if (value[0] == '\0')
687			wpa_s->dpp_discovery_override = NULL;
688		else
689			wpa_s->dpp_discovery_override = os_strdup(value);
690	} else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
691		os_free(wpa_s->dpp_groups_override);
692		if (value[0] == '\0')
693			wpa_s->dpp_groups_override = NULL;
694		else
695			wpa_s->dpp_groups_override = os_strdup(value);
696	} else if (os_strcasecmp(cmd,
697				 "dpp_ignore_netaccesskey_mismatch") == 0) {
698		wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
699	} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
700		dpp_test = atoi(value);
701#endif /* CONFIG_DPP */
702#endif /* CONFIG_TESTING_OPTIONS */
703#ifdef CONFIG_FILS
704	} else if (os_strcasecmp(cmd, "disable_fils") == 0) {
705		wpa_s->disable_fils = !!atoi(value);
706		wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
707		wpa_supplicant_set_default_scan_ies(wpa_s);
708#endif /* CONFIG_FILS */
709#ifndef CONFIG_NO_CONFIG_BLOBS
710	} else if (os_strcmp(cmd, "blob") == 0) {
711		ret = wpas_ctrl_set_blob(wpa_s, value);
712#endif /* CONFIG_NO_CONFIG_BLOBS */
713	} else if (os_strcasecmp(cmd, "setband") == 0) {
714		ret = wpas_ctrl_set_band(wpa_s, value);
715#ifdef CONFIG_MBO
716	} else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
717		ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
718		if (ret == 0) {
719			value[-1] = '=';
720			wpa_config_process_global(wpa_s->conf, cmd, -1);
721		}
722	} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
723		wpas_mbo_update_cell_capa(wpa_s, atoi(value));
724	} else if (os_strcasecmp(cmd, "oce") == 0) {
725		wpa_s->conf->oce = atoi(value);
726		if (wpa_s->conf->oce) {
727			if ((wpa_s->conf->oce & OCE_STA) &&
728			    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
729				wpa_s->enable_oce = OCE_STA;
730
731			if ((wpa_s->conf->oce & OCE_STA_CFON) &&
732			    (wpa_s->drv_flags &
733			     WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
734				/* TODO: Need to add STA-CFON support */
735				wpa_printf(MSG_ERROR,
736					   "OCE STA-CFON feature is not yet supported");
737				return -1;
738			}
739		} else {
740			wpa_s->enable_oce = 0;
741		}
742		wpa_supplicant_set_default_scan_ies(wpa_s);
743#endif /* CONFIG_MBO */
744	} else if (os_strcasecmp(cmd, "lci") == 0) {
745		ret = wpas_ctrl_iface_set_lci(wpa_s, value);
746	} else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
747		ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
748	} else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
749		ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
750	} else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
751		ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
752	} else if (os_strcasecmp(cmd, "ric_ies") == 0) {
753		ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
754	} else if (os_strcasecmp(cmd, "roaming") == 0) {
755		ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
756#ifdef CONFIG_WNM
757	} else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
758		struct wpabuf *elems;
759
760		elems = wpabuf_parse_bin(value);
761		if (!elems)
762			return -1;
763		wnm_set_coloc_intf_elems(wpa_s, elems);
764#endif /* CONFIG_WNM */
765	} else {
766		value[-1] = '=';
767		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
768		if (ret == 0)
769			wpa_supplicant_update_config(wpa_s);
770	}
771
772	return ret;
773}
774
775
776static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
777					 char *cmd, char *buf, size_t buflen)
778{
779	int res = -1;
780
781	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
782
783	if (os_strcmp(cmd, "version") == 0) {
784		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
785	} else if (os_strcasecmp(cmd, "country") == 0) {
786		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
787			res = os_snprintf(buf, buflen, "%c%c",
788					  wpa_s->conf->country[0],
789					  wpa_s->conf->country[1]);
790#ifdef CONFIG_WIFI_DISPLAY
791	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
792		int enabled;
793		if (wpa_s->global->p2p == NULL ||
794		    wpa_s->global->p2p_disabled)
795			enabled = 0;
796		else
797			enabled = wpa_s->global->wifi_display;
798		res = os_snprintf(buf, buflen, "%d", enabled);
799#endif /* CONFIG_WIFI_DISPLAY */
800#ifdef CONFIG_TESTING_GET_GTK
801	} else if (os_strcmp(cmd, "gtk") == 0) {
802		if (wpa_s->last_gtk_len == 0)
803			return -1;
804		res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
805				       wpa_s->last_gtk_len);
806		return res;
807#endif /* CONFIG_TESTING_GET_GTK */
808	} else if (os_strcmp(cmd, "tls_library") == 0) {
809		res = tls_get_library_version(buf, buflen);
810#ifdef CONFIG_TESTING_OPTIONS
811	} else if (os_strcmp(cmd, "anonce") == 0) {
812		return wpa_snprintf_hex(buf, buflen,
813					wpa_sm_get_anonce(wpa_s->wpa),
814					WPA_NONCE_LEN);
815#endif /* CONFIG_TESTING_OPTIONS */
816	} else {
817		res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
818	}
819
820	if (os_snprintf_error(buflen, res))
821		return -1;
822	return res;
823}
824
825
826#ifdef IEEE8021X_EAPOL
827static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
828					     char *addr)
829{
830	u8 bssid[ETH_ALEN];
831	struct wpa_ssid *ssid = wpa_s->current_ssid;
832
833	if (hwaddr_aton(addr, bssid)) {
834		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
835			   "'%s'", addr);
836		return -1;
837	}
838
839	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
840	rsn_preauth_deinit(wpa_s->wpa);
841	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
842		return -1;
843
844	return 0;
845}
846#endif /* IEEE8021X_EAPOL */
847
848
849#ifdef CONFIG_TDLS
850
851static int wpa_supplicant_ctrl_iface_tdls_discover(
852	struct wpa_supplicant *wpa_s, char *addr)
853{
854	u8 peer[ETH_ALEN];
855	int ret;
856
857	if (hwaddr_aton(addr, peer)) {
858		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
859			   "address '%s'", addr);
860		return -1;
861	}
862
863	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
864		   MAC2STR(peer));
865
866	if (wpa_tdls_is_external_setup(wpa_s->wpa))
867		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
868	else
869		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
870
871	return ret;
872}
873
874
875static int wpa_supplicant_ctrl_iface_tdls_setup(
876	struct wpa_supplicant *wpa_s, char *addr)
877{
878	u8 peer[ETH_ALEN];
879	int ret;
880
881	if (hwaddr_aton(addr, peer)) {
882		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
883			   "address '%s'", addr);
884		return -1;
885	}
886
887	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
888		   MAC2STR(peer));
889
890	if ((wpa_s->conf->tdls_external_control) &&
891	    wpa_tdls_is_external_setup(wpa_s->wpa))
892		return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
893
894	wpa_tdls_remove(wpa_s->wpa, peer);
895
896	if (wpa_tdls_is_external_setup(wpa_s->wpa))
897		ret = wpa_tdls_start(wpa_s->wpa, peer);
898	else
899		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
900
901	return ret;
902}
903
904
905static int wpa_supplicant_ctrl_iface_tdls_teardown(
906	struct wpa_supplicant *wpa_s, char *addr)
907{
908	u8 peer[ETH_ALEN];
909	int ret;
910
911	if (os_strcmp(addr, "*") == 0) {
912		/* remove everyone */
913		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
914		wpa_tdls_teardown_peers(wpa_s->wpa);
915		return 0;
916	}
917
918	if (hwaddr_aton(addr, peer)) {
919		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
920			   "address '%s'", addr);
921		return -1;
922	}
923
924	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
925		   MAC2STR(peer));
926
927	if ((wpa_s->conf->tdls_external_control) &&
928	    wpa_tdls_is_external_setup(wpa_s->wpa))
929		return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
930
931	if (wpa_tdls_is_external_setup(wpa_s->wpa))
932		ret = wpa_tdls_teardown_link(
933			wpa_s->wpa, peer,
934			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
935	else
936		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
937
938	return ret;
939}
940
941
942static int ctrl_iface_get_capability_tdls(
943	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
944{
945	int ret;
946
947	ret = os_snprintf(buf, buflen, "%s\n",
948			  wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
949			  (wpa_s->drv_flags &
950			   WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
951			   "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
952	if (os_snprintf_error(buflen, ret))
953		return -1;
954	return ret;
955}
956
957
958static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
959	struct wpa_supplicant *wpa_s, char *cmd)
960{
961	u8 peer[ETH_ALEN];
962	struct hostapd_freq_params freq_params;
963	u8 oper_class;
964	char *pos, *end;
965
966	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
967		wpa_printf(MSG_INFO,
968			   "tdls_chanswitch: Only supported with external setup");
969		return -1;
970	}
971
972	os_memset(&freq_params, 0, sizeof(freq_params));
973
974	pos = os_strchr(cmd, ' ');
975	if (pos == NULL)
976		return -1;
977	*pos++ = '\0';
978
979	oper_class = strtol(pos, &end, 10);
980	if (pos == end) {
981		wpa_printf(MSG_INFO,
982			   "tdls_chanswitch: Invalid op class provided");
983		return -1;
984	}
985
986	pos = end;
987	freq_params.freq = atoi(pos);
988	if (freq_params.freq == 0) {
989		wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
990		return -1;
991	}
992
993#define SET_FREQ_SETTING(str) \
994	do { \
995		const char *pos2 = os_strstr(pos, " " #str "="); \
996		if (pos2) { \
997			pos2 += sizeof(" " #str "=") - 1; \
998			freq_params.str = atoi(pos2); \
999		} \
1000	} while (0)
1001
1002	SET_FREQ_SETTING(center_freq1);
1003	SET_FREQ_SETTING(center_freq2);
1004	SET_FREQ_SETTING(bandwidth);
1005	SET_FREQ_SETTING(sec_channel_offset);
1006#undef SET_FREQ_SETTING
1007
1008	freq_params.ht_enabled = !!os_strstr(pos, " ht");
1009	freq_params.vht_enabled = !!os_strstr(pos, " vht");
1010
1011	if (hwaddr_aton(cmd, peer)) {
1012		wpa_printf(MSG_DEBUG,
1013			   "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1014			   cmd);
1015		return -1;
1016	}
1017
1018	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1019		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1020		   MAC2STR(peer), oper_class, freq_params.freq,
1021		   freq_params.center_freq1, freq_params.center_freq2,
1022		   freq_params.bandwidth, freq_params.sec_channel_offset,
1023		   freq_params.ht_enabled ? " HT" : "",
1024		   freq_params.vht_enabled ? " VHT" : "");
1025
1026	return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1027					   &freq_params);
1028}
1029
1030
1031static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1032	struct wpa_supplicant *wpa_s, char *cmd)
1033{
1034	u8 peer[ETH_ALEN];
1035
1036	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1037		wpa_printf(MSG_INFO,
1038			   "tdls_chanswitch: Only supported with external setup");
1039		return -1;
1040	}
1041
1042	if (hwaddr_aton(cmd, peer)) {
1043		wpa_printf(MSG_DEBUG,
1044			   "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1045			   cmd);
1046		return -1;
1047	}
1048
1049	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1050		   MAC2STR(peer));
1051
1052	return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1053}
1054
1055
1056static int wpa_supplicant_ctrl_iface_tdls_link_status(
1057	struct wpa_supplicant *wpa_s, const char *addr,
1058	char *buf, size_t buflen)
1059{
1060	u8 peer[ETH_ALEN];
1061	const char *tdls_status;
1062	int ret;
1063
1064	if (hwaddr_aton(addr, peer)) {
1065		wpa_printf(MSG_DEBUG,
1066			   "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1067			   addr);
1068		return -1;
1069	}
1070	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1071		   MAC2STR(peer));
1072
1073	tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1074	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1075	ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1076	if (os_snprintf_error(buflen, ret))
1077		return -1;
1078
1079	return ret;
1080}
1081
1082#endif /* CONFIG_TDLS */
1083
1084
1085static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1086{
1087	char *token, *context = NULL;
1088	struct wmm_ac_ts_setup_params params = {
1089		.tsid = 0xff,
1090		.direction = 0xff,
1091	};
1092
1093	while ((token = str_token(cmd, " ", &context))) {
1094		if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
1095		    sscanf(token, "up=%i", &params.user_priority) == 1 ||
1096		    sscanf(token, "nominal_msdu_size=%i",
1097			   &params.nominal_msdu_size) == 1 ||
1098		    sscanf(token, "mean_data_rate=%i",
1099			   &params.mean_data_rate) == 1 ||
1100		    sscanf(token, "min_phy_rate=%i",
1101			   &params.minimum_phy_rate) == 1 ||
1102		    sscanf(token, "sba=%i",
1103			   &params.surplus_bandwidth_allowance) == 1)
1104			continue;
1105
1106		if (os_strcasecmp(token, "downlink") == 0) {
1107			params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1108		} else if (os_strcasecmp(token, "uplink") == 0) {
1109			params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1110		} else if (os_strcasecmp(token, "bidi") == 0) {
1111			params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1112		} else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1113			params.fixed_nominal_msdu = 1;
1114		} else {
1115			wpa_printf(MSG_DEBUG,
1116				   "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1117				   token);
1118			return -1;
1119		}
1120
1121	}
1122
1123	return wpas_wmm_ac_addts(wpa_s, &params);
1124}
1125
1126
1127static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1128{
1129	u8 tsid = atoi(cmd);
1130
1131	return wpas_wmm_ac_delts(wpa_s, tsid);
1132}
1133
1134
1135#ifdef CONFIG_IEEE80211R
1136static int wpa_supplicant_ctrl_iface_ft_ds(
1137	struct wpa_supplicant *wpa_s, char *addr)
1138{
1139	u8 target_ap[ETH_ALEN];
1140	struct wpa_bss *bss;
1141	const u8 *mdie;
1142
1143	if (hwaddr_aton(addr, target_ap)) {
1144		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1145			   "address '%s'", addr);
1146		return -1;
1147	}
1148
1149	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1150
1151	bss = wpa_bss_get_bssid(wpa_s, target_ap);
1152	if (bss)
1153		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1154	else
1155		mdie = NULL;
1156
1157	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
1158}
1159#endif /* CONFIG_IEEE80211R */
1160
1161
1162#ifdef CONFIG_WPS
1163static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1164					     char *cmd)
1165{
1166	u8 bssid[ETH_ALEN], *_bssid = bssid;
1167#ifdef CONFIG_P2P
1168	u8 p2p_dev_addr[ETH_ALEN];
1169#endif /* CONFIG_P2P */
1170#ifdef CONFIG_AP
1171	u8 *_p2p_dev_addr = NULL;
1172#endif /* CONFIG_AP */
1173	char *pos;
1174	int multi_ap = 0;
1175
1176	if (!cmd || os_strcmp(cmd, "any") == 0 ||
1177	    os_strncmp(cmd, "any ", 4) == 0) {
1178		_bssid = NULL;
1179#ifdef CONFIG_P2P
1180	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1181		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1182			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1183				   "P2P Device Address '%s'",
1184				   cmd + 13);
1185			return -1;
1186		}
1187		_p2p_dev_addr = p2p_dev_addr;
1188#endif /* CONFIG_P2P */
1189	} else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1190		_bssid = NULL;
1191		multi_ap = atoi(cmd + 9);
1192	} else if (hwaddr_aton(cmd, bssid)) {
1193		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1194			   cmd);
1195		return -1;
1196	}
1197
1198	if (cmd) {
1199		pos = os_strstr(cmd, " multi_ap=");
1200		if (pos) {
1201			pos += 10;
1202			multi_ap = atoi(pos);
1203		}
1204	}
1205
1206#ifdef CONFIG_AP
1207	if (wpa_s->ap_iface)
1208		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1209#endif /* CONFIG_AP */
1210
1211	return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
1212}
1213
1214
1215static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1216					     char *cmd, char *buf,
1217					     size_t buflen)
1218{
1219	u8 bssid[ETH_ALEN], *_bssid = bssid;
1220	char *pin;
1221	int ret;
1222
1223	pin = os_strchr(cmd, ' ');
1224	if (pin)
1225		*pin++ = '\0';
1226
1227	if (os_strcmp(cmd, "any") == 0)
1228		_bssid = NULL;
1229	else if (os_strcmp(cmd, "get") == 0) {
1230		if (wps_generate_pin((unsigned int *) &ret) < 0)
1231			return -1;
1232		goto done;
1233	} else if (hwaddr_aton(cmd, bssid)) {
1234		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1235			   cmd);
1236		return -1;
1237	}
1238
1239#ifdef CONFIG_AP
1240	if (wpa_s->ap_iface) {
1241		int timeout = 0;
1242		char *pos;
1243
1244		if (pin) {
1245			pos = os_strchr(pin, ' ');
1246			if (pos) {
1247				*pos++ = '\0';
1248				timeout = atoi(pos);
1249			}
1250		}
1251
1252		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
1253						 buf, buflen, timeout);
1254	}
1255#endif /* CONFIG_AP */
1256
1257	if (pin) {
1258		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1259					 DEV_PW_DEFAULT);
1260		if (ret < 0)
1261			return -1;
1262		ret = os_snprintf(buf, buflen, "%s", pin);
1263		if (os_snprintf_error(buflen, ret))
1264			return -1;
1265		return ret;
1266	}
1267
1268	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1269	if (ret < 0)
1270		return -1;
1271
1272done:
1273	/* Return the generated PIN */
1274	ret = os_snprintf(buf, buflen, "%08d", ret);
1275	if (os_snprintf_error(buflen, ret))
1276		return -1;
1277	return ret;
1278}
1279
1280
1281static int wpa_supplicant_ctrl_iface_wps_check_pin(
1282	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1283{
1284	char pin[9];
1285	size_t len;
1286	char *pos;
1287	int ret;
1288
1289	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1290			      (u8 *) cmd, os_strlen(cmd));
1291	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1292		if (*pos < '0' || *pos > '9')
1293			continue;
1294		pin[len++] = *pos;
1295		if (len == 9) {
1296			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1297			return -1;
1298		}
1299	}
1300	if (len != 4 && len != 8) {
1301		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1302		return -1;
1303	}
1304	pin[len] = '\0';
1305
1306	if (len == 8) {
1307		unsigned int pin_val;
1308		pin_val = atoi(pin);
1309		if (!wps_pin_valid(pin_val)) {
1310			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1311			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
1312			if (os_snprintf_error(buflen, ret))
1313				return -1;
1314			return ret;
1315		}
1316	}
1317
1318	ret = os_snprintf(buf, buflen, "%s", pin);
1319	if (os_snprintf_error(buflen, ret))
1320		return -1;
1321
1322	return ret;
1323}
1324
1325
1326#ifdef CONFIG_WPS_NFC
1327
1328static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1329					     char *cmd)
1330{
1331	u8 bssid[ETH_ALEN], *_bssid = bssid;
1332
1333	if (cmd == NULL || cmd[0] == '\0')
1334		_bssid = NULL;
1335	else if (hwaddr_aton(cmd, bssid))
1336		return -1;
1337
1338	return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1339				  0, 0);
1340}
1341
1342
1343static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1344	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1345{
1346	int ndef;
1347	struct wpabuf *buf;
1348	int res;
1349	char *pos;
1350
1351	pos = os_strchr(cmd, ' ');
1352	if (pos)
1353		*pos++ = '\0';
1354	if (os_strcmp(cmd, "WPS") == 0)
1355		ndef = 0;
1356	else if (os_strcmp(cmd, "NDEF") == 0)
1357		ndef = 1;
1358	else
1359		return -1;
1360
1361	buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
1362	if (buf == NULL)
1363		return -1;
1364
1365	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1366					 wpabuf_len(buf));
1367	reply[res++] = '\n';
1368	reply[res] = '\0';
1369
1370	wpabuf_free(buf);
1371
1372	return res;
1373}
1374
1375
1376static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1377	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1378{
1379	int ndef;
1380	struct wpabuf *buf;
1381	int res;
1382
1383	if (os_strcmp(cmd, "WPS") == 0)
1384		ndef = 0;
1385	else if (os_strcmp(cmd, "NDEF") == 0)
1386		ndef = 1;
1387	else
1388		return -1;
1389
1390	buf = wpas_wps_nfc_token(wpa_s, ndef);
1391	if (buf == NULL)
1392		return -1;
1393
1394	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1395					 wpabuf_len(buf));
1396	reply[res++] = '\n';
1397	reply[res] = '\0';
1398
1399	wpabuf_free(buf);
1400
1401	return res;
1402}
1403
1404
1405static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1406	struct wpa_supplicant *wpa_s, char *pos)
1407{
1408	size_t len;
1409	struct wpabuf *buf;
1410	int ret;
1411	char *freq;
1412	int forced_freq = 0;
1413
1414	freq = strstr(pos, " freq=");
1415	if (freq) {
1416		*freq = '\0';
1417		freq += 6;
1418		forced_freq = atoi(freq);
1419	}
1420
1421	len = os_strlen(pos);
1422	if (len & 0x01)
1423		return -1;
1424	len /= 2;
1425
1426	buf = wpabuf_alloc(len);
1427	if (buf == NULL)
1428		return -1;
1429	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1430		wpabuf_free(buf);
1431		return -1;
1432	}
1433
1434	ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
1435	wpabuf_free(buf);
1436
1437	return ret;
1438}
1439
1440
1441static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
1442					      char *reply, size_t max_len,
1443					      int ndef)
1444{
1445	struct wpabuf *buf;
1446	int res;
1447
1448	buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
1449	if (buf == NULL)
1450		return -1;
1451
1452	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1453					 wpabuf_len(buf));
1454	reply[res++] = '\n';
1455	reply[res] = '\0';
1456
1457	wpabuf_free(buf);
1458
1459	return res;
1460}
1461
1462
1463#ifdef CONFIG_P2P
1464static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1465					      char *reply, size_t max_len,
1466					      int ndef)
1467{
1468	struct wpabuf *buf;
1469	int res;
1470
1471	buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1472	if (buf == NULL) {
1473		wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1474		return -1;
1475	}
1476
1477	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1478					 wpabuf_len(buf));
1479	reply[res++] = '\n';
1480	reply[res] = '\0';
1481
1482	wpabuf_free(buf);
1483
1484	return res;
1485}
1486#endif /* CONFIG_P2P */
1487
1488
1489static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1490					  char *cmd, char *reply,
1491					  size_t max_len)
1492{
1493	char *pos;
1494	int ndef;
1495
1496	pos = os_strchr(cmd, ' ');
1497	if (pos == NULL)
1498		return -1;
1499	*pos++ = '\0';
1500
1501	if (os_strcmp(cmd, "WPS") == 0)
1502		ndef = 0;
1503	else if (os_strcmp(cmd, "NDEF") == 0)
1504		ndef = 1;
1505	else
1506		return -1;
1507
1508	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1509		if (!ndef)
1510			return -1;
1511		return wpas_ctrl_nfc_get_handover_req_wps(
1512			wpa_s, reply, max_len, ndef);
1513	}
1514
1515#ifdef CONFIG_P2P
1516	if (os_strcmp(pos, "P2P-CR") == 0) {
1517		return wpas_ctrl_nfc_get_handover_req_p2p(
1518			wpa_s, reply, max_len, ndef);
1519	}
1520#endif /* CONFIG_P2P */
1521
1522	return -1;
1523}
1524
1525
1526static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1527					      char *reply, size_t max_len,
1528					      int ndef, int cr, char *uuid)
1529{
1530	struct wpabuf *buf;
1531	int res;
1532
1533	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1534	if (buf == NULL)
1535		return -1;
1536
1537	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1538					 wpabuf_len(buf));
1539	reply[res++] = '\n';
1540	reply[res] = '\0';
1541
1542	wpabuf_free(buf);
1543
1544	return res;
1545}
1546
1547
1548#ifdef CONFIG_P2P
1549static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1550					      char *reply, size_t max_len,
1551					      int ndef, int tag)
1552{
1553	struct wpabuf *buf;
1554	int res;
1555
1556	buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1557	if (buf == NULL)
1558		return -1;
1559
1560	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1561					 wpabuf_len(buf));
1562	reply[res++] = '\n';
1563	reply[res] = '\0';
1564
1565	wpabuf_free(buf);
1566
1567	return res;
1568}
1569#endif /* CONFIG_P2P */
1570
1571
1572static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1573					  char *cmd, char *reply,
1574					  size_t max_len)
1575{
1576	char *pos, *pos2;
1577	int ndef;
1578
1579	pos = os_strchr(cmd, ' ');
1580	if (pos == NULL)
1581		return -1;
1582	*pos++ = '\0';
1583
1584	if (os_strcmp(cmd, "WPS") == 0)
1585		ndef = 0;
1586	else if (os_strcmp(cmd, "NDEF") == 0)
1587		ndef = 1;
1588	else
1589		return -1;
1590
1591	pos2 = os_strchr(pos, ' ');
1592	if (pos2)
1593		*pos2++ = '\0';
1594	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1595		if (!ndef)
1596			return -1;
1597		return wpas_ctrl_nfc_get_handover_sel_wps(
1598			wpa_s, reply, max_len, ndef,
1599			os_strcmp(pos, "WPS-CR") == 0, pos2);
1600	}
1601
1602#ifdef CONFIG_P2P
1603	if (os_strcmp(pos, "P2P-CR") == 0) {
1604		return wpas_ctrl_nfc_get_handover_sel_p2p(
1605			wpa_s, reply, max_len, ndef, 0);
1606	}
1607
1608	if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1609		return wpas_ctrl_nfc_get_handover_sel_p2p(
1610			wpa_s, reply, max_len, ndef, 1);
1611	}
1612#endif /* CONFIG_P2P */
1613
1614	return -1;
1615}
1616
1617
1618static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1619					 char *cmd)
1620{
1621	size_t len;
1622	struct wpabuf *req, *sel;
1623	int ret;
1624	char *pos, *role, *type, *pos2;
1625#ifdef CONFIG_P2P
1626	char *freq;
1627	int forced_freq = 0;
1628
1629	freq = strstr(cmd, " freq=");
1630	if (freq) {
1631		*freq = '\0';
1632		freq += 6;
1633		forced_freq = atoi(freq);
1634	}
1635#endif /* CONFIG_P2P */
1636
1637	role = cmd;
1638	pos = os_strchr(role, ' ');
1639	if (pos == NULL) {
1640		wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1641		return -1;
1642	}
1643	*pos++ = '\0';
1644
1645	type = pos;
1646	pos = os_strchr(type, ' ');
1647	if (pos == NULL) {
1648		wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1649		return -1;
1650	}
1651	*pos++ = '\0';
1652
1653	pos2 = os_strchr(pos, ' ');
1654	if (pos2 == NULL) {
1655		wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1656		return -1;
1657	}
1658	*pos2++ = '\0';
1659
1660	len = os_strlen(pos);
1661	if (len & 0x01) {
1662		wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1663		return -1;
1664	}
1665	len /= 2;
1666
1667	req = wpabuf_alloc(len);
1668	if (req == NULL) {
1669		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1670		return -1;
1671	}
1672	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1673		wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1674		wpabuf_free(req);
1675		return -1;
1676	}
1677
1678	len = os_strlen(pos2);
1679	if (len & 0x01) {
1680		wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1681		wpabuf_free(req);
1682		return -1;
1683	}
1684	len /= 2;
1685
1686	sel = wpabuf_alloc(len);
1687	if (sel == NULL) {
1688		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1689		wpabuf_free(req);
1690		return -1;
1691	}
1692	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1693		wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1694		wpabuf_free(req);
1695		wpabuf_free(sel);
1696		return -1;
1697	}
1698
1699	wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1700		   role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1701
1702	if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1703		ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1704#ifdef CONFIG_AP
1705	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1706	{
1707		ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1708		if (ret < 0)
1709			ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1710#endif /* CONFIG_AP */
1711#ifdef CONFIG_P2P
1712	} else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1713	{
1714		ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1715	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1716	{
1717		ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1718						   forced_freq);
1719#endif /* CONFIG_P2P */
1720	} else {
1721		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1722			   "reported: role=%s type=%s", role, type);
1723		ret = -1;
1724	}
1725	wpabuf_free(req);
1726	wpabuf_free(sel);
1727
1728	if (ret)
1729		wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1730
1731	return ret;
1732}
1733
1734#endif /* CONFIG_WPS_NFC */
1735
1736
1737static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1738					     char *cmd)
1739{
1740	u8 bssid[ETH_ALEN];
1741	char *pin;
1742	char *new_ssid;
1743	char *new_auth;
1744	char *new_encr;
1745	char *new_key;
1746	struct wps_new_ap_settings ap;
1747
1748	pin = os_strchr(cmd, ' ');
1749	if (pin == NULL)
1750		return -1;
1751	*pin++ = '\0';
1752
1753	if (hwaddr_aton(cmd, bssid)) {
1754		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1755			   cmd);
1756		return -1;
1757	}
1758
1759	new_ssid = os_strchr(pin, ' ');
1760	if (new_ssid == NULL)
1761		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1762	*new_ssid++ = '\0';
1763
1764	new_auth = os_strchr(new_ssid, ' ');
1765	if (new_auth == NULL)
1766		return -1;
1767	*new_auth++ = '\0';
1768
1769	new_encr = os_strchr(new_auth, ' ');
1770	if (new_encr == NULL)
1771		return -1;
1772	*new_encr++ = '\0';
1773
1774	new_key = os_strchr(new_encr, ' ');
1775	if (new_key == NULL)
1776		return -1;
1777	*new_key++ = '\0';
1778
1779	os_memset(&ap, 0, sizeof(ap));
1780	ap.ssid_hex = new_ssid;
1781	ap.auth = new_auth;
1782	ap.encr = new_encr;
1783	ap.key_hex = new_key;
1784	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1785}
1786
1787
1788#ifdef CONFIG_AP
1789static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1790						char *cmd, char *buf,
1791						size_t buflen)
1792{
1793	int timeout = 300;
1794	char *pos;
1795	const char *pin_txt;
1796
1797	if (!wpa_s->ap_iface)
1798		return -1;
1799
1800	pos = os_strchr(cmd, ' ');
1801	if (pos)
1802		*pos++ = '\0';
1803
1804	if (os_strcmp(cmd, "disable") == 0) {
1805		wpas_wps_ap_pin_disable(wpa_s);
1806		return os_snprintf(buf, buflen, "OK\n");
1807	}
1808
1809	if (os_strcmp(cmd, "random") == 0) {
1810		if (pos)
1811			timeout = atoi(pos);
1812		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1813		if (pin_txt == NULL)
1814			return -1;
1815		return os_snprintf(buf, buflen, "%s", pin_txt);
1816	}
1817
1818	if (os_strcmp(cmd, "get") == 0) {
1819		pin_txt = wpas_wps_ap_pin_get(wpa_s);
1820		if (pin_txt == NULL)
1821			return -1;
1822		return os_snprintf(buf, buflen, "%s", pin_txt);
1823	}
1824
1825	if (os_strcmp(cmd, "set") == 0) {
1826		char *pin;
1827		if (pos == NULL)
1828			return -1;
1829		pin = pos;
1830		pos = os_strchr(pos, ' ');
1831		if (pos) {
1832			*pos++ = '\0';
1833			timeout = atoi(pos);
1834		}
1835		if (os_strlen(pin) > buflen)
1836			return -1;
1837		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1838			return -1;
1839		return os_snprintf(buf, buflen, "%s", pin);
1840	}
1841
1842	return -1;
1843}
1844#endif /* CONFIG_AP */
1845
1846
1847#ifdef CONFIG_WPS_ER
1848static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1849						char *cmd)
1850{
1851	char *uuid = cmd, *pin, *pos;
1852	u8 addr_buf[ETH_ALEN], *addr = NULL;
1853	pin = os_strchr(uuid, ' ');
1854	if (pin == NULL)
1855		return -1;
1856	*pin++ = '\0';
1857	pos = os_strchr(pin, ' ');
1858	if (pos) {
1859		*pos++ = '\0';
1860		if (hwaddr_aton(pos, addr_buf) == 0)
1861			addr = addr_buf;
1862	}
1863	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
1864}
1865
1866
1867static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
1868						  char *cmd)
1869{
1870	char *uuid = cmd, *pin;
1871	pin = os_strchr(uuid, ' ');
1872	if (pin == NULL)
1873		return -1;
1874	*pin++ = '\0';
1875	return wpas_wps_er_learn(wpa_s, uuid, pin);
1876}
1877
1878
1879static int wpa_supplicant_ctrl_iface_wps_er_set_config(
1880	struct wpa_supplicant *wpa_s, char *cmd)
1881{
1882	char *uuid = cmd, *id;
1883	id = os_strchr(uuid, ' ');
1884	if (id == NULL)
1885		return -1;
1886	*id++ = '\0';
1887	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
1888}
1889
1890
1891static int wpa_supplicant_ctrl_iface_wps_er_config(
1892	struct wpa_supplicant *wpa_s, char *cmd)
1893{
1894	char *pin;
1895	char *new_ssid;
1896	char *new_auth;
1897	char *new_encr;
1898	char *new_key;
1899	struct wps_new_ap_settings ap;
1900
1901	pin = os_strchr(cmd, ' ');
1902	if (pin == NULL)
1903		return -1;
1904	*pin++ = '\0';
1905
1906	new_ssid = os_strchr(pin, ' ');
1907	if (new_ssid == NULL)
1908		return -1;
1909	*new_ssid++ = '\0';
1910
1911	new_auth = os_strchr(new_ssid, ' ');
1912	if (new_auth == NULL)
1913		return -1;
1914	*new_auth++ = '\0';
1915
1916	new_encr = os_strchr(new_auth, ' ');
1917	if (new_encr == NULL)
1918		return -1;
1919	*new_encr++ = '\0';
1920
1921	new_key = os_strchr(new_encr, ' ');
1922	if (new_key == NULL)
1923		return -1;
1924	*new_key++ = '\0';
1925
1926	os_memset(&ap, 0, sizeof(ap));
1927	ap.ssid_hex = new_ssid;
1928	ap.auth = new_auth;
1929	ap.encr = new_encr;
1930	ap.key_hex = new_key;
1931	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
1932}
1933
1934
1935#ifdef CONFIG_WPS_NFC
1936static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
1937	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1938{
1939	int ndef;
1940	struct wpabuf *buf;
1941	int res;
1942	char *uuid;
1943
1944	uuid = os_strchr(cmd, ' ');
1945	if (uuid == NULL)
1946		return -1;
1947	*uuid++ = '\0';
1948
1949	if (os_strcmp(cmd, "WPS") == 0)
1950		ndef = 0;
1951	else if (os_strcmp(cmd, "NDEF") == 0)
1952		ndef = 1;
1953	else
1954		return -1;
1955
1956	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
1957	if (buf == NULL)
1958		return -1;
1959
1960	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1961					 wpabuf_len(buf));
1962	reply[res++] = '\n';
1963	reply[res] = '\0';
1964
1965	wpabuf_free(buf);
1966
1967	return res;
1968}
1969#endif /* CONFIG_WPS_NFC */
1970#endif /* CONFIG_WPS_ER */
1971
1972#endif /* CONFIG_WPS */
1973
1974
1975#ifdef CONFIG_IBSS_RSN
1976static int wpa_supplicant_ctrl_iface_ibss_rsn(
1977	struct wpa_supplicant *wpa_s, char *addr)
1978{
1979	u8 peer[ETH_ALEN];
1980
1981	if (hwaddr_aton(addr, peer)) {
1982		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
1983			   "address '%s'", addr);
1984		return -1;
1985	}
1986
1987	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
1988		   MAC2STR(peer));
1989
1990	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
1991}
1992#endif /* CONFIG_IBSS_RSN */
1993
1994
1995static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
1996					      char *rsp)
1997{
1998#ifdef IEEE8021X_EAPOL
1999	char *pos, *id_pos;
2000	int id;
2001	struct wpa_ssid *ssid;
2002
2003	pos = os_strchr(rsp, '-');
2004	if (pos == NULL)
2005		return -1;
2006	*pos++ = '\0';
2007	id_pos = pos;
2008	pos = os_strchr(pos, ':');
2009	if (pos == NULL)
2010		return -1;
2011	*pos++ = '\0';
2012	id = atoi(id_pos);
2013	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2014	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2015			      (u8 *) pos, os_strlen(pos));
2016
2017	ssid = wpa_config_get_network(wpa_s->conf, id);
2018	if (ssid == NULL) {
2019		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2020			   "to update", id);
2021		return -1;
2022	}
2023
2024	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2025							 pos);
2026#else /* IEEE8021X_EAPOL */
2027	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2028	return -1;
2029#endif /* IEEE8021X_EAPOL */
2030}
2031
2032
2033static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2034					    const char *params,
2035					    char *buf, size_t buflen)
2036{
2037	char *pos, *end, tmp[30];
2038	int res, verbose, wps, ret;
2039#ifdef CONFIG_HS20
2040	const u8 *hs20;
2041#endif /* CONFIG_HS20 */
2042	const u8 *sess_id;
2043	size_t sess_id_len;
2044
2045	if (os_strcmp(params, "-DRIVER") == 0)
2046		return wpa_drv_status(wpa_s, buf, buflen);
2047	verbose = os_strcmp(params, "-VERBOSE") == 0;
2048	wps = os_strcmp(params, "-WPS") == 0;
2049	pos = buf;
2050	end = buf + buflen;
2051	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2052		struct wpa_ssid *ssid = wpa_s->current_ssid;
2053		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2054				  MAC2STR(wpa_s->bssid));
2055		if (os_snprintf_error(end - pos, ret))
2056			return pos - buf;
2057		pos += ret;
2058		ret = os_snprintf(pos, end - pos, "freq=%u\n",
2059				  wpa_s->assoc_freq);
2060		if (os_snprintf_error(end - pos, ret))
2061			return pos - buf;
2062		pos += ret;
2063		if (ssid) {
2064			u8 *_ssid = ssid->ssid;
2065			size_t ssid_len = ssid->ssid_len;
2066			u8 ssid_buf[SSID_MAX_LEN];
2067			if (ssid_len == 0) {
2068				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2069				if (_res < 0)
2070					ssid_len = 0;
2071				else
2072					ssid_len = _res;
2073				_ssid = ssid_buf;
2074			}
2075			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2076					  wpa_ssid_txt(_ssid, ssid_len),
2077					  ssid->id);
2078			if (os_snprintf_error(end - pos, ret))
2079				return pos - buf;
2080			pos += ret;
2081
2082			if (wps && ssid->passphrase &&
2083			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2084			    (ssid->mode == WPAS_MODE_AP ||
2085			     ssid->mode == WPAS_MODE_P2P_GO)) {
2086				ret = os_snprintf(pos, end - pos,
2087						  "passphrase=%s\n",
2088						  ssid->passphrase);
2089				if (os_snprintf_error(end - pos, ret))
2090					return pos - buf;
2091				pos += ret;
2092			}
2093			if (ssid->id_str) {
2094				ret = os_snprintf(pos, end - pos,
2095						  "id_str=%s\n",
2096						  ssid->id_str);
2097				if (os_snprintf_error(end - pos, ret))
2098					return pos - buf;
2099				pos += ret;
2100			}
2101
2102			switch (ssid->mode) {
2103			case WPAS_MODE_INFRA:
2104				ret = os_snprintf(pos, end - pos,
2105						  "mode=station\n");
2106				break;
2107			case WPAS_MODE_IBSS:
2108				ret = os_snprintf(pos, end - pos,
2109						  "mode=IBSS\n");
2110				break;
2111			case WPAS_MODE_AP:
2112				ret = os_snprintf(pos, end - pos,
2113						  "mode=AP\n");
2114				break;
2115			case WPAS_MODE_P2P_GO:
2116				ret = os_snprintf(pos, end - pos,
2117						  "mode=P2P GO\n");
2118				break;
2119			case WPAS_MODE_P2P_GROUP_FORMATION:
2120				ret = os_snprintf(pos, end - pos,
2121						  "mode=P2P GO - group "
2122						  "formation\n");
2123				break;
2124			case WPAS_MODE_MESH:
2125				ret = os_snprintf(pos, end - pos,
2126						  "mode=mesh\n");
2127				break;
2128			default:
2129				ret = 0;
2130				break;
2131			}
2132			if (os_snprintf_error(end - pos, ret))
2133				return pos - buf;
2134			pos += ret;
2135		}
2136
2137		if (wpa_s->connection_set &&
2138		    (wpa_s->connection_ht || wpa_s->connection_vht ||
2139		     wpa_s->connection_he)) {
2140			ret = os_snprintf(pos, end - pos,
2141					  "wifi_generation=%u\n",
2142					  wpa_s->connection_he ? 6 :
2143					  (wpa_s->connection_vht ? 5 : 4));
2144			if (os_snprintf_error(end - pos, ret))
2145				return pos - buf;
2146			pos += ret;
2147		}
2148
2149#ifdef CONFIG_AP
2150		if (wpa_s->ap_iface) {
2151			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2152							    end - pos,
2153							    verbose);
2154		} else
2155#endif /* CONFIG_AP */
2156		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2157	}
2158#ifdef CONFIG_SME
2159#ifdef CONFIG_SAE
2160	if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
2161#ifdef CONFIG_AP
2162	    !wpa_s->ap_iface &&
2163#endif /* CONFIG_AP */
2164	    wpa_s->sme.sae.state == SAE_ACCEPTED) {
2165		ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
2166				  wpa_s->sme.sae.group);
2167		if (os_snprintf_error(end - pos, ret))
2168			return pos - buf;
2169		pos += ret;
2170	}
2171#endif /* CONFIG_SAE */
2172#endif /* CONFIG_SME */
2173	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2174			  wpa_supplicant_state_txt(wpa_s->wpa_state));
2175	if (os_snprintf_error(end - pos, ret))
2176		return pos - buf;
2177	pos += ret;
2178
2179	if (wpa_s->l2 &&
2180	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2181		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
2182		if (os_snprintf_error(end - pos, ret))
2183			return pos - buf;
2184		pos += ret;
2185	}
2186
2187#ifdef CONFIG_P2P
2188	if (wpa_s->global->p2p) {
2189		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2190				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
2191		if (os_snprintf_error(end - pos, ret))
2192			return pos - buf;
2193		pos += ret;
2194	}
2195#endif /* CONFIG_P2P */
2196
2197	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2198			  MAC2STR(wpa_s->own_addr));
2199	if (os_snprintf_error(end - pos, ret))
2200		return pos - buf;
2201	pos += ret;
2202
2203#ifdef CONFIG_HS20
2204	if (wpa_s->current_bss &&
2205	    (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2206					  HS20_IE_VENDOR_TYPE)) &&
2207	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
2208	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2209		int release = 1;
2210		if (hs20[1] >= 5) {
2211			u8 rel_num = (hs20[6] & 0xf0) >> 4;
2212			release = rel_num + 1;
2213		}
2214		ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
2215		if (os_snprintf_error(end - pos, ret))
2216			return pos - buf;
2217		pos += ret;
2218	}
2219
2220	if (wpa_s->current_ssid) {
2221		struct wpa_cred *cred;
2222		char *type;
2223
2224		for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
2225			size_t i;
2226
2227			if (wpa_s->current_ssid->parent_cred != cred)
2228				continue;
2229
2230			if (cred->provisioning_sp) {
2231				ret = os_snprintf(pos, end - pos,
2232						  "provisioning_sp=%s\n",
2233						  cred->provisioning_sp);
2234				if (os_snprintf_error(end - pos, ret))
2235					return pos - buf;
2236				pos += ret;
2237			}
2238
2239			if (!cred->domain)
2240				goto no_domain;
2241
2242			i = 0;
2243			if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2244				struct wpabuf *names =
2245					wpa_s->current_bss->anqp->domain_name;
2246				for (i = 0; names && i < cred->num_domain; i++)
2247				{
2248					if (domain_name_list_contains(
2249						    names, cred->domain[i], 1))
2250						break;
2251				}
2252				if (i == cred->num_domain)
2253					i = 0; /* show first entry by default */
2254			}
2255			ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2256					  cred->domain[i]);
2257			if (os_snprintf_error(end - pos, ret))
2258				return pos - buf;
2259			pos += ret;
2260
2261		no_domain:
2262			if (wpa_s->current_bss == NULL ||
2263			    wpa_s->current_bss->anqp == NULL)
2264				res = -1;
2265			else
2266				res = interworking_home_sp_cred(
2267					wpa_s, cred,
2268					wpa_s->current_bss->anqp->domain_name);
2269			if (res > 0)
2270				type = "home";
2271			else if (res == 0)
2272				type = "roaming";
2273			else
2274				type = "unknown";
2275
2276			ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
2277			if (os_snprintf_error(end - pos, ret))
2278				return pos - buf;
2279			pos += ret;
2280
2281			break;
2282		}
2283	}
2284#endif /* CONFIG_HS20 */
2285
2286	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2287	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2288		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2289					  verbose);
2290		if (res >= 0)
2291			pos += res;
2292	}
2293
2294#ifdef CONFIG_MACSEC
2295	res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2296	if (res > 0)
2297		pos += res;
2298#endif /* CONFIG_MACSEC */
2299
2300	sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2301	if (sess_id) {
2302		char *start = pos;
2303
2304		ret = os_snprintf(pos, end - pos, "eap_session_id=");
2305		if (os_snprintf_error(end - pos, ret))
2306			return start - buf;
2307		pos += ret;
2308		ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2309		if (ret <= 0)
2310			return start - buf;
2311		pos += ret;
2312		ret = os_snprintf(pos, end - pos, "\n");
2313		if (os_snprintf_error(end - pos, ret))
2314			return start - buf;
2315		pos += ret;
2316	}
2317
2318	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2319	if (res >= 0)
2320		pos += res;
2321
2322#ifdef CONFIG_WPS
2323	{
2324		char uuid_str[100];
2325		uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2326		ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
2327		if (os_snprintf_error(end - pos, ret))
2328			return pos - buf;
2329		pos += ret;
2330	}
2331#endif /* CONFIG_WPS */
2332
2333	if (wpa_s->ieee80211ac) {
2334		ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2335		if (os_snprintf_error(end - pos, ret))
2336			return pos - buf;
2337		pos += ret;
2338	}
2339
2340#ifdef ANDROID
2341	/*
2342	 * Allow using the STATUS command with default behavior, say for debug,
2343	 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2344	 * events with STATUS-NO_EVENTS.
2345	 */
2346	if (os_strcmp(params, "-NO_EVENTS")) {
2347		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2348			     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2349			     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2350			     wpa_s->wpa_state,
2351			     MAC2STR(wpa_s->bssid),
2352			     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2353			     wpa_ssid_txt(wpa_s->current_ssid->ssid,
2354					  wpa_s->current_ssid->ssid_len) : "");
2355		if (wpa_s->wpa_state == WPA_COMPLETED) {
2356			struct wpa_ssid *ssid = wpa_s->current_ssid;
2357			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2358				     "- connection to " MACSTR
2359				     " completed %s [id=%d id_str=%s]",
2360				     MAC2STR(wpa_s->bssid), "(auth)",
2361				     ssid ? ssid->id : -1,
2362				     ssid && ssid->id_str ? ssid->id_str : "");
2363		}
2364	}
2365#endif /* ANDROID */
2366
2367	return pos - buf;
2368}
2369
2370
2371static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2372					   char *cmd)
2373{
2374	char *pos;
2375	int id;
2376	struct wpa_ssid *ssid;
2377	u8 bssid[ETH_ALEN];
2378
2379	/* cmd: "<network id> <BSSID>" */
2380	pos = os_strchr(cmd, ' ');
2381	if (pos == NULL)
2382		return -1;
2383	*pos++ = '\0';
2384	id = atoi(cmd);
2385	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2386	if (hwaddr_aton(pos, bssid)) {
2387		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2388		return -1;
2389	}
2390
2391	ssid = wpa_config_get_network(wpa_s->conf, id);
2392	if (ssid == NULL) {
2393		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2394			   "to update", id);
2395		return -1;
2396	}
2397
2398	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2399	ssid->bssid_set = !is_zero_ether_addr(bssid);
2400
2401	return 0;
2402}
2403
2404
2405static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
2406					       char *cmd, char *buf,
2407					       size_t buflen)
2408{
2409	u8 bssid[ETH_ALEN];
2410	struct wpa_blacklist *e;
2411	char *pos, *end;
2412	int ret;
2413
2414	/* cmd: "BLACKLIST [<BSSID>]" */
2415	if (*cmd == '\0') {
2416		pos = buf;
2417		end = buf + buflen;
2418		e = wpa_s->blacklist;
2419		while (e) {
2420			ret = os_snprintf(pos, end - pos, MACSTR "\n",
2421					  MAC2STR(e->bssid));
2422			if (os_snprintf_error(end - pos, ret))
2423				return pos - buf;
2424			pos += ret;
2425			e = e->next;
2426		}
2427		return pos - buf;
2428	}
2429
2430	cmd++;
2431	if (os_strncmp(cmd, "clear", 5) == 0) {
2432		wpa_blacklist_clear(wpa_s);
2433		os_memcpy(buf, "OK\n", 3);
2434		return 3;
2435	}
2436
2437	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
2438	if (hwaddr_aton(cmd, bssid)) {
2439		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
2440		return -1;
2441	}
2442
2443	/*
2444	 * Add the BSSID twice, so its count will be 2, causing it to be
2445	 * skipped when processing scan results.
2446	 */
2447	ret = wpa_blacklist_add(wpa_s, bssid);
2448	if (ret < 0)
2449		return -1;
2450	ret = wpa_blacklist_add(wpa_s, bssid);
2451	if (ret < 0)
2452		return -1;
2453	os_memcpy(buf, "OK\n", 3);
2454	return 3;
2455}
2456
2457
2458static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2459					       char *cmd, char *buf,
2460					       size_t buflen)
2461{
2462	char *pos, *end, *stamp;
2463	int ret;
2464
2465	/* cmd: "LOG_LEVEL [<level>]" */
2466	if (*cmd == '\0') {
2467		pos = buf;
2468		end = buf + buflen;
2469		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2470				  "Timestamp: %d\n",
2471				  debug_level_str(wpa_debug_level),
2472				  wpa_debug_timestamp);
2473		if (os_snprintf_error(end - pos, ret))
2474			ret = 0;
2475
2476		return ret;
2477	}
2478
2479	while (*cmd == ' ')
2480		cmd++;
2481
2482	stamp = os_strchr(cmd, ' ');
2483	if (stamp) {
2484		*stamp++ = '\0';
2485		while (*stamp == ' ') {
2486			stamp++;
2487		}
2488	}
2489
2490	if (os_strlen(cmd)) {
2491		int level = str_to_debug_level(cmd);
2492		if (level < 0)
2493			return -1;
2494		wpa_debug_level = level;
2495	}
2496
2497	if (stamp && os_strlen(stamp))
2498		wpa_debug_timestamp = atoi(stamp);
2499
2500	os_memcpy(buf, "OK\n", 3);
2501	return 3;
2502}
2503
2504
2505static int wpa_supplicant_ctrl_iface_list_networks(
2506	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2507{
2508	char *pos, *end, *prev;
2509	struct wpa_ssid *ssid;
2510	int ret;
2511
2512	pos = buf;
2513	end = buf + buflen;
2514	ret = os_snprintf(pos, end - pos,
2515			  "network id / ssid / bssid / flags\n");
2516	if (os_snprintf_error(end - pos, ret))
2517		return pos - buf;
2518	pos += ret;
2519
2520	ssid = wpa_s->conf->ssid;
2521
2522	/* skip over ssids until we find next one */
2523	if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2524		int last_id = atoi(cmd + 8);
2525		if (last_id != -1) {
2526			while (ssid != NULL && ssid->id <= last_id) {
2527				ssid = ssid->next;
2528			}
2529		}
2530	}
2531
2532	while (ssid) {
2533		prev = pos;
2534		ret = os_snprintf(pos, end - pos, "%d\t%s",
2535				  ssid->id,
2536				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2537		if (os_snprintf_error(end - pos, ret))
2538			return prev - buf;
2539		pos += ret;
2540		if (ssid->bssid_set) {
2541			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2542					  MAC2STR(ssid->bssid));
2543		} else {
2544			ret = os_snprintf(pos, end - pos, "\tany");
2545		}
2546		if (os_snprintf_error(end - pos, ret))
2547			return prev - buf;
2548		pos += ret;
2549		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2550				  ssid == wpa_s->current_ssid ?
2551				  "[CURRENT]" : "",
2552				  ssid->disabled ? "[DISABLED]" : "",
2553				  ssid->disabled_until.sec ?
2554				  "[TEMP-DISABLED]" : "",
2555				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2556				  "");
2557		if (os_snprintf_error(end - pos, ret))
2558			return prev - buf;
2559		pos += ret;
2560		ret = os_snprintf(pos, end - pos, "\n");
2561		if (os_snprintf_error(end - pos, ret))
2562			return prev - buf;
2563		pos += ret;
2564
2565		ssid = ssid->next;
2566	}
2567
2568	return pos - buf;
2569}
2570
2571
2572static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2573{
2574	int ret;
2575	ret = os_snprintf(pos, end - pos, "-");
2576	if (os_snprintf_error(end - pos, ret))
2577		return pos;
2578	pos += ret;
2579	ret = wpa_write_ciphers(pos, end, cipher, "+");
2580	if (ret < 0)
2581		return pos;
2582	pos += ret;
2583	return pos;
2584}
2585
2586
2587static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2588				    const u8 *ie, size_t ie_len)
2589{
2590	struct wpa_ie_data data;
2591	char *start;
2592	int ret;
2593
2594	ret = os_snprintf(pos, end - pos, "[%s-", proto);
2595	if (os_snprintf_error(end - pos, ret))
2596		return pos;
2597	pos += ret;
2598
2599	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2600		ret = os_snprintf(pos, end - pos, "?]");
2601		if (os_snprintf_error(end - pos, ret))
2602			return pos;
2603		pos += ret;
2604		return pos;
2605	}
2606
2607	start = pos;
2608	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2609		ret = os_snprintf(pos, end - pos, "%sEAP",
2610				  pos == start ? "" : "+");
2611		if (os_snprintf_error(end - pos, ret))
2612			return pos;
2613		pos += ret;
2614	}
2615	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2616		ret = os_snprintf(pos, end - pos, "%sPSK",
2617				  pos == start ? "" : "+");
2618		if (os_snprintf_error(end - pos, ret))
2619			return pos;
2620		pos += ret;
2621	}
2622	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2623		ret = os_snprintf(pos, end - pos, "%sNone",
2624				  pos == start ? "" : "+");
2625		if (os_snprintf_error(end - pos, ret))
2626			return pos;
2627		pos += ret;
2628	}
2629	if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2630		ret = os_snprintf(pos, end - pos, "%sSAE",
2631				  pos == start ? "" : "+");
2632		if (os_snprintf_error(end - pos, ret))
2633			return pos;
2634		pos += ret;
2635	}
2636#ifdef CONFIG_IEEE80211R
2637	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2638		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2639				  pos == start ? "" : "+");
2640		if (os_snprintf_error(end - pos, ret))
2641			return pos;
2642		pos += ret;
2643	}
2644	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2645		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2646				  pos == start ? "" : "+");
2647		if (os_snprintf_error(end - pos, ret))
2648			return pos;
2649		pos += ret;
2650	}
2651	if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2652		ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2653				  pos == start ? "" : "+");
2654		if (os_snprintf_error(end - pos, ret))
2655			return pos;
2656		pos += ret;
2657	}
2658#endif /* CONFIG_IEEE80211R */
2659#ifdef CONFIG_IEEE80211W
2660	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2661		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2662				  pos == start ? "" : "+");
2663		if (os_snprintf_error(end - pos, ret))
2664			return pos;
2665		pos += ret;
2666	}
2667	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2668		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2669				  pos == start ? "" : "+");
2670		if (os_snprintf_error(end - pos, ret))
2671			return pos;
2672		pos += ret;
2673	}
2674#endif /* CONFIG_IEEE80211W */
2675
2676#ifdef CONFIG_SUITEB
2677	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2678		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2679				  pos == start ? "" : "+");
2680		if (os_snprintf_error(end - pos, ret))
2681			return pos;
2682		pos += ret;
2683	}
2684#endif /* CONFIG_SUITEB */
2685
2686#ifdef CONFIG_SUITEB192
2687	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2688		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2689				  pos == start ? "" : "+");
2690		if (os_snprintf_error(end - pos, ret))
2691			return pos;
2692		pos += ret;
2693	}
2694#endif /* CONFIG_SUITEB192 */
2695
2696#ifdef CONFIG_FILS
2697	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
2698		ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
2699				  pos == start ? "" : "+");
2700		if (os_snprintf_error(end - pos, ret))
2701			return pos;
2702		pos += ret;
2703	}
2704	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
2705		ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
2706				  pos == start ? "" : "+");
2707		if (os_snprintf_error(end - pos, ret))
2708			return pos;
2709		pos += ret;
2710	}
2711#ifdef CONFIG_IEEE80211R
2712	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
2713		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
2714				  pos == start ? "" : "+");
2715		if (os_snprintf_error(end - pos, ret))
2716			return pos;
2717		pos += ret;
2718	}
2719	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
2720		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
2721				  pos == start ? "" : "+");
2722		if (os_snprintf_error(end - pos, ret))
2723			return pos;
2724		pos += ret;
2725	}
2726#endif /* CONFIG_IEEE80211R */
2727#endif /* CONFIG_FILS */
2728
2729#ifdef CONFIG_OWE
2730	if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
2731		ret = os_snprintf(pos, end - pos, "%sOWE",
2732				  pos == start ? "" : "+");
2733		if (os_snprintf_error(end - pos, ret))
2734			return pos;
2735		pos += ret;
2736	}
2737#endif /* CONFIG_OWE */
2738
2739#ifdef CONFIG_DPP
2740	if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
2741		ret = os_snprintf(pos, end - pos, "%sDPP",
2742				  pos == start ? "" : "+");
2743		if (os_snprintf_error(end - pos, ret))
2744			return pos;
2745		pos += ret;
2746	}
2747#endif /* CONFIG_DPP */
2748
2749	if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
2750		ret = os_snprintf(pos, end - pos, "%sOSEN",
2751				  pos == start ? "" : "+");
2752		if (os_snprintf_error(end - pos, ret))
2753			return pos;
2754		pos += ret;
2755	}
2756
2757	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
2758
2759	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
2760		ret = os_snprintf(pos, end - pos, "-preauth");
2761		if (os_snprintf_error(end - pos, ret))
2762			return pos;
2763		pos += ret;
2764	}
2765
2766	ret = os_snprintf(pos, end - pos, "]");
2767	if (os_snprintf_error(end - pos, ret))
2768		return pos;
2769	pos += ret;
2770
2771	return pos;
2772}
2773
2774
2775#ifdef CONFIG_WPS
2776static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
2777					    char *pos, char *end,
2778					    struct wpabuf *wps_ie)
2779{
2780	int ret;
2781	const char *txt;
2782
2783	if (wps_ie == NULL)
2784		return pos;
2785	if (wps_is_selected_pbc_registrar(wps_ie))
2786		txt = "[WPS-PBC]";
2787	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2788		txt = "[WPS-AUTH]";
2789	else if (wps_is_selected_pin_registrar(wps_ie))
2790		txt = "[WPS-PIN]";
2791	else
2792		txt = "[WPS]";
2793
2794	ret = os_snprintf(pos, end - pos, "%s", txt);
2795	if (!os_snprintf_error(end - pos, ret))
2796		pos += ret;
2797	wpabuf_free(wps_ie);
2798	return pos;
2799}
2800#endif /* CONFIG_WPS */
2801
2802
2803static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2804					char *pos, char *end,
2805					const struct wpa_bss *bss)
2806{
2807#ifdef CONFIG_WPS
2808	struct wpabuf *wps_ie;
2809	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2810	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2811#else /* CONFIG_WPS */
2812	return pos;
2813#endif /* CONFIG_WPS */
2814}
2815
2816
2817/* Format one result on one text line into a buffer. */
2818static int wpa_supplicant_ctrl_iface_scan_result(
2819	struct wpa_supplicant *wpa_s,
2820	const struct wpa_bss *bss, char *buf, size_t buflen)
2821{
2822	char *pos, *end;
2823	int ret;
2824	const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe;
2825
2826	mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
2827	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2828	if (!p2p)
2829		p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
2830	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2831	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2832	    0)
2833		return 0; /* Do not show P2P listen discovery results here */
2834
2835	pos = buf;
2836	end = buf + buflen;
2837
2838	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2839			  MAC2STR(bss->bssid), bss->freq, bss->level);
2840	if (os_snprintf_error(end - pos, ret))
2841		return -1;
2842	pos += ret;
2843	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2844	if (ie)
2845		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2846	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2847	if (ie2) {
2848		pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
2849					    ie2, 2 + ie2[1]);
2850	}
2851	osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
2852	if (osen_ie)
2853		pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
2854					    osen_ie, 2 + osen_ie[1]);
2855	owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
2856	if (owe) {
2857		ret = os_snprintf(pos, end - pos,
2858				  ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
2859		if (os_snprintf_error(end - pos, ret))
2860			return -1;
2861		pos += ret;
2862	}
2863	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2864	if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
2865		ret = os_snprintf(pos, end - pos, "[WEP]");
2866		if (os_snprintf_error(end - pos, ret))
2867			return -1;
2868		pos += ret;
2869	}
2870	if (mesh) {
2871		ret = os_snprintf(pos, end - pos, "[MESH]");
2872		if (os_snprintf_error(end - pos, ret))
2873			return -1;
2874		pos += ret;
2875	}
2876	if (bss_is_dmg(bss)) {
2877		const char *s;
2878		ret = os_snprintf(pos, end - pos, "[DMG]");
2879		if (os_snprintf_error(end - pos, ret))
2880			return -1;
2881		pos += ret;
2882		switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
2883		case IEEE80211_CAP_DMG_IBSS:
2884			s = "[IBSS]";
2885			break;
2886		case IEEE80211_CAP_DMG_AP:
2887			s = "[ESS]";
2888			break;
2889		case IEEE80211_CAP_DMG_PBSS:
2890			s = "[PBSS]";
2891			break;
2892		default:
2893			s = "";
2894			break;
2895		}
2896		ret = os_snprintf(pos, end - pos, "%s", s);
2897		if (os_snprintf_error(end - pos, ret))
2898			return -1;
2899		pos += ret;
2900	} else {
2901		if (bss->caps & IEEE80211_CAP_IBSS) {
2902			ret = os_snprintf(pos, end - pos, "[IBSS]");
2903			if (os_snprintf_error(end - pos, ret))
2904				return -1;
2905			pos += ret;
2906		}
2907		if (bss->caps & IEEE80211_CAP_ESS) {
2908			ret = os_snprintf(pos, end - pos, "[ESS]");
2909			if (os_snprintf_error(end - pos, ret))
2910				return -1;
2911			pos += ret;
2912		}
2913	}
2914	if (p2p) {
2915		ret = os_snprintf(pos, end - pos, "[P2P]");
2916		if (os_snprintf_error(end - pos, ret))
2917			return -1;
2918		pos += ret;
2919	}
2920#ifdef CONFIG_HS20
2921	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2922		ret = os_snprintf(pos, end - pos, "[HS20]");
2923		if (os_snprintf_error(end - pos, ret))
2924			return -1;
2925		pos += ret;
2926	}
2927#endif /* CONFIG_HS20 */
2928#ifdef CONFIG_FILS
2929	if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
2930		ret = os_snprintf(pos, end - pos, "[FILS]");
2931		if (os_snprintf_error(end - pos, ret))
2932			return -1;
2933		pos += ret;
2934	}
2935#endif /* CONFIG_FILS */
2936#ifdef CONFIG_FST
2937	if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
2938		ret = os_snprintf(pos, end - pos, "[FST]");
2939		if (os_snprintf_error(end - pos, ret))
2940			return -1;
2941		pos += ret;
2942	}
2943#endif /* CONFIG_FST */
2944	if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
2945		ret = os_snprintf(pos, end - pos, "[UTF-8]");
2946		if (os_snprintf_error(end - pos, ret))
2947			return -1;
2948		pos += ret;
2949	}
2950
2951	ret = os_snprintf(pos, end - pos, "\t%s",
2952			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
2953	if (os_snprintf_error(end - pos, ret))
2954		return -1;
2955	pos += ret;
2956
2957	ret = os_snprintf(pos, end - pos, "\n");
2958	if (os_snprintf_error(end - pos, ret))
2959		return -1;
2960	pos += ret;
2961
2962	return pos - buf;
2963}
2964
2965
2966static int wpa_supplicant_ctrl_iface_scan_results(
2967	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2968{
2969	char *pos, *end;
2970	struct wpa_bss *bss;
2971	int ret;
2972
2973	pos = buf;
2974	end = buf + buflen;
2975	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2976			  "flags / ssid\n");
2977	if (os_snprintf_error(end - pos, ret))
2978		return pos - buf;
2979	pos += ret;
2980
2981	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2982		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2983							    end - pos);
2984		if (ret < 0 || ret >= end - pos)
2985			return pos - buf;
2986		pos += ret;
2987	}
2988
2989	return pos - buf;
2990}
2991
2992
2993#ifdef CONFIG_MESH
2994
2995static int wpa_supplicant_ctrl_iface_mesh_interface_add(
2996	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2997{
2998	char *pos, ifname[IFNAMSIZ + 1];
2999
3000	ifname[0] = '\0';
3001
3002	pos = os_strstr(cmd, "ifname=");
3003	if (pos) {
3004		pos += 7;
3005		os_strlcpy(ifname, pos, sizeof(ifname));
3006	}
3007
3008	if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3009		return -1;
3010
3011	os_strlcpy(reply, ifname, max_len);
3012	return os_strlen(ifname);
3013}
3014
3015
3016static int wpa_supplicant_ctrl_iface_mesh_group_add(
3017	struct wpa_supplicant *wpa_s, char *cmd)
3018{
3019	int id;
3020	struct wpa_ssid *ssid;
3021
3022	id = atoi(cmd);
3023	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3024
3025	ssid = wpa_config_get_network(wpa_s->conf, id);
3026	if (ssid == NULL) {
3027		wpa_printf(MSG_DEBUG,
3028			   "CTRL_IFACE: Could not find network id=%d", id);
3029		return -1;
3030	}
3031	if (ssid->mode != WPAS_MODE_MESH) {
3032		wpa_printf(MSG_DEBUG,
3033			   "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3034		return -1;
3035	}
3036	if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
3037	    ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
3038		wpa_printf(MSG_ERROR,
3039			   "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3040		return -1;
3041	}
3042
3043	/*
3044	 * TODO: If necessary write our own group_add function,
3045	 * for now we can reuse select_network
3046	 */
3047	wpa_supplicant_select_network(wpa_s, ssid);
3048
3049	return 0;
3050}
3051
3052
3053static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3054	struct wpa_supplicant *wpa_s, char *cmd)
3055{
3056	struct wpa_supplicant *orig;
3057	struct wpa_global *global;
3058	int found = 0;
3059
3060	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3061
3062	global = wpa_s->global;
3063	orig = wpa_s;
3064
3065	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3066		if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3067			found = 1;
3068			break;
3069		}
3070	}
3071	if (!found) {
3072		wpa_printf(MSG_ERROR,
3073			   "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3074			   cmd);
3075		return -1;
3076	}
3077	if (wpa_s->mesh_if_created && wpa_s == orig) {
3078		wpa_printf(MSG_ERROR,
3079			   "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3080		return -1;
3081	}
3082
3083	wpa_s->reassociate = 0;
3084	wpa_s->disconnected = 1;
3085	wpa_supplicant_cancel_sched_scan(wpa_s);
3086	wpa_supplicant_cancel_scan(wpa_s);
3087
3088	/*
3089	 * TODO: If necessary write our own group_remove function,
3090	 * for now we can reuse deauthenticate
3091	 */
3092	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3093
3094	if (wpa_s->mesh_if_created)
3095		wpa_supplicant_remove_iface(global, wpa_s, 0);
3096
3097	return 0;
3098}
3099
3100
3101static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3102	struct wpa_supplicant *wpa_s, char *cmd)
3103{
3104	u8 addr[ETH_ALEN];
3105
3106	if (hwaddr_aton(cmd, addr) < 0)
3107		return -1;
3108
3109	return wpas_mesh_peer_remove(wpa_s, addr);
3110}
3111
3112
3113static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3114	struct wpa_supplicant *wpa_s, char *cmd)
3115{
3116	u8 addr[ETH_ALEN];
3117	int duration;
3118	char *pos;
3119
3120	pos = os_strstr(cmd, " duration=");
3121	if (pos) {
3122		*pos = '\0';
3123		duration = atoi(pos + 10);
3124	} else {
3125		duration = -1;
3126	}
3127
3128	if (hwaddr_aton(cmd, addr))
3129		return -1;
3130
3131	return wpas_mesh_peer_add(wpa_s, addr, duration);
3132}
3133
3134
3135static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3136	struct wpa_supplicant *wpa_s, char *cmd)
3137{
3138	struct ether_header *eth;
3139	u8 addr[ETH_ALEN];
3140	u8 *buf;
3141	char *pos;
3142	size_t payload_len = 0, len;
3143	int ret = -1;
3144
3145	if (hwaddr_aton(cmd, addr))
3146		return -1;
3147
3148	pos = os_strstr(cmd, " payload=");
3149	if (pos) {
3150		pos = pos + 9;
3151		payload_len = os_strlen(pos);
3152		if (payload_len & 1)
3153			return -1;
3154
3155		payload_len /= 2;
3156	}
3157
3158	len = ETH_HLEN + payload_len;
3159	buf = os_malloc(len);
3160	if (!buf)
3161		return -1;
3162
3163	eth = (struct ether_header *) buf;
3164	os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3165	os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3166	eth->ether_type = htons(ETH_P_802_3);
3167
3168	if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3169		goto fail;
3170
3171	ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3172fail:
3173	os_free(buf);
3174	return -ret;
3175}
3176
3177#endif /* CONFIG_MESH */
3178
3179
3180static int wpa_supplicant_ctrl_iface_select_network(
3181	struct wpa_supplicant *wpa_s, char *cmd)
3182{
3183	int id;
3184	struct wpa_ssid *ssid;
3185	char *pos;
3186
3187	/* cmd: "<network id>" or "any" */
3188	if (os_strncmp(cmd, "any", 3) == 0) {
3189		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3190		ssid = NULL;
3191	} else {
3192		id = atoi(cmd);
3193		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3194
3195		ssid = wpa_config_get_network(wpa_s->conf, id);
3196		if (ssid == NULL) {
3197			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3198				   "network id=%d", id);
3199			return -1;
3200		}
3201		if (ssid->disabled == 2) {
3202			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3203				   "SELECT_NETWORK with persistent P2P group");
3204			return -1;
3205		}
3206	}
3207
3208	pos = os_strstr(cmd, " freq=");
3209	if (pos) {
3210		int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3211		if (freqs) {
3212			os_free(wpa_s->select_network_scan_freqs);
3213			wpa_s->select_network_scan_freqs = freqs;
3214		}
3215	}
3216
3217	wpa_s->scan_min_time.sec = 0;
3218	wpa_s->scan_min_time.usec = 0;
3219	wpa_supplicant_select_network(wpa_s, ssid);
3220
3221	return 0;
3222}
3223
3224
3225static int wpa_supplicant_ctrl_iface_enable_network(
3226	struct wpa_supplicant *wpa_s, char *cmd)
3227{
3228	int id;
3229	struct wpa_ssid *ssid;
3230
3231	/* cmd: "<network id>" or "all" */
3232	if (os_strcmp(cmd, "all") == 0) {
3233		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3234		ssid = NULL;
3235	} else {
3236		id = atoi(cmd);
3237		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3238
3239		ssid = wpa_config_get_network(wpa_s->conf, id);
3240		if (ssid == NULL) {
3241			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3242				   "network id=%d", id);
3243			return -1;
3244		}
3245		if (ssid->disabled == 2) {
3246			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3247				   "ENABLE_NETWORK with persistent P2P group");
3248			return -1;
3249		}
3250
3251		if (os_strstr(cmd, " no-connect")) {
3252			ssid->disabled = 0;
3253			return 0;
3254		}
3255	}
3256	wpa_s->scan_min_time.sec = 0;
3257	wpa_s->scan_min_time.usec = 0;
3258	wpa_supplicant_enable_network(wpa_s, ssid);
3259
3260	return 0;
3261}
3262
3263
3264static int wpa_supplicant_ctrl_iface_disable_network(
3265	struct wpa_supplicant *wpa_s, char *cmd)
3266{
3267	int id;
3268	struct wpa_ssid *ssid;
3269
3270	/* cmd: "<network id>" or "all" */
3271	if (os_strcmp(cmd, "all") == 0) {
3272		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3273		ssid = NULL;
3274	} else {
3275		id = atoi(cmd);
3276		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3277
3278		ssid = wpa_config_get_network(wpa_s->conf, id);
3279		if (ssid == NULL) {
3280			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3281				   "network id=%d", id);
3282			return -1;
3283		}
3284		if (ssid->disabled == 2) {
3285			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3286				   "DISABLE_NETWORK with persistent P2P "
3287				   "group");
3288			return -1;
3289		}
3290	}
3291	wpa_supplicant_disable_network(wpa_s, ssid);
3292
3293	return 0;
3294}
3295
3296
3297static int wpa_supplicant_ctrl_iface_add_network(
3298	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3299{
3300	struct wpa_ssid *ssid;
3301	int ret;
3302
3303	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3304
3305	ssid = wpa_supplicant_add_network(wpa_s);
3306	if (ssid == NULL)
3307		return -1;
3308
3309	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
3310	if (os_snprintf_error(buflen, ret))
3311		return -1;
3312	return ret;
3313}
3314
3315
3316static int wpa_supplicant_ctrl_iface_remove_network(
3317	struct wpa_supplicant *wpa_s, char *cmd)
3318{
3319	int id;
3320	struct wpa_ssid *ssid;
3321	int result;
3322
3323	/* cmd: "<network id>" or "all" */
3324	if (os_strcmp(cmd, "all") == 0) {
3325		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
3326		if (wpa_s->sched_scanning)
3327			wpa_supplicant_cancel_sched_scan(wpa_s);
3328
3329		eapol_sm_invalidate_cached_session(wpa_s->eapol);
3330		if (wpa_s->current_ssid) {
3331#ifdef CONFIG_SME
3332			wpa_s->sme.prev_bssid_set = 0;
3333#endif /* CONFIG_SME */
3334			wpa_sm_set_config(wpa_s->wpa, NULL);
3335			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3336			if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3337				wpa_s->own_disconnect_req = 1;
3338			wpa_supplicant_deauthenticate(
3339				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3340		}
3341		ssid = wpa_s->conf->ssid;
3342		while (ssid) {
3343			struct wpa_ssid *remove_ssid = ssid;
3344			id = ssid->id;
3345			ssid = ssid->next;
3346			if (wpa_s->last_ssid == remove_ssid)
3347				wpa_s->last_ssid = NULL;
3348			wpas_notify_network_removed(wpa_s, remove_ssid);
3349			wpa_config_remove_network(wpa_s->conf, id);
3350		}
3351		return 0;
3352	}
3353
3354	id = atoi(cmd);
3355	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3356
3357	result = wpa_supplicant_remove_network(wpa_s, id);
3358	if (result == -1) {
3359		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3360			   "id=%d", id);
3361		return -1;
3362	}
3363	if (result == -2) {
3364		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3365			   "network id=%d", id);
3366		return -1;
3367	}
3368	return 0;
3369}
3370
3371
3372static int wpa_supplicant_ctrl_iface_update_network(
3373	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3374	char *name, char *value)
3375{
3376	int ret;
3377
3378	ret = wpa_config_set(ssid, name, value, 0);
3379	if (ret < 0) {
3380		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3381			   "variable '%s'", name);
3382		return -1;
3383	}
3384	if (ret == 1)
3385		return 0; /* No change to the previously configured value */
3386
3387	if (os_strcmp(name, "bssid") != 0 &&
3388	    os_strcmp(name, "bssid_hint") != 0 &&
3389	    os_strcmp(name, "priority") != 0) {
3390		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3391
3392		if (wpa_s->current_ssid == ssid ||
3393		    wpa_s->current_ssid == NULL) {
3394			/*
3395			 * Invalidate the EAP session cache if anything in the
3396			 * current or previously used configuration changes.
3397			 */
3398			eapol_sm_invalidate_cached_session(wpa_s->eapol);
3399		}
3400	}
3401
3402	if ((os_strcmp(name, "psk") == 0 &&
3403	     value[0] == '"' && ssid->ssid_len) ||
3404	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3405		wpa_config_update_psk(ssid);
3406	else if (os_strcmp(name, "priority") == 0)
3407		wpa_config_update_prio_list(wpa_s->conf);
3408
3409	return 0;
3410}
3411
3412
3413static int wpa_supplicant_ctrl_iface_set_network(
3414	struct wpa_supplicant *wpa_s, char *cmd)
3415{
3416	int id, ret, prev_bssid_set, prev_disabled;
3417	struct wpa_ssid *ssid;
3418	char *name, *value;
3419	u8 prev_bssid[ETH_ALEN];
3420
3421	/* cmd: "<network id> <variable name> <value>" */
3422	name = os_strchr(cmd, ' ');
3423	if (name == NULL)
3424		return -1;
3425	*name++ = '\0';
3426
3427	value = os_strchr(name, ' ');
3428	if (value == NULL)
3429		return -1;
3430	*value++ = '\0';
3431
3432	id = atoi(cmd);
3433	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3434		   id, name);
3435	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3436			      (u8 *) value, os_strlen(value));
3437
3438	ssid = wpa_config_get_network(wpa_s->conf, id);
3439	if (ssid == NULL) {
3440		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3441			   "id=%d", id);
3442		return -1;
3443	}
3444
3445	prev_bssid_set = ssid->bssid_set;
3446	prev_disabled = ssid->disabled;
3447	os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3448	ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3449						       value);
3450	if (ret == 0 &&
3451	    (ssid->bssid_set != prev_bssid_set ||
3452	     os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
3453		wpas_notify_network_bssid_set_changed(wpa_s, ssid);
3454
3455	if (prev_disabled != ssid->disabled &&
3456	    (prev_disabled == 2 || ssid->disabled == 2))
3457		wpas_notify_network_type_changed(wpa_s, ssid);
3458
3459	return ret;
3460}
3461
3462
3463static int wpa_supplicant_ctrl_iface_get_network(
3464	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3465{
3466	int id;
3467	size_t res;
3468	struct wpa_ssid *ssid;
3469	char *name, *value;
3470
3471	/* cmd: "<network id> <variable name>" */
3472	name = os_strchr(cmd, ' ');
3473	if (name == NULL || buflen == 0)
3474		return -1;
3475	*name++ = '\0';
3476
3477	id = atoi(cmd);
3478	wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
3479		   id, name);
3480
3481	ssid = wpa_config_get_network(wpa_s->conf, id);
3482	if (ssid == NULL) {
3483		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
3484			   "id=%d", id);
3485		return -1;
3486	}
3487
3488	value = wpa_config_get_no_key(ssid, name);
3489	if (value == NULL) {
3490		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
3491			   "variable '%s'", name);
3492		return -1;
3493	}
3494
3495	res = os_strlcpy(buf, value, buflen);
3496	if (res >= buflen) {
3497		os_free(value);
3498		return -1;
3499	}
3500
3501	os_free(value);
3502
3503	return res;
3504}
3505
3506
3507static int wpa_supplicant_ctrl_iface_dup_network(
3508	struct wpa_supplicant *wpa_s, char *cmd,
3509	struct wpa_supplicant *dst_wpa_s)
3510{
3511	struct wpa_ssid *ssid_s, *ssid_d;
3512	char *name, *id, *value;
3513	int id_s, id_d, ret;
3514
3515	/* cmd: "<src network id> <dst network id> <variable name>" */
3516	id = os_strchr(cmd, ' ');
3517	if (id == NULL)
3518		return -1;
3519	*id++ = '\0';
3520
3521	name = os_strchr(id, ' ');
3522	if (name == NULL)
3523		return -1;
3524	*name++ = '\0';
3525
3526	id_s = atoi(cmd);
3527	id_d = atoi(id);
3528
3529	wpa_printf(MSG_DEBUG,
3530		   "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3531		   wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
3532
3533	ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3534	if (ssid_s == NULL) {
3535		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3536			   "network id=%d", id_s);
3537		return -1;
3538	}
3539
3540	ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
3541	if (ssid_d == NULL) {
3542		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3543			   "network id=%d", id_d);
3544		return -1;
3545	}
3546
3547	value = wpa_config_get(ssid_s, name);
3548	if (value == NULL) {
3549		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3550			   "variable '%s'", name);
3551		return -1;
3552	}
3553
3554	ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
3555						       value);
3556
3557	os_free(value);
3558
3559	return ret;
3560}
3561
3562
3563static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3564						char *buf, size_t buflen)
3565{
3566	char *pos, *end;
3567	struct wpa_cred *cred;
3568	int ret;
3569
3570	pos = buf;
3571	end = buf + buflen;
3572	ret = os_snprintf(pos, end - pos,
3573			  "cred id / realm / username / domain / imsi\n");
3574	if (os_snprintf_error(end - pos, ret))
3575		return pos - buf;
3576	pos += ret;
3577
3578	cred = wpa_s->conf->cred;
3579	while (cred) {
3580		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3581				  cred->id, cred->realm ? cred->realm : "",
3582				  cred->username ? cred->username : "",
3583				  cred->domain ? cred->domain[0] : "",
3584				  cred->imsi ? cred->imsi : "");
3585		if (os_snprintf_error(end - pos, ret))
3586			return pos - buf;
3587		pos += ret;
3588
3589		cred = cred->next;
3590	}
3591
3592	return pos - buf;
3593}
3594
3595
3596static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3597					      char *buf, size_t buflen)
3598{
3599	struct wpa_cred *cred;
3600	int ret;
3601
3602	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3603
3604	cred = wpa_config_add_cred(wpa_s->conf);
3605	if (cred == NULL)
3606		return -1;
3607
3608	wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3609
3610	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
3611	if (os_snprintf_error(buflen, ret))
3612		return -1;
3613	return ret;
3614}
3615
3616
3617static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
3618				 struct wpa_cred *cred)
3619{
3620	struct wpa_ssid *ssid;
3621	char str[20];
3622	int id;
3623
3624	if (cred == NULL) {
3625		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3626		return -1;
3627	}
3628
3629	id = cred->id;
3630	if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
3631		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3632		return -1;
3633	}
3634
3635	wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
3636
3637	/* Remove any network entry created based on the removed credential */
3638	ssid = wpa_s->conf->ssid;
3639	while (ssid) {
3640		if (ssid->parent_cred == cred) {
3641			int res;
3642
3643			wpa_printf(MSG_DEBUG, "Remove network id %d since it "
3644				   "used the removed credential", ssid->id);
3645			res = os_snprintf(str, sizeof(str), "%d", ssid->id);
3646			if (os_snprintf_error(sizeof(str), res))
3647				str[sizeof(str) - 1] = '\0';
3648			ssid = ssid->next;
3649			wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
3650		} else
3651			ssid = ssid->next;
3652	}
3653
3654	return 0;
3655}
3656
3657
3658static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3659						 char *cmd)
3660{
3661	int id;
3662	struct wpa_cred *cred, *prev;
3663
3664	/* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3665	 * "provisioning_sp=<FQDN> */
3666	if (os_strcmp(cmd, "all") == 0) {
3667		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
3668		cred = wpa_s->conf->cred;
3669		while (cred) {
3670			prev = cred;
3671			cred = cred->next;
3672			wpas_ctrl_remove_cred(wpa_s, prev);
3673		}
3674		return 0;
3675	}
3676
3677	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3678		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3679			   cmd + 8);
3680		cred = wpa_s->conf->cred;
3681		while (cred) {
3682			prev = cred;
3683			cred = cred->next;
3684			if (prev->domain) {
3685				size_t i;
3686				for (i = 0; i < prev->num_domain; i++) {
3687					if (os_strcmp(prev->domain[i], cmd + 8)
3688					    != 0)
3689						continue;
3690					wpas_ctrl_remove_cred(wpa_s, prev);
3691					break;
3692				}
3693			}
3694		}
3695		return 0;
3696	}
3697
3698	if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3699		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3700			   cmd + 16);
3701		cred = wpa_s->conf->cred;
3702		while (cred) {
3703			prev = cred;
3704			cred = cred->next;
3705			if (prev->provisioning_sp &&
3706			    os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
3707				wpas_ctrl_remove_cred(wpa_s, prev);
3708		}
3709		return 0;
3710	}
3711
3712	id = atoi(cmd);
3713	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3714
3715	cred = wpa_config_get_cred(wpa_s->conf, id);
3716	return wpas_ctrl_remove_cred(wpa_s, cred);
3717}
3718
3719
3720static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3721					      char *cmd)
3722{
3723	int id;
3724	struct wpa_cred *cred;
3725	char *name, *value;
3726
3727	/* cmd: "<cred id> <variable name> <value>" */
3728	name = os_strchr(cmd, ' ');
3729	if (name == NULL)
3730		return -1;
3731	*name++ = '\0';
3732
3733	value = os_strchr(name, ' ');
3734	if (value == NULL)
3735		return -1;
3736	*value++ = '\0';
3737
3738	id = atoi(cmd);
3739	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3740		   id, name);
3741	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3742			      (u8 *) value, os_strlen(value));
3743
3744	cred = wpa_config_get_cred(wpa_s->conf, id);
3745	if (cred == NULL) {
3746		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3747			   id);
3748		return -1;
3749	}
3750
3751	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3752		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3753			   "variable '%s'", name);
3754		return -1;
3755	}
3756
3757	wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3758
3759	return 0;
3760}
3761
3762
3763static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
3764					      char *cmd, char *buf,
3765					      size_t buflen)
3766{
3767	int id;
3768	size_t res;
3769	struct wpa_cred *cred;
3770	char *name, *value;
3771
3772	/* cmd: "<cred id> <variable name>" */
3773	name = os_strchr(cmd, ' ');
3774	if (name == NULL)
3775		return -1;
3776	*name++ = '\0';
3777
3778	id = atoi(cmd);
3779	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
3780		   id, name);
3781
3782	cred = wpa_config_get_cred(wpa_s->conf, id);
3783	if (cred == NULL) {
3784		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3785			   id);
3786		return -1;
3787	}
3788
3789	value = wpa_config_get_cred_no_key(cred, name);
3790	if (value == NULL) {
3791		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
3792			   name);
3793		return -1;
3794	}
3795
3796	res = os_strlcpy(buf, value, buflen);
3797	if (res >= buflen) {
3798		os_free(value);
3799		return -1;
3800	}
3801
3802	os_free(value);
3803
3804	return res;
3805}
3806
3807
3808#ifndef CONFIG_NO_CONFIG_WRITE
3809static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
3810{
3811	int ret;
3812
3813	if (!wpa_s->conf->update_config) {
3814		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
3815			   "to update configuration (update_config=0)");
3816		return -1;
3817	}
3818
3819	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
3820	if (ret) {
3821		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
3822			   "update configuration");
3823	} else {
3824		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
3825			   " updated");
3826	}
3827
3828	return ret;
3829}
3830#endif /* CONFIG_NO_CONFIG_WRITE */
3831
3832
3833struct cipher_info {
3834	unsigned int capa;
3835	const char *name;
3836	int group_only;
3837};
3838
3839static const struct cipher_info ciphers[] = {
3840	{ WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
3841	{ WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
3842	{ WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
3843	{ WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
3844	{ WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
3845	{ WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
3846	{ WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
3847	{ WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
3848};
3849
3850static const struct cipher_info ciphers_group_mgmt[] = {
3851	{ WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
3852	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
3853	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
3854	{ WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
3855};
3856
3857
3858static int ctrl_iface_get_capability_pairwise(int res, char *strict,
3859					      struct wpa_driver_capa *capa,
3860					      char *buf, size_t buflen)
3861{
3862	int ret;
3863	char *pos, *end;
3864	size_t len;
3865	unsigned int i;
3866
3867	pos = buf;
3868	end = pos + buflen;
3869
3870	if (res < 0) {
3871		if (strict)
3872			return 0;
3873		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
3874		if (len >= buflen)
3875			return -1;
3876		return len;
3877	}
3878
3879	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
3880		if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
3881			ret = os_snprintf(pos, end - pos, "%s%s",
3882					  pos == buf ? "" : " ",
3883					  ciphers[i].name);
3884			if (os_snprintf_error(end - pos, ret))
3885				return pos - buf;
3886			pos += ret;
3887		}
3888	}
3889
3890	return pos - buf;
3891}
3892
3893
3894static int ctrl_iface_get_capability_group(int res, char *strict,
3895					   struct wpa_driver_capa *capa,
3896					   char *buf, size_t buflen)
3897{
3898	int ret;
3899	char *pos, *end;
3900	size_t len;
3901	unsigned int i;
3902
3903	pos = buf;
3904	end = pos + buflen;
3905
3906	if (res < 0) {
3907		if (strict)
3908			return 0;
3909		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
3910		if (len >= buflen)
3911			return -1;
3912		return len;
3913	}
3914
3915	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
3916		if (capa->enc & ciphers[i].capa) {
3917			ret = os_snprintf(pos, end - pos, "%s%s",
3918					  pos == buf ? "" : " ",
3919					  ciphers[i].name);
3920			if (os_snprintf_error(end - pos, ret))
3921				return pos - buf;
3922			pos += ret;
3923		}
3924	}
3925
3926	return pos - buf;
3927}
3928
3929
3930static int ctrl_iface_get_capability_group_mgmt(int res, char *strict,
3931						struct wpa_driver_capa *capa,
3932						char *buf, size_t buflen)
3933{
3934	int ret;
3935	char *pos, *end;
3936	unsigned int i;
3937
3938	pos = buf;
3939	end = pos + buflen;
3940
3941	if (res < 0)
3942		return 0;
3943
3944	for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
3945		if (capa->enc & ciphers_group_mgmt[i].capa) {
3946			ret = os_snprintf(pos, end - pos, "%s%s",
3947					  pos == buf ? "" : " ",
3948					  ciphers_group_mgmt[i].name);
3949			if (os_snprintf_error(end - pos, ret))
3950				return pos - buf;
3951			pos += ret;
3952		}
3953	}
3954
3955	return pos - buf;
3956}
3957
3958
3959static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
3960					      struct wpa_driver_capa *capa,
3961					      char *buf, size_t buflen)
3962{
3963	int ret;
3964	char *pos, *end;
3965	size_t len;
3966
3967	pos = buf;
3968	end = pos + buflen;
3969
3970	if (res < 0) {
3971		if (strict)
3972			return 0;
3973		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
3974				 "NONE", buflen);
3975		if (len >= buflen)
3976			return -1;
3977		return len;
3978	}
3979
3980	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
3981	if (os_snprintf_error(end - pos, ret))
3982		return pos - buf;
3983	pos += ret;
3984
3985	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3986			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
3987		ret = os_snprintf(pos, end - pos, " WPA-EAP");
3988		if (os_snprintf_error(end - pos, ret))
3989			return pos - buf;
3990		pos += ret;
3991	}
3992
3993	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3994			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3995		ret = os_snprintf(pos, end - pos, " WPA-PSK");
3996		if (os_snprintf_error(end - pos, ret))
3997			return pos - buf;
3998		pos += ret;
3999	}
4000
4001	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
4002		ret = os_snprintf(pos, end - pos, " WPA-NONE");
4003		if (os_snprintf_error(end - pos, ret))
4004			return pos - buf;
4005		pos += ret;
4006	}
4007
4008#ifdef CONFIG_SUITEB
4009	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
4010		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4011		if (os_snprintf_error(end - pos, ret))
4012			return pos - buf;
4013		pos += ret;
4014	}
4015#endif /* CONFIG_SUITEB */
4016#ifdef CONFIG_SUITEB192
4017	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
4018		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4019		if (os_snprintf_error(end - pos, ret))
4020			return pos - buf;
4021		pos += ret;
4022	}
4023#endif /* CONFIG_SUITEB192 */
4024#ifdef CONFIG_OWE
4025	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
4026		ret = os_snprintf(pos, end - pos, " OWE");
4027		if (os_snprintf_error(end - pos, ret))
4028			return pos - buf;
4029		pos += ret;
4030	}
4031#endif /* CONFIG_OWE */
4032#ifdef CONFIG_DPP
4033	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
4034		ret = os_snprintf(pos, end - pos, " DPP");
4035		if (os_snprintf_error(end - pos, ret))
4036			return pos - buf;
4037		pos += ret;
4038	}
4039#endif /* CONFIG_DPP */
4040#ifdef CONFIG_FILS
4041	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
4042		ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4043		if (os_snprintf_error(end - pos, ret))
4044			return pos - buf;
4045		pos += ret;
4046	}
4047	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
4048		ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4049		if (os_snprintf_error(end - pos, ret))
4050			return pos - buf;
4051		pos += ret;
4052	}
4053#ifdef CONFIG_IEEE80211R
4054	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
4055		ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4056		if (os_snprintf_error(end - pos, ret))
4057			return pos - buf;
4058		pos += ret;
4059	}
4060	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
4061		ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4062		if (os_snprintf_error(end - pos, ret))
4063			return pos - buf;
4064		pos += ret;
4065	}
4066#endif /* CONFIG_IEEE80211R */
4067#endif /* CONFIG_FILS */
4068#ifdef CONFIG_IEEE80211R
4069	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
4070		ret = os_snprintf(pos, end - pos, " FT-PSK");
4071		if (os_snprintf_error(end - pos, ret))
4072			return pos - buf;
4073		pos += ret;
4074	}
4075#endif /* CONFIG_IEEE80211R */
4076#ifdef CONFIG_SAE
4077	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
4078		ret = os_snprintf(pos, end - pos, " SAE");
4079		if (os_snprintf_error(end - pos, ret))
4080			return pos - buf;
4081		pos += ret;
4082	}
4083#endif /* CONFIG_SAE */
4084
4085	return pos - buf;
4086}
4087
4088
4089static int ctrl_iface_get_capability_proto(int res, char *strict,
4090					   struct wpa_driver_capa *capa,
4091					   char *buf, size_t buflen)
4092{
4093	int ret;
4094	char *pos, *end;
4095	size_t len;
4096
4097	pos = buf;
4098	end = pos + buflen;
4099
4100	if (res < 0) {
4101		if (strict)
4102			return 0;
4103		len = os_strlcpy(buf, "RSN WPA", buflen);
4104		if (len >= buflen)
4105			return -1;
4106		return len;
4107	}
4108
4109	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4110			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4111		ret = os_snprintf(pos, end - pos, "%sRSN",
4112				  pos == buf ? "" : " ");
4113		if (os_snprintf_error(end - pos, ret))
4114			return pos - buf;
4115		pos += ret;
4116	}
4117
4118	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4119			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
4120		ret = os_snprintf(pos, end - pos, "%sWPA",
4121				  pos == buf ? "" : " ");
4122		if (os_snprintf_error(end - pos, ret))
4123			return pos - buf;
4124		pos += ret;
4125	}
4126
4127	return pos - buf;
4128}
4129
4130
4131static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
4132					      int res, char *strict,
4133					      struct wpa_driver_capa *capa,
4134					      char *buf, size_t buflen)
4135{
4136	int ret;
4137	char *pos, *end;
4138	size_t len;
4139
4140	pos = buf;
4141	end = pos + buflen;
4142
4143	if (res < 0) {
4144		if (strict)
4145			return 0;
4146		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4147		if (len >= buflen)
4148			return -1;
4149		return len;
4150	}
4151
4152	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
4153		ret = os_snprintf(pos, end - pos, "%sOPEN",
4154				  pos == buf ? "" : " ");
4155		if (os_snprintf_error(end - pos, ret))
4156			return pos - buf;
4157		pos += ret;
4158	}
4159
4160	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4161		ret = os_snprintf(pos, end - pos, "%sSHARED",
4162				  pos == buf ? "" : " ");
4163		if (os_snprintf_error(end - pos, ret))
4164			return pos - buf;
4165		pos += ret;
4166	}
4167
4168	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
4169		ret = os_snprintf(pos, end - pos, "%sLEAP",
4170				  pos == buf ? "" : " ");
4171		if (os_snprintf_error(end - pos, ret))
4172			return pos - buf;
4173		pos += ret;
4174	}
4175
4176#ifdef CONFIG_SAE
4177	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4178		ret = os_snprintf(pos, end - pos, "%sSAE",
4179				  pos == buf ? "" : " ");
4180		if (os_snprintf_error(end - pos, ret))
4181			return pos - buf;
4182		pos += ret;
4183	}
4184#endif /* CONFIG_SAE */
4185
4186#ifdef CONFIG_FILS
4187	if (wpa_is_fils_supported(wpa_s)) {
4188		ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4189				  pos == buf ? "" : " ");
4190		if (os_snprintf_error(end - pos, ret))
4191			return pos - buf;
4192		pos += ret;
4193	}
4194
4195#ifdef CONFIG_FILS_SK_PFS
4196	if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4197		ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4198				  pos == buf ? "" : " ");
4199		if (os_snprintf_error(end - pos, ret))
4200			return pos - buf;
4201		pos += ret;
4202	}
4203#endif /* CONFIG_FILS_SK_PFS */
4204#endif /* CONFIG_FILS */
4205
4206	return pos - buf;
4207}
4208
4209
4210static int ctrl_iface_get_capability_modes(int res, char *strict,
4211					   struct wpa_driver_capa *capa,
4212					   char *buf, size_t buflen)
4213{
4214	int ret;
4215	char *pos, *end;
4216	size_t len;
4217
4218	pos = buf;
4219	end = pos + buflen;
4220
4221	if (res < 0) {
4222		if (strict)
4223			return 0;
4224		len = os_strlcpy(buf, "IBSS AP", buflen);
4225		if (len >= buflen)
4226			return -1;
4227		return len;
4228	}
4229
4230	if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
4231		ret = os_snprintf(pos, end - pos, "%sIBSS",
4232				  pos == buf ? "" : " ");
4233		if (os_snprintf_error(end - pos, ret))
4234			return pos - buf;
4235		pos += ret;
4236	}
4237
4238	if (capa->flags & WPA_DRIVER_FLAGS_AP) {
4239		ret = os_snprintf(pos, end - pos, "%sAP",
4240				  pos == buf ? "" : " ");
4241		if (os_snprintf_error(end - pos, ret))
4242			return pos - buf;
4243		pos += ret;
4244	}
4245
4246#ifdef CONFIG_MESH
4247	if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4248		ret = os_snprintf(pos, end - pos, "%sMESH",
4249				  pos == buf ? "" : " ");
4250		if (os_snprintf_error(end - pos, ret))
4251			return pos - buf;
4252		pos += ret;
4253	}
4254#endif /* CONFIG_MESH */
4255
4256	return pos - buf;
4257}
4258
4259
4260static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4261					      char *buf, size_t buflen)
4262{
4263	struct hostapd_channel_data *chnl;
4264	int ret, i, j;
4265	char *pos, *end, *hmode;
4266
4267	pos = buf;
4268	end = pos + buflen;
4269
4270	for (j = 0; j < wpa_s->hw.num_modes; j++) {
4271		switch (wpa_s->hw.modes[j].mode) {
4272		case HOSTAPD_MODE_IEEE80211B:
4273			hmode = "B";
4274			break;
4275		case HOSTAPD_MODE_IEEE80211G:
4276			hmode = "G";
4277			break;
4278		case HOSTAPD_MODE_IEEE80211A:
4279			hmode = "A";
4280			break;
4281		case HOSTAPD_MODE_IEEE80211AD:
4282			hmode = "AD";
4283			break;
4284		default:
4285			continue;
4286		}
4287		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
4288		if (os_snprintf_error(end - pos, ret))
4289			return pos - buf;
4290		pos += ret;
4291		chnl = wpa_s->hw.modes[j].channels;
4292		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4293			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4294				continue;
4295			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
4296			if (os_snprintf_error(end - pos, ret))
4297				return pos - buf;
4298			pos += ret;
4299		}
4300		ret = os_snprintf(pos, end - pos, "\n");
4301		if (os_snprintf_error(end - pos, ret))
4302			return pos - buf;
4303		pos += ret;
4304	}
4305
4306	return pos - buf;
4307}
4308
4309
4310static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4311					  char *buf, size_t buflen)
4312{
4313	struct hostapd_channel_data *chnl;
4314	int ret, i, j;
4315	char *pos, *end, *hmode;
4316
4317	pos = buf;
4318	end = pos + buflen;
4319
4320	for (j = 0; j < wpa_s->hw.num_modes; j++) {
4321		switch (wpa_s->hw.modes[j].mode) {
4322		case HOSTAPD_MODE_IEEE80211B:
4323			hmode = "B";
4324			break;
4325		case HOSTAPD_MODE_IEEE80211G:
4326			hmode = "G";
4327			break;
4328		case HOSTAPD_MODE_IEEE80211A:
4329			hmode = "A";
4330			break;
4331		case HOSTAPD_MODE_IEEE80211AD:
4332			hmode = "AD";
4333			break;
4334		default:
4335			continue;
4336		}
4337		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4338				  hmode);
4339		if (os_snprintf_error(end - pos, ret))
4340			return pos - buf;
4341		pos += ret;
4342		chnl = wpa_s->hw.modes[j].channels;
4343		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4344			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4345				continue;
4346			ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
4347					  chnl[i].chan, chnl[i].freq,
4348					  chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4349					  " (NO_IR)" : "",
4350					  chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4351					  " (DFS)" : "");
4352
4353			if (os_snprintf_error(end - pos, ret))
4354				return pos - buf;
4355			pos += ret;
4356		}
4357		ret = os_snprintf(pos, end - pos, "\n");
4358		if (os_snprintf_error(end - pos, ret))
4359			return pos - buf;
4360		pos += ret;
4361	}
4362
4363	return pos - buf;
4364}
4365
4366
4367static int wpa_supplicant_ctrl_iface_get_capability(
4368	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4369	size_t buflen)
4370{
4371	struct wpa_driver_capa capa;
4372	int res;
4373	char *strict;
4374	char field[30];
4375	size_t len;
4376
4377	/* Determine whether or not strict checking was requested */
4378	len = os_strlcpy(field, _field, sizeof(field));
4379	if (len >= sizeof(field))
4380		return -1;
4381	strict = os_strchr(field, ' ');
4382	if (strict != NULL) {
4383		*strict++ = '\0';
4384		if (os_strcmp(strict, "strict") != 0)
4385			return -1;
4386	}
4387
4388	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
4389		field, strict ? strict : "");
4390
4391	if (os_strcmp(field, "eap") == 0) {
4392		return eap_get_names(buf, buflen);
4393	}
4394
4395	res = wpa_drv_get_capa(wpa_s, &capa);
4396
4397	if (os_strcmp(field, "pairwise") == 0)
4398		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4399							  buf, buflen);
4400
4401	if (os_strcmp(field, "group") == 0)
4402		return ctrl_iface_get_capability_group(res, strict, &capa,
4403						       buf, buflen);
4404
4405	if (os_strcmp(field, "group_mgmt") == 0)
4406		return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4407							    buf, buflen);
4408
4409	if (os_strcmp(field, "key_mgmt") == 0)
4410		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
4411							  buf, buflen);
4412
4413	if (os_strcmp(field, "proto") == 0)
4414		return ctrl_iface_get_capability_proto(res, strict, &capa,
4415						       buf, buflen);
4416
4417	if (os_strcmp(field, "auth_alg") == 0)
4418		return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4419							  &capa, buf, buflen);
4420
4421	if (os_strcmp(field, "modes") == 0)
4422		return ctrl_iface_get_capability_modes(res, strict, &capa,
4423						       buf, buflen);
4424
4425	if (os_strcmp(field, "channels") == 0)
4426		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4427
4428	if (os_strcmp(field, "freq") == 0)
4429		return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4430
4431#ifdef CONFIG_TDLS
4432	if (os_strcmp(field, "tdls") == 0)
4433		return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4434#endif /* CONFIG_TDLS */
4435
4436#ifdef CONFIG_ERP
4437	if (os_strcmp(field, "erp") == 0) {
4438		res = os_snprintf(buf, buflen, "ERP");
4439		if (os_snprintf_error(buflen, res))
4440			return -1;
4441		return res;
4442	}
4443#endif /* CONFIG_EPR */
4444
4445#ifdef CONFIG_FIPS
4446	if (os_strcmp(field, "fips") == 0) {
4447		res = os_snprintf(buf, buflen, "FIPS");
4448		if (os_snprintf_error(buflen, res))
4449			return -1;
4450		return res;
4451	}
4452#endif /* CONFIG_FIPS */
4453
4454#ifdef CONFIG_ACS
4455	if (os_strcmp(field, "acs") == 0) {
4456		res = os_snprintf(buf, buflen, "ACS");
4457		if (os_snprintf_error(buflen, res))
4458			return -1;
4459		return res;
4460	}
4461#endif /* CONFIG_ACS */
4462
4463#ifdef CONFIG_FILS
4464	if (os_strcmp(field, "fils") == 0) {
4465#ifdef CONFIG_FILS_SK_PFS
4466		if (wpa_is_fils_supported(wpa_s) &&
4467		    wpa_is_fils_sk_pfs_supported(wpa_s)) {
4468			res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4469			if (os_snprintf_error(buflen, res))
4470				return -1;
4471			return res;
4472		}
4473#endif /* CONFIG_FILS_SK_PFS */
4474
4475		if (wpa_is_fils_supported(wpa_s)) {
4476			res = os_snprintf(buf, buflen, "FILS");
4477			if (os_snprintf_error(buflen, res))
4478				return -1;
4479			return res;
4480		}
4481	}
4482#endif /* CONFIG_FILS */
4483
4484	if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4485		res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4486		if (os_snprintf_error(buflen, res))
4487			return -1;
4488		return res;
4489	}
4490
4491#ifdef CONFIG_DPP
4492	if (os_strcmp(field, "dpp") == 0) {
4493#ifdef CONFIG_DPP2
4494		res = os_snprintf(buf, buflen, "DPP=2");
4495#else /* CONFIG_DPP2 */
4496		res = os_snprintf(buf, buflen, "DPP=1");
4497#endif /* CONFIG_DPP2 */
4498		if (os_snprintf_error(buflen, res))
4499			return -1;
4500		return res;
4501	}
4502#endif /* CONFIG_DPP */
4503
4504	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
4505		   field);
4506
4507	return -1;
4508}
4509
4510
4511#ifdef CONFIG_INTERWORKING
4512static char * anqp_add_hex(char *pos, char *end, const char *title,
4513			   struct wpabuf *data)
4514{
4515	char *start = pos;
4516	size_t i;
4517	int ret;
4518	const u8 *d;
4519
4520	if (data == NULL)
4521		return start;
4522
4523	ret = os_snprintf(pos, end - pos, "%s=", title);
4524	if (os_snprintf_error(end - pos, ret))
4525		return start;
4526	pos += ret;
4527
4528	d = wpabuf_head_u8(data);
4529	for (i = 0; i < wpabuf_len(data); i++) {
4530		ret = os_snprintf(pos, end - pos, "%02x", *d++);
4531		if (os_snprintf_error(end - pos, ret))
4532			return start;
4533		pos += ret;
4534	}
4535
4536	ret = os_snprintf(pos, end - pos, "\n");
4537	if (os_snprintf_error(end - pos, ret))
4538		return start;
4539	pos += ret;
4540
4541	return pos;
4542}
4543#endif /* CONFIG_INTERWORKING */
4544
4545
4546#ifdef CONFIG_FILS
4547static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
4548{
4549	char *start = pos;
4550	const u8 *ie, *ie_end;
4551	u16 info, realms;
4552	int ret;
4553
4554	ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
4555	if (!ie)
4556		return 0;
4557	ie_end = ie + 2 + ie[1];
4558	ie += 2;
4559	if (ie_end - ie < 2)
4560		return -1;
4561
4562	info = WPA_GET_LE16(ie);
4563	ie += 2;
4564	ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
4565	if (os_snprintf_error(end - pos, ret))
4566		return 0;
4567	pos += ret;
4568
4569	if (info & BIT(7)) {
4570		/* Cache Identifier Included */
4571		if (ie_end - ie < 2)
4572			return -1;
4573		ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
4574				  ie[0], ie[1]);
4575		if (os_snprintf_error(end - pos, ret))
4576			return 0;
4577		pos += ret;
4578		ie += 2;
4579	}
4580
4581	if (info & BIT(8)) {
4582		/* HESSID Included */
4583		if (ie_end - ie < ETH_ALEN)
4584			return -1;
4585		ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
4586				  MAC2STR(ie));
4587		if (os_snprintf_error(end - pos, ret))
4588			return 0;
4589		pos += ret;
4590		ie += ETH_ALEN;
4591	}
4592
4593	realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
4594	if (realms) {
4595		if (ie_end - ie < realms * 2)
4596			return -1;
4597		ret = os_snprintf(pos, end - pos, "fils_realms=");
4598		if (os_snprintf_error(end - pos, ret))
4599			return 0;
4600		pos += ret;
4601
4602		ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
4603		if (ret <= 0)
4604			return 0;
4605		pos += ret;
4606		ie += realms * 2;
4607		ret = os_snprintf(pos, end - pos, "\n");
4608		if (os_snprintf_error(end - pos, ret))
4609			return 0;
4610		pos += ret;
4611	}
4612
4613	return pos - start;
4614}
4615#endif /* CONFIG_FILS */
4616
4617
4618static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
4619			  unsigned long mask, char *buf, size_t buflen)
4620{
4621	size_t i;
4622	int ret;
4623	char *pos, *end;
4624	const u8 *ie, *ie2, *osen_ie, *mesh, *owe;
4625
4626	pos = buf;
4627	end = buf + buflen;
4628
4629	if (mask & WPA_BSS_MASK_ID) {
4630		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
4631		if (os_snprintf_error(end - pos, ret))
4632			return 0;
4633		pos += ret;
4634	}
4635
4636	if (mask & WPA_BSS_MASK_BSSID) {
4637		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
4638				  MAC2STR(bss->bssid));
4639		if (os_snprintf_error(end - pos, ret))
4640			return 0;
4641		pos += ret;
4642	}
4643
4644	if (mask & WPA_BSS_MASK_FREQ) {
4645		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
4646		if (os_snprintf_error(end - pos, ret))
4647			return 0;
4648		pos += ret;
4649	}
4650
4651	if (mask & WPA_BSS_MASK_BEACON_INT) {
4652		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
4653				  bss->beacon_int);
4654		if (os_snprintf_error(end - pos, ret))
4655			return 0;
4656		pos += ret;
4657	}
4658
4659	if (mask & WPA_BSS_MASK_CAPABILITIES) {
4660		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
4661				  bss->caps);
4662		if (os_snprintf_error(end - pos, ret))
4663			return 0;
4664		pos += ret;
4665	}
4666
4667	if (mask & WPA_BSS_MASK_QUAL) {
4668		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
4669		if (os_snprintf_error(end - pos, ret))
4670			return 0;
4671		pos += ret;
4672	}
4673
4674	if (mask & WPA_BSS_MASK_NOISE) {
4675		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
4676		if (os_snprintf_error(end - pos, ret))
4677			return 0;
4678		pos += ret;
4679	}
4680
4681	if (mask & WPA_BSS_MASK_LEVEL) {
4682		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
4683		if (os_snprintf_error(end - pos, ret))
4684			return 0;
4685		pos += ret;
4686	}
4687
4688	if (mask & WPA_BSS_MASK_TSF) {
4689		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
4690				  (unsigned long long) bss->tsf);
4691		if (os_snprintf_error(end - pos, ret))
4692			return 0;
4693		pos += ret;
4694	}
4695
4696	if (mask & WPA_BSS_MASK_AGE) {
4697		struct os_reltime now;
4698
4699		os_get_reltime(&now);
4700		ret = os_snprintf(pos, end - pos, "age=%d\n",
4701				  (int) (now.sec - bss->last_update.sec));
4702		if (os_snprintf_error(end - pos, ret))
4703			return 0;
4704		pos += ret;
4705	}
4706
4707	if (mask & WPA_BSS_MASK_IE) {
4708		ret = os_snprintf(pos, end - pos, "ie=");
4709		if (os_snprintf_error(end - pos, ret))
4710			return 0;
4711		pos += ret;
4712
4713		ie = (const u8 *) (bss + 1);
4714		for (i = 0; i < bss->ie_len; i++) {
4715			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
4716			if (os_snprintf_error(end - pos, ret))
4717				return 0;
4718			pos += ret;
4719		}
4720
4721		ret = os_snprintf(pos, end - pos, "\n");
4722		if (os_snprintf_error(end - pos, ret))
4723			return 0;
4724		pos += ret;
4725	}
4726
4727	if (mask & WPA_BSS_MASK_FLAGS) {
4728		ret = os_snprintf(pos, end - pos, "flags=");
4729		if (os_snprintf_error(end - pos, ret))
4730			return 0;
4731		pos += ret;
4732
4733		mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
4734
4735		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
4736		if (ie)
4737			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
4738						    2 + ie[1]);
4739		ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4740		if (ie2)
4741			pos = wpa_supplicant_ie_txt(pos, end,
4742						    mesh ? "RSN" : "WPA2", ie2,
4743						    2 + ie2[1]);
4744		osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
4745		if (osen_ie)
4746			pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
4747						    osen_ie, 2 + osen_ie[1]);
4748		owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4749		if (owe) {
4750			ret = os_snprintf(
4751				pos, end - pos,
4752				ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
4753			if (os_snprintf_error(end - pos, ret))
4754				return 0;
4755			pos += ret;
4756		}
4757		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
4758		if (!ie && !ie2 && !osen_ie &&
4759		    (bss->caps & IEEE80211_CAP_PRIVACY)) {
4760			ret = os_snprintf(pos, end - pos, "[WEP]");
4761			if (os_snprintf_error(end - pos, ret))
4762				return 0;
4763			pos += ret;
4764		}
4765
4766		if (mesh) {
4767			ret = os_snprintf(pos, end - pos, "[MESH]");
4768			if (os_snprintf_error(end - pos, ret))
4769				return 0;
4770			pos += ret;
4771		}
4772
4773		if (bss_is_dmg(bss)) {
4774			const char *s;
4775			ret = os_snprintf(pos, end - pos, "[DMG]");
4776			if (os_snprintf_error(end - pos, ret))
4777				return 0;
4778			pos += ret;
4779			switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
4780			case IEEE80211_CAP_DMG_IBSS:
4781				s = "[IBSS]";
4782				break;
4783			case IEEE80211_CAP_DMG_AP:
4784				s = "[ESS]";
4785				break;
4786			case IEEE80211_CAP_DMG_PBSS:
4787				s = "[PBSS]";
4788				break;
4789			default:
4790				s = "";
4791				break;
4792			}
4793			ret = os_snprintf(pos, end - pos, "%s", s);
4794			if (os_snprintf_error(end - pos, ret))
4795				return 0;
4796			pos += ret;
4797		} else {
4798			if (bss->caps & IEEE80211_CAP_IBSS) {
4799				ret = os_snprintf(pos, end - pos, "[IBSS]");
4800				if (os_snprintf_error(end - pos, ret))
4801					return 0;
4802				pos += ret;
4803			}
4804			if (bss->caps & IEEE80211_CAP_ESS) {
4805				ret = os_snprintf(pos, end - pos, "[ESS]");
4806				if (os_snprintf_error(end - pos, ret))
4807					return 0;
4808				pos += ret;
4809			}
4810		}
4811		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
4812		    wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
4813			ret = os_snprintf(pos, end - pos, "[P2P]");
4814			if (os_snprintf_error(end - pos, ret))
4815				return 0;
4816			pos += ret;
4817		}
4818#ifdef CONFIG_HS20
4819		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
4820			ret = os_snprintf(pos, end - pos, "[HS20]");
4821			if (os_snprintf_error(end - pos, ret))
4822				return 0;
4823			pos += ret;
4824		}
4825#endif /* CONFIG_HS20 */
4826#ifdef CONFIG_FILS
4827		if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
4828			ret = os_snprintf(pos, end - pos, "[FILS]");
4829			if (os_snprintf_error(end - pos, ret))
4830				return 0;
4831			pos += ret;
4832		}
4833#endif /* CONFIG_FILS */
4834#ifdef CONFIG_FST
4835		if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
4836			ret = os_snprintf(pos, end - pos, "[FST]");
4837			if (os_snprintf_error(end - pos, ret))
4838				return 0;
4839			pos += ret;
4840		}
4841#endif /* CONFIG_FST */
4842		if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
4843			ret = os_snprintf(pos, end - pos, "[UTF-8]");
4844			if (os_snprintf_error(end - pos, ret))
4845				return 0;
4846			pos += ret;
4847		}
4848
4849		ret = os_snprintf(pos, end - pos, "\n");
4850		if (os_snprintf_error(end - pos, ret))
4851			return 0;
4852		pos += ret;
4853	}
4854
4855	if (mask & WPA_BSS_MASK_SSID) {
4856		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
4857				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
4858		if (os_snprintf_error(end - pos, ret))
4859			return 0;
4860		pos += ret;
4861	}
4862
4863#ifdef CONFIG_WPS
4864	if (mask & WPA_BSS_MASK_WPS_SCAN) {
4865		ie = (const u8 *) (bss + 1);
4866		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
4867		if (ret >= end - pos)
4868			return 0;
4869		if (ret > 0)
4870			pos += ret;
4871	}
4872#endif /* CONFIG_WPS */
4873
4874#ifdef CONFIG_P2P
4875	if (mask & WPA_BSS_MASK_P2P_SCAN) {
4876		ie = (const u8 *) (bss + 1);
4877		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
4878		if (ret >= end - pos)
4879			return 0;
4880		if (ret > 0)
4881			pos += ret;
4882	}
4883#endif /* CONFIG_P2P */
4884
4885#ifdef CONFIG_WIFI_DISPLAY
4886	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
4887		struct wpabuf *wfd;
4888		ie = (const u8 *) (bss + 1);
4889		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
4890						  WFD_IE_VENDOR_TYPE);
4891		if (wfd) {
4892			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
4893			if (os_snprintf_error(end - pos, ret)) {
4894				wpabuf_free(wfd);
4895				return 0;
4896			}
4897			pos += ret;
4898
4899			pos += wpa_snprintf_hex(pos, end - pos,
4900						wpabuf_head(wfd),
4901						wpabuf_len(wfd));
4902			wpabuf_free(wfd);
4903
4904			ret = os_snprintf(pos, end - pos, "\n");
4905			if (os_snprintf_error(end - pos, ret))
4906				return 0;
4907			pos += ret;
4908		}
4909	}
4910#endif /* CONFIG_WIFI_DISPLAY */
4911
4912#ifdef CONFIG_INTERWORKING
4913	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
4914		struct wpa_bss_anqp *anqp = bss->anqp;
4915		struct wpa_bss_anqp_elem *elem;
4916
4917		pos = anqp_add_hex(pos, end, "anqp_capability_list",
4918				   anqp->capability_list);
4919		pos = anqp_add_hex(pos, end, "anqp_venue_name",
4920				   anqp->venue_name);
4921		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
4922				   anqp->network_auth_type);
4923		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
4924				   anqp->roaming_consortium);
4925		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
4926				   anqp->ip_addr_type_availability);
4927		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
4928				   anqp->nai_realm);
4929		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
4930		pos = anqp_add_hex(pos, end, "anqp_domain_name",
4931				   anqp->domain_name);
4932		pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
4933				   anqp->fils_realm_info);
4934#ifdef CONFIG_HS20
4935		pos = anqp_add_hex(pos, end, "hs20_capability_list",
4936				   anqp->hs20_capability_list);
4937		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
4938				   anqp->hs20_operator_friendly_name);
4939		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
4940				   anqp->hs20_wan_metrics);
4941		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
4942				   anqp->hs20_connection_capability);
4943		pos = anqp_add_hex(pos, end, "hs20_operating_class",
4944				   anqp->hs20_operating_class);
4945		pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
4946				   anqp->hs20_osu_providers_list);
4947		pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
4948				   anqp->hs20_operator_icon_metadata);
4949		pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
4950				   anqp->hs20_osu_providers_nai_list);
4951#endif /* CONFIG_HS20 */
4952
4953		dl_list_for_each(elem, &anqp->anqp_elems,
4954				 struct wpa_bss_anqp_elem, list) {
4955			char title[20];
4956
4957			os_snprintf(title, sizeof(title), "anqp[%u]",
4958				    elem->infoid);
4959			pos = anqp_add_hex(pos, end, title, elem->payload);
4960		}
4961	}
4962#endif /* CONFIG_INTERWORKING */
4963
4964#ifdef CONFIG_MESH
4965	if (mask & WPA_BSS_MASK_MESH_SCAN) {
4966		ie = (const u8 *) (bss + 1);
4967		ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
4968		if (ret >= end - pos)
4969			return 0;
4970		if (ret > 0)
4971			pos += ret;
4972	}
4973#endif /* CONFIG_MESH */
4974
4975	if (mask & WPA_BSS_MASK_SNR) {
4976		ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
4977		if (os_snprintf_error(end - pos, ret))
4978			return 0;
4979		pos += ret;
4980	}
4981
4982	if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
4983		ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
4984				  bss->est_throughput);
4985		if (os_snprintf_error(end - pos, ret))
4986			return 0;
4987		pos += ret;
4988	}
4989
4990#ifdef CONFIG_FST
4991	if (mask & WPA_BSS_MASK_FST) {
4992		ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
4993		if (ret < 0 || ret >= end - pos)
4994			return 0;
4995		pos += ret;
4996	}
4997#endif /* CONFIG_FST */
4998
4999	if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5000		ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5001				  bss->last_update_idx);
5002		if (os_snprintf_error(end - pos, ret))
5003			return 0;
5004		pos += ret;
5005	}
5006
5007	if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5008		ret = os_snprintf(pos, end - pos, "beacon_ie=");
5009		if (os_snprintf_error(end - pos, ret))
5010			return 0;
5011		pos += ret;
5012
5013		ie = (const u8 *) (bss + 1);
5014		ie += bss->ie_len;
5015		for (i = 0; i < bss->beacon_ie_len; i++) {
5016			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5017			if (os_snprintf_error(end - pos, ret))
5018				return 0;
5019			pos += ret;
5020		}
5021
5022		ret = os_snprintf(pos, end - pos, "\n");
5023		if (os_snprintf_error(end - pos, ret))
5024			return 0;
5025		pos += ret;
5026	}
5027
5028#ifdef CONFIG_FILS
5029	if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5030		ret = print_fils_indication(bss, pos, end);
5031		if (ret < 0)
5032			return 0;
5033		pos += ret;
5034	}
5035#endif /* CONFIG_FILS */
5036
5037	if (mask & WPA_BSS_MASK_DELIM) {
5038		ret = os_snprintf(pos, end - pos, "====\n");
5039		if (os_snprintf_error(end - pos, ret))
5040			return 0;
5041		pos += ret;
5042	}
5043
5044	return pos - buf;
5045}
5046
5047
5048static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5049					 const char *cmd, char *buf,
5050					 size_t buflen)
5051{
5052	u8 bssid[ETH_ALEN];
5053	size_t i;
5054	struct wpa_bss *bss;
5055	struct wpa_bss *bsslast = NULL;
5056	struct dl_list *next;
5057	int ret = 0;
5058	int len;
5059	char *ctmp, *end = buf + buflen;
5060	unsigned long mask = WPA_BSS_MASK_ALL;
5061
5062	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5063		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5064			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
5065					    list_id);
5066			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5067					       list_id);
5068		} else { /* N1-N2 */
5069			unsigned int id1, id2;
5070
5071			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5072				wpa_printf(MSG_INFO, "Wrong BSS range "
5073					   "format");
5074				return 0;
5075			}
5076
5077			if (*(cmd + 6) == '-')
5078				id1 = 0;
5079			else
5080				id1 = atoi(cmd + 6);
5081			ctmp++;
5082			if (*ctmp >= '0' && *ctmp <= '9')
5083				id2 = atoi(ctmp);
5084			else
5085				id2 = (unsigned int) -1;
5086			bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5087			if (id2 == (unsigned int) -1)
5088				bsslast = dl_list_last(&wpa_s->bss_id,
5089						       struct wpa_bss,
5090						       list_id);
5091			else {
5092				bsslast = wpa_bss_get_id(wpa_s, id2);
5093				if (bsslast == NULL && bss && id2 > id1) {
5094					struct wpa_bss *tmp = bss;
5095					for (;;) {
5096						next = tmp->list_id.next;
5097						if (next == &wpa_s->bss_id)
5098							break;
5099						tmp = dl_list_entry(
5100							next, struct wpa_bss,
5101							list_id);
5102						if (tmp->id > id2)
5103							break;
5104						bsslast = tmp;
5105					}
5106				}
5107			}
5108		}
5109	} else if (os_strncmp(cmd, "FIRST", 5) == 0)
5110		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
5111	else if (os_strncmp(cmd, "LAST", 4) == 0)
5112		bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
5113	else if (os_strncmp(cmd, "ID-", 3) == 0) {
5114		i = atoi(cmd + 3);
5115		bss = wpa_bss_get_id(wpa_s, i);
5116	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5117		i = atoi(cmd + 5);
5118		bss = wpa_bss_get_id(wpa_s, i);
5119		if (bss) {
5120			next = bss->list_id.next;
5121			if (next == &wpa_s->bss_id)
5122				bss = NULL;
5123			else
5124				bss = dl_list_entry(next, struct wpa_bss,
5125						    list_id);
5126		}
5127	} else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5128		bss = wpa_s->current_bss;
5129#ifdef CONFIG_P2P
5130	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5131		if (hwaddr_aton(cmd + 13, bssid) == 0)
5132			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5133		else
5134			bss = NULL;
5135#endif /* CONFIG_P2P */
5136	} else if (hwaddr_aton(cmd, bssid) == 0)
5137		bss = wpa_bss_get_bssid(wpa_s, bssid);
5138	else {
5139		struct wpa_bss *tmp;
5140		i = atoi(cmd);
5141		bss = NULL;
5142		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5143		{
5144			if (i == 0) {
5145				bss = tmp;
5146				break;
5147			}
5148			i--;
5149		}
5150	}
5151
5152	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5153		mask = strtoul(ctmp + 5, NULL, 0x10);
5154		if (mask == 0)
5155			mask = WPA_BSS_MASK_ALL;
5156	}
5157
5158	if (bss == NULL)
5159		return 0;
5160
5161	if (bsslast == NULL)
5162		bsslast = bss;
5163	do {
5164		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5165		ret += len;
5166		buf += len;
5167		buflen -= len;
5168		if (bss == bsslast) {
5169			if ((mask & WPA_BSS_MASK_DELIM) && len &&
5170			    (bss == dl_list_last(&wpa_s->bss_id,
5171						 struct wpa_bss, list_id))) {
5172				int res;
5173
5174				res = os_snprintf(buf - 5, end - buf + 5,
5175						  "####\n");
5176				if (os_snprintf_error(end - buf + 5, res)) {
5177					wpa_printf(MSG_DEBUG,
5178						   "Could not add end delim");
5179				}
5180			}
5181			break;
5182		}
5183		next = bss->list_id.next;
5184		if (next == &wpa_s->bss_id)
5185			break;
5186		bss = dl_list_entry(next, struct wpa_bss, list_id);
5187	} while (bss && len);
5188
5189	return ret;
5190}
5191
5192
5193static int wpa_supplicant_ctrl_iface_ap_scan(
5194	struct wpa_supplicant *wpa_s, char *cmd)
5195{
5196	int ap_scan = atoi(cmd);
5197	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5198}
5199
5200
5201static int wpa_supplicant_ctrl_iface_scan_interval(
5202	struct wpa_supplicant *wpa_s, char *cmd)
5203{
5204	int scan_int = atoi(cmd);
5205	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
5206}
5207
5208
5209static int wpa_supplicant_ctrl_iface_bss_expire_age(
5210	struct wpa_supplicant *wpa_s, char *cmd)
5211{
5212	int expire_age = atoi(cmd);
5213	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5214}
5215
5216
5217static int wpa_supplicant_ctrl_iface_bss_expire_count(
5218	struct wpa_supplicant *wpa_s, char *cmd)
5219{
5220	int expire_count = atoi(cmd);
5221	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5222}
5223
5224
5225static void wpa_supplicant_ctrl_iface_bss_flush(
5226	struct wpa_supplicant *wpa_s, char *cmd)
5227{
5228	int flush_age = atoi(cmd);
5229
5230	if (flush_age == 0)
5231		wpa_bss_flush(wpa_s);
5232	else
5233		wpa_bss_flush_by_age(wpa_s, flush_age);
5234}
5235
5236
5237#ifdef CONFIG_TESTING_OPTIONS
5238static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5239{
5240	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5241	/* MLME-DELETEKEYS.request */
5242	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
5243	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
5244	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
5245	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
5246#ifdef CONFIG_IEEE80211W
5247	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
5248	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
5249#endif /* CONFIG_IEEE80211W */
5250
5251	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
5252			0);
5253	/* MLME-SETPROTECTION.request(None) */
5254	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
5255				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
5256				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
5257	wpa_sm_drop_sa(wpa_s->wpa);
5258}
5259#endif /* CONFIG_TESTING_OPTIONS */
5260
5261
5262static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
5263					  char *addr)
5264{
5265#ifdef CONFIG_NO_SCAN_PROCESSING
5266	return -1;
5267#else /* CONFIG_NO_SCAN_PROCESSING */
5268	u8 bssid[ETH_ALEN];
5269	struct wpa_bss *bss;
5270	struct wpa_ssid *ssid = wpa_s->current_ssid;
5271
5272	if (hwaddr_aton(addr, bssid)) {
5273		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
5274			   "address '%s'", addr);
5275		return -1;
5276	}
5277
5278	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
5279
5280	if (!ssid) {
5281		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
5282			   "configuration known for the target AP");
5283		return -1;
5284	}
5285
5286	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
5287	if (!bss) {
5288		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
5289			   "from BSS table");
5290		return -1;
5291	}
5292
5293	/*
5294	 * TODO: Find best network configuration block from configuration to
5295	 * allow roaming to other networks
5296	 */
5297
5298	wpa_s->reassociate = 1;
5299	wpa_supplicant_connect(wpa_s, bss, ssid);
5300
5301	return 0;
5302#endif /* CONFIG_NO_SCAN_PROCESSING */
5303}
5304
5305
5306#ifdef CONFIG_P2P
5307static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
5308{
5309	unsigned int timeout = atoi(cmd);
5310	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
5311	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
5312	u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
5313	char *pos;
5314	unsigned int search_delay;
5315	const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
5316	u8 seek_count = 0;
5317	int freq = 0;
5318
5319	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5320		wpa_dbg(wpa_s, MSG_INFO,
5321			"Reject P2P_FIND since interface is disabled");
5322		return -1;
5323	}
5324	if (os_strstr(cmd, "type=social"))
5325		type = P2P_FIND_ONLY_SOCIAL;
5326	else if (os_strstr(cmd, "type=progressive"))
5327		type = P2P_FIND_PROGRESSIVE;
5328
5329	pos = os_strstr(cmd, "dev_id=");
5330	if (pos) {
5331		pos += 7;
5332		if (hwaddr_aton(pos, dev_id))
5333			return -1;
5334		_dev_id = dev_id;
5335	}
5336
5337	pos = os_strstr(cmd, "dev_type=");
5338	if (pos) {
5339		pos += 9;
5340		if (wps_dev_type_str2bin(pos, dev_type) < 0)
5341			return -1;
5342		_dev_type = dev_type;
5343	}
5344
5345	pos = os_strstr(cmd, "delay=");
5346	if (pos) {
5347		pos += 6;
5348		search_delay = atoi(pos);
5349	} else
5350		search_delay = wpas_p2p_search_delay(wpa_s);
5351
5352	pos = os_strstr(cmd, "freq=");
5353	if (pos) {
5354		pos += 5;
5355		freq = atoi(pos);
5356		if (freq <= 0)
5357			return -1;
5358	}
5359
5360	/* Must be searched for last, because it adds nul termination */
5361	pos = os_strstr(cmd, " seek=");
5362	if (pos)
5363		pos += 6;
5364	while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
5365		char *term;
5366
5367		_seek[seek_count++] = pos;
5368		seek = _seek;
5369		term = os_strchr(pos, ' ');
5370		if (!term)
5371			break;
5372		*term = '\0';
5373		pos = os_strstr(term + 1, "seek=");
5374		if (pos)
5375			pos += 5;
5376	}
5377	if (seek_count > P2P_MAX_QUERY_HASH) {
5378		seek[0] = NULL;
5379		seek_count = 1;
5380	}
5381
5382	return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
5383			     _dev_id, search_delay, seek_count, seek, freq);
5384}
5385
5386
5387static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
5388{
5389	const char *last = NULL;
5390	const char *token;
5391	long int token_len;
5392	unsigned int i;
5393
5394	/* Expected predefined CPT names delimited by ':' */
5395	for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
5396		if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
5397			wpa_printf(MSG_ERROR,
5398				   "P2PS: CPT name list is too long, expected up to %d names",
5399				   P2PS_FEATURE_CAPAB_CPT_MAX);
5400			cpt[0] = 0;
5401			return -1;
5402		}
5403
5404		token_len = last - token;
5405
5406		if (token_len  == 3 &&
5407		    os_memcmp(token, "UDP", token_len) == 0) {
5408			cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
5409		} else if (token_len == 3 &&
5410			   os_memcmp(token, "MAC", token_len) == 0) {
5411			cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
5412		} else {
5413			wpa_printf(MSG_ERROR,
5414				   "P2PS: Unsupported CPT name '%s'", token);
5415			cpt[0] = 0;
5416			return -1;
5417		}
5418
5419		if (isblank((unsigned char) *last)) {
5420			i++;
5421			break;
5422		}
5423	}
5424	cpt[i] = 0;
5425	return 0;
5426}
5427
5428
5429static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
5430{
5431	struct p2ps_provision *p2ps_prov;
5432	char *pos;
5433	size_t info_len = 0;
5434	char *info = NULL;
5435	u8 role = P2PS_SETUP_NONE;
5436	long long unsigned val;
5437	int i;
5438
5439	pos = os_strstr(cmd, "info=");
5440	if (pos) {
5441		pos += 5;
5442		info_len = os_strlen(pos);
5443
5444		if (info_len) {
5445			info = os_malloc(info_len + 1);
5446			if (info) {
5447				info_len = utf8_unescape(pos, info_len,
5448							 info, info_len + 1);
5449			} else
5450				info_len = 0;
5451		}
5452	}
5453
5454	p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
5455	if (p2ps_prov == NULL) {
5456		os_free(info);
5457		return NULL;
5458	}
5459
5460	if (info) {
5461		os_memcpy(p2ps_prov->info, info, info_len);
5462		p2ps_prov->info[info_len] = '\0';
5463		os_free(info);
5464	}
5465
5466	pos = os_strstr(cmd, "status=");
5467	if (pos)
5468		p2ps_prov->status = atoi(pos + 7);
5469	else
5470		p2ps_prov->status = -1;
5471
5472	pos = os_strstr(cmd, "adv_id=");
5473	if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
5474		goto invalid_args;
5475	p2ps_prov->adv_id = val;
5476
5477	pos = os_strstr(cmd, "method=");
5478	if (pos)
5479		p2ps_prov->method = strtol(pos + 7, NULL, 16);
5480	else
5481		p2ps_prov->method = 0;
5482
5483	pos = os_strstr(cmd, "session=");
5484	if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
5485		goto invalid_args;
5486	p2ps_prov->session_id = val;
5487
5488	pos = os_strstr(cmd, "adv_mac=");
5489	if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
5490		goto invalid_args;
5491
5492	pos = os_strstr(cmd, "session_mac=");
5493	if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
5494		goto invalid_args;
5495
5496	pos = os_strstr(cmd, "cpt=");
5497	if (pos) {
5498		if (p2ps_ctrl_parse_cpt_priority(pos + 4,
5499						 p2ps_prov->cpt_priority))
5500			goto invalid_args;
5501	} else {
5502		p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
5503	}
5504
5505	for (i = 0; p2ps_prov->cpt_priority[i]; i++)
5506		p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
5507
5508	/* force conncap with tstCap (no sanity checks) */
5509	pos = os_strstr(cmd, "tstCap=");
5510	if (pos) {
5511		role = strtol(pos + 7, NULL, 16);
5512	} else {
5513		pos = os_strstr(cmd, "role=");
5514		if (pos) {
5515			role = strtol(pos + 5, NULL, 16);
5516			if (role != P2PS_SETUP_CLIENT &&
5517			    role != P2PS_SETUP_GROUP_OWNER)
5518				role = P2PS_SETUP_NONE;
5519		}
5520	}
5521	p2ps_prov->role = role;
5522
5523	return p2ps_prov;
5524
5525invalid_args:
5526	os_free(p2ps_prov);
5527	return NULL;
5528}
5529
5530
5531static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
5532{
5533	u8 addr[ETH_ALEN];
5534	struct p2ps_provision *p2ps_prov;
5535	char *pos;
5536
5537	/* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
5538
5539	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
5540
5541	if (hwaddr_aton(cmd, addr))
5542		return -1;
5543
5544	pos = cmd + 17;
5545	if (*pos != ' ')
5546		return -1;
5547
5548	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
5549	if (!p2ps_prov)
5550		return -1;
5551
5552	if (p2ps_prov->status < 0) {
5553		os_free(p2ps_prov);
5554		return -1;
5555	}
5556
5557	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
5558				  p2ps_prov);
5559}
5560
5561
5562static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
5563{
5564	u8 addr[ETH_ALEN];
5565	struct p2ps_provision *p2ps_prov;
5566	char *pos;
5567
5568	/* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
5569	 *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
5570	 */
5571
5572	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
5573	if (hwaddr_aton(cmd, addr))
5574		return -1;
5575
5576	pos = cmd + 17;
5577	if (*pos != ' ')
5578		return -1;
5579
5580	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
5581	if (!p2ps_prov)
5582		return -1;
5583
5584	p2ps_prov->pd_seeker = 1;
5585
5586	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
5587				  p2ps_prov);
5588}
5589
5590
5591static int parse_freq(int chwidth, int freq2)
5592{
5593	if (freq2 < 0)
5594		return -1;
5595	if (freq2)
5596		return CHANWIDTH_80P80MHZ;
5597
5598	switch (chwidth) {
5599	case 0:
5600	case 20:
5601	case 40:
5602		return CHANWIDTH_USE_HT;
5603	case 80:
5604		return CHANWIDTH_80MHZ;
5605	case 160:
5606		return CHANWIDTH_160MHZ;
5607	default:
5608		wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
5609			   chwidth);
5610		return -1;
5611	}
5612}
5613
5614
5615static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
5616			    char *buf, size_t buflen)
5617{
5618	u8 addr[ETH_ALEN];
5619	char *pos, *pos2;
5620	char *pin = NULL;
5621	enum p2p_wps_method wps_method;
5622	int new_pin;
5623	int ret;
5624	int persistent_group, persistent_id = -1;
5625	int join;
5626	int auth;
5627	int automatic;
5628	int go_intent = -1;
5629	int freq = 0;
5630	int pd;
5631	int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
5632	u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
5633	size_t group_ssid_len = 0;
5634	int he;
5635
5636	if (!wpa_s->global->p2p_init_wpa_s)
5637		return -1;
5638	if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
5639		wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
5640			wpa_s->global->p2p_init_wpa_s->ifname);
5641		wpa_s = wpa_s->global->p2p_init_wpa_s;
5642	}
5643
5644	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
5645	 * [persistent|persistent=<network id>]
5646	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
5647	 * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */
5648
5649	if (hwaddr_aton(cmd, addr))
5650		return -1;
5651
5652	pos = cmd + 17;
5653	if (*pos != ' ')
5654		return -1;
5655	pos++;
5656
5657	persistent_group = os_strstr(pos, " persistent") != NULL;
5658	pos2 = os_strstr(pos, " persistent=");
5659	if (pos2) {
5660		struct wpa_ssid *ssid;
5661		persistent_id = atoi(pos2 + 12);
5662		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
5663		if (ssid == NULL || ssid->disabled != 2 ||
5664		    ssid->mode != WPAS_MODE_P2P_GO) {
5665			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
5666				   "SSID id=%d for persistent P2P group (GO)",
5667				   persistent_id);
5668			return -1;
5669		}
5670	}
5671	join = os_strstr(pos, " join") != NULL;
5672	auth = os_strstr(pos, " auth") != NULL;
5673	automatic = os_strstr(pos, " auto") != NULL;
5674	pd = os_strstr(pos, " provdisc") != NULL;
5675	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
5676	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
5677		vht;
5678	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
5679
5680	pos2 = os_strstr(pos, " go_intent=");
5681	if (pos2) {
5682		pos2 += 11;
5683		go_intent = atoi(pos2);
5684		if (go_intent < 0 || go_intent > 15)
5685			return -1;
5686	}
5687
5688	pos2 = os_strstr(pos, " freq=");
5689	if (pos2) {
5690		pos2 += 6;
5691		freq = atoi(pos2);
5692		if (freq <= 0)
5693			return -1;
5694	}
5695
5696	pos2 = os_strstr(pos, " freq2=");
5697	if (pos2)
5698		freq2 = atoi(pos2 + 7);
5699
5700	pos2 = os_strstr(pos, " max_oper_chwidth=");
5701	if (pos2)
5702		chwidth = atoi(pos2 + 18);
5703
5704	max_oper_chwidth = parse_freq(chwidth, freq2);
5705	if (max_oper_chwidth < 0)
5706		return -1;
5707
5708	pos2 = os_strstr(pos, " ssid=");
5709	if (pos2) {
5710		char *end;
5711
5712		pos2 += 6;
5713		end = os_strchr(pos2, ' ');
5714		if (!end)
5715			group_ssid_len = os_strlen(pos2) / 2;
5716		else
5717			group_ssid_len = (end - pos2) / 2;
5718		if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
5719		    hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
5720			return -1;
5721		group_ssid = _group_ssid;
5722	}
5723
5724	if (os_strncmp(pos, "pin", 3) == 0) {
5725		/* Request random PIN (to be displayed) and enable the PIN */
5726		wps_method = WPS_PIN_DISPLAY;
5727	} else if (os_strncmp(pos, "pbc", 3) == 0) {
5728		wps_method = WPS_PBC;
5729	} else if (os_strstr(pos, "p2ps") != NULL) {
5730		wps_method = WPS_P2PS;
5731	} else {
5732		pin = pos;
5733		pos = os_strchr(pin, ' ');
5734		wps_method = WPS_PIN_KEYPAD;
5735		if (pos) {
5736			*pos++ = '\0';
5737			if (os_strncmp(pos, "display", 7) == 0)
5738				wps_method = WPS_PIN_DISPLAY;
5739		}
5740		if (!wps_pin_str_valid(pin)) {
5741			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
5742			return 17;
5743		}
5744	}
5745
5746	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
5747				   persistent_group, automatic, join,
5748				   auth, go_intent, freq, freq2, persistent_id,
5749				   pd, ht40, vht, max_oper_chwidth, he,
5750				   group_ssid, group_ssid_len);
5751	if (new_pin == -2) {
5752		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
5753		return 25;
5754	}
5755	if (new_pin == -3) {
5756		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
5757		return 25;
5758	}
5759	if (new_pin < 0)
5760		return -1;
5761	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
5762		ret = os_snprintf(buf, buflen, "%08d", new_pin);
5763		if (os_snprintf_error(buflen, ret))
5764			return -1;
5765		return ret;
5766	}
5767
5768	os_memcpy(buf, "OK\n", 3);
5769	return 3;
5770}
5771
5772
5773static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
5774{
5775	unsigned int timeout = atoi(cmd);
5776	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5777		wpa_dbg(wpa_s, MSG_INFO,
5778			"Reject P2P_LISTEN since interface is disabled");
5779		return -1;
5780	}
5781	return wpas_p2p_listen(wpa_s, timeout);
5782}
5783
5784
5785static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
5786{
5787	u8 addr[ETH_ALEN];
5788	char *pos;
5789	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
5790
5791	/* <addr> <config method> [join|auto] */
5792
5793	if (hwaddr_aton(cmd, addr))
5794		return -1;
5795
5796	pos = cmd + 17;
5797	if (*pos != ' ')
5798		return -1;
5799	pos++;
5800
5801	if (os_strstr(pos, " join") != NULL)
5802		use = WPAS_P2P_PD_FOR_JOIN;
5803	else if (os_strstr(pos, " auto") != NULL)
5804		use = WPAS_P2P_PD_AUTO;
5805
5806	return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
5807}
5808
5809
5810static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
5811			      size_t buflen)
5812{
5813	struct wpa_ssid *ssid = wpa_s->current_ssid;
5814
5815	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
5816	    ssid->passphrase == NULL)
5817		return -1;
5818
5819	os_strlcpy(buf, ssid->passphrase, buflen);
5820	return os_strlen(buf);
5821}
5822
5823
5824static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
5825				  char *buf, size_t buflen)
5826{
5827	u64 ref;
5828	int res;
5829	u8 dst_buf[ETH_ALEN], *dst;
5830	struct wpabuf *tlvs;
5831	char *pos;
5832	size_t len;
5833
5834	if (hwaddr_aton(cmd, dst_buf))
5835		return -1;
5836	dst = dst_buf;
5837	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
5838	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
5839		dst = NULL;
5840	pos = cmd + 17;
5841	if (*pos != ' ')
5842		return -1;
5843	pos++;
5844
5845	if (os_strncmp(pos, "upnp ", 5) == 0) {
5846		u8 version;
5847		pos += 5;
5848		if (hexstr2bin(pos, &version, 1) < 0)
5849			return -1;
5850		pos += 2;
5851		if (*pos != ' ')
5852			return -1;
5853		pos++;
5854		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
5855#ifdef CONFIG_WIFI_DISPLAY
5856	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
5857		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
5858#endif /* CONFIG_WIFI_DISPLAY */
5859	} else if (os_strncmp(pos, "asp ", 4) == 0) {
5860		char *svc_str;
5861		char *svc_info = NULL;
5862		u32 id;
5863
5864		pos += 4;
5865		if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
5866			return -1;
5867
5868		pos = os_strchr(pos, ' ');
5869		if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
5870			return -1;
5871
5872		svc_str = pos + 1;
5873
5874		pos = os_strchr(svc_str, ' ');
5875
5876		if (pos)
5877			*pos++ = '\0';
5878
5879		/* All remaining data is the svc_info string */
5880		if (pos && pos[0] && pos[0] != ' ') {
5881			len = os_strlen(pos);
5882
5883			/* Unescape in place */
5884			len = utf8_unescape(pos, len, pos, len);
5885			if (len > 0xff)
5886				return -1;
5887
5888			svc_info = pos;
5889		}
5890
5891		ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
5892					      svc_str, svc_info);
5893	} else {
5894		len = os_strlen(pos);
5895		if (len & 1)
5896			return -1;
5897		len /= 2;
5898		tlvs = wpabuf_alloc(len);
5899		if (tlvs == NULL)
5900			return -1;
5901		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
5902			wpabuf_free(tlvs);
5903			return -1;
5904		}
5905
5906		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
5907		wpabuf_free(tlvs);
5908	}
5909	if (ref == 0)
5910		return -1;
5911	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
5912	if (os_snprintf_error(buflen, res))
5913		return -1;
5914	return res;
5915}
5916
5917
5918static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
5919					 char *cmd)
5920{
5921	long long unsigned val;
5922	u64 req;
5923	if (sscanf(cmd, "%llx", &val) != 1)
5924		return -1;
5925	req = val;
5926	return wpas_p2p_sd_cancel_request(wpa_s, req);
5927}
5928
5929
5930static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
5931{
5932	int freq;
5933	u8 dst[ETH_ALEN];
5934	u8 dialog_token;
5935	struct wpabuf *resp_tlvs;
5936	char *pos, *pos2;
5937	size_t len;
5938
5939	pos = os_strchr(cmd, ' ');
5940	if (pos == NULL)
5941		return -1;
5942	*pos++ = '\0';
5943	freq = atoi(cmd);
5944	if (freq == 0)
5945		return -1;
5946
5947	if (hwaddr_aton(pos, dst))
5948		return -1;
5949	pos += 17;
5950	if (*pos != ' ')
5951		return -1;
5952	pos++;
5953
5954	pos2 = os_strchr(pos, ' ');
5955	if (pos2 == NULL)
5956		return -1;
5957	*pos2++ = '\0';
5958	dialog_token = atoi(pos);
5959
5960	len = os_strlen(pos2);
5961	if (len & 1)
5962		return -1;
5963	len /= 2;
5964	resp_tlvs = wpabuf_alloc(len);
5965	if (resp_tlvs == NULL)
5966		return -1;
5967	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
5968		wpabuf_free(resp_tlvs);
5969		return -1;
5970	}
5971
5972	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
5973	wpabuf_free(resp_tlvs);
5974	return 0;
5975}
5976
5977
5978static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
5979				       char *cmd)
5980{
5981	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
5982		return -1;
5983	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
5984	return 0;
5985}
5986
5987
5988static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
5989					char *cmd)
5990{
5991	char *pos;
5992	size_t len;
5993	struct wpabuf *query, *resp;
5994
5995	pos = os_strchr(cmd, ' ');
5996	if (pos == NULL)
5997		return -1;
5998	*pos++ = '\0';
5999
6000	len = os_strlen(cmd);
6001	if (len & 1)
6002		return -1;
6003	len /= 2;
6004	query = wpabuf_alloc(len);
6005	if (query == NULL)
6006		return -1;
6007	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6008		wpabuf_free(query);
6009		return -1;
6010	}
6011
6012	len = os_strlen(pos);
6013	if (len & 1) {
6014		wpabuf_free(query);
6015		return -1;
6016	}
6017	len /= 2;
6018	resp = wpabuf_alloc(len);
6019	if (resp == NULL) {
6020		wpabuf_free(query);
6021		return -1;
6022	}
6023	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
6024		wpabuf_free(query);
6025		wpabuf_free(resp);
6026		return -1;
6027	}
6028
6029	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
6030		wpabuf_free(query);
6031		wpabuf_free(resp);
6032		return -1;
6033	}
6034	return 0;
6035}
6036
6037
6038static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6039{
6040	char *pos;
6041	u8 version;
6042
6043	pos = os_strchr(cmd, ' ');
6044	if (pos == NULL)
6045		return -1;
6046	*pos++ = '\0';
6047
6048	if (hexstr2bin(cmd, &version, 1) < 0)
6049		return -1;
6050
6051	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6052}
6053
6054
6055static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6056				    u8 replace, char *cmd)
6057{
6058	char *pos;
6059	char *adv_str;
6060	u32 auto_accept, adv_id, svc_state, config_methods;
6061	char *svc_info = NULL;
6062	char *cpt_prio_str;
6063	u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
6064
6065	pos = os_strchr(cmd, ' ');
6066	if (pos == NULL)
6067		return -1;
6068	*pos++ = '\0';
6069
6070	/* Auto-Accept value is mandatory, and must be one of the
6071	 * single values (0, 1, 2, 4) */
6072	auto_accept = atoi(cmd);
6073	switch (auto_accept) {
6074	case P2PS_SETUP_NONE: /* No auto-accept */
6075	case P2PS_SETUP_NEW:
6076	case P2PS_SETUP_CLIENT:
6077	case P2PS_SETUP_GROUP_OWNER:
6078		break;
6079	default:
6080		return -1;
6081	}
6082
6083	/* Advertisement ID is mandatory */
6084	cmd = pos;
6085	pos = os_strchr(cmd, ' ');
6086	if (pos == NULL)
6087		return -1;
6088	*pos++ = '\0';
6089
6090	/* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6091	if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6092		return -1;
6093
6094	/* Only allow replacements if exist, and adds if not */
6095	if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6096		if (!replace)
6097			return -1;
6098	} else {
6099		if (replace)
6100			return -1;
6101	}
6102
6103	/* svc_state between 0 - 0xff is mandatory */
6104	if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6105		return -1;
6106
6107	pos = os_strchr(pos, ' ');
6108	if (pos == NULL)
6109		return -1;
6110
6111	/* config_methods is mandatory */
6112	pos++;
6113	if (sscanf(pos, "%x", &config_methods) != 1)
6114		return -1;
6115
6116	if (!(config_methods &
6117	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6118		return -1;
6119
6120	pos = os_strchr(pos, ' ');
6121	if (pos == NULL)
6122		return -1;
6123
6124	pos++;
6125	adv_str = pos;
6126
6127	/* Advertisement string is mandatory */
6128	if (!pos[0] || pos[0] == ' ')
6129		return -1;
6130
6131	/* Terminate svc string */
6132	pos = os_strchr(pos, ' ');
6133	if (pos != NULL)
6134		*pos++ = '\0';
6135
6136	cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6137	if (cpt_prio_str) {
6138		pos = os_strchr(pos, ' ');
6139		if (pos != NULL)
6140			*pos++ = '\0';
6141
6142		if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6143			return -1;
6144	} else {
6145		cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6146		cpt_prio[1] = 0;
6147	}
6148
6149	/* Service and Response Information are optional */
6150	if (pos && pos[0]) {
6151		size_t len;
6152
6153		/* Note the bare ' included, which cannot exist legally
6154		 * in unescaped string. */
6155		svc_info = os_strstr(pos, "svc_info='");
6156
6157		if (svc_info) {
6158			svc_info += 9;
6159			len = os_strlen(svc_info);
6160			utf8_unescape(svc_info, len, svc_info, len);
6161		}
6162	}
6163
6164	return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
6165					(u8) svc_state, (u16) config_methods,
6166					svc_info, cpt_prio);
6167}
6168
6169
6170static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
6171{
6172	char *pos;
6173
6174	pos = os_strchr(cmd, ' ');
6175	if (pos == NULL)
6176		return -1;
6177	*pos++ = '\0';
6178
6179	if (os_strcmp(cmd, "bonjour") == 0)
6180		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
6181	if (os_strcmp(cmd, "upnp") == 0)
6182		return p2p_ctrl_service_add_upnp(wpa_s, pos);
6183	if (os_strcmp(cmd, "asp") == 0)
6184		return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
6185	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6186	return -1;
6187}
6188
6189
6190static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
6191					char *cmd)
6192{
6193	size_t len;
6194	struct wpabuf *query;
6195	int ret;
6196
6197	len = os_strlen(cmd);
6198	if (len & 1)
6199		return -1;
6200	len /= 2;
6201	query = wpabuf_alloc(len);
6202	if (query == NULL)
6203		return -1;
6204	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6205		wpabuf_free(query);
6206		return -1;
6207	}
6208
6209	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
6210	wpabuf_free(query);
6211	return ret;
6212}
6213
6214
6215static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6216{
6217	char *pos;
6218	u8 version;
6219
6220	pos = os_strchr(cmd, ' ');
6221	if (pos == NULL)
6222		return -1;
6223	*pos++ = '\0';
6224
6225	if (hexstr2bin(cmd, &version, 1) < 0)
6226		return -1;
6227
6228	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
6229}
6230
6231
6232static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
6233{
6234	u32 adv_id;
6235
6236	if (os_strcmp(cmd, "all") == 0) {
6237		wpas_p2p_service_flush_asp(wpa_s);
6238		return 0;
6239	}
6240
6241	if (sscanf(cmd, "%x", &adv_id) != 1)
6242		return -1;
6243
6244	return wpas_p2p_service_del_asp(wpa_s, adv_id);
6245}
6246
6247
6248static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
6249{
6250	char *pos;
6251
6252	pos = os_strchr(cmd, ' ');
6253	if (pos == NULL)
6254		return -1;
6255	*pos++ = '\0';
6256
6257	if (os_strcmp(cmd, "bonjour") == 0)
6258		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
6259	if (os_strcmp(cmd, "upnp") == 0)
6260		return p2p_ctrl_service_del_upnp(wpa_s, pos);
6261	if (os_strcmp(cmd, "asp") == 0)
6262		return p2p_ctrl_service_del_asp(wpa_s, pos);
6263	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6264	return -1;
6265}
6266
6267
6268static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
6269{
6270	char *pos;
6271
6272	pos = os_strchr(cmd, ' ');
6273	if (pos == NULL)
6274		return -1;
6275	*pos++ = '\0';
6276
6277	if (os_strcmp(cmd, "asp") == 0)
6278		return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
6279
6280	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6281	return -1;
6282}
6283
6284
6285static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
6286{
6287	u8 addr[ETH_ALEN];
6288
6289	/* <addr> */
6290
6291	if (hwaddr_aton(cmd, addr))
6292		return -1;
6293
6294	return wpas_p2p_reject(wpa_s, addr);
6295}
6296
6297
6298static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
6299{
6300	char *pos;
6301	int id;
6302	struct wpa_ssid *ssid;
6303	u8 *_peer = NULL, peer[ETH_ALEN];
6304	int freq = 0, pref_freq = 0;
6305	int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
6306
6307	id = atoi(cmd);
6308	pos = os_strstr(cmd, " peer=");
6309	if (pos) {
6310		pos += 6;
6311		if (hwaddr_aton(pos, peer))
6312			return -1;
6313		_peer = peer;
6314	}
6315	ssid = wpa_config_get_network(wpa_s->conf, id);
6316	if (ssid == NULL || ssid->disabled != 2) {
6317		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
6318			   "for persistent P2P group",
6319			   id);
6320		return -1;
6321	}
6322
6323	pos = os_strstr(cmd, " freq=");
6324	if (pos) {
6325		pos += 6;
6326		freq = atoi(pos);
6327		if (freq <= 0)
6328			return -1;
6329	}
6330
6331	pos = os_strstr(cmd, " pref=");
6332	if (pos) {
6333		pos += 6;
6334		pref_freq = atoi(pos);
6335		if (pref_freq <= 0)
6336			return -1;
6337	}
6338
6339	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6340	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6341		vht;
6342	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
6343
6344	pos = os_strstr(cmd, "freq2=");
6345	if (pos)
6346		freq2 = atoi(pos + 6);
6347
6348	pos = os_strstr(cmd, " max_oper_chwidth=");
6349	if (pos)
6350		chwidth = atoi(pos + 18);
6351
6352	max_oper_chwidth = parse_freq(chwidth, freq2);
6353	if (max_oper_chwidth < 0)
6354		return -1;
6355
6356	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
6357			       max_oper_chwidth, pref_freq, he);
6358}
6359
6360
6361static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
6362{
6363	char *pos;
6364	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
6365
6366	pos = os_strstr(cmd, " peer=");
6367	if (!pos)
6368		return -1;
6369
6370	*pos = '\0';
6371	pos += 6;
6372	if (hwaddr_aton(pos, peer)) {
6373		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
6374		return -1;
6375	}
6376
6377	pos = os_strstr(pos, " go_dev_addr=");
6378	if (pos) {
6379		pos += 13;
6380		if (hwaddr_aton(pos, go_dev_addr)) {
6381			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
6382				   pos);
6383			return -1;
6384		}
6385		go_dev = go_dev_addr;
6386	}
6387
6388	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
6389}
6390
6391
6392static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
6393{
6394	if (os_strncmp(cmd, "persistent=", 11) == 0)
6395		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
6396	if (os_strncmp(cmd, "group=", 6) == 0)
6397		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
6398
6399	return -1;
6400}
6401
6402
6403static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
6404					 int id, int freq, int vht_center_freq2,
6405					 int ht40, int vht, int vht_chwidth,
6406					 int he)
6407{
6408	struct wpa_ssid *ssid;
6409
6410	ssid = wpa_config_get_network(wpa_s->conf, id);
6411	if (ssid == NULL || ssid->disabled != 2) {
6412		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
6413			   "for persistent P2P group",
6414			   id);
6415		return -1;
6416	}
6417
6418	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
6419					     vht_center_freq2, 0, ht40, vht,
6420					     vht_chwidth, he, NULL, 0, 0);
6421}
6422
6423
6424static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
6425{
6426	int freq = 0, persistent = 0, group_id = -1;
6427	int vht = wpa_s->conf->p2p_go_vht;
6428	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
6429	int he = wpa_s->conf->p2p_go_he;
6430	int max_oper_chwidth, chwidth = 0, freq2 = 0;
6431	char *token, *context = NULL;
6432#ifdef CONFIG_ACS
6433	int acs = 0;
6434#endif /* CONFIG_ACS */
6435
6436	while ((token = str_token(cmd, " ", &context))) {
6437		if (sscanf(token, "freq2=%d", &freq2) == 1 ||
6438		    sscanf(token, "persistent=%d", &group_id) == 1 ||
6439		    sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
6440			continue;
6441#ifdef CONFIG_ACS
6442		} else if (os_strcmp(token, "freq=acs") == 0) {
6443			acs = 1;
6444#endif /* CONFIG_ACS */
6445		} else if (sscanf(token, "freq=%d", &freq) == 1) {
6446			continue;
6447		} else if (os_strcmp(token, "ht40") == 0) {
6448			ht40 = 1;
6449		} else if (os_strcmp(token, "vht") == 0) {
6450			vht = 1;
6451			ht40 = 1;
6452		} else if (os_strcmp(token, "he") == 0) {
6453			he = 1;
6454		} else if (os_strcmp(token, "persistent") == 0) {
6455			persistent = 1;
6456		} else {
6457			wpa_printf(MSG_DEBUG,
6458				   "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
6459				   token);
6460			return -1;
6461		}
6462	}
6463
6464#ifdef CONFIG_ACS
6465	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
6466	    (acs || freq == 2 || freq == 5)) {
6467		if (freq == 2 && wpa_s->best_24_freq <= 0) {
6468			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
6469			wpa_s->p2p_go_do_acs = 1;
6470			freq = 0;
6471		} else if (freq == 5 && wpa_s->best_5_freq <= 0) {
6472			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
6473			wpa_s->p2p_go_do_acs = 1;
6474			freq = 0;
6475		} else {
6476			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
6477			wpa_s->p2p_go_do_acs = 1;
6478		}
6479	} else {
6480		wpa_s->p2p_go_do_acs = 0;
6481	}
6482#endif /* CONFIG_ACS */
6483
6484	max_oper_chwidth = parse_freq(chwidth, freq2);
6485	if (max_oper_chwidth < 0)
6486		return -1;
6487
6488	if (group_id >= 0)
6489		return p2p_ctrl_group_add_persistent(wpa_s, group_id,
6490						     freq, freq2, ht40, vht,
6491						     max_oper_chwidth, he);
6492
6493	return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
6494				  max_oper_chwidth, he);
6495}
6496
6497
6498static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
6499				 char *buf, size_t buflen)
6500{
6501	u8 dev_addr[ETH_ALEN];
6502	struct wpa_ssid *ssid;
6503	int res;
6504	const u8 *iaddr;
6505
6506	ssid = wpa_s->current_ssid;
6507	if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
6508	    hwaddr_aton(cmd, dev_addr))
6509		return -1;
6510
6511	iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
6512	if (!iaddr)
6513		return -1;
6514	res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
6515	if (os_snprintf_error(buflen, res))
6516		return -1;
6517	return res;
6518}
6519
6520
6521static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
6522				      const u8 *p2p_dev_addr)
6523{
6524	struct wpa_supplicant *wpa_s;
6525
6526	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6527		if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
6528			return 1;
6529	}
6530
6531	return 0;
6532}
6533
6534
6535static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
6536			 char *buf, size_t buflen)
6537{
6538	u8 addr[ETH_ALEN], *addr_ptr, group_capab;
6539	int next, res;
6540	const struct p2p_peer_info *info;
6541	char *pos, *end;
6542	char devtype[WPS_DEV_TYPE_BUFSIZE];
6543	struct wpa_ssid *ssid;
6544	size_t i;
6545
6546	if (!wpa_s->global->p2p)
6547		return -1;
6548
6549	if (os_strcmp(cmd, "FIRST") == 0) {
6550		addr_ptr = NULL;
6551		next = 0;
6552	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
6553		if (hwaddr_aton(cmd + 5, addr) < 0)
6554			return -1;
6555		addr_ptr = addr;
6556		next = 1;
6557	} else {
6558		if (hwaddr_aton(cmd, addr) < 0)
6559			return -1;
6560		addr_ptr = addr;
6561		next = 0;
6562	}
6563
6564	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
6565	if (info == NULL)
6566		return -1;
6567	group_capab = info->group_capab;
6568
6569	if (group_capab &&
6570	    !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
6571		wpa_printf(MSG_DEBUG,
6572			   "P2P: Could not find any BSS with p2p_dev_addr "
6573			   MACSTR ", hence override group_capab from 0x%x to 0",
6574			   MAC2STR(info->p2p_device_addr), group_capab);
6575		group_capab = 0;
6576	}
6577
6578	pos = buf;
6579	end = buf + buflen;
6580
6581	res = os_snprintf(pos, end - pos, MACSTR "\n"
6582			  "pri_dev_type=%s\n"
6583			  "device_name=%s\n"
6584			  "manufacturer=%s\n"
6585			  "model_name=%s\n"
6586			  "model_number=%s\n"
6587			  "serial_number=%s\n"
6588			  "config_methods=0x%x\n"
6589			  "dev_capab=0x%x\n"
6590			  "group_capab=0x%x\n"
6591			  "level=%d\n",
6592			  MAC2STR(info->p2p_device_addr),
6593			  wps_dev_type_bin2str(info->pri_dev_type,
6594					       devtype, sizeof(devtype)),
6595			  info->device_name,
6596			  info->manufacturer,
6597			  info->model_name,
6598			  info->model_number,
6599			  info->serial_number,
6600			  info->config_methods,
6601			  info->dev_capab,
6602			  group_capab,
6603			  info->level);
6604	if (os_snprintf_error(end - pos, res))
6605		return pos - buf;
6606	pos += res;
6607
6608	for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
6609	{
6610		const u8 *t;
6611		t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
6612		res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
6613				  wps_dev_type_bin2str(t, devtype,
6614						       sizeof(devtype)));
6615		if (os_snprintf_error(end - pos, res))
6616			return pos - buf;
6617		pos += res;
6618	}
6619
6620	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
6621	if (ssid) {
6622		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
6623		if (os_snprintf_error(end - pos, res))
6624			return pos - buf;
6625		pos += res;
6626	}
6627
6628	res = p2p_get_peer_info_txt(info, pos, end - pos);
6629	if (res < 0)
6630		return pos - buf;
6631	pos += res;
6632
6633	if (info->vendor_elems) {
6634		res = os_snprintf(pos, end - pos, "vendor_elems=");
6635		if (os_snprintf_error(end - pos, res))
6636			return pos - buf;
6637		pos += res;
6638
6639		pos += wpa_snprintf_hex(pos, end - pos,
6640					wpabuf_head(info->vendor_elems),
6641					wpabuf_len(info->vendor_elems));
6642
6643		res = os_snprintf(pos, end - pos, "\n");
6644		if (os_snprintf_error(end - pos, res))
6645			return pos - buf;
6646		pos += res;
6647	}
6648
6649	return pos - buf;
6650}
6651
6652
6653static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
6654				  const char *param)
6655{
6656	unsigned int i;
6657
6658	if (wpa_s->global->p2p == NULL)
6659		return -1;
6660
6661	if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
6662		return -1;
6663
6664	for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
6665		struct wpa_freq_range *freq;
6666		freq = &wpa_s->global->p2p_disallow_freq.range[i];
6667		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
6668			   freq->min, freq->max);
6669	}
6670
6671	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
6672	return 0;
6673}
6674
6675
6676static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
6677{
6678	char *param;
6679
6680	if (wpa_s->global->p2p == NULL)
6681		return -1;
6682
6683	param = os_strchr(cmd, ' ');
6684	if (param == NULL)
6685		return -1;
6686	*param++ = '\0';
6687
6688	if (os_strcmp(cmd, "discoverability") == 0) {
6689		p2p_set_client_discoverability(wpa_s->global->p2p,
6690					       atoi(param));
6691		return 0;
6692	}
6693
6694	if (os_strcmp(cmd, "managed") == 0) {
6695		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
6696		return 0;
6697	}
6698
6699	if (os_strcmp(cmd, "listen_channel") == 0) {
6700		char *pos;
6701		u8 channel, op_class;
6702
6703		channel = atoi(param);
6704		pos = os_strchr(param, ' ');
6705		op_class = pos ? atoi(pos) : 81;
6706
6707		return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
6708					      channel, 1);
6709	}
6710
6711	if (os_strcmp(cmd, "ssid_postfix") == 0) {
6712		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
6713					    os_strlen(param));
6714	}
6715
6716	if (os_strcmp(cmd, "noa") == 0) {
6717		char *pos;
6718		int count, start, duration;
6719		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
6720		count = atoi(param);
6721		pos = os_strchr(param, ',');
6722		if (pos == NULL)
6723			return -1;
6724		pos++;
6725		start = atoi(pos);
6726		pos = os_strchr(pos, ',');
6727		if (pos == NULL)
6728			return -1;
6729		pos++;
6730		duration = atoi(pos);
6731		if (count < 0 || count > 255 || start < 0 || duration < 0)
6732			return -1;
6733		if (count == 0 && duration > 0)
6734			return -1;
6735		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
6736			   "start=%d duration=%d", count, start, duration);
6737		return wpas_p2p_set_noa(wpa_s, count, start, duration);
6738	}
6739
6740	if (os_strcmp(cmd, "ps") == 0)
6741		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
6742
6743	if (os_strcmp(cmd, "oppps") == 0)
6744		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
6745
6746	if (os_strcmp(cmd, "ctwindow") == 0)
6747		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
6748
6749	if (os_strcmp(cmd, "disabled") == 0) {
6750		wpa_s->global->p2p_disabled = atoi(param);
6751		wpa_printf(MSG_DEBUG, "P2P functionality %s",
6752			   wpa_s->global->p2p_disabled ?
6753			   "disabled" : "enabled");
6754		if (wpa_s->global->p2p_disabled) {
6755			wpas_p2p_stop_find(wpa_s);
6756			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
6757			p2p_flush(wpa_s->global->p2p);
6758		}
6759		return 0;
6760	}
6761
6762	if (os_strcmp(cmd, "conc_pref") == 0) {
6763		if (os_strcmp(param, "sta") == 0)
6764			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
6765		else if (os_strcmp(param, "p2p") == 0)
6766			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
6767		else {
6768			wpa_printf(MSG_INFO, "Invalid conc_pref value");
6769			return -1;
6770		}
6771		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
6772			   "%s", param);
6773		return 0;
6774	}
6775
6776	if (os_strcmp(cmd, "force_long_sd") == 0) {
6777		wpa_s->force_long_sd = atoi(param);
6778		return 0;
6779	}
6780
6781	if (os_strcmp(cmd, "peer_filter") == 0) {
6782		u8 addr[ETH_ALEN];
6783		if (hwaddr_aton(param, addr))
6784			return -1;
6785		p2p_set_peer_filter(wpa_s->global->p2p, addr);
6786		return 0;
6787	}
6788
6789	if (os_strcmp(cmd, "cross_connect") == 0)
6790		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
6791
6792	if (os_strcmp(cmd, "go_apsd") == 0) {
6793		if (os_strcmp(param, "disable") == 0)
6794			wpa_s->set_ap_uapsd = 0;
6795		else {
6796			wpa_s->set_ap_uapsd = 1;
6797			wpa_s->ap_uapsd = atoi(param);
6798		}
6799		return 0;
6800	}
6801
6802	if (os_strcmp(cmd, "client_apsd") == 0) {
6803		if (os_strcmp(param, "disable") == 0)
6804			wpa_s->set_sta_uapsd = 0;
6805		else {
6806			int be, bk, vi, vo;
6807			char *pos;
6808			/* format: BE,BK,VI,VO;max SP Length */
6809			be = atoi(param);
6810			pos = os_strchr(param, ',');
6811			if (pos == NULL)
6812				return -1;
6813			pos++;
6814			bk = atoi(pos);
6815			pos = os_strchr(pos, ',');
6816			if (pos == NULL)
6817				return -1;
6818			pos++;
6819			vi = atoi(pos);
6820			pos = os_strchr(pos, ',');
6821			if (pos == NULL)
6822				return -1;
6823			pos++;
6824			vo = atoi(pos);
6825			/* ignore max SP Length for now */
6826
6827			wpa_s->set_sta_uapsd = 1;
6828			wpa_s->sta_uapsd = 0;
6829			if (be)
6830				wpa_s->sta_uapsd |= BIT(0);
6831			if (bk)
6832				wpa_s->sta_uapsd |= BIT(1);
6833			if (vi)
6834				wpa_s->sta_uapsd |= BIT(2);
6835			if (vo)
6836				wpa_s->sta_uapsd |= BIT(3);
6837		}
6838		return 0;
6839	}
6840
6841	if (os_strcmp(cmd, "disallow_freq") == 0)
6842		return p2p_ctrl_disallow_freq(wpa_s, param);
6843
6844	if (os_strcmp(cmd, "disc_int") == 0) {
6845		int min_disc_int, max_disc_int, max_disc_tu;
6846		char *pos;
6847
6848		pos = param;
6849
6850		min_disc_int = atoi(pos);
6851		pos = os_strchr(pos, ' ');
6852		if (pos == NULL)
6853			return -1;
6854		*pos++ = '\0';
6855
6856		max_disc_int = atoi(pos);
6857		pos = os_strchr(pos, ' ');
6858		if (pos == NULL)
6859			return -1;
6860		*pos++ = '\0';
6861
6862		max_disc_tu = atoi(pos);
6863
6864		return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
6865					max_disc_int, max_disc_tu);
6866	}
6867
6868	if (os_strcmp(cmd, "per_sta_psk") == 0) {
6869		wpa_s->global->p2p_per_sta_psk = !!atoi(param);
6870		return 0;
6871	}
6872
6873#ifdef CONFIG_WPS_NFC
6874	if (os_strcmp(cmd, "nfc_tag") == 0)
6875		return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
6876#endif /* CONFIG_WPS_NFC */
6877
6878	if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
6879		wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
6880		return 0;
6881	}
6882
6883	if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
6884		int op_class, chan;
6885
6886		op_class = atoi(param);
6887		param = os_strchr(param, ':');
6888		if (!param)
6889			return -1;
6890		param++;
6891		chan = atoi(param);
6892		p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
6893					      chan);
6894		return 0;
6895	}
6896
6897	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
6898		   cmd);
6899
6900	return -1;
6901}
6902
6903
6904static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
6905{
6906	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
6907	wpa_s->force_long_sd = 0;
6908
6909#ifdef CONFIG_TESTING_OPTIONS
6910	os_free(wpa_s->get_pref_freq_list_override);
6911	wpa_s->get_pref_freq_list_override = NULL;
6912#endif /* CONFIG_TESTING_OPTIONS */
6913
6914	wpas_p2p_stop_find(wpa_s);
6915	wpa_s->parent->p2ps_method_config_any = 0;
6916	if (wpa_s->global->p2p)
6917		p2p_flush(wpa_s->global->p2p);
6918}
6919
6920
6921static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
6922{
6923	char *pos, *pos2;
6924	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
6925
6926	if (cmd[0]) {
6927		pos = os_strchr(cmd, ' ');
6928		if (pos == NULL)
6929			return -1;
6930		*pos++ = '\0';
6931		dur1 = atoi(cmd);
6932
6933		pos2 = os_strchr(pos, ' ');
6934		if (pos2)
6935			*pos2++ = '\0';
6936		int1 = atoi(pos);
6937	} else
6938		pos2 = NULL;
6939
6940	if (pos2) {
6941		pos = os_strchr(pos2, ' ');
6942		if (pos == NULL)
6943			return -1;
6944		*pos++ = '\0';
6945		dur2 = atoi(pos2);
6946		int2 = atoi(pos);
6947	}
6948
6949	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
6950}
6951
6952
6953static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
6954{
6955	char *pos;
6956	unsigned int period = 0, interval = 0;
6957
6958	if (cmd[0]) {
6959		pos = os_strchr(cmd, ' ');
6960		if (pos == NULL)
6961			return -1;
6962		*pos++ = '\0';
6963		period = atoi(cmd);
6964		interval = atoi(pos);
6965	}
6966
6967	return wpas_p2p_ext_listen(wpa_s, period, interval);
6968}
6969
6970
6971static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
6972{
6973	const char *pos;
6974	u8 peer[ETH_ALEN];
6975	int iface_addr = 0;
6976
6977	pos = cmd;
6978	if (os_strncmp(pos, "iface=", 6) == 0) {
6979		iface_addr = 1;
6980		pos += 6;
6981	}
6982	if (hwaddr_aton(pos, peer))
6983		return -1;
6984
6985	wpas_p2p_remove_client(wpa_s, peer, iface_addr);
6986	return 0;
6987}
6988
6989
6990static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
6991{
6992	int freq = 0, period = 0, interval = 0, count = 0;
6993
6994	if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
6995	{
6996		wpa_printf(MSG_DEBUG,
6997			   "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
6998		return -1;
6999	}
7000
7001	return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7002}
7003
7004#endif /* CONFIG_P2P */
7005
7006
7007static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7008{
7009	struct wpa_freq_range_list ranges;
7010	int *freqs = NULL;
7011	struct hostapd_hw_modes *mode;
7012	u16 i;
7013
7014	if (wpa_s->hw.modes == NULL)
7015		return NULL;
7016
7017	os_memset(&ranges, 0, sizeof(ranges));
7018	if (freq_range_list_parse(&ranges, val) < 0)
7019		return NULL;
7020
7021	for (i = 0; i < wpa_s->hw.num_modes; i++) {
7022		int j;
7023
7024		mode = &wpa_s->hw.modes[i];
7025		for (j = 0; j < mode->num_channels; j++) {
7026			unsigned int freq;
7027
7028			if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7029				continue;
7030
7031			freq = mode->channels[j].freq;
7032			if (!freq_range_list_includes(&ranges, freq))
7033				continue;
7034
7035			int_array_add_unique(&freqs, freq);
7036		}
7037	}
7038
7039	os_free(ranges.range);
7040	return freqs;
7041}
7042
7043
7044#ifdef CONFIG_INTERWORKING
7045
7046static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
7047{
7048	int auto_sel = 0;
7049	int *freqs = NULL;
7050
7051	if (param) {
7052		char *pos;
7053
7054		auto_sel = os_strstr(param, "auto") != NULL;
7055
7056		pos = os_strstr(param, "freq=");
7057		if (pos) {
7058			freqs = freq_range_to_channel_list(wpa_s, pos + 5);
7059			if (freqs == NULL)
7060				return -1;
7061		}
7062
7063	}
7064
7065	return interworking_select(wpa_s, auto_sel, freqs);
7066}
7067
7068
7069static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
7070				     int only_add)
7071{
7072	u8 bssid[ETH_ALEN];
7073	struct wpa_bss *bss;
7074
7075	if (hwaddr_aton(dst, bssid)) {
7076		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
7077		return -1;
7078	}
7079
7080	bss = wpa_bss_get_bssid(wpa_s, bssid);
7081	if (bss == NULL) {
7082		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
7083			   MAC2STR(bssid));
7084		return -1;
7085	}
7086
7087	if (bss->ssid_len == 0) {
7088		int found = 0;
7089
7090		wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
7091			   " does not have SSID information", MAC2STR(bssid));
7092
7093		dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
7094					 list) {
7095			if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
7096			    bss->ssid_len > 0) {
7097				found = 1;
7098				break;
7099			}
7100		}
7101
7102		if (!found)
7103			return -1;
7104		wpa_printf(MSG_DEBUG,
7105			   "Found another matching BSS entry with SSID");
7106	}
7107
7108	return interworking_connect(wpa_s, bss, only_add);
7109}
7110
7111
7112static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
7113{
7114	u8 dst_addr[ETH_ALEN];
7115	int used;
7116	char *pos;
7117#define MAX_ANQP_INFO_ID 100
7118	u16 id[MAX_ANQP_INFO_ID];
7119	size_t num_id = 0;
7120	u32 subtypes = 0;
7121	u32 mbo_subtypes = 0;
7122
7123	used = hwaddr_aton2(dst, dst_addr);
7124	if (used < 0)
7125		return -1;
7126	pos = dst + used;
7127	if (*pos == ' ')
7128		pos++;
7129	while (num_id < MAX_ANQP_INFO_ID) {
7130		if (os_strncmp(pos, "hs20:", 5) == 0) {
7131#ifdef CONFIG_HS20
7132			int num = atoi(pos + 5);
7133			if (num <= 0 || num > 31)
7134				return -1;
7135			subtypes |= BIT(num);
7136#else /* CONFIG_HS20 */
7137			return -1;
7138#endif /* CONFIG_HS20 */
7139		} else if (os_strncmp(pos, "mbo:", 4) == 0) {
7140#ifdef CONFIG_MBO
7141			int num = atoi(pos + 4);
7142
7143			if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
7144				return -1;
7145			mbo_subtypes |= BIT(num);
7146#else /* CONFIG_MBO */
7147			return -1;
7148#endif /* CONFIG_MBO */
7149		} else {
7150			id[num_id] = atoi(pos);
7151			if (id[num_id])
7152				num_id++;
7153		}
7154		pos = os_strchr(pos + 1, ',');
7155		if (pos == NULL)
7156			break;
7157		pos++;
7158	}
7159
7160	if (num_id == 0 && !subtypes && !mbo_subtypes)
7161		return -1;
7162
7163	return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes,
7164			     mbo_subtypes);
7165}
7166
7167
7168static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
7169{
7170	u8 dst_addr[ETH_ALEN];
7171	struct wpabuf *advproto, *query = NULL;
7172	int used, ret = -1;
7173	char *pos, *end;
7174	size_t len;
7175
7176	used = hwaddr_aton2(cmd, dst_addr);
7177	if (used < 0)
7178		return -1;
7179
7180	pos = cmd + used;
7181	while (*pos == ' ')
7182		pos++;
7183
7184	/* Advertisement Protocol ID */
7185	end = os_strchr(pos, ' ');
7186	if (end)
7187		len = end - pos;
7188	else
7189		len = os_strlen(pos);
7190	if (len & 0x01)
7191		return -1;
7192	len /= 2;
7193	if (len == 0)
7194		return -1;
7195	advproto = wpabuf_alloc(len);
7196	if (advproto == NULL)
7197		return -1;
7198	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
7199		goto fail;
7200
7201	if (end) {
7202		/* Optional Query Request */
7203		pos = end + 1;
7204		while (*pos == ' ')
7205			pos++;
7206
7207		len = os_strlen(pos);
7208		if (len) {
7209			if (len & 0x01)
7210				goto fail;
7211			len /= 2;
7212			if (len == 0)
7213				goto fail;
7214			query = wpabuf_alloc(len);
7215			if (query == NULL)
7216				goto fail;
7217			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
7218				goto fail;
7219		}
7220	}
7221
7222	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
7223
7224fail:
7225	wpabuf_free(advproto);
7226	wpabuf_free(query);
7227
7228	return ret;
7229}
7230
7231
7232static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
7233			    size_t buflen)
7234{
7235	u8 addr[ETH_ALEN];
7236	int dialog_token;
7237	int used;
7238	char *pos;
7239	size_t resp_len, start, requested_len;
7240	struct wpabuf *resp;
7241	int ret;
7242
7243	used = hwaddr_aton2(cmd, addr);
7244	if (used < 0)
7245		return -1;
7246
7247	pos = cmd + used;
7248	while (*pos == ' ')
7249		pos++;
7250	dialog_token = atoi(pos);
7251
7252	if (wpa_s->last_gas_resp &&
7253	    os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
7254	    dialog_token == wpa_s->last_gas_dialog_token)
7255		resp = wpa_s->last_gas_resp;
7256	else if (wpa_s->prev_gas_resp &&
7257		 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
7258		 dialog_token == wpa_s->prev_gas_dialog_token)
7259		resp = wpa_s->prev_gas_resp;
7260	else
7261		return -1;
7262
7263	resp_len = wpabuf_len(resp);
7264	start = 0;
7265	requested_len = resp_len;
7266
7267	pos = os_strchr(pos, ' ');
7268	if (pos) {
7269		start = atoi(pos);
7270		if (start > resp_len)
7271			return os_snprintf(buf, buflen, "FAIL-Invalid range");
7272		pos = os_strchr(pos, ',');
7273		if (pos == NULL)
7274			return -1;
7275		pos++;
7276		requested_len = atoi(pos);
7277		if (start + requested_len > resp_len)
7278			return os_snprintf(buf, buflen, "FAIL-Invalid range");
7279	}
7280
7281	if (requested_len * 2 + 1 > buflen)
7282		return os_snprintf(buf, buflen, "FAIL-Too long response");
7283
7284	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
7285			       requested_len);
7286
7287	if (start + requested_len == resp_len) {
7288		/*
7289		 * Free memory by dropping the response after it has been
7290		 * fetched.
7291		 */
7292		if (resp == wpa_s->prev_gas_resp) {
7293			wpabuf_free(wpa_s->prev_gas_resp);
7294			wpa_s->prev_gas_resp = NULL;
7295		} else {
7296			wpabuf_free(wpa_s->last_gas_resp);
7297			wpa_s->last_gas_resp = NULL;
7298		}
7299	}
7300
7301	return ret;
7302}
7303#endif /* CONFIG_INTERWORKING */
7304
7305
7306#ifdef CONFIG_HS20
7307
7308static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
7309{
7310	u8 dst_addr[ETH_ALEN];
7311	int used;
7312	char *pos;
7313	u32 subtypes = 0;
7314
7315	used = hwaddr_aton2(dst, dst_addr);
7316	if (used < 0)
7317		return -1;
7318	pos = dst + used;
7319	if (*pos == ' ')
7320		pos++;
7321	for (;;) {
7322		int num = atoi(pos);
7323		if (num <= 0 || num > 31)
7324			return -1;
7325		subtypes |= BIT(num);
7326		pos = os_strchr(pos + 1, ',');
7327		if (pos == NULL)
7328			break;
7329		pos++;
7330	}
7331
7332	if (subtypes == 0)
7333		return -1;
7334
7335	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
7336}
7337
7338
7339static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
7340				    const u8 *addr, const char *realm)
7341{
7342	u8 *buf;
7343	size_t rlen, len;
7344	int ret;
7345
7346	rlen = os_strlen(realm);
7347	len = 3 + rlen;
7348	buf = os_malloc(len);
7349	if (buf == NULL)
7350		return -1;
7351	buf[0] = 1; /* NAI Home Realm Count */
7352	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
7353	buf[2] = rlen;
7354	os_memcpy(buf + 3, realm, rlen);
7355
7356	ret = hs20_anqp_send_req(wpa_s, addr,
7357				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
7358				 buf, len, 0);
7359
7360	os_free(buf);
7361
7362	return ret;
7363}
7364
7365
7366static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
7367					char *dst)
7368{
7369	struct wpa_cred *cred = wpa_s->conf->cred;
7370	u8 dst_addr[ETH_ALEN];
7371	int used;
7372	u8 *buf;
7373	size_t len;
7374	int ret;
7375
7376	used = hwaddr_aton2(dst, dst_addr);
7377	if (used < 0)
7378		return -1;
7379
7380	while (dst[used] == ' ')
7381		used++;
7382	if (os_strncmp(dst + used, "realm=", 6) == 0)
7383		return hs20_nai_home_realm_list(wpa_s, dst_addr,
7384						dst + used + 6);
7385
7386	len = os_strlen(dst + used);
7387
7388	if (len == 0 && cred && cred->realm)
7389		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
7390
7391	if (len & 1)
7392		return -1;
7393	len /= 2;
7394	buf = os_malloc(len);
7395	if (buf == NULL)
7396		return -1;
7397	if (hexstr2bin(dst + used, buf, len) < 0) {
7398		os_free(buf);
7399		return -1;
7400	}
7401
7402	ret = hs20_anqp_send_req(wpa_s, dst_addr,
7403				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
7404				 buf, len, 0);
7405	os_free(buf);
7406
7407	return ret;
7408}
7409
7410
7411static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
7412			 int buflen)
7413{
7414	u8 dst_addr[ETH_ALEN];
7415	int used;
7416	char *ctx = NULL, *icon, *poffset, *psize;
7417
7418	used = hwaddr_aton2(cmd, dst_addr);
7419	if (used < 0)
7420		return -1;
7421	cmd += used;
7422
7423	icon = str_token(cmd, " ", &ctx);
7424	poffset = str_token(cmd, " ", &ctx);
7425	psize = str_token(cmd, " ", &ctx);
7426	if (!icon || !poffset || !psize)
7427		return -1;
7428
7429	wpa_s->fetch_osu_icon_in_progress = 0;
7430	return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
7431			     reply, buflen);
7432}
7433
7434
7435static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
7436{
7437	u8 dst_addr[ETH_ALEN];
7438	int used;
7439	char *icon;
7440
7441	if (!cmd[0])
7442		return hs20_del_icon(wpa_s, NULL, NULL);
7443
7444	used = hwaddr_aton2(cmd, dst_addr);
7445	if (used < 0)
7446		return -1;
7447
7448	while (cmd[used] == ' ')
7449		used++;
7450	icon = cmd[used] ? &cmd[used] : NULL;
7451
7452	return hs20_del_icon(wpa_s, dst_addr, icon);
7453}
7454
7455
7456static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
7457{
7458	u8 dst_addr[ETH_ALEN];
7459	int used;
7460	char *icon;
7461
7462	used = hwaddr_aton2(cmd, dst_addr);
7463	if (used < 0)
7464		return -1;
7465
7466	while (cmd[used] == ' ')
7467		used++;
7468	icon = &cmd[used];
7469
7470	wpa_s->fetch_osu_icon_in_progress = 0;
7471	return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
7472				  (u8 *) icon, os_strlen(icon), inmem);
7473}
7474
7475#endif /* CONFIG_HS20 */
7476
7477
7478#ifdef CONFIG_AUTOSCAN
7479
7480static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
7481					      char *cmd)
7482{
7483	enum wpa_states state = wpa_s->wpa_state;
7484	char *new_params = NULL;
7485
7486	if (os_strlen(cmd) > 0) {
7487		new_params = os_strdup(cmd);
7488		if (new_params == NULL)
7489			return -1;
7490	}
7491
7492	os_free(wpa_s->conf->autoscan);
7493	wpa_s->conf->autoscan = new_params;
7494
7495	if (wpa_s->conf->autoscan == NULL)
7496		autoscan_deinit(wpa_s);
7497	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
7498		autoscan_init(wpa_s, 1);
7499	else if (state == WPA_SCANNING)
7500		wpa_supplicant_reinit_autoscan(wpa_s);
7501	else
7502		wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
7503			   wpa_supplicant_state_txt(state));
7504
7505	return 0;
7506}
7507
7508#endif /* CONFIG_AUTOSCAN */
7509
7510
7511#ifdef CONFIG_WNM
7512
7513static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
7514{
7515	int enter;
7516	int intval = 0;
7517	char *pos;
7518	int ret;
7519	struct wpabuf *tfs_req = NULL;
7520
7521	if (os_strncmp(cmd, "enter", 5) == 0)
7522		enter = 1;
7523	else if (os_strncmp(cmd, "exit", 4) == 0)
7524		enter = 0;
7525	else
7526		return -1;
7527
7528	pos = os_strstr(cmd, " interval=");
7529	if (pos)
7530		intval = atoi(pos + 10);
7531
7532	pos = os_strstr(cmd, " tfs_req=");
7533	if (pos) {
7534		char *end;
7535		size_t len;
7536		pos += 9;
7537		end = os_strchr(pos, ' ');
7538		if (end)
7539			len = end - pos;
7540		else
7541			len = os_strlen(pos);
7542		if (len & 1)
7543			return -1;
7544		len /= 2;
7545		tfs_req = wpabuf_alloc(len);
7546		if (tfs_req == NULL)
7547			return -1;
7548		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
7549			wpabuf_free(tfs_req);
7550			return -1;
7551		}
7552	}
7553
7554	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
7555					   WNM_SLEEP_MODE_EXIT, intval,
7556					   tfs_req);
7557	wpabuf_free(tfs_req);
7558
7559	return ret;
7560}
7561
7562
7563static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
7564{
7565	int query_reason, list = 0;
7566	char *btm_candidates = NULL;
7567
7568	query_reason = atoi(cmd);
7569
7570	cmd = os_strchr(cmd, ' ');
7571	if (cmd) {
7572		if (os_strncmp(cmd, " list", 5) == 0)
7573			list = 1;
7574		else
7575			btm_candidates = cmd;
7576	}
7577
7578	wpa_printf(MSG_DEBUG,
7579		   "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
7580		   query_reason, list ? " candidate list" : "");
7581
7582	return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
7583						  btm_candidates,
7584						  list);
7585}
7586
7587
7588static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
7589					     char *cmd)
7590{
7591	struct wpabuf *elems;
7592	int ret;
7593
7594	elems = wpabuf_parse_bin(cmd);
7595	if (!elems)
7596		return -1;
7597
7598	ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
7599	wpabuf_free(elems);
7600	return ret;
7601}
7602
7603#endif /* CONFIG_WNM */
7604
7605
7606static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
7607				      size_t buflen)
7608{
7609	struct wpa_signal_info si;
7610	int ret;
7611	char *pos, *end;
7612
7613	ret = wpa_drv_signal_poll(wpa_s, &si);
7614	if (ret)
7615		return -1;
7616
7617	pos = buf;
7618	end = buf + buflen;
7619
7620	ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
7621			  "NOISE=%d\nFREQUENCY=%u\n",
7622			  si.current_signal, si.current_txrate / 1000,
7623			  si.current_noise, si.frequency);
7624	if (os_snprintf_error(end - pos, ret))
7625		return -1;
7626	pos += ret;
7627
7628	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
7629		ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
7630				  channel_width_to_string(si.chanwidth));
7631		if (os_snprintf_error(end - pos, ret))
7632			return -1;
7633		pos += ret;
7634	}
7635
7636	if (si.center_frq1 > 0) {
7637		ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
7638				  si.center_frq1);
7639		if (os_snprintf_error(end - pos, ret))
7640			return -1;
7641		pos += ret;
7642	}
7643
7644	if (si.center_frq2 > 0) {
7645		ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
7646				  si.center_frq2);
7647		if (os_snprintf_error(end - pos, ret))
7648			return -1;
7649		pos += ret;
7650	}
7651
7652	if (si.avg_signal) {
7653		ret = os_snprintf(pos, end - pos,
7654				  "AVG_RSSI=%d\n", si.avg_signal);
7655		if (os_snprintf_error(end - pos, ret))
7656			return -1;
7657		pos += ret;
7658	}
7659
7660	if (si.avg_beacon_signal) {
7661		ret = os_snprintf(pos, end - pos,
7662				  "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal);
7663		if (os_snprintf_error(end - pos, ret))
7664			return -1;
7665		pos += ret;
7666	}
7667
7668	return pos - buf;
7669}
7670
7671
7672static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
7673					  const char *cmd)
7674{
7675	const char *pos;
7676	int threshold = 0;
7677	int hysteresis = 0;
7678
7679	if (wpa_s->bgscan && wpa_s->bgscan_priv) {
7680		wpa_printf(MSG_DEBUG,
7681			   "Reject SIGNAL_MONITOR command - bgscan is active");
7682		return -1;
7683	}
7684	pos = os_strstr(cmd, "THRESHOLD=");
7685	if (pos)
7686		threshold = atoi(pos + 10);
7687	pos = os_strstr(cmd, "HYSTERESIS=");
7688	if (pos)
7689		hysteresis = atoi(pos + 11);
7690	return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
7691}
7692
7693
7694#ifdef CONFIG_TESTING_OPTIONS
7695int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
7696						enum wpa_driver_if_type if_type,
7697						unsigned int *num,
7698						unsigned int *freq_list)
7699{
7700	char *pos = wpa_s->get_pref_freq_list_override;
7701	char *end;
7702	unsigned int count = 0;
7703
7704	/* Override string format:
7705	 *  <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
7706
7707	while (pos) {
7708		if (atoi(pos) == (int) if_type)
7709			break;
7710		pos = os_strchr(pos, ' ');
7711		if (pos)
7712			pos++;
7713	}
7714	if (!pos)
7715		return -1;
7716	pos = os_strchr(pos, ':');
7717	if (!pos)
7718		return -1;
7719	pos++;
7720	end = os_strchr(pos, ' ');
7721	while (pos && (!end || pos < end) && count < *num) {
7722		freq_list[count++] = atoi(pos);
7723		pos = os_strchr(pos, ',');
7724		if (pos)
7725			pos++;
7726	}
7727
7728	*num = count;
7729	return 0;
7730}
7731#endif /* CONFIG_TESTING_OPTIONS */
7732
7733
7734static int wpas_ctrl_iface_get_pref_freq_list(
7735	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
7736{
7737	unsigned int freq_list[100], num = 100, i;
7738	int ret;
7739	enum wpa_driver_if_type iface_type;
7740	char *pos, *end;
7741
7742	pos = buf;
7743	end = buf + buflen;
7744
7745	/* buf: "<interface_type>" */
7746	if (os_strcmp(cmd, "STATION") == 0)
7747		iface_type = WPA_IF_STATION;
7748	else if (os_strcmp(cmd, "AP") == 0)
7749		iface_type = WPA_IF_AP_BSS;
7750	else if (os_strcmp(cmd, "P2P_GO") == 0)
7751		iface_type = WPA_IF_P2P_GO;
7752	else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
7753		iface_type = WPA_IF_P2P_CLIENT;
7754	else if (os_strcmp(cmd, "IBSS") == 0)
7755		iface_type = WPA_IF_IBSS;
7756	else if (os_strcmp(cmd, "TDLS") == 0)
7757		iface_type = WPA_IF_TDLS;
7758	else
7759		return -1;
7760
7761	wpa_printf(MSG_DEBUG,
7762		   "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
7763		   iface_type, cmd);
7764
7765	ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
7766	if (ret)
7767		return -1;
7768
7769	for (i = 0; i < num; i++) {
7770		ret = os_snprintf(pos, end - pos, "%s%u",
7771				  i > 0 ? "," : "", freq_list[i]);
7772		if (os_snprintf_error(end - pos, ret))
7773			return -1;
7774		pos += ret;
7775	}
7776
7777	return pos - buf;
7778}
7779
7780
7781static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
7782					char *buf, size_t buflen)
7783{
7784	int ret, i;
7785	char *pos, *end;
7786
7787	ret = os_snprintf(buf, buflen, "%016llX:\n",
7788			  (long long unsigned) wpa_s->drv_flags);
7789	if (os_snprintf_error(buflen, ret))
7790		return -1;
7791
7792	pos = buf + ret;
7793	end = buf + buflen;
7794
7795	for (i = 0; i < 64; i++) {
7796		if (wpa_s->drv_flags & (1LLU << i)) {
7797			ret = os_snprintf(pos, end - pos, "%s\n",
7798					  driver_flag_to_string(1LLU << i));
7799			if (os_snprintf_error(end - pos, ret))
7800				return -1;
7801			pos += ret;
7802		}
7803	}
7804
7805	return pos - buf;
7806}
7807
7808
7809static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
7810				      size_t buflen)
7811{
7812	struct hostap_sta_driver_data sta;
7813	int ret;
7814
7815	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
7816	if (ret)
7817		return -1;
7818
7819	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
7820			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
7821	if (os_snprintf_error(buflen, ret))
7822		return -1;
7823	return ret;
7824}
7825
7826
7827#ifdef ANDROID
7828static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
7829				     char *buf, size_t buflen)
7830{
7831	int ret;
7832
7833	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
7834	if (ret == 0) {
7835		if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
7836			struct p2p_data *p2p = wpa_s->global->p2p;
7837			if (p2p) {
7838				char country[3];
7839				country[0] = cmd[8];
7840				country[1] = cmd[9];
7841				country[2] = 0x04;
7842				p2p_set_country(p2p, country);
7843			}
7844		}
7845		ret = os_snprintf(buf, buflen, "%s\n", "OK");
7846		if (os_snprintf_error(buflen, ret))
7847			ret = -1;
7848	}
7849	return ret;
7850}
7851#endif /* ANDROID */
7852
7853
7854static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
7855				     char *buf, size_t buflen)
7856{
7857	int ret;
7858	char *pos;
7859	u8 *data = NULL;
7860	unsigned int vendor_id, subcmd;
7861	struct wpabuf *reply;
7862	size_t data_len = 0;
7863
7864	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
7865	vendor_id = strtoul(cmd, &pos, 16);
7866	if (!isblank((unsigned char) *pos))
7867		return -EINVAL;
7868
7869	subcmd = strtoul(pos, &pos, 10);
7870
7871	if (*pos != '\0') {
7872		if (!isblank((unsigned char) *pos++))
7873			return -EINVAL;
7874		data_len = os_strlen(pos);
7875	}
7876
7877	if (data_len) {
7878		data_len /= 2;
7879		data = os_malloc(data_len);
7880		if (!data)
7881			return -1;
7882
7883		if (hexstr2bin(pos, data, data_len)) {
7884			wpa_printf(MSG_DEBUG,
7885				   "Vendor command: wrong parameter format");
7886			os_free(data);
7887			return -EINVAL;
7888		}
7889	}
7890
7891	reply = wpabuf_alloc((buflen - 1) / 2);
7892	if (!reply) {
7893		os_free(data);
7894		return -1;
7895	}
7896
7897	ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
7898				 reply);
7899
7900	if (ret == 0)
7901		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
7902				       wpabuf_len(reply));
7903
7904	wpabuf_free(reply);
7905	os_free(data);
7906
7907	return ret;
7908}
7909
7910
7911static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
7912{
7913#ifdef CONFIG_P2P
7914	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
7915		wpa_s->global->p2p_init_wpa_s : wpa_s;
7916#endif /* CONFIG_P2P */
7917
7918	wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
7919
7920	if (wpas_abort_ongoing_scan(wpa_s) == 0)
7921		wpa_s->ignore_post_flush_scan_res = 1;
7922
7923	if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
7924		/*
7925		 * Avoid possible auto connect re-connection on getting
7926		 * disconnected due to state flush.
7927		 */
7928		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
7929	}
7930
7931#ifdef CONFIG_P2P
7932	wpas_p2p_group_remove(p2p_wpa_s, "*");
7933	wpas_p2p_cancel(p2p_wpa_s);
7934	p2p_ctrl_flush(p2p_wpa_s);
7935	wpas_p2p_service_flush(p2p_wpa_s);
7936	p2p_wpa_s->global->p2p_disabled = 0;
7937	p2p_wpa_s->global->p2p_per_sta_psk = 0;
7938	p2p_wpa_s->conf->num_sec_device_types = 0;
7939	p2p_wpa_s->p2p_disable_ip_addr_req = 0;
7940	os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
7941	p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
7942	p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
7943	p2p_wpa_s->global->pending_p2ps_group = 0;
7944	p2p_wpa_s->global->pending_p2ps_group_freq = 0;
7945#endif /* CONFIG_P2P */
7946
7947#ifdef CONFIG_WPS_TESTING
7948	wps_version_number = 0x20;
7949	wps_testing_dummy_cred = 0;
7950	wps_corrupt_pkhash = 0;
7951	wps_force_auth_types_in_use = 0;
7952	wps_force_encr_types_in_use = 0;
7953#endif /* CONFIG_WPS_TESTING */
7954#ifdef CONFIG_WPS
7955	wpa_s->wps_fragment_size = 0;
7956	wpas_wps_cancel(wpa_s);
7957	wps_registrar_flush(wpa_s->wps->registrar);
7958#endif /* CONFIG_WPS */
7959	wpa_s->after_wps = 0;
7960	wpa_s->known_wps_freq = 0;
7961
7962#ifdef CONFIG_DPP
7963	wpas_dpp_deinit(wpa_s);
7964	wpa_s->dpp_init_max_tries = 0;
7965	wpa_s->dpp_init_retry_time = 0;
7966	wpa_s->dpp_resp_wait_time = 0;
7967	wpa_s->dpp_resp_max_tries = 0;
7968	wpa_s->dpp_resp_retry_time = 0;
7969#ifdef CONFIG_TESTING_OPTIONS
7970	os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
7971	os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
7972	dpp_pkex_ephemeral_key_override_len = 0;
7973	dpp_protocol_key_override_len = 0;
7974	dpp_nonce_override_len = 0;
7975#endif /* CONFIG_TESTING_OPTIONS */
7976#endif /* CONFIG_DPP */
7977
7978#ifdef CONFIG_TDLS
7979#ifdef CONFIG_TDLS_TESTING
7980	tdls_testing = 0;
7981#endif /* CONFIG_TDLS_TESTING */
7982	wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
7983	wpa_tdls_enable(wpa_s->wpa, 1);
7984#endif /* CONFIG_TDLS */
7985
7986	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
7987	wpa_supplicant_stop_countermeasures(wpa_s, NULL);
7988
7989	wpa_s->no_keep_alive = 0;
7990	wpa_s->own_disconnect_req = 0;
7991
7992	os_free(wpa_s->disallow_aps_bssid);
7993	wpa_s->disallow_aps_bssid = NULL;
7994	wpa_s->disallow_aps_bssid_count = 0;
7995	os_free(wpa_s->disallow_aps_ssid);
7996	wpa_s->disallow_aps_ssid = NULL;
7997	wpa_s->disallow_aps_ssid_count = 0;
7998
7999	wpa_s->set_sta_uapsd = 0;
8000	wpa_s->sta_uapsd = 0;
8001
8002	wpa_drv_radio_disable(wpa_s, 0);
8003	wpa_blacklist_clear(wpa_s);
8004	wpa_s->extra_blacklist_count = 0;
8005	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
8006	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
8007	wpa_config_flush_blobs(wpa_s->conf);
8008	wpa_s->conf->auto_interworking = 0;
8009	wpa_s->conf->okc = 0;
8010
8011	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
8012	rsn_preauth_deinit(wpa_s->wpa);
8013
8014	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
8015	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
8016	wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
8017	eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
8018
8019	radio_remove_works(wpa_s, NULL, 1);
8020	wpa_s->ext_work_in_progress = 0;
8021
8022	wpa_s->next_ssid = NULL;
8023
8024#ifdef CONFIG_INTERWORKING
8025#ifdef CONFIG_HS20
8026	hs20_cancel_fetch_osu(wpa_s);
8027	hs20_del_icon(wpa_s, NULL, NULL);
8028#endif /* CONFIG_HS20 */
8029#endif /* CONFIG_INTERWORKING */
8030
8031	wpa_s->ext_mgmt_frame_handling = 0;
8032	wpa_s->ext_eapol_frame_io = 0;
8033#ifdef CONFIG_TESTING_OPTIONS
8034	wpa_s->extra_roc_dur = 0;
8035	wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
8036	wpa_s->p2p_go_csa_on_inv = 0;
8037	wpa_s->ignore_auth_resp = 0;
8038	wpa_s->ignore_assoc_disallow = 0;
8039	wpa_s->testing_resend_assoc = 0;
8040	wpa_s->reject_btm_req_reason = 0;
8041	wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
8042	os_free(wpa_s->get_pref_freq_list_override);
8043	wpa_s->get_pref_freq_list_override = NULL;
8044	wpabuf_free(wpa_s->sae_commit_override);
8045	wpa_s->sae_commit_override = NULL;
8046#ifdef CONFIG_DPP
8047	os_free(wpa_s->dpp_config_obj_override);
8048	wpa_s->dpp_config_obj_override = NULL;
8049	os_free(wpa_s->dpp_discovery_override);
8050	wpa_s->dpp_discovery_override = NULL;
8051	os_free(wpa_s->dpp_groups_override);
8052	wpa_s->dpp_groups_override = NULL;
8053	dpp_test = DPP_TEST_DISABLED;
8054#endif /* CONFIG_DPP */
8055#endif /* CONFIG_TESTING_OPTIONS */
8056
8057	wpa_s->disconnected = 0;
8058	os_free(wpa_s->next_scan_freqs);
8059	wpa_s->next_scan_freqs = NULL;
8060	os_free(wpa_s->select_network_scan_freqs);
8061	wpa_s->select_network_scan_freqs = NULL;
8062
8063	wpa_bss_flush(wpa_s);
8064	if (!dl_list_empty(&wpa_s->bss)) {
8065		wpa_printf(MSG_DEBUG,
8066			   "BSS table not empty after flush: %u entries, current_bss=%p bssid="
8067			   MACSTR " pending_bssid=" MACSTR,
8068			   dl_list_len(&wpa_s->bss), wpa_s->current_bss,
8069			   MAC2STR(wpa_s->bssid),
8070			   MAC2STR(wpa_s->pending_bssid));
8071	}
8072
8073	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
8074	wpa_s->wnmsleep_used = 0;
8075
8076#ifdef CONFIG_SME
8077	wpa_s->sme.last_unprot_disconnect.sec = 0;
8078#endif /* CONFIG_SME */
8079
8080	wpabuf_free(wpa_s->ric_ies);
8081	wpa_s->ric_ies = NULL;
8082
8083	wpa_supplicant_update_channel_list(wpa_s, NULL);
8084
8085	free_bss_tmp_disallowed(wpa_s);
8086}
8087
8088
8089static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
8090				     char *buf, size_t buflen)
8091{
8092	struct wpa_radio_work *work;
8093	char *pos, *end;
8094	struct os_reltime now, diff;
8095
8096	pos = buf;
8097	end = buf + buflen;
8098
8099	os_get_reltime(&now);
8100
8101	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
8102	{
8103		int ret;
8104
8105		os_reltime_sub(&now, &work->time, &diff);
8106		ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%jd.%06ld\n",
8107				  work->type, work->wpa_s->ifname, work->freq,
8108				  work->started, (intmax_t)diff.sec,
8109				  (long)diff.usec);
8110		if (os_snprintf_error(end - pos, ret))
8111			break;
8112		pos += ret;
8113	}
8114
8115	return pos - buf;
8116}
8117
8118
8119static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
8120{
8121	struct wpa_radio_work *work = eloop_ctx;
8122	struct wpa_external_work *ework = work->ctx;
8123
8124	wpa_dbg(work->wpa_s, MSG_DEBUG,
8125		"Timing out external radio work %u (%s)",
8126		ework->id, work->type);
8127	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
8128	work->wpa_s->ext_work_in_progress = 0;
8129	radio_work_done(work);
8130	os_free(ework);
8131}
8132
8133
8134static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
8135{
8136	struct wpa_external_work *ework = work->ctx;
8137
8138	if (deinit) {
8139		if (work->started)
8140			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
8141					     work, NULL);
8142
8143		/*
8144		 * work->type points to a buffer in ework, so need to replace
8145		 * that here with a fixed string to avoid use of freed memory
8146		 * in debug prints.
8147		 */
8148		work->type = "freed-ext-work";
8149		work->ctx = NULL;
8150		os_free(ework);
8151		return;
8152	}
8153
8154	wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
8155		ework->id, ework->type);
8156	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
8157	work->wpa_s->ext_work_in_progress = 1;
8158	if (!ework->timeout)
8159		ework->timeout = 10;
8160	eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
8161			       work, NULL);
8162}
8163
8164
8165static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
8166				    char *buf, size_t buflen)
8167{
8168	struct wpa_external_work *ework;
8169	char *pos, *pos2;
8170	size_t type_len;
8171	int ret;
8172	unsigned int freq = 0;
8173
8174	/* format: <name> [freq=<MHz>] [timeout=<seconds>] */
8175
8176	ework = os_zalloc(sizeof(*ework));
8177	if (ework == NULL)
8178		return -1;
8179
8180	pos = os_strchr(cmd, ' ');
8181	if (pos) {
8182		type_len = pos - cmd;
8183		pos++;
8184
8185		pos2 = os_strstr(pos, "freq=");
8186		if (pos2)
8187			freq = atoi(pos2 + 5);
8188
8189		pos2 = os_strstr(pos, "timeout=");
8190		if (pos2)
8191			ework->timeout = atoi(pos2 + 8);
8192	} else {
8193		type_len = os_strlen(cmd);
8194	}
8195	if (4 + type_len >= sizeof(ework->type))
8196		type_len = sizeof(ework->type) - 4 - 1;
8197	os_strlcpy(ework->type, "ext:", sizeof(ework->type));
8198	os_memcpy(ework->type + 4, cmd, type_len);
8199	ework->type[4 + type_len] = '\0';
8200
8201	wpa_s->ext_work_id++;
8202	if (wpa_s->ext_work_id == 0)
8203		wpa_s->ext_work_id++;
8204	ework->id = wpa_s->ext_work_id;
8205
8206	if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
8207			   ework) < 0) {
8208		os_free(ework);
8209		return -1;
8210	}
8211
8212	ret = os_snprintf(buf, buflen, "%u", ework->id);
8213	if (os_snprintf_error(buflen, ret))
8214		return -1;
8215	return ret;
8216}
8217
8218
8219static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
8220{
8221	struct wpa_radio_work *work;
8222	unsigned int id = atoi(cmd);
8223
8224	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
8225	{
8226		struct wpa_external_work *ework;
8227
8228		if (os_strncmp(work->type, "ext:", 4) != 0)
8229			continue;
8230		ework = work->ctx;
8231		if (id && ework->id != id)
8232			continue;
8233		wpa_dbg(wpa_s, MSG_DEBUG,
8234			"Completed external radio work %u (%s)",
8235			ework->id, ework->type);
8236		eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
8237		wpa_s->ext_work_in_progress = 0;
8238		radio_work_done(work);
8239		os_free(ework);
8240		return 3; /* "OK\n" */
8241	}
8242
8243	return -1;
8244}
8245
8246
8247static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
8248				char *buf, size_t buflen)
8249{
8250	if (os_strcmp(cmd, "show") == 0)
8251		return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
8252	if (os_strncmp(cmd, "add ", 4) == 0)
8253		return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
8254	if (os_strncmp(cmd, "done ", 5) == 0)
8255		return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
8256	return -1;
8257}
8258
8259
8260void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
8261{
8262	struct wpa_radio_work *work, *tmp;
8263
8264	if (!wpa_s || !wpa_s->radio)
8265		return;
8266
8267	dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
8268			      struct wpa_radio_work, list) {
8269		struct wpa_external_work *ework;
8270
8271		if (os_strncmp(work->type, "ext:", 4) != 0)
8272			continue;
8273		ework = work->ctx;
8274		wpa_dbg(wpa_s, MSG_DEBUG,
8275			"Flushing%s external radio work %u (%s)",
8276			work->started ? " started" : "", ework->id,
8277			ework->type);
8278		if (work->started)
8279			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
8280					     work, NULL);
8281		radio_work_done(work);
8282		os_free(ework);
8283	}
8284}
8285
8286
8287static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
8288{
8289	struct wpa_supplicant *wpa_s = eloop_ctx;
8290	eapol_sm_notify_ctrl_response(wpa_s->eapol);
8291}
8292
8293
8294static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
8295			      unsigned int *scan_id_count, int scan_id[])
8296{
8297	const char *pos = value;
8298
8299	while (pos) {
8300		if (*pos == ' ' || *pos == '\0')
8301			break;
8302		if (*scan_id_count == MAX_SCAN_ID)
8303			return -1;
8304		scan_id[(*scan_id_count)++] = atoi(pos);
8305		pos = os_strchr(pos, ',');
8306		if (pos)
8307			pos++;
8308	}
8309
8310	return 0;
8311}
8312
8313
8314static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
8315			   char *reply, int reply_size, int *reply_len)
8316{
8317	char *pos;
8318	unsigned int manual_scan_passive = 0;
8319	unsigned int manual_scan_use_id = 0;
8320	unsigned int manual_scan_only_new = 0;
8321	unsigned int scan_only = 0;
8322	unsigned int scan_id_count = 0;
8323	int scan_id[MAX_SCAN_ID];
8324	void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
8325				 struct wpa_scan_results *scan_res);
8326	int *manual_scan_freqs = NULL;
8327	struct wpa_ssid_value *ssid = NULL, *ns;
8328	unsigned int ssid_count = 0;
8329
8330	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
8331		*reply_len = -1;
8332		return;
8333	}
8334
8335	if (radio_work_pending(wpa_s, "scan")) {
8336		wpa_printf(MSG_DEBUG,
8337			   "Pending scan scheduled - reject new request");
8338		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
8339		return;
8340	}
8341
8342#ifdef CONFIG_INTERWORKING
8343	if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
8344		wpa_printf(MSG_DEBUG,
8345			   "Interworking select in progress - reject new scan");
8346		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
8347		return;
8348	}
8349#endif /* CONFIG_INTERWORKING */
8350
8351	if (params) {
8352		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
8353			scan_only = 1;
8354
8355		pos = os_strstr(params, "freq=");
8356		if (pos) {
8357			manual_scan_freqs = freq_range_to_channel_list(wpa_s,
8358								       pos + 5);
8359			if (manual_scan_freqs == NULL) {
8360				*reply_len = -1;
8361				goto done;
8362			}
8363		}
8364
8365		pos = os_strstr(params, "passive=");
8366		if (pos)
8367			manual_scan_passive = !!atoi(pos + 8);
8368
8369		pos = os_strstr(params, "use_id=");
8370		if (pos)
8371			manual_scan_use_id = atoi(pos + 7);
8372
8373		pos = os_strstr(params, "only_new=1");
8374		if (pos)
8375			manual_scan_only_new = 1;
8376
8377		pos = os_strstr(params, "scan_id=");
8378		if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
8379					      scan_id) < 0) {
8380			*reply_len = -1;
8381			goto done;
8382		}
8383
8384		pos = os_strstr(params, "bssid=");
8385		if (pos) {
8386			u8 bssid[ETH_ALEN];
8387
8388			pos += 6;
8389			if (hwaddr_aton(pos, bssid)) {
8390				wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
8391				*reply_len = -1;
8392				goto done;
8393			}
8394			os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
8395		}
8396
8397		pos = params;
8398		while (pos && *pos != '\0') {
8399			if (os_strncmp(pos, "ssid ", 5) == 0) {
8400				char *end;
8401
8402				pos += 5;
8403				end = pos;
8404				while (*end) {
8405					if (*end == '\0' || *end == ' ')
8406						break;
8407					end++;
8408				}
8409
8410				ns = os_realloc_array(
8411					ssid, ssid_count + 1,
8412					sizeof(struct wpa_ssid_value));
8413				if (ns == NULL) {
8414					*reply_len = -1;
8415					goto done;
8416				}
8417				ssid = ns;
8418
8419				if ((end - pos) & 0x01 ||
8420				    end - pos > 2 * SSID_MAX_LEN ||
8421				    hexstr2bin(pos, ssid[ssid_count].ssid,
8422					       (end - pos) / 2) < 0) {
8423					wpa_printf(MSG_DEBUG,
8424						   "Invalid SSID value '%s'",
8425						   pos);
8426					*reply_len = -1;
8427					goto done;
8428				}
8429				ssid[ssid_count].ssid_len = (end - pos) / 2;
8430				wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
8431						  ssid[ssid_count].ssid,
8432						  ssid[ssid_count].ssid_len);
8433				ssid_count++;
8434				pos = end;
8435			}
8436
8437			pos = os_strchr(pos, ' ');
8438			if (pos)
8439				pos++;
8440		}
8441	}
8442
8443	wpa_s->num_ssids_from_scan_req = ssid_count;
8444	os_free(wpa_s->ssids_from_scan_req);
8445	if (ssid_count) {
8446		wpa_s->ssids_from_scan_req = ssid;
8447		ssid = NULL;
8448	} else {
8449		wpa_s->ssids_from_scan_req = NULL;
8450	}
8451
8452	if (scan_only)
8453		scan_res_handler = scan_only_handler;
8454	else if (wpa_s->scan_res_handler == scan_only_handler)
8455		scan_res_handler = NULL;
8456	else
8457		scan_res_handler = wpa_s->scan_res_handler;
8458
8459	if (!wpa_s->sched_scanning && !wpa_s->scanning &&
8460	    ((wpa_s->wpa_state <= WPA_SCANNING) ||
8461	     (wpa_s->wpa_state == WPA_COMPLETED))) {
8462		wpa_s->manual_scan_passive = manual_scan_passive;
8463		wpa_s->manual_scan_use_id = manual_scan_use_id;
8464		wpa_s->manual_scan_only_new = manual_scan_only_new;
8465		wpa_s->scan_id_count = scan_id_count;
8466		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
8467		wpa_s->scan_res_handler = scan_res_handler;
8468		os_free(wpa_s->manual_scan_freqs);
8469		wpa_s->manual_scan_freqs = manual_scan_freqs;
8470		manual_scan_freqs = NULL;
8471
8472		wpa_s->normal_scans = 0;
8473		wpa_s->scan_req = MANUAL_SCAN_REQ;
8474		wpa_s->after_wps = 0;
8475		wpa_s->known_wps_freq = 0;
8476		wpa_supplicant_req_scan(wpa_s, 0, 0);
8477		if (wpa_s->manual_scan_use_id) {
8478			wpa_s->manual_scan_id++;
8479			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
8480				wpa_s->manual_scan_id);
8481			*reply_len = os_snprintf(reply, reply_size, "%u\n",
8482						 wpa_s->manual_scan_id);
8483		}
8484	} else if (wpa_s->sched_scanning) {
8485		wpa_s->manual_scan_passive = manual_scan_passive;
8486		wpa_s->manual_scan_use_id = manual_scan_use_id;
8487		wpa_s->manual_scan_only_new = manual_scan_only_new;
8488		wpa_s->scan_id_count = scan_id_count;
8489		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
8490		wpa_s->scan_res_handler = scan_res_handler;
8491		os_free(wpa_s->manual_scan_freqs);
8492		wpa_s->manual_scan_freqs = manual_scan_freqs;
8493		manual_scan_freqs = NULL;
8494
8495		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
8496		wpa_supplicant_cancel_sched_scan(wpa_s);
8497		wpa_s->scan_req = MANUAL_SCAN_REQ;
8498		wpa_supplicant_req_scan(wpa_s, 0, 0);
8499		if (wpa_s->manual_scan_use_id) {
8500			wpa_s->manual_scan_id++;
8501			*reply_len = os_snprintf(reply, reply_size, "%u\n",
8502						 wpa_s->manual_scan_id);
8503			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
8504				wpa_s->manual_scan_id);
8505		}
8506	} else {
8507		wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
8508		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
8509	}
8510
8511done:
8512	os_free(manual_scan_freqs);
8513	os_free(ssid);
8514}
8515
8516
8517#ifdef CONFIG_TESTING_OPTIONS
8518
8519static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
8520				       unsigned int freq, const u8 *dst,
8521				       const u8 *src, const u8 *bssid,
8522				       const u8 *data, size_t data_len,
8523				       enum offchannel_send_action_result
8524				       result)
8525{
8526	wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
8527		" src=" MACSTR " bssid=" MACSTR " result=%s",
8528		freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
8529		result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
8530		"SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
8531			     "NO_ACK" : "FAILED"));
8532}
8533
8534
8535static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
8536{
8537	char *pos, *param;
8538	size_t len;
8539	u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
8540	int res, used;
8541	int freq = 0, no_cck = 0, wait_time = 0;
8542
8543	/* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
8544	 *    <action=Action frame payload> */
8545
8546	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
8547
8548	pos = cmd;
8549	used = hwaddr_aton2(pos, da);
8550	if (used < 0)
8551		return -1;
8552	pos += used;
8553	while (*pos == ' ')
8554		pos++;
8555	used = hwaddr_aton2(pos, bssid);
8556	if (used < 0)
8557		return -1;
8558	pos += used;
8559
8560	param = os_strstr(pos, " freq=");
8561	if (param) {
8562		param += 6;
8563		freq = atoi(param);
8564	}
8565
8566	param = os_strstr(pos, " no_cck=");
8567	if (param) {
8568		param += 8;
8569		no_cck = atoi(param);
8570	}
8571
8572	param = os_strstr(pos, " wait_time=");
8573	if (param) {
8574		param += 11;
8575		wait_time = atoi(param);
8576	}
8577
8578	param = os_strstr(pos, " action=");
8579	if (param == NULL)
8580		return -1;
8581	param += 8;
8582
8583	len = os_strlen(param);
8584	if (len & 1)
8585		return -1;
8586	len /= 2;
8587
8588	buf = os_malloc(len);
8589	if (buf == NULL)
8590		return -1;
8591
8592	if (hexstr2bin(param, buf, len) < 0) {
8593		os_free(buf);
8594		return -1;
8595	}
8596
8597	res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
8598				     buf, len, wait_time,
8599				     wpas_ctrl_iface_mgmt_tx_cb, no_cck);
8600	os_free(buf);
8601	return res;
8602}
8603
8604
8605static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
8606{
8607	wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
8608	offchannel_send_action_done(wpa_s);
8609}
8610
8611
8612static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
8613					   char *cmd)
8614{
8615	char *pos, *param;
8616	size_t len;
8617	u8 *buf;
8618	int freq = 0, datarate = 0, ssi_signal = 0;
8619	union wpa_event_data event;
8620
8621	if (!wpa_s->ext_mgmt_frame_handling)
8622		return -1;
8623
8624	/* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
8625
8626	wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
8627
8628	pos = cmd;
8629	param = os_strstr(pos, "freq=");
8630	if (param) {
8631		param += 5;
8632		freq = atoi(param);
8633	}
8634
8635	param = os_strstr(pos, " datarate=");
8636	if (param) {
8637		param += 10;
8638		datarate = atoi(param);
8639	}
8640
8641	param = os_strstr(pos, " ssi_signal=");
8642	if (param) {
8643		param += 12;
8644		ssi_signal = atoi(param);
8645	}
8646
8647	param = os_strstr(pos, " frame=");
8648	if (param == NULL)
8649		return -1;
8650	param += 7;
8651
8652	len = os_strlen(param);
8653	if (len & 1)
8654		return -1;
8655	len /= 2;
8656
8657	buf = os_malloc(len);
8658	if (buf == NULL)
8659		return -1;
8660
8661	if (hexstr2bin(param, buf, len) < 0) {
8662		os_free(buf);
8663		return -1;
8664	}
8665
8666	os_memset(&event, 0, sizeof(event));
8667	event.rx_mgmt.freq = freq;
8668	event.rx_mgmt.frame = buf;
8669	event.rx_mgmt.frame_len = len;
8670	event.rx_mgmt.ssi_signal = ssi_signal;
8671	event.rx_mgmt.datarate = datarate;
8672	wpa_s->ext_mgmt_frame_handling = 0;
8673	wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
8674	wpa_s->ext_mgmt_frame_handling = 1;
8675
8676	os_free(buf);
8677
8678	return 0;
8679}
8680
8681
8682static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
8683					   char *param)
8684{
8685	struct wpa_scan_res *res;
8686	struct os_reltime now;
8687	char *pos, *end;
8688	int ret = -1;
8689
8690	if (!param)
8691		return -1;
8692
8693	if (os_strcmp(param, "START") == 0) {
8694		wpa_bss_update_start(wpa_s);
8695		return 0;
8696	}
8697
8698	if (os_strcmp(param, "END") == 0) {
8699		wpa_bss_update_end(wpa_s, NULL, 1);
8700		return 0;
8701	}
8702
8703	if (os_strncmp(param, "BSS ", 4) != 0)
8704		return -1;
8705	param += 3;
8706
8707	res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
8708	if (!res)
8709		return -1;
8710
8711	pos = os_strstr(param, " flags=");
8712	if (pos)
8713		res->flags = strtol(pos + 7, NULL, 16);
8714
8715	pos = os_strstr(param, " bssid=");
8716	if (pos && hwaddr_aton(pos + 7, res->bssid))
8717		goto fail;
8718
8719	pos = os_strstr(param, " freq=");
8720	if (pos)
8721		res->freq = atoi(pos + 6);
8722
8723	pos = os_strstr(param, " beacon_int=");
8724	if (pos)
8725		res->beacon_int = atoi(pos + 12);
8726
8727	pos = os_strstr(param, " caps=");
8728	if (pos)
8729		res->caps = strtol(pos + 6, NULL, 16);
8730
8731	pos = os_strstr(param, " qual=");
8732	if (pos)
8733		res->qual = atoi(pos + 6);
8734
8735	pos = os_strstr(param, " noise=");
8736	if (pos)
8737		res->noise = atoi(pos + 7);
8738
8739	pos = os_strstr(param, " level=");
8740	if (pos)
8741		res->level = atoi(pos + 7);
8742
8743	pos = os_strstr(param, " tsf=");
8744	if (pos)
8745		res->tsf = strtoll(pos + 5, NULL, 16);
8746
8747	pos = os_strstr(param, " age=");
8748	if (pos)
8749		res->age = atoi(pos + 5);
8750
8751	pos = os_strstr(param, " est_throughput=");
8752	if (pos)
8753		res->est_throughput = atoi(pos + 16);
8754
8755	pos = os_strstr(param, " snr=");
8756	if (pos)
8757		res->snr = atoi(pos + 5);
8758
8759	pos = os_strstr(param, " parent_tsf=");
8760	if (pos)
8761		res->parent_tsf = strtoll(pos + 7, NULL, 16);
8762
8763	pos = os_strstr(param, " tsf_bssid=");
8764	if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
8765		goto fail;
8766
8767	pos = os_strstr(param, " ie=");
8768	if (pos) {
8769		pos += 4;
8770		end = os_strchr(pos, ' ');
8771		if (!end)
8772			end = pos + os_strlen(pos);
8773		res->ie_len = (end - pos) / 2;
8774		if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
8775			goto fail;
8776	}
8777
8778	pos = os_strstr(param, " beacon_ie=");
8779	if (pos) {
8780		pos += 11;
8781		end = os_strchr(pos, ' ');
8782		if (!end)
8783			end = pos + os_strlen(pos);
8784		res->beacon_ie_len = (end - pos) / 2;
8785		if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
8786			       res->beacon_ie_len))
8787			goto fail;
8788	}
8789
8790	os_get_reltime(&now);
8791	wpa_bss_update_scan_res(wpa_s, res, &now);
8792	ret = 0;
8793fail:
8794	os_free(res);
8795
8796	return ret;
8797}
8798
8799
8800static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
8801{
8802	char *pos, *param;
8803	union wpa_event_data event;
8804	enum wpa_event_type ev;
8805
8806	/* <event name> [parameters..] */
8807
8808	wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
8809
8810	pos = cmd;
8811	param = os_strchr(pos, ' ');
8812	if (param)
8813		*param++ = '\0';
8814
8815	os_memset(&event, 0, sizeof(event));
8816
8817	if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
8818		ev = EVENT_INTERFACE_ENABLED;
8819	} else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
8820		ev = EVENT_INTERFACE_DISABLED;
8821	} else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
8822		ev = EVENT_AVOID_FREQUENCIES;
8823		if (param == NULL)
8824			param = "";
8825		if (freq_range_list_parse(&event.freq_range, param) < 0)
8826			return -1;
8827		wpa_supplicant_event(wpa_s, ev, &event);
8828		os_free(event.freq_range.range);
8829		return 0;
8830	} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
8831		return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
8832	} else {
8833		wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
8834			cmd);
8835		return -1;
8836	}
8837
8838	wpa_supplicant_event(wpa_s, ev, &event);
8839
8840	return 0;
8841}
8842
8843
8844static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
8845{
8846	char *pos;
8847	u8 src[ETH_ALEN], *buf;
8848	int used;
8849	size_t len;
8850
8851	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
8852
8853	pos = cmd;
8854	used = hwaddr_aton2(pos, src);
8855	if (used < 0)
8856		return -1;
8857	pos += used;
8858	while (*pos == ' ')
8859		pos++;
8860
8861	len = os_strlen(pos);
8862	if (len & 1)
8863		return -1;
8864	len /= 2;
8865
8866	buf = os_malloc(len);
8867	if (buf == NULL)
8868		return -1;
8869
8870	if (hexstr2bin(pos, buf, len) < 0) {
8871		os_free(buf);
8872		return -1;
8873	}
8874
8875	wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
8876	os_free(buf);
8877
8878	return 0;
8879}
8880
8881
8882static u16 ipv4_hdr_checksum(const void *buf, size_t len)
8883{
8884	size_t i;
8885	u32 sum = 0;
8886	const u16 *pos = buf;
8887
8888	for (i = 0; i < len / 2; i++)
8889		sum += *pos++;
8890
8891	while (sum >> 16)
8892		sum = (sum & 0xffff) + (sum >> 16);
8893
8894	return sum ^ 0xffff;
8895}
8896
8897
8898#define HWSIM_PACKETLEN 1500
8899#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
8900
8901static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
8902			      size_t len)
8903{
8904	struct wpa_supplicant *wpa_s = ctx;
8905	const struct ether_header *eth;
8906	struct iphdr ip;
8907	const u8 *pos;
8908	unsigned int i;
8909	char extra[30];
8910
8911	if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
8912		wpa_printf(MSG_DEBUG,
8913			   "test data: RX - ignore unexpected length %d",
8914			   (int) len);
8915		return;
8916	}
8917
8918	eth = (const struct ether_header *) buf;
8919	os_memcpy(&ip, eth + 1, sizeof(ip));
8920	pos = &buf[sizeof(*eth) + sizeof(ip)];
8921
8922	if (ip.ihl != 5 || ip.version != 4 ||
8923	    ntohs(ip.tot_len) > HWSIM_IP_LEN) {
8924		wpa_printf(MSG_DEBUG,
8925			   "test data: RX - ignore unexpect IP header");
8926		return;
8927	}
8928
8929	for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
8930		if (*pos != (u8) i) {
8931			wpa_printf(MSG_DEBUG,
8932				   "test data: RX - ignore mismatching payload");
8933			return;
8934		}
8935		pos++;
8936	}
8937	extra[0] = '\0';
8938	if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
8939		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
8940	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
8941		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
8942}
8943
8944
8945static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
8946					    char *cmd)
8947{
8948	int enabled = atoi(cmd);
8949	char *pos;
8950	const char *ifname;
8951
8952	if (!enabled) {
8953		if (wpa_s->l2_test) {
8954			l2_packet_deinit(wpa_s->l2_test);
8955			wpa_s->l2_test = NULL;
8956			wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
8957		}
8958		return 0;
8959	}
8960
8961	if (wpa_s->l2_test)
8962		return 0;
8963
8964	pos = os_strstr(cmd, " ifname=");
8965	if (pos)
8966		ifname = pos + 8;
8967	else
8968		ifname = wpa_s->ifname;
8969
8970	wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
8971					ETHERTYPE_IP, wpas_data_test_rx,
8972					wpa_s, 1);
8973	if (wpa_s->l2_test == NULL)
8974		return -1;
8975
8976	wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
8977
8978	return 0;
8979}
8980
8981
8982static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
8983{
8984	u8 dst[ETH_ALEN], src[ETH_ALEN];
8985	char *pos, *pos2;
8986	int used;
8987	long int val;
8988	u8 tos;
8989	u8 buf[2 + HWSIM_PACKETLEN];
8990	struct ether_header *eth;
8991	struct iphdr *ip;
8992	u8 *dpos;
8993	unsigned int i;
8994	size_t send_len = HWSIM_IP_LEN;
8995
8996	if (wpa_s->l2_test == NULL)
8997		return -1;
8998
8999	/* format: <dst> <src> <tos> [len=<length>] */
9000
9001	pos = cmd;
9002	used = hwaddr_aton2(pos, dst);
9003	if (used < 0)
9004		return -1;
9005	pos += used;
9006	while (*pos == ' ')
9007		pos++;
9008	used = hwaddr_aton2(pos, src);
9009	if (used < 0)
9010		return -1;
9011	pos += used;
9012
9013	val = strtol(pos, &pos2, 0);
9014	if (val < 0 || val > 0xff)
9015		return -1;
9016	tos = val;
9017
9018	pos = os_strstr(pos2, " len=");
9019	if (pos) {
9020		i = atoi(pos + 5);
9021		if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
9022			return -1;
9023		send_len = i;
9024	}
9025
9026	eth = (struct ether_header *) &buf[2];
9027	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
9028	os_memcpy(eth->ether_shost, src, ETH_ALEN);
9029	eth->ether_type = htons(ETHERTYPE_IP);
9030	ip = (struct iphdr *) (eth + 1);
9031	os_memset(ip, 0, sizeof(*ip));
9032	ip->ihl = 5;
9033	ip->version = 4;
9034	ip->ttl = 64;
9035	ip->tos = tos;
9036	ip->tot_len = htons(send_len);
9037	ip->protocol = 1;
9038	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
9039	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
9040	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
9041	dpos = (u8 *) (ip + 1);
9042	for (i = 0; i < send_len - sizeof(*ip); i++)
9043		*dpos++ = i;
9044
9045	if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
9046			   sizeof(struct ether_header) + send_len) < 0)
9047		return -1;
9048
9049	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
9050		" tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
9051
9052	return 0;
9053}
9054
9055
9056static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
9057					   char *cmd)
9058{
9059	u8 *buf;
9060	struct ether_header *eth;
9061	struct l2_packet_data *l2 = NULL;
9062	size_t len;
9063	u16 ethertype;
9064	int res = -1;
9065
9066	len = os_strlen(cmd);
9067	if (len & 1 || len < ETH_HLEN * 2)
9068		return -1;
9069	len /= 2;
9070
9071	buf = os_malloc(len);
9072	if (buf == NULL)
9073		return -1;
9074
9075	if (hexstr2bin(cmd, buf, len) < 0)
9076		goto done;
9077
9078	eth = (struct ether_header *) buf;
9079	ethertype = ntohs(eth->ether_type);
9080
9081	l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
9082			    wpas_data_test_rx, wpa_s, 1);
9083	if (l2 == NULL)
9084		goto done;
9085
9086	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
9087	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
9088done:
9089	if (l2)
9090		l2_packet_deinit(l2);
9091	os_free(buf);
9092
9093	return res < 0 ? -1 : 0;
9094}
9095
9096
9097static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
9098{
9099#ifdef WPA_TRACE_BFD
9100	char *pos;
9101
9102	wpa_trace_fail_after = atoi(cmd);
9103	pos = os_strchr(cmd, ':');
9104	if (pos) {
9105		pos++;
9106		os_strlcpy(wpa_trace_fail_func, pos,
9107			   sizeof(wpa_trace_fail_func));
9108	} else {
9109		wpa_trace_fail_after = 0;
9110	}
9111	return 0;
9112#else /* WPA_TRACE_BFD */
9113	return -1;
9114#endif /* WPA_TRACE_BFD */
9115}
9116
9117
9118static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
9119				    char *buf, size_t buflen)
9120{
9121#ifdef WPA_TRACE_BFD
9122	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
9123			   wpa_trace_fail_func);
9124#else /* WPA_TRACE_BFD */
9125	return -1;
9126#endif /* WPA_TRACE_BFD */
9127}
9128
9129
9130static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
9131{
9132#ifdef WPA_TRACE_BFD
9133	char *pos;
9134
9135	wpa_trace_test_fail_after = atoi(cmd);
9136	pos = os_strchr(cmd, ':');
9137	if (pos) {
9138		pos++;
9139		os_strlcpy(wpa_trace_test_fail_func, pos,
9140			   sizeof(wpa_trace_test_fail_func));
9141	} else {
9142		wpa_trace_test_fail_after = 0;
9143	}
9144	return 0;
9145#else /* WPA_TRACE_BFD */
9146	return -1;
9147#endif /* WPA_TRACE_BFD */
9148}
9149
9150
9151static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
9152				    char *buf, size_t buflen)
9153{
9154#ifdef WPA_TRACE_BFD
9155	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
9156			   wpa_trace_test_fail_func);
9157#else /* WPA_TRACE_BFD */
9158	return -1;
9159#endif /* WPA_TRACE_BFD */
9160}
9161
9162
9163static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
9164{
9165	struct wpa_supplicant *wpa_s = eloop_ctx;
9166	int i, count = (intptr_t) timeout_ctx;
9167
9168	wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
9169		   count);
9170	for (i = 0; i < count; i++) {
9171		wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
9172			     i + 1, count);
9173	}
9174}
9175
9176
9177static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
9178{
9179	int count;
9180
9181	count = atoi(cmd);
9182	if (count <= 0)
9183		return -1;
9184
9185	return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
9186				      (void *) (intptr_t) count);
9187}
9188
9189
9190static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
9191				   const char *cmd)
9192{
9193	struct wpabuf *buf;
9194	size_t len;
9195
9196	len = os_strlen(cmd);
9197	if (len & 1)
9198		return -1;
9199	len /= 2;
9200
9201	if (len == 0) {
9202		buf = NULL;
9203	} else {
9204		buf = wpabuf_alloc(len);
9205		if (buf == NULL)
9206			return -1;
9207
9208		if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
9209			wpabuf_free(buf);
9210			return -1;
9211		}
9212	}
9213
9214	wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
9215	return 0;
9216}
9217
9218
9219static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
9220{
9221	u8 zero[WPA_TK_MAX_LEN];
9222
9223	if (wpa_s->last_tk_alg == WPA_ALG_NONE)
9224		return -1;
9225
9226	wpa_printf(MSG_INFO, "TESTING: Reset PN");
9227	os_memset(zero, 0, sizeof(zero));
9228
9229	/* First, use a zero key to avoid any possible duplicate key avoidance
9230	 * in the driver. */
9231	if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
9232			    wpa_s->last_tk_key_idx, 1, zero, 6,
9233			    zero, wpa_s->last_tk_len) < 0)
9234		return -1;
9235
9236	/* Set the previously configured key to reset its TSC/RSC */
9237	return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
9238			       wpa_s->last_tk_key_idx, 1, zero, 6,
9239			       wpa_s->last_tk, wpa_s->last_tk_len);
9240}
9241
9242
9243static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
9244{
9245	const char *pos = cmd;
9246	int error, pairwise;
9247
9248	error = atoi(pos);
9249	pos = os_strchr(pos, ' ');
9250	if (!pos)
9251		return -1;
9252	pairwise = atoi(pos);
9253	wpa_sm_key_request(wpa_s->wpa, error, pairwise);
9254	return 0;
9255}
9256
9257
9258static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
9259{
9260#ifdef CONFIG_SME
9261	struct wpa_driver_associate_params params;
9262	int ret;
9263
9264	os_memset(&params, 0, sizeof(params));
9265	params.bssid = wpa_s->bssid;
9266	params.ssid = wpa_s->sme.ssid;
9267	params.ssid_len = wpa_s->sme.ssid_len;
9268	params.freq.freq = wpa_s->sme.freq;
9269	if (wpa_s->last_assoc_req_wpa_ie) {
9270		params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
9271		params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
9272	}
9273	params.pairwise_suite = wpa_s->pairwise_cipher;
9274	params.group_suite = wpa_s->group_cipher;
9275	params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
9276	params.key_mgmt_suite = wpa_s->key_mgmt;
9277	params.wpa_proto = wpa_s->wpa_proto;
9278	params.mgmt_frame_protection = wpa_s->sme.mfp;
9279	params.rrm_used = wpa_s->rrm.rrm_used;
9280	if (wpa_s->sme.prev_bssid_set)
9281		params.prev_bssid = wpa_s->sme.prev_bssid;
9282	wpa_printf(MSG_INFO, "TESTING: Resend association request");
9283	ret = wpa_drv_associate(wpa_s, &params);
9284	wpa_s->testing_resend_assoc = 1;
9285	return ret;
9286#else /* CONFIG_SME */
9287	return -1;
9288#endif /* CONFIG_SME */
9289}
9290
9291#endif /* CONFIG_TESTING_OPTIONS */
9292
9293
9294static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
9295{
9296	char *pos = cmd;
9297	int frame;
9298	size_t len;
9299	struct wpabuf *buf;
9300	struct ieee802_11_elems elems;
9301
9302	frame = atoi(pos);
9303	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
9304		return -1;
9305	wpa_s = wpas_vendor_elem(wpa_s, frame);
9306
9307	pos = os_strchr(pos, ' ');
9308	if (pos == NULL)
9309		return -1;
9310	pos++;
9311
9312	len = os_strlen(pos);
9313	if (len == 0)
9314		return 0;
9315	if (len & 1)
9316		return -1;
9317	len /= 2;
9318
9319	buf = wpabuf_alloc(len);
9320	if (buf == NULL)
9321		return -1;
9322
9323	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
9324		wpabuf_free(buf);
9325		return -1;
9326	}
9327
9328	if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
9329	    ParseFailed) {
9330		wpabuf_free(buf);
9331		return -1;
9332	}
9333
9334	if (wpa_s->vendor_elem[frame] == NULL) {
9335		wpa_s->vendor_elem[frame] = buf;
9336		wpas_vendor_elem_update(wpa_s);
9337		return 0;
9338	}
9339
9340	if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
9341		wpabuf_free(buf);
9342		return -1;
9343	}
9344
9345	wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
9346	wpabuf_free(buf);
9347	wpas_vendor_elem_update(wpa_s);
9348
9349	return 0;
9350}
9351
9352
9353static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
9354				     char *buf, size_t buflen)
9355{
9356	int frame = atoi(cmd);
9357
9358	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
9359		return -1;
9360	wpa_s = wpas_vendor_elem(wpa_s, frame);
9361
9362	if (wpa_s->vendor_elem[frame] == NULL)
9363		return 0;
9364
9365	return wpa_snprintf_hex(buf, buflen,
9366				wpabuf_head_u8(wpa_s->vendor_elem[frame]),
9367				wpabuf_len(wpa_s->vendor_elem[frame]));
9368}
9369
9370
9371static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
9372{
9373	char *pos = cmd;
9374	int frame;
9375	size_t len;
9376	u8 *buf;
9377	struct ieee802_11_elems elems;
9378	int res;
9379
9380	frame = atoi(pos);
9381	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
9382		return -1;
9383	wpa_s = wpas_vendor_elem(wpa_s, frame);
9384
9385	pos = os_strchr(pos, ' ');
9386	if (pos == NULL)
9387		return -1;
9388	pos++;
9389
9390	if (*pos == '*') {
9391		wpabuf_free(wpa_s->vendor_elem[frame]);
9392		wpa_s->vendor_elem[frame] = NULL;
9393		wpas_vendor_elem_update(wpa_s);
9394		return 0;
9395	}
9396
9397	if (wpa_s->vendor_elem[frame] == NULL)
9398		return -1;
9399
9400	len = os_strlen(pos);
9401	if (len == 0)
9402		return 0;
9403	if (len & 1)
9404		return -1;
9405	len /= 2;
9406
9407	buf = os_malloc(len);
9408	if (buf == NULL)
9409		return -1;
9410
9411	if (hexstr2bin(pos, buf, len) < 0) {
9412		os_free(buf);
9413		return -1;
9414	}
9415
9416	if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
9417		os_free(buf);
9418		return -1;
9419	}
9420
9421	res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
9422	os_free(buf);
9423	return res;
9424}
9425
9426
9427static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
9428{
9429	struct wpa_supplicant *wpa_s = ctx;
9430	size_t len;
9431	const u8 *data;
9432
9433	/*
9434	 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
9435	 * BSSID[6]
9436	 * BSSID Information[4]
9437	 * Operating Class[1]
9438	 * Channel Number[1]
9439	 * PHY Type[1]
9440	 * Optional Subelements[variable]
9441	 */
9442#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
9443
9444	if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
9445		wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
9446		goto out;
9447	}
9448
9449	data = wpabuf_head_u8(neighbor_rep);
9450	len = wpabuf_len(neighbor_rep);
9451
9452	while (len >= 2 + NR_IE_MIN_LEN) {
9453		const u8 *nr;
9454		char lci[256 * 2 + 1];
9455		char civic[256 * 2 + 1];
9456		u8 nr_len = data[1];
9457		const u8 *pos = data, *end;
9458
9459		if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
9460		    nr_len < NR_IE_MIN_LEN) {
9461			wpa_printf(MSG_DEBUG,
9462				   "CTRL: Invalid Neighbor Report element: id=%u len=%u",
9463				   data[0], nr_len);
9464			goto out;
9465		}
9466
9467		if (2U + nr_len > len) {
9468			wpa_printf(MSG_DEBUG,
9469				   "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
9470				   data[0], len, nr_len);
9471			goto out;
9472		}
9473		pos += 2;
9474		end = pos + nr_len;
9475
9476		nr = pos;
9477		pos += NR_IE_MIN_LEN;
9478
9479		lci[0] = '\0';
9480		civic[0] = '\0';
9481		while (end - pos > 2) {
9482			u8 s_id, s_len;
9483
9484			s_id = *pos++;
9485			s_len = *pos++;
9486			if (s_len > end - pos)
9487				goto out;
9488			if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
9489				/* Measurement Token[1] */
9490				/* Measurement Report Mode[1] */
9491				/* Measurement Type[1] */
9492				/* Measurement Report[variable] */
9493				switch (pos[2]) {
9494				case MEASURE_TYPE_LCI:
9495					if (lci[0])
9496						break;
9497					wpa_snprintf_hex(lci, sizeof(lci),
9498							 pos, s_len);
9499					break;
9500				case MEASURE_TYPE_LOCATION_CIVIC:
9501					if (civic[0])
9502						break;
9503					wpa_snprintf_hex(civic, sizeof(civic),
9504							 pos, s_len);
9505					break;
9506				}
9507			}
9508
9509			pos += s_len;
9510		}
9511
9512		wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
9513			"bssid=" MACSTR
9514			" info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
9515			MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
9516			nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
9517			nr[ETH_ALEN + 6],
9518			lci[0] ? " lci=" : "", lci,
9519			civic[0] ? " civic=" : "", civic);
9520
9521		data = end;
9522		len -= 2 + nr_len;
9523	}
9524
9525out:
9526	wpabuf_free(neighbor_rep);
9527}
9528
9529
9530static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
9531					     char *cmd)
9532{
9533	struct wpa_ssid_value ssid, *ssid_p = NULL;
9534	int ret, lci = 0, civic = 0;
9535	char *ssid_s;
9536
9537	ssid_s = os_strstr(cmd, "ssid=");
9538	if (ssid_s) {
9539		if (ssid_parse(ssid_s + 5, &ssid)) {
9540			wpa_printf(MSG_ERROR,
9541				   "CTRL: Send Neighbor Report: bad SSID");
9542			return -1;
9543		}
9544
9545		ssid_p = &ssid;
9546
9547		/*
9548		 * Move cmd after the SSID text that may include "lci" or
9549		 * "civic".
9550		 */
9551		cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
9552		if (cmd)
9553			cmd++;
9554
9555	}
9556
9557	if (cmd && os_strstr(cmd, "lci"))
9558		lci = 1;
9559
9560	if (cmd && os_strstr(cmd, "civic"))
9561		civic = 1;
9562
9563	ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
9564						 wpas_ctrl_neighbor_rep_cb,
9565						 wpa_s);
9566
9567	return ret;
9568}
9569
9570
9571static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
9572{
9573	eapol_sm_erp_flush(wpa_s->eapol);
9574	return 0;
9575}
9576
9577
9578static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
9579					 char *cmd)
9580{
9581	char *token, *context = NULL;
9582	unsigned int enable = ~0, type = 0;
9583	u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
9584	u8 *addr = NULL, *mask = NULL;
9585
9586	while ((token = str_token(cmd, " ", &context))) {
9587		if (os_strcasecmp(token, "scan") == 0) {
9588			type |= MAC_ADDR_RAND_SCAN;
9589		} else if (os_strcasecmp(token, "sched") == 0) {
9590			type |= MAC_ADDR_RAND_SCHED_SCAN;
9591		} else if (os_strcasecmp(token, "pno") == 0) {
9592			type |= MAC_ADDR_RAND_PNO;
9593		} else if (os_strcasecmp(token, "all") == 0) {
9594			type = wpa_s->mac_addr_rand_supported;
9595		} else if (os_strncasecmp(token, "enable=", 7) == 0) {
9596			enable = atoi(token + 7);
9597		} else if (os_strncasecmp(token, "addr=", 5) == 0) {
9598			addr = _addr;
9599			if (hwaddr_aton(token + 5, addr)) {
9600				wpa_printf(MSG_INFO,
9601					   "CTRL: Invalid MAC address: %s",
9602					   token);
9603				return -1;
9604			}
9605		} else if (os_strncasecmp(token, "mask=", 5) == 0) {
9606			mask = _mask;
9607			if (hwaddr_aton(token + 5, mask)) {
9608				wpa_printf(MSG_INFO,
9609					   "CTRL: Invalid MAC address mask: %s",
9610					   token);
9611				return -1;
9612			}
9613		} else {
9614			wpa_printf(MSG_INFO,
9615				   "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
9616				   token);
9617			return -1;
9618		}
9619	}
9620
9621	if (!type) {
9622		wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
9623		return -1;
9624	}
9625
9626	if (enable > 1) {
9627		wpa_printf(MSG_INFO,
9628			   "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
9629		return -1;
9630	}
9631
9632	if (!enable)
9633		return wpas_disable_mac_addr_randomization(wpa_s, type);
9634
9635	return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
9636}
9637
9638
9639static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
9640				 char *buf, size_t buflen)
9641{
9642	size_t reply_len;
9643
9644	reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
9645#ifdef CONFIG_AP
9646	reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
9647					      buflen - reply_len);
9648#endif /* CONFIG_AP */
9649	return reply_len;
9650}
9651
9652
9653static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
9654{
9655	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
9656#ifdef CONFIG_AP
9657	wpas_ap_pmksa_cache_flush(wpa_s);
9658#endif /* CONFIG_AP */
9659}
9660
9661
9662#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
9663
9664static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
9665				     const char *cmd, char *buf, size_t buflen)
9666{
9667	struct rsn_pmksa_cache_entry *entry;
9668	struct wpa_ssid *ssid;
9669	char *pos, *pos2, *end;
9670	int ret;
9671	struct os_reltime now;
9672
9673	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
9674	if (!ssid)
9675		return -1;
9676
9677	pos = buf;
9678	end = buf + buflen;
9679
9680	os_get_reltime(&now);
9681
9682	/*
9683	 * Entry format:
9684	 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
9685	 * <expiration in seconds> <akmp> <opportunistic>
9686	 * [FILS Cache Identifier]
9687	 */
9688
9689	for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
9690	     entry = entry->next) {
9691		if (entry->network_ctx != ssid)
9692			continue;
9693
9694		pos2 = pos;
9695		ret = os_snprintf(pos2, end - pos2, MACSTR " ",
9696				  MAC2STR(entry->aa));
9697		if (os_snprintf_error(end - pos2, ret))
9698			break;
9699		pos2 += ret;
9700
9701		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
9702					 PMKID_LEN);
9703
9704		ret = os_snprintf(pos2, end - pos2, " ");
9705		if (os_snprintf_error(end - pos2, ret))
9706			break;
9707		pos2 += ret;
9708
9709		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
9710					 entry->pmk_len);
9711
9712		ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
9713				  (int) (entry->reauth_time - now.sec),
9714				  (int) (entry->expiration - now.sec),
9715				  entry->akmp,
9716				  entry->opportunistic);
9717		if (os_snprintf_error(end - pos2, ret))
9718			break;
9719		pos2 += ret;
9720
9721		if (entry->fils_cache_id_set) {
9722			ret = os_snprintf(pos2, end - pos2, " %02x%02x",
9723					  entry->fils_cache_id[0],
9724					  entry->fils_cache_id[1]);
9725			if (os_snprintf_error(end - pos2, ret))
9726				break;
9727			pos2 += ret;
9728		}
9729
9730		ret = os_snprintf(pos2, end - pos2, "\n");
9731		if (os_snprintf_error(end - pos2, ret))
9732			break;
9733		pos2 += ret;
9734
9735		pos = pos2;
9736	}
9737
9738	return pos - buf;
9739}
9740
9741
9742static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
9743				     char *cmd)
9744{
9745	struct rsn_pmksa_cache_entry *entry;
9746	struct wpa_ssid *ssid;
9747	char *pos, *pos2;
9748	int ret = -1;
9749	struct os_reltime now;
9750	int reauth_time = 0, expiration = 0, i;
9751
9752	/*
9753	 * Entry format:
9754	 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
9755	 * <expiration in seconds> <akmp> <opportunistic>
9756	 * [FILS Cache Identifier]
9757	 */
9758
9759	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
9760	if (!ssid)
9761		return -1;
9762
9763	pos = os_strchr(cmd, ' ');
9764	if (!pos)
9765		return -1;
9766	pos++;
9767
9768	entry = os_zalloc(sizeof(*entry));
9769	if (!entry)
9770		return -1;
9771
9772	if (hwaddr_aton(pos, entry->aa))
9773		goto fail;
9774
9775	pos = os_strchr(pos, ' ');
9776	if (!pos)
9777		goto fail;
9778	pos++;
9779
9780	if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
9781		goto fail;
9782
9783	pos = os_strchr(pos, ' ');
9784	if (!pos)
9785		goto fail;
9786	pos++;
9787
9788	pos2 = os_strchr(pos, ' ');
9789	if (!pos2)
9790		goto fail;
9791	entry->pmk_len = (pos2 - pos) / 2;
9792	if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
9793	    hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
9794		goto fail;
9795
9796	pos = os_strchr(pos, ' ');
9797	if (!pos)
9798		goto fail;
9799	pos++;
9800
9801	if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
9802		   &entry->akmp, &entry->opportunistic) != 4)
9803		goto fail;
9804	for (i = 0; i < 4; i++) {
9805		pos = os_strchr(pos, ' ');
9806		if (!pos) {
9807			if (i < 3)
9808				goto fail;
9809			break;
9810		}
9811		pos++;
9812	}
9813	if (pos) {
9814		if (hexstr2bin(pos, entry->fils_cache_id,
9815			       FILS_CACHE_ID_LEN) < 0)
9816			goto fail;
9817		entry->fils_cache_id_set = 1;
9818	}
9819	os_get_reltime(&now);
9820	entry->expiration = now.sec + expiration;
9821	entry->reauth_time = now.sec + reauth_time;
9822
9823	entry->network_ctx = ssid;
9824
9825	wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
9826	entry = NULL;
9827	ret = 0;
9828fail:
9829	os_free(entry);
9830	return ret;
9831}
9832
9833
9834#ifdef CONFIG_MESH
9835
9836static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
9837					  const char *cmd, char *buf,
9838					  size_t buflen)
9839{
9840	u8 spa[ETH_ALEN];
9841
9842	if (!wpa_s->ifmsh)
9843		return -1;
9844
9845	if (os_strcasecmp(cmd, "any") == 0)
9846		return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
9847
9848	if (hwaddr_aton(cmd, spa))
9849		return -1;
9850
9851	return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
9852}
9853
9854
9855static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
9856					  char *cmd)
9857{
9858	/*
9859	 * We do not check mesh interface existance because PMKSA should be
9860	 * stored before wpa_s->ifmsh creation to suppress commit message
9861	 * creation.
9862	 */
9863	return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
9864}
9865
9866#endif /* CONFIG_MESH */
9867#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
9868
9869
9870#ifdef CONFIG_FILS
9871static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
9872					    const char *cmd)
9873{
9874	struct fils_hlp_req *req;
9875	const char *pos;
9876
9877	/* format: <dst> <packet starting from ethertype> */
9878
9879	req = os_zalloc(sizeof(*req));
9880	if (!req)
9881		return -1;
9882
9883	if (hwaddr_aton(cmd, req->dst))
9884		goto fail;
9885
9886	pos = os_strchr(cmd, ' ');
9887	if (!pos)
9888		goto fail;
9889	pos++;
9890	req->pkt = wpabuf_parse_bin(pos);
9891	if (!req->pkt)
9892		goto fail;
9893
9894	dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
9895	return 0;
9896fail:
9897	wpabuf_free(req->pkt);
9898	os_free(req);
9899	return -1;
9900}
9901#endif /* CONFIG_FILS */
9902
9903
9904static int wpas_ctrl_cmd_debug_level(const char *cmd)
9905{
9906	if (os_strcmp(cmd, "PING") == 0 ||
9907	    os_strncmp(cmd, "BSS ", 4) == 0 ||
9908	    os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
9909	    os_strncmp(cmd, "STATUS", 6) == 0 ||
9910	    os_strncmp(cmd, "STA ", 4) == 0 ||
9911	    os_strncmp(cmd, "STA-", 4) == 0)
9912		return MSG_EXCESSIVE;
9913	return MSG_DEBUG;
9914}
9915
9916
9917char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
9918					 char *buf, size_t *resp_len)
9919{
9920	char *reply;
9921	const int reply_size = 4096;
9922	int reply_len;
9923
9924	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
9925	    os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
9926	    os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
9927	    os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
9928		if (wpa_debug_show_keys)
9929			wpa_dbg(wpa_s, MSG_DEBUG,
9930				"Control interface command '%s'", buf);
9931		else
9932			wpa_dbg(wpa_s, MSG_DEBUG,
9933				"Control interface command '%s [REMOVED]'",
9934				os_strncmp(buf, WPA_CTRL_RSP,
9935					   os_strlen(WPA_CTRL_RSP)) == 0 ?
9936				WPA_CTRL_RSP :
9937				(os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
9938				 "SET_NETWORK" : "key-add"));
9939	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
9940		   os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
9941		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
9942				      (const u8 *) buf, os_strlen(buf));
9943	} else {
9944		int level = wpas_ctrl_cmd_debug_level(buf);
9945		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
9946	}
9947
9948	reply = os_malloc(reply_size);
9949	if (reply == NULL) {
9950		*resp_len = 1;
9951		return NULL;
9952	}
9953
9954	os_memcpy(reply, "OK\n", 3);
9955	reply_len = 3;
9956
9957	if (os_strcmp(buf, "PING") == 0) {
9958		os_memcpy(reply, "PONG\n", 5);
9959		reply_len = 5;
9960	} else if (os_strcmp(buf, "IFNAME") == 0) {
9961		reply_len = os_strlen(wpa_s->ifname);
9962		os_memcpy(reply, wpa_s->ifname, reply_len);
9963	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
9964		if (wpa_debug_reopen_file() < 0)
9965			reply_len = -1;
9966	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
9967		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
9968	} else if (os_strcmp(buf, "MIB") == 0) {
9969		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
9970		if (reply_len >= 0) {
9971			reply_len += eapol_sm_get_mib(wpa_s->eapol,
9972						      reply + reply_len,
9973						      reply_size - reply_len);
9974#ifdef CONFIG_MACSEC
9975			reply_len += ieee802_1x_kay_get_mib(
9976				wpa_s->kay, reply + reply_len,
9977				reply_size - reply_len);
9978#endif /* CONFIG_MACSEC */
9979		}
9980	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
9981		reply_len = wpa_supplicant_ctrl_iface_status(
9982			wpa_s, buf + 6, reply, reply_size);
9983	} else if (os_strcmp(buf, "PMKSA") == 0) {
9984		reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
9985	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
9986		wpas_ctrl_iface_pmksa_flush(wpa_s);
9987#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
9988	} else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
9989		reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
9990						      reply, reply_size);
9991	} else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
9992		if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
9993			reply_len = -1;
9994#ifdef CONFIG_MESH
9995	} else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
9996		reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
9997							   reply, reply_size);
9998	} else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
9999		if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
10000			reply_len = -1;
10001#endif /* CONFIG_MESH */
10002#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
10003	} else if (os_strncmp(buf, "SET ", 4) == 0) {
10004		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
10005			reply_len = -1;
10006	} else if (os_strncmp(buf, "DUMP", 4) == 0) {
10007		reply_len = wpa_config_dump_values(wpa_s->conf,
10008						   reply, reply_size);
10009	} else if (os_strncmp(buf, "GET ", 4) == 0) {
10010		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
10011							  reply, reply_size);
10012	} else if (os_strcmp(buf, "LOGON") == 0) {
10013		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
10014	} else if (os_strcmp(buf, "LOGOFF") == 0) {
10015		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
10016	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
10017		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
10018			reply_len = -1;
10019		else
10020			wpas_request_connection(wpa_s);
10021	} else if (os_strcmp(buf, "REATTACH") == 0) {
10022		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
10023		    !wpa_s->current_ssid)
10024			reply_len = -1;
10025		else {
10026			wpa_s->reattach = 1;
10027			wpas_request_connection(wpa_s);
10028		}
10029	} else if (os_strcmp(buf, "RECONNECT") == 0) {
10030		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
10031			reply_len = -1;
10032		else if (wpa_s->disconnected)
10033			wpas_request_connection(wpa_s);
10034#ifdef IEEE8021X_EAPOL
10035	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
10036		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
10037			reply_len = -1;
10038#endif /* IEEE8021X_EAPOL */
10039#ifdef CONFIG_IEEE80211R
10040	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
10041		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
10042			reply_len = -1;
10043#endif /* CONFIG_IEEE80211R */
10044#ifdef CONFIG_WPS
10045	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
10046		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
10047		if (res == -2) {
10048			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
10049			reply_len = 17;
10050		} else if (res)
10051			reply_len = -1;
10052	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
10053		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
10054		if (res == -2) {
10055			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
10056			reply_len = 17;
10057		} else if (res)
10058			reply_len = -1;
10059	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
10060		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
10061							      reply,
10062							      reply_size);
10063	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
10064		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
10065			wpa_s, buf + 14, reply, reply_size);
10066	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
10067		if (wpas_wps_cancel(wpa_s))
10068			reply_len = -1;
10069#ifdef CONFIG_WPS_NFC
10070	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
10071		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
10072			reply_len = -1;
10073	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
10074		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
10075			reply_len = -1;
10076	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
10077		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
10078			wpa_s, buf + 21, reply, reply_size);
10079	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
10080		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
10081			wpa_s, buf + 14, reply, reply_size);
10082	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
10083		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
10084							       buf + 17))
10085			reply_len = -1;
10086	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
10087		reply_len = wpas_ctrl_nfc_get_handover_req(
10088			wpa_s, buf + 21, reply, reply_size);
10089	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
10090		reply_len = wpas_ctrl_nfc_get_handover_sel(
10091			wpa_s, buf + 21, reply, reply_size);
10092	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
10093		if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
10094			reply_len = -1;
10095#endif /* CONFIG_WPS_NFC */
10096	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
10097		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
10098			reply_len = -1;
10099#ifdef CONFIG_AP
10100	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
10101		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
10102			wpa_s, buf + 11, reply, reply_size);
10103#endif /* CONFIG_AP */
10104#ifdef CONFIG_WPS_ER
10105	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
10106		if (wpas_wps_er_start(wpa_s, NULL))
10107			reply_len = -1;
10108	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
10109		if (wpas_wps_er_start(wpa_s, buf + 13))
10110			reply_len = -1;
10111	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
10112		wpas_wps_er_stop(wpa_s);
10113	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
10114		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
10115			reply_len = -1;
10116	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
10117		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
10118		if (ret == -2) {
10119			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
10120			reply_len = 17;
10121		} else if (ret == -3) {
10122			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
10123			reply_len = 18;
10124		} else if (ret == -4) {
10125			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
10126			reply_len = 20;
10127		} else if (ret)
10128			reply_len = -1;
10129	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
10130		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
10131			reply_len = -1;
10132	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
10133		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
10134								buf + 18))
10135			reply_len = -1;
10136	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
10137		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
10138			reply_len = -1;
10139#ifdef CONFIG_WPS_NFC
10140	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
10141		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
10142			wpa_s, buf + 24, reply, reply_size);
10143#endif /* CONFIG_WPS_NFC */
10144#endif /* CONFIG_WPS_ER */
10145#endif /* CONFIG_WPS */
10146#ifdef CONFIG_IBSS_RSN
10147	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
10148		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
10149			reply_len = -1;
10150#endif /* CONFIG_IBSS_RSN */
10151#ifdef CONFIG_MESH
10152	} else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
10153		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
10154			wpa_s, buf + 19, reply, reply_size);
10155	} else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
10156		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
10157			wpa_s, "", reply, reply_size);
10158	} else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
10159		if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
10160			reply_len = -1;
10161	} else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
10162		if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
10163								buf + 18))
10164			reply_len = -1;
10165	} else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
10166		if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
10167			reply_len = -1;
10168	} else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
10169		if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
10170			reply_len = -1;
10171	} else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
10172		if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
10173			reply_len = -1;
10174#endif /* CONFIG_MESH */
10175#ifdef CONFIG_P2P
10176	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
10177		if (p2p_ctrl_find(wpa_s, buf + 8))
10178			reply_len = -1;
10179	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
10180		if (p2p_ctrl_find(wpa_s, ""))
10181			reply_len = -1;
10182	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
10183		wpas_p2p_stop_find(wpa_s);
10184	} else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
10185		if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
10186			reply_len = -1;
10187	} else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
10188		if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
10189			reply_len = -1;
10190	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
10191		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
10192					     reply_size);
10193	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
10194		if (p2p_ctrl_listen(wpa_s, buf + 11))
10195			reply_len = -1;
10196	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
10197		if (p2p_ctrl_listen(wpa_s, ""))
10198			reply_len = -1;
10199	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
10200		if (wpas_p2p_group_remove(wpa_s, buf + 17))
10201			reply_len = -1;
10202	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
10203		if (p2p_ctrl_group_add(wpa_s, ""))
10204			reply_len = -1;
10205	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
10206		if (p2p_ctrl_group_add(wpa_s, buf + 14))
10207			reply_len = -1;
10208	} else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
10209		reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
10210						  reply_size);
10211	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
10212		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
10213			reply_len = -1;
10214	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
10215		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
10216	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
10217		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
10218						   reply_size);
10219	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
10220		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
10221			reply_len = -1;
10222	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
10223		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
10224			reply_len = -1;
10225	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
10226		wpas_p2p_sd_service_update(wpa_s);
10227	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
10228		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
10229			reply_len = -1;
10230	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
10231		wpas_p2p_service_flush(wpa_s);
10232	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
10233		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
10234			reply_len = -1;
10235	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
10236		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
10237			reply_len = -1;
10238	} else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
10239		if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
10240			reply_len = -1;
10241	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
10242		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
10243			reply_len = -1;
10244	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
10245		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
10246			reply_len = -1;
10247	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
10248		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
10249					      reply_size);
10250	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
10251		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
10252			reply_len = -1;
10253	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
10254		p2p_ctrl_flush(wpa_s);
10255	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
10256		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
10257			reply_len = -1;
10258	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
10259		if (wpas_p2p_cancel(wpa_s))
10260			reply_len = -1;
10261	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
10262		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
10263			reply_len = -1;
10264	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
10265		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
10266			reply_len = -1;
10267	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
10268		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
10269			reply_len = -1;
10270	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
10271		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
10272			reply_len = -1;
10273	} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
10274		if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
10275			reply_len = -1;
10276	} else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
10277		if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
10278			reply_len = -1;
10279	} else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
10280		if (wpas_p2p_lo_stop(wpa_s))
10281			reply_len = -1;
10282#endif /* CONFIG_P2P */
10283#ifdef CONFIG_WIFI_DISPLAY
10284	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
10285		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
10286			reply_len = -1;
10287	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
10288		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
10289						     reply, reply_size);
10290#endif /* CONFIG_WIFI_DISPLAY */
10291#ifdef CONFIG_INTERWORKING
10292	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
10293		if (interworking_fetch_anqp(wpa_s) < 0)
10294			reply_len = -1;
10295	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
10296		interworking_stop_fetch_anqp(wpa_s);
10297	} else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
10298		if (ctrl_interworking_select(wpa_s, NULL) < 0)
10299			reply_len = -1;
10300	} else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
10301		if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
10302			reply_len = -1;
10303	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
10304		if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
10305			reply_len = -1;
10306	} else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
10307		int id;
10308
10309		id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
10310		if (id < 0)
10311			reply_len = -1;
10312		else {
10313			reply_len = os_snprintf(reply, reply_size, "%d\n", id);
10314			if (os_snprintf_error(reply_size, reply_len))
10315				reply_len = -1;
10316		}
10317	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
10318		if (get_anqp(wpa_s, buf + 9) < 0)
10319			reply_len = -1;
10320	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
10321		if (gas_request(wpa_s, buf + 12) < 0)
10322			reply_len = -1;
10323	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
10324		reply_len = gas_response_get(wpa_s, buf + 17, reply,
10325					     reply_size);
10326#endif /* CONFIG_INTERWORKING */
10327#ifdef CONFIG_HS20
10328	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
10329		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
10330			reply_len = -1;
10331	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
10332		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
10333			reply_len = -1;
10334	} else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
10335		if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
10336			reply_len = -1;
10337	} else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
10338		if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
10339			reply_len = -1;
10340	} else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
10341		reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
10342	} else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
10343		if (del_hs20_icon(wpa_s, buf + 14) < 0)
10344			reply_len = -1;
10345	} else if (os_strcmp(buf, "FETCH_OSU") == 0) {
10346		if (hs20_fetch_osu(wpa_s, 0) < 0)
10347			reply_len = -1;
10348	} else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
10349		if (hs20_fetch_osu(wpa_s, 1) < 0)
10350			reply_len = -1;
10351	} else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
10352		hs20_cancel_fetch_osu(wpa_s);
10353#endif /* CONFIG_HS20 */
10354	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
10355	{
10356		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
10357			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
10358			reply_len = -1;
10359		else {
10360			/*
10361			 * Notify response from timeout to allow the control
10362			 * interface response to be sent first.
10363			 */
10364			eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
10365					       wpa_s, NULL);
10366		}
10367	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
10368		if (wpa_supplicant_reload_configuration(wpa_s))
10369			reply_len = -1;
10370	} else if (os_strcmp(buf, "TERMINATE") == 0) {
10371		wpa_supplicant_terminate_proc(wpa_s->global);
10372	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
10373		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
10374			reply_len = -1;
10375	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
10376		reply_len = wpa_supplicant_ctrl_iface_blacklist(
10377			wpa_s, buf + 9, reply, reply_size);
10378	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
10379		reply_len = wpa_supplicant_ctrl_iface_log_level(
10380			wpa_s, buf + 9, reply, reply_size);
10381	} else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
10382		reply_len = wpa_supplicant_ctrl_iface_list_networks(
10383			wpa_s, buf + 14, reply, reply_size);
10384	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
10385		reply_len = wpa_supplicant_ctrl_iface_list_networks(
10386			wpa_s, NULL, reply, reply_size);
10387	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
10388		wpas_request_disconnection(wpa_s);
10389	} else if (os_strcmp(buf, "SCAN") == 0) {
10390		wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
10391	} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
10392		wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
10393	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
10394		reply_len = wpa_supplicant_ctrl_iface_scan_results(
10395			wpa_s, reply, reply_size);
10396	} else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
10397		if (wpas_abort_ongoing_scan(wpa_s) < 0)
10398			reply_len = -1;
10399	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
10400		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
10401			reply_len = -1;
10402	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
10403		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
10404			reply_len = -1;
10405	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
10406		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
10407			reply_len = -1;
10408	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
10409		reply_len = wpa_supplicant_ctrl_iface_add_network(
10410			wpa_s, reply, reply_size);
10411	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
10412		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
10413			reply_len = -1;
10414	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
10415		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
10416			reply_len = -1;
10417	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
10418		reply_len = wpa_supplicant_ctrl_iface_get_network(
10419			wpa_s, buf + 12, reply, reply_size);
10420	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
10421		if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
10422							  wpa_s))
10423			reply_len = -1;
10424	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
10425		reply_len = wpa_supplicant_ctrl_iface_list_creds(
10426			wpa_s, reply, reply_size);
10427	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
10428		reply_len = wpa_supplicant_ctrl_iface_add_cred(
10429			wpa_s, reply, reply_size);
10430	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
10431		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
10432			reply_len = -1;
10433	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
10434		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
10435			reply_len = -1;
10436	} else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
10437		reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
10438							       reply,
10439							       reply_size);
10440#ifndef CONFIG_NO_CONFIG_WRITE
10441	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
10442		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
10443			reply_len = -1;
10444#endif /* CONFIG_NO_CONFIG_WRITE */
10445	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
10446		reply_len = wpa_supplicant_ctrl_iface_get_capability(
10447			wpa_s, buf + 15, reply, reply_size);
10448	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
10449		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
10450			reply_len = -1;
10451	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
10452		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
10453			reply_len = -1;
10454	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
10455		reply_len = wpa_supplicant_global_iface_list(
10456			wpa_s->global, reply, reply_size);
10457	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
10458		reply_len = wpa_supplicant_global_iface_interfaces(
10459			wpa_s->global, buf + 10, reply, reply_size);
10460	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
10461		reply_len = wpa_supplicant_ctrl_iface_bss(
10462			wpa_s, buf + 4, reply, reply_size);
10463#ifdef CONFIG_AP
10464	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
10465		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
10466	} else if (os_strncmp(buf, "STA ", 4) == 0) {
10467		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
10468					      reply_size);
10469	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
10470		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
10471						   reply_size);
10472	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
10473		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
10474			reply_len = -1;
10475	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
10476		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
10477			reply_len = -1;
10478	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
10479		if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
10480			reply_len = -1;
10481	} else if (os_strcmp(buf, "STOP_AP") == 0) {
10482		if (wpas_ap_stop_ap(wpa_s))
10483			reply_len = -1;
10484#endif /* CONFIG_AP */
10485	} else if (os_strcmp(buf, "SUSPEND") == 0) {
10486		wpas_notify_suspend(wpa_s->global);
10487	} else if (os_strcmp(buf, "RESUME") == 0) {
10488		wpas_notify_resume(wpa_s->global);
10489#ifdef CONFIG_TESTING_OPTIONS
10490	} else if (os_strcmp(buf, "DROP_SA") == 0) {
10491		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
10492#endif /* CONFIG_TESTING_OPTIONS */
10493	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
10494		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
10495			reply_len = -1;
10496	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
10497		wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
10498	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
10499		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
10500			reply_len = -1;
10501	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
10502		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
10503							       buf + 17))
10504			reply_len = -1;
10505	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
10506		wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
10507#ifdef CONFIG_TDLS
10508	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
10509		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
10510			reply_len = -1;
10511	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
10512		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
10513			reply_len = -1;
10514	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
10515		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
10516			reply_len = -1;
10517	} else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
10518		if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
10519							       buf + 17))
10520			reply_len = -1;
10521	} else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
10522		if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
10523								      buf + 24))
10524			reply_len = -1;
10525	} else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
10526		reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
10527			wpa_s, buf + 17, reply, reply_size);
10528#endif /* CONFIG_TDLS */
10529	} else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
10530		reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
10531	} else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
10532		if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
10533			reply_len = -1;
10534	} else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
10535		if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
10536			reply_len = -1;
10537	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
10538		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
10539						       reply_size);
10540	} else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
10541		if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
10542			reply_len = -1;
10543	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
10544		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
10545						       reply_size);
10546#ifdef CONFIG_AUTOSCAN
10547	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
10548		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
10549			reply_len = -1;
10550#endif /* CONFIG_AUTOSCAN */
10551	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
10552		reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
10553							 reply_size);
10554#ifdef ANDROID
10555	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
10556		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
10557						      reply_size);
10558#endif /* ANDROID */
10559	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
10560		reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
10561						      reply_size);
10562	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
10563		pmksa_cache_clear_current(wpa_s->wpa);
10564		eapol_sm_request_reauth(wpa_s->eapol);
10565#ifdef CONFIG_WNM
10566	} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
10567		if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
10568			reply_len = -1;
10569	} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
10570		if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
10571				reply_len = -1;
10572	} else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
10573		if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
10574			reply_len = -1;
10575#endif /* CONFIG_WNM */
10576	} else if (os_strcmp(buf, "FLUSH") == 0) {
10577		wpa_supplicant_ctrl_iface_flush(wpa_s);
10578	} else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
10579		reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
10580						 reply_size);
10581#ifdef CONFIG_TESTING_OPTIONS
10582	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
10583		if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
10584			reply_len = -1;
10585	} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
10586		wpas_ctrl_iface_mgmt_tx_done(wpa_s);
10587	} else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
10588		if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
10589			reply_len = -1;
10590	} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
10591		if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
10592			reply_len = -1;
10593	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
10594		if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
10595			reply_len = -1;
10596	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
10597		if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
10598			reply_len = -1;
10599	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
10600		if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
10601			reply_len = -1;
10602	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
10603		if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
10604			reply_len = -1;
10605	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
10606		if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
10607			reply_len = -1;
10608	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
10609		reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
10610	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
10611		if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0)
10612			reply_len = -1;
10613	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
10614		reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
10615	} else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
10616		if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
10617			reply_len = -1;
10618	} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
10619		if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
10620			reply_len = -1;
10621	} else if (os_strcmp(buf, "RESET_PN") == 0) {
10622		if (wpas_ctrl_reset_pn(wpa_s) < 0)
10623			reply_len = -1;
10624	} else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
10625		if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
10626			reply_len = -1;
10627	} else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
10628		if (wpas_ctrl_resend_assoc(wpa_s) < 0)
10629			reply_len = -1;
10630#ifdef CONFIG_IEEE80211W
10631	} else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
10632		sme_event_unprot_disconnect(
10633			wpa_s, wpa_s->bssid, NULL,
10634			WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
10635#endif /* CONFIG_IEEE80211W */
10636#endif /* CONFIG_TESTING_OPTIONS */
10637	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
10638		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
10639			reply_len = -1;
10640	} else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
10641		reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
10642						      reply_size);
10643	} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
10644		if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
10645			reply_len = -1;
10646	} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
10647		if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
10648			reply_len = -1;
10649	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
10650		wpas_ctrl_iface_erp_flush(wpa_s);
10651	} else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
10652		if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
10653			reply_len = -1;
10654	} else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
10655		reply_len = wpas_ctrl_iface_get_pref_freq_list(
10656			wpa_s, buf + 19, reply, reply_size);
10657#ifdef CONFIG_FILS
10658	} else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
10659		if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
10660			reply_len = -1;
10661	} else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
10662		wpas_flush_fils_hlp_req(wpa_s);
10663#endif /* CONFIG_FILS */
10664#ifdef CONFIG_DPP
10665	} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
10666		int res;
10667
10668		res = wpas_dpp_qr_code(wpa_s, buf + 12);
10669		if (res < 0) {
10670			reply_len = -1;
10671		} else {
10672			reply_len = os_snprintf(reply, reply_size, "%d", res);
10673			if (os_snprintf_error(reply_size, reply_len))
10674				reply_len = -1;
10675		}
10676	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
10677		int res;
10678
10679		res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
10680		if (res < 0) {
10681			reply_len = -1;
10682		} else {
10683			reply_len = os_snprintf(reply, reply_size, "%d", res);
10684			if (os_snprintf_error(reply_size, reply_len))
10685				reply_len = -1;
10686		}
10687	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
10688		if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
10689			reply_len = -1;
10690	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
10691		const char *uri;
10692
10693		uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
10694		if (!uri) {
10695			reply_len = -1;
10696		} else {
10697			reply_len = os_snprintf(reply, reply_size, "%s", uri);
10698			if (os_snprintf_error(reply_size, reply_len))
10699				reply_len = -1;
10700		}
10701	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
10702		reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
10703					       reply, reply_size);
10704	} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
10705		if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
10706			reply_len = -1;
10707	} else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
10708		if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
10709			reply_len = -1;
10710	} else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
10711		wpas_dpp_stop(wpa_s);
10712		wpas_dpp_listen_stop(wpa_s);
10713	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
10714		int res;
10715
10716		res = dpp_configurator_add(wpa_s->dpp, buf + 20);
10717		if (res < 0) {
10718			reply_len = -1;
10719		} else {
10720			reply_len = os_snprintf(reply, reply_size, "%d", res);
10721			if (os_snprintf_error(reply_size, reply_len))
10722				reply_len = -1;
10723		}
10724	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
10725		if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
10726			reply_len = -1;
10727	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
10728		if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
10729			reply_len = -1;
10730	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
10731		reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
10732							atoi(buf + 25),
10733							reply, reply_size);
10734	} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
10735		int res;
10736
10737		res = wpas_dpp_pkex_add(wpa_s, buf + 12);
10738		if (res < 0) {
10739			reply_len = -1;
10740		} else {
10741			reply_len = os_snprintf(reply, reply_size, "%d", res);
10742			if (os_snprintf_error(reply_size, reply_len))
10743				reply_len = -1;
10744		}
10745	} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
10746		if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
10747			reply_len = -1;
10748#ifdef CONFIG_DPP2
10749	} else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
10750		if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
10751			reply_len = -1;
10752	} else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
10753		if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
10754			reply_len = -1;
10755	} else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
10756		dpp_controller_stop(wpa_s->dpp);
10757#endif /* CONFIG_DPP2 */
10758#endif /* CONFIG_DPP */
10759	} else {
10760		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
10761		reply_len = 16;
10762	}
10763
10764	if (reply_len < 0) {
10765		os_memcpy(reply, "FAIL\n", 5);
10766		reply_len = 5;
10767	}
10768
10769	*resp_len = reply_len;
10770	return reply;
10771}
10772
10773
10774static int wpa_supplicant_global_iface_add(struct wpa_global *global,
10775					   char *cmd)
10776{
10777	struct wpa_interface iface;
10778	char *pos, *extra;
10779	struct wpa_supplicant *wpa_s;
10780	unsigned int create_iface = 0;
10781	u8 mac_addr[ETH_ALEN];
10782	enum wpa_driver_if_type type = WPA_IF_STATION;
10783
10784	/*
10785	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
10786	 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
10787	 */
10788	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
10789
10790	os_memset(&iface, 0, sizeof(iface));
10791
10792	do {
10793		iface.ifname = pos = cmd;
10794		pos = os_strchr(pos, '\t');
10795		if (pos)
10796			*pos++ = '\0';
10797		if (iface.ifname[0] == '\0')
10798			return -1;
10799		if (pos == NULL)
10800			break;
10801
10802		iface.confname = pos;
10803		pos = os_strchr(pos, '\t');
10804		if (pos)
10805			*pos++ = '\0';
10806		if (iface.confname[0] == '\0')
10807			iface.confname = NULL;
10808		if (pos == NULL)
10809			break;
10810
10811		iface.driver = pos;
10812		pos = os_strchr(pos, '\t');
10813		if (pos)
10814			*pos++ = '\0';
10815		if (iface.driver[0] == '\0')
10816			iface.driver = NULL;
10817		if (pos == NULL)
10818			break;
10819
10820		iface.ctrl_interface = pos;
10821		pos = os_strchr(pos, '\t');
10822		if (pos)
10823			*pos++ = '\0';
10824		if (iface.ctrl_interface[0] == '\0')
10825			iface.ctrl_interface = NULL;
10826		if (pos == NULL)
10827			break;
10828
10829		iface.driver_param = pos;
10830		pos = os_strchr(pos, '\t');
10831		if (pos)
10832			*pos++ = '\0';
10833		if (iface.driver_param[0] == '\0')
10834			iface.driver_param = NULL;
10835		if (pos == NULL)
10836			break;
10837
10838		iface.bridge_ifname = pos;
10839		pos = os_strchr(pos, '\t');
10840		if (pos)
10841			*pos++ = '\0';
10842		if (iface.bridge_ifname[0] == '\0')
10843			iface.bridge_ifname = NULL;
10844		if (pos == NULL)
10845			break;
10846
10847		extra = pos;
10848		pos = os_strchr(pos, '\t');
10849		if (pos)
10850			*pos++ = '\0';
10851		if (!extra[0])
10852			break;
10853
10854		if (os_strcmp(extra, "create") == 0) {
10855			create_iface = 1;
10856			if (!pos)
10857				break;
10858
10859			if (os_strcmp(pos, "sta") == 0) {
10860				type = WPA_IF_STATION;
10861			} else if (os_strcmp(pos, "ap") == 0) {
10862				type = WPA_IF_AP_BSS;
10863			} else {
10864				wpa_printf(MSG_DEBUG,
10865					   "INTERFACE_ADD unsupported interface type: '%s'",
10866					   pos);
10867				return -1;
10868			}
10869		} else {
10870			wpa_printf(MSG_DEBUG,
10871				   "INTERFACE_ADD unsupported extra parameter: '%s'",
10872				   extra);
10873			return -1;
10874		}
10875	} while (0);
10876
10877	if (create_iface) {
10878		wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
10879			   iface.ifname);
10880		if (!global->ifaces)
10881			return -1;
10882		if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
10883				   NULL, NULL, NULL, mac_addr, NULL) < 0) {
10884			wpa_printf(MSG_ERROR,
10885				   "CTRL_IFACE interface creation failed");
10886			return -1;
10887		}
10888
10889		wpa_printf(MSG_DEBUG,
10890			   "CTRL_IFACE interface '%s' created with MAC addr: "
10891			   MACSTR, iface.ifname, MAC2STR(mac_addr));
10892	}
10893
10894	if (wpa_supplicant_get_iface(global, iface.ifname))
10895		goto fail;
10896
10897	wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
10898	if (!wpa_s)
10899		goto fail;
10900	wpa_s->added_vif = create_iface;
10901	return 0;
10902
10903fail:
10904	if (create_iface)
10905		wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
10906	return -1;
10907}
10908
10909
10910static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
10911					      char *cmd)
10912{
10913	struct wpa_supplicant *wpa_s;
10914	int ret;
10915	unsigned int delete_iface;
10916
10917	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
10918
10919	wpa_s = wpa_supplicant_get_iface(global, cmd);
10920	if (wpa_s == NULL)
10921		return -1;
10922	delete_iface = wpa_s->added_vif;
10923	ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
10924	if (!ret && delete_iface) {
10925		wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
10926			   cmd);
10927		ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
10928	}
10929	return ret;
10930}
10931
10932
10933static void wpa_free_iface_info(struct wpa_interface_info *iface)
10934{
10935	struct wpa_interface_info *prev;
10936
10937	while (iface) {
10938		prev = iface;
10939		iface = iface->next;
10940
10941		os_free(prev->ifname);
10942		os_free(prev->desc);
10943		os_free(prev);
10944	}
10945}
10946
10947
10948static int wpa_supplicant_global_iface_list(struct wpa_global *global,
10949					    char *buf, int len)
10950{
10951	int i, res;
10952	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
10953	char *pos, *end;
10954
10955	for (i = 0; wpa_drivers[i]; i++) {
10956		const struct wpa_driver_ops *drv = wpa_drivers[i];
10957		if (drv->get_interfaces == NULL)
10958			continue;
10959		tmp = drv->get_interfaces(global->drv_priv[i]);
10960		if (tmp == NULL)
10961			continue;
10962
10963		if (last == NULL)
10964			iface = last = tmp;
10965		else
10966			last->next = tmp;
10967		while (last->next)
10968			last = last->next;
10969	}
10970
10971	pos = buf;
10972	end = buf + len;
10973	for (tmp = iface; tmp; tmp = tmp->next) {
10974		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
10975				  tmp->drv_name, tmp->ifname,
10976				  tmp->desc ? tmp->desc : "");
10977		if (os_snprintf_error(end - pos, res)) {
10978			*pos = '\0';
10979			break;
10980		}
10981		pos += res;
10982	}
10983
10984	wpa_free_iface_info(iface);
10985
10986	return pos - buf;
10987}
10988
10989
10990static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
10991						  const char *input,
10992						  char *buf, int len)
10993{
10994	int res;
10995	char *pos, *end;
10996	struct wpa_supplicant *wpa_s;
10997	int show_ctrl = 0;
10998
10999	if (input)
11000		show_ctrl = !!os_strstr(input, "ctrl");
11001
11002	wpa_s = global->ifaces;
11003	pos = buf;
11004	end = buf + len;
11005
11006	while (wpa_s) {
11007		if (show_ctrl)
11008			res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
11009					  wpa_s->ifname,
11010					  wpa_s->conf->ctrl_interface ?
11011					  wpa_s->conf->ctrl_interface : "N/A");
11012		else
11013			res = os_snprintf(pos, end - pos, "%s\n",
11014					  wpa_s->ifname);
11015
11016		if (os_snprintf_error(end - pos, res)) {
11017			*pos = '\0';
11018			break;
11019		}
11020		pos += res;
11021		wpa_s = wpa_s->next;
11022	}
11023	return pos - buf;
11024}
11025
11026
11027static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
11028					    const char *ifname,
11029					    char *cmd, size_t *resp_len)
11030{
11031	struct wpa_supplicant *wpa_s;
11032
11033	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
11034		if (os_strcmp(ifname, wpa_s->ifname) == 0)
11035			break;
11036	}
11037
11038	if (wpa_s == NULL) {
11039		char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
11040		if (resp)
11041			*resp_len = os_strlen(resp);
11042		else
11043			*resp_len = 1;
11044		return resp;
11045	}
11046
11047	return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
11048}
11049
11050
11051static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
11052					       char *buf, size_t *resp_len)
11053{
11054#ifdef CONFIG_P2P
11055	static const char * cmd[] = {
11056		"LIST_NETWORKS",
11057		"P2P_FIND",
11058		"P2P_STOP_FIND",
11059		"P2P_LISTEN",
11060		"P2P_GROUP_ADD",
11061		"P2P_GET_PASSPHRASE",
11062		"P2P_SERVICE_UPDATE",
11063		"P2P_SERVICE_FLUSH",
11064		"P2P_FLUSH",
11065		"P2P_CANCEL",
11066		"P2P_PRESENCE_REQ",
11067		"P2P_EXT_LISTEN",
11068#ifdef CONFIG_AP
11069		"STA-FIRST",
11070#endif /* CONFIG_AP */
11071		NULL
11072	};
11073	static const char * prefix[] = {
11074#ifdef ANDROID
11075		"DRIVER ",
11076#endif /* ANDROID */
11077		"GET_CAPABILITY ",
11078		"GET_NETWORK ",
11079		"REMOVE_NETWORK ",
11080		"P2P_FIND ",
11081		"P2P_CONNECT ",
11082		"P2P_LISTEN ",
11083		"P2P_GROUP_REMOVE ",
11084		"P2P_GROUP_ADD ",
11085		"P2P_GROUP_MEMBER ",
11086		"P2P_PROV_DISC ",
11087		"P2P_SERV_DISC_REQ ",
11088		"P2P_SERV_DISC_CANCEL_REQ ",
11089		"P2P_SERV_DISC_RESP ",
11090		"P2P_SERV_DISC_EXTERNAL ",
11091		"P2P_SERVICE_ADD ",
11092		"P2P_SERVICE_DEL ",
11093		"P2P_SERVICE_REP ",
11094		"P2P_REJECT ",
11095		"P2P_INVITE ",
11096		"P2P_PEER ",
11097		"P2P_SET ",
11098		"P2P_UNAUTHORIZE ",
11099		"P2P_PRESENCE_REQ ",
11100		"P2P_EXT_LISTEN ",
11101		"P2P_REMOVE_CLIENT ",
11102		"WPS_NFC_TOKEN ",
11103		"WPS_NFC_TAG_READ ",
11104		"NFC_GET_HANDOVER_SEL ",
11105		"NFC_GET_HANDOVER_REQ ",
11106		"NFC_REPORT_HANDOVER ",
11107		"P2P_ASP_PROVISION ",
11108		"P2P_ASP_PROVISION_RESP ",
11109#ifdef CONFIG_AP
11110		"STA ",
11111		"STA-NEXT ",
11112#endif /* CONFIG_AP */
11113		NULL
11114	};
11115	int found = 0;
11116	int i;
11117
11118	if (global->p2p_init_wpa_s == NULL)
11119		return NULL;
11120
11121	for (i = 0; !found && cmd[i]; i++) {
11122		if (os_strcmp(buf, cmd[i]) == 0)
11123			found = 1;
11124	}
11125
11126	for (i = 0; !found && prefix[i]; i++) {
11127		if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
11128			found = 1;
11129	}
11130
11131	if (found)
11132		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
11133							 buf, resp_len);
11134#endif /* CONFIG_P2P */
11135	return NULL;
11136}
11137
11138
11139static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
11140					       char *buf, size_t *resp_len)
11141{
11142#ifdef CONFIG_WIFI_DISPLAY
11143	if (global->p2p_init_wpa_s == NULL)
11144		return NULL;
11145	if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
11146	    os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
11147		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
11148							 buf, resp_len);
11149#endif /* CONFIG_WIFI_DISPLAY */
11150	return NULL;
11151}
11152
11153
11154static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
11155					   char *buf, size_t *resp_len)
11156{
11157	char *ret;
11158
11159	ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
11160	if (ret)
11161		return ret;
11162
11163	ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
11164	if (ret)
11165		return ret;
11166
11167	return NULL;
11168}
11169
11170
11171static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
11172{
11173	char *value;
11174
11175	value = os_strchr(cmd, ' ');
11176	if (value == NULL)
11177		return -1;
11178	*value++ = '\0';
11179
11180	wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
11181
11182#ifdef CONFIG_WIFI_DISPLAY
11183	if (os_strcasecmp(cmd, "wifi_display") == 0) {
11184		wifi_display_enable(global, !!atoi(value));
11185		return 0;
11186	}
11187#endif /* CONFIG_WIFI_DISPLAY */
11188
11189	/* Restore cmd to its original value to allow redirection */
11190	value[-1] = ' ';
11191
11192	return -1;
11193}
11194
11195
11196static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
11197					      char *cmd)
11198{
11199	struct wpa_supplicant *wpa_s[2]; /* src, dst */
11200	char *p;
11201	unsigned int i;
11202
11203	/* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
11204	 * <variable name> */
11205
11206	for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
11207		p = os_strchr(cmd, ' ');
11208		if (p == NULL)
11209			return -1;
11210		*p = '\0';
11211
11212		wpa_s[i] = global->ifaces;
11213		for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
11214			if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
11215				break;
11216		}
11217
11218		if (!wpa_s[i]) {
11219			wpa_printf(MSG_DEBUG,
11220				   "CTRL_IFACE: Could not find iface=%s", cmd);
11221			return -1;
11222		}
11223
11224		cmd = p + 1;
11225	}
11226
11227	return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
11228}
11229
11230
11231#ifndef CONFIG_NO_CONFIG_WRITE
11232static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
11233{
11234	int ret = 0, saved = 0;
11235	struct wpa_supplicant *wpa_s;
11236
11237	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
11238		if (!wpa_s->conf->update_config) {
11239			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
11240			continue;
11241		}
11242
11243		if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
11244			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
11245			ret = 1;
11246		} else {
11247			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
11248			saved++;
11249		}
11250	}
11251
11252	if (!saved && !ret) {
11253		wpa_dbg(wpa_s, MSG_DEBUG,
11254			"CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
11255		ret = 1;
11256	}
11257
11258	return ret;
11259}
11260#endif /* CONFIG_NO_CONFIG_WRITE */
11261
11262
11263static int wpas_global_ctrl_iface_status(struct wpa_global *global,
11264					 char *buf, size_t buflen)
11265{
11266	char *pos, *end;
11267	int ret;
11268	struct wpa_supplicant *wpa_s;
11269
11270	pos = buf;
11271	end = buf + buflen;
11272
11273#ifdef CONFIG_P2P
11274	if (global->p2p && !global->p2p_disabled) {
11275		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
11276				  "\n"
11277				  "p2p_state=%s\n",
11278				  MAC2STR(global->p2p_dev_addr),
11279				  p2p_get_state_txt(global->p2p));
11280		if (os_snprintf_error(end - pos, ret))
11281			return pos - buf;
11282		pos += ret;
11283	} else if (global->p2p) {
11284		ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
11285		if (os_snprintf_error(end - pos, ret))
11286			return pos - buf;
11287		pos += ret;
11288	}
11289#endif /* CONFIG_P2P */
11290
11291#ifdef CONFIG_WIFI_DISPLAY
11292	ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
11293			  !!global->wifi_display);
11294	if (os_snprintf_error(end - pos, ret))
11295		return pos - buf;
11296	pos += ret;
11297#endif /* CONFIG_WIFI_DISPLAY */
11298
11299	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
11300		ret = os_snprintf(pos, end - pos, "ifname=%s\n"
11301				  "address=" MACSTR "\n",
11302				  wpa_s->ifname, MAC2STR(wpa_s->own_addr));
11303		if (os_snprintf_error(end - pos, ret))
11304			return pos - buf;
11305		pos += ret;
11306	}
11307
11308	return pos - buf;
11309}
11310
11311
11312#ifdef CONFIG_FST
11313
11314static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
11315					     char *cmd, char *buf,
11316					     size_t reply_size)
11317{
11318	char ifname[IFNAMSIZ + 1];
11319	struct fst_iface_cfg cfg;
11320	struct wpa_supplicant *wpa_s;
11321	struct fst_wpa_obj iface_obj;
11322
11323	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
11324		wpa_s = wpa_supplicant_get_iface(global, ifname);
11325		if (wpa_s) {
11326			if (wpa_s->fst) {
11327				wpa_printf(MSG_INFO, "FST: Already attached");
11328				return -1;
11329			}
11330			fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
11331			wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
11332						&iface_obj, &cfg);
11333			if (wpa_s->fst)
11334				return os_snprintf(buf, reply_size, "OK\n");
11335		}
11336	}
11337
11338	return -1;
11339}
11340
11341
11342static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
11343					     char *cmd, char *buf,
11344					     size_t reply_size)
11345{
11346	char ifname[IFNAMSIZ + 1];
11347	struct wpa_supplicant *wpa_s;
11348
11349	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
11350		wpa_s = wpa_supplicant_get_iface(global, ifname);
11351		if (wpa_s) {
11352			if (!fst_iface_detach(ifname)) {
11353				wpa_s->fst = NULL;
11354				return os_snprintf(buf, reply_size, "OK\n");
11355			}
11356		}
11357	}
11358
11359	return -1;
11360}
11361
11362#endif /* CONFIG_FST */
11363
11364
11365char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
11366						char *buf, size_t *resp_len)
11367{
11368	char *reply;
11369	const int reply_size = 2048;
11370	int reply_len;
11371	int level = MSG_DEBUG;
11372
11373	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
11374		char *pos = os_strchr(buf + 7, ' ');
11375		if (pos) {
11376			*pos++ = '\0';
11377			return wpas_global_ctrl_iface_ifname(global,
11378							     buf + 7, pos,
11379							     resp_len);
11380		}
11381	}
11382
11383	reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
11384	if (reply)
11385		return reply;
11386
11387	if (os_strcmp(buf, "PING") == 0)
11388		level = MSG_EXCESSIVE;
11389	wpa_hexdump_ascii(level, "RX global ctrl_iface",
11390			  (const u8 *) buf, os_strlen(buf));
11391
11392	reply = os_malloc(reply_size);
11393	if (reply == NULL) {
11394		*resp_len = 1;
11395		return NULL;
11396	}
11397
11398	os_memcpy(reply, "OK\n", 3);
11399	reply_len = 3;
11400
11401	if (os_strcmp(buf, "PING") == 0) {
11402		os_memcpy(reply, "PONG\n", 5);
11403		reply_len = 5;
11404	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
11405		if (wpa_supplicant_global_iface_add(global, buf + 14))
11406			reply_len = -1;
11407	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
11408		if (wpa_supplicant_global_iface_remove(global, buf + 17))
11409			reply_len = -1;
11410	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
11411		reply_len = wpa_supplicant_global_iface_list(
11412			global, reply, reply_size);
11413	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
11414		reply_len = wpa_supplicant_global_iface_interfaces(
11415			global, buf + 10, reply, reply_size);
11416#ifdef CONFIG_FST
11417	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
11418		reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
11419							      reply,
11420							      reply_size);
11421	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
11422		reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
11423							      reply,
11424							      reply_size);
11425	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
11426		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
11427#endif /* CONFIG_FST */
11428	} else if (os_strcmp(buf, "TERMINATE") == 0) {
11429		wpa_supplicant_terminate_proc(global);
11430	} else if (os_strcmp(buf, "SUSPEND") == 0) {
11431		wpas_notify_suspend(global);
11432	} else if (os_strcmp(buf, "RESUME") == 0) {
11433		wpas_notify_resume(global);
11434	} else if (os_strncmp(buf, "SET ", 4) == 0) {
11435		if (wpas_global_ctrl_iface_set(global, buf + 4)) {
11436#ifdef CONFIG_P2P
11437			if (global->p2p_init_wpa_s) {
11438				os_free(reply);
11439				/* Check if P2P redirection would work for this
11440				 * command. */
11441				return wpa_supplicant_ctrl_iface_process(
11442					global->p2p_init_wpa_s,
11443					buf, resp_len);
11444			}
11445#endif /* CONFIG_P2P */
11446			reply_len = -1;
11447		}
11448	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
11449		if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
11450			reply_len = -1;
11451#ifndef CONFIG_NO_CONFIG_WRITE
11452	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
11453		if (wpas_global_ctrl_iface_save_config(global))
11454			reply_len = -1;
11455#endif /* CONFIG_NO_CONFIG_WRITE */
11456	} else if (os_strcmp(buf, "STATUS") == 0) {
11457		reply_len = wpas_global_ctrl_iface_status(global, reply,
11458							  reply_size);
11459#ifdef CONFIG_MODULE_TESTS
11460	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
11461		if (wpas_module_tests() < 0)
11462			reply_len = -1;
11463#endif /* CONFIG_MODULE_TESTS */
11464	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
11465		if (wpa_debug_reopen_file() < 0)
11466			reply_len = -1;
11467	} else {
11468		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
11469		reply_len = 16;
11470	}
11471
11472	if (reply_len < 0) {
11473		os_memcpy(reply, "FAIL\n", 5);
11474		reply_len = 5;
11475	}
11476
11477	*resp_len = reply_len;
11478	return reply;
11479}
11480