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