• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 #ifdef CONFIG_TESTING_OPTIONS
11 #include <netinet/ip.h>
12 #endif /* CONFIG_TESTING_OPTIONS */
13 
14 #include "utils/common.h"
15 #include "utils/eloop.h"
16 #include "utils/uuid.h"
17 #include "utils/module_tests.h"
18 #include "common/version.h"
19 #include "common/ieee802_11_defs.h"
20 #include "common/ieee802_11_common.h"
21 #include "common/wpa_ctrl.h"
22 #ifdef CONFIG_DPP
23 #include "common/dpp.h"
24 #endif /* CONFIG_DPP */
25 #include "common/ptksa_cache.h"
26 #include "crypto/tls.h"
27 #include "ap/hostapd.h"
28 #include "eap_peer/eap.h"
29 #include "eapol_supp/eapol_supp_sm.h"
30 #include "rsn_supp/wpa.h"
31 #include "rsn_supp/preauth.h"
32 #include "rsn_supp/pmksa_cache.h"
33 #include "l2_packet/l2_packet.h"
34 #include "wps/wps.h"
35 #include "fst/fst.h"
36 #include "fst/fst_ctrl_iface.h"
37 #include "config.h"
38 #include "wpa_supplicant_i.h"
39 #include "driver_i.h"
40 #include "wps_supplicant.h"
41 #include "ibss_rsn.h"
42 #include "wpas_glue.h"
43 #include "ap.h"
44 #include "p2p_supplicant.h"
45 #include "p2p/p2p.h"
46 #include "p2p/p2p_i.h"
47 #ifndef EXT_CODE_CROP
48 #include "hs20_supplicant.h"
49 #endif /* EXT_CODE_CROP */
50 #include "wifi_display.h"
51 #include "notify.h"
52 #include "bss.h"
53 #include "scan.h"
54 #include "ctrl_iface.h"
55 #include "interworking.h"
56 #include "bssid_ignore.h"
57 #include "autoscan.h"
58 #include "wnm_sta.h"
59 #include "offchannel.h"
60 #include "drivers/driver.h"
61 #include "mesh.h"
62 #include "dpp_supplicant.h"
63 #include "sme.h"
64 #include "ap/ap_drv_ops.h"
65 #include "ap/sta_info.h"
66 #include "hostapd_if.h"
67 #include "wpa_supplicant_if.h"
68 #include "wifi_api.h"
69 #ifdef __NetBSD__
70 #include <net/if_ether.h>
71 #elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS)
72 #include <net/ethernet.h>
73 #endif
74 
75 struct p2p_user_cfg_pos {
76 	char *name;
77 	char *pos_start;
78 	char *pos_end;
79 	char **dst;
80 	unsigned int changed;
81 };
82 
83 struct wpa_ssid *g_connecting_ssid = NULL;
84 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
85 					    char *buf, int len);
86 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
87 						  const char *input,
88 						  char *buf, int len);
89 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
90 					char *val);
91 
92 
93 #ifndef EXT_CODE_CROP
set_bssid_filter(struct wpa_supplicant * wpa_s,char * val)94 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
95 {
96 	char *pos;
97 	u8 addr[ETH_ALEN], *filter = NULL, *n;
98 	size_t count = 0;
99 
100 	pos = val;
101 	while (pos) {
102 		if (*pos == '\0')
103 			break;
104 		if (hwaddr_aton(pos, addr)) {
105 			os_free(filter);
106 			return -1;
107 		}
108 		n = os_realloc_array(filter, count + 1, ETH_ALEN);
109 		if (n == NULL) {
110 			os_free(filter);
111 			return -1;
112 		}
113 		filter = n;
114 		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
115 		count++;
116 
117 		pos = os_strchr(pos, ' ');
118 		if (pos)
119 			pos++;
120 	}
121 
122 	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
123 	os_free(wpa_s->bssid_filter);
124 	wpa_s->bssid_filter = filter;
125 	wpa_s->bssid_filter_count = count;
126 
127 	return 0;
128 }
129 
130 
set_disallow_aps(struct wpa_supplicant * wpa_s,char * val)131 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
132 {
133 	char *pos;
134 	u8 addr[ETH_ALEN], *bssid = NULL, *n;
135 	struct wpa_ssid_value *ssid = NULL, *ns;
136 	size_t count = 0, ssid_count = 0;
137 	struct wpa_ssid *c;
138 
139 	/*
140 	 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
141 	 * SSID_SPEC ::= ssid <SSID_HEX>
142 	 * BSSID_SPEC ::= bssid <BSSID_HEX>
143 	 */
144 
145 	pos = val;
146 	while (pos) {
147 		if (*pos == '\0')
148 			break;
149 		if (os_strncmp(pos, "bssid ", 6) == 0) {
150 			int res;
151 			pos += 6;
152 			res = hwaddr_aton2(pos, addr);
153 			if (res < 0) {
154 				os_free(ssid);
155 				os_free(bssid);
156 				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
157 					   "BSSID value '%s'", pos);
158 				return -1;
159 			}
160 			pos += res;
161 			n = os_realloc_array(bssid, count + 1, ETH_ALEN);
162 			if (n == NULL) {
163 				os_free(ssid);
164 				os_free(bssid);
165 				return -1;
166 			}
167 			bssid = n;
168 			os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
169 			count++;
170 		} else if (os_strncmp(pos, "ssid ", 5) == 0) {
171 			char *end;
172 			pos += 5;
173 
174 			end = pos;
175 			while (*end) {
176 				if (*end == '\0' || *end == ' ')
177 					break;
178 				end++;
179 			}
180 
181 			ns = os_realloc_array(ssid, ssid_count + 1,
182 					      sizeof(struct wpa_ssid_value));
183 			if (ns == NULL) {
184 				os_free(ssid);
185 				os_free(bssid);
186 				return -1;
187 			}
188 			ssid = ns;
189 
190 			if ((end - pos) & 0x01 ||
191 			    end - pos > 2 * SSID_MAX_LEN ||
192 			    hexstr2bin(pos, ssid[ssid_count].ssid,
193 				       (end - pos) / 2) < 0) {
194 				os_free(ssid);
195 				os_free(bssid);
196 				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
197 					   "SSID value '%s'", pos);
198 				return -1;
199 			}
200 			ssid[ssid_count].ssid_len = (end - pos) / 2;
201 			wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
202 					  ssid[ssid_count].ssid,
203 					  ssid[ssid_count].ssid_len);
204 			ssid_count++;
205 			pos = end;
206 		} else {
207 			wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
208 				   "'%s'", pos);
209 			os_free(ssid);
210 			os_free(bssid);
211 			return -1;
212 		}
213 
214 		pos = os_strchr(pos, ' ');
215 		if (pos)
216 			pos++;
217 	}
218 
219 	wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
220 	os_free(wpa_s->disallow_aps_bssid);
221 	wpa_s->disallow_aps_bssid = bssid;
222 	wpa_s->disallow_aps_bssid_count = count;
223 
224 	wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
225 	os_free(wpa_s->disallow_aps_ssid);
226 	wpa_s->disallow_aps_ssid = ssid;
227 	wpa_s->disallow_aps_ssid_count = ssid_count;
228 
229 	if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
230 		return 0;
231 
232 	c = wpa_s->current_ssid;
233 	if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
234 		return 0;
235 
236 	if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
237 	    !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
238 		return 0;
239 
240 	wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
241 		   "because current AP was marked disallowed");
242 
243 #ifdef CONFIG_SME
244 	wpa_s->sme.prev_bssid_set = 0;
245 #endif /* CONFIG_SME */
246 	wpa_s->reassociate = 1;
247 	wpa_s->own_disconnect_req = 1;
248 	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
249 	wpa_supplicant_req_scan(wpa_s, 0, 0);
250 
251 	return 0;
252 }
253 
254 
255 #ifndef CONFIG_NO_CONFIG_BLOBS
wpas_ctrl_set_blob(struct wpa_supplicant * wpa_s,char * pos)256 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
257 {
258 	char *name = pos;
259 	struct wpa_config_blob *blob;
260 	size_t len;
261 
262 	pos = os_strchr(pos, ' ');
263 	if (pos == NULL)
264 		return -1;
265 	*pos++ = '\0';
266 	len = os_strlen(pos);
267 	if (len & 1)
268 		return -1;
269 
270 	wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
271 	blob = os_zalloc(sizeof(*blob));
272 	if (blob == NULL)
273 		return -1;
274 	blob->name = os_strdup(name);
275 	blob->data = os_malloc(len / 2);
276 	if (blob->name == NULL || blob->data == NULL) {
277 		wpa_config_free_blob(blob);
278 		return -1;
279 	}
280 
281 	if (hexstr2bin(pos, blob->data, len / 2) < 0) {
282 		wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
283 		wpa_config_free_blob(blob);
284 		return -1;
285 	}
286 	blob->len = len / 2;
287 
288 	wpa_config_set_blob(wpa_s->conf, blob);
289 
290 	return 0;
291 }
292 #endif /* CONFIG_NO_CONFIG_BLOBS */
293 
294 
wpas_ctrl_pno(struct wpa_supplicant * wpa_s,char * cmd)295 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
296 {
297 	char *params;
298 	char *pos;
299 	int *freqs = NULL;
300 	int ret;
301 
302 	if (atoi(cmd)) {
303 		params = os_strchr(cmd, ' ');
304 		os_free(wpa_s->manual_sched_scan_freqs);
305 		if (params) {
306 			params++;
307 			pos = os_strstr(params, "freq=");
308 			if (pos)
309 				freqs = freq_range_to_channel_list(wpa_s,
310 								   pos + 5);
311 		}
312 		wpa_s->manual_sched_scan_freqs = freqs;
313 		ret = wpas_start_pno(wpa_s);
314 	} else {
315 		ret = wpas_stop_pno(wpa_s);
316 	}
317 	return ret;
318 }
319 
320 
wpas_ctrl_set_band(struct wpa_supplicant * wpa_s,char * bands)321 static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
322 {
323 	union wpa_event_data event;
324 	u32 setband_mask = WPA_SETBAND_AUTO;
325 
326 	/*
327 	 * For example:
328 	 *  SET setband 2G,6G
329 	 *  SET setband 5G
330 	 *  SET setband AUTO
331 	 */
332 	if (!os_strstr(bands, "AUTO")) {
333 		if (os_strstr(bands, "5G"))
334 			setband_mask |= WPA_SETBAND_5G;
335 		if (os_strstr(bands, "6G"))
336 			setband_mask |= WPA_SETBAND_6G;
337 		if (os_strstr(bands, "2G"))
338 			setband_mask |= WPA_SETBAND_2G;
339 		if (setband_mask == WPA_SETBAND_AUTO)
340 			return -1;
341 	}
342 
343 	wpa_s->setband_mask = setband_mask;
344 	if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
345 		os_memset(&event, 0, sizeof(event));
346 		event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
347 		event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
348 		wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
349 	}
350 
351 	return 0;
352 }
353 
354 
wpas_ctrl_iface_set_lci(struct wpa_supplicant * wpa_s,const char * cmd)355 static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
356 				   const char *cmd)
357 {
358 	struct wpabuf *lci;
359 
360 	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
361 		wpabuf_free(wpa_s->lci);
362 		wpa_s->lci = NULL;
363 		return 0;
364 	}
365 
366 	lci = wpabuf_parse_bin(cmd);
367 	if (!lci)
368 		return -1;
369 
370 	if (os_get_reltime(&wpa_s->lci_time)) {
371 		wpabuf_free(lci);
372 		return -1;
373 	}
374 
375 	wpabuf_free(wpa_s->lci);
376 	wpa_s->lci = lci;
377 
378 	return 0;
379 }
380 
381 
382 static int
wpas_ctrl_set_relative_rssi(struct wpa_supplicant * wpa_s,const char * cmd)383 wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
384 {
385 	int relative_rssi;
386 
387 	if (os_strcmp(cmd, "disable") == 0) {
388 		wpa_s->srp.relative_rssi_set = 0;
389 		return 0;
390 	}
391 
392 	relative_rssi = atoi(cmd);
393 	if (relative_rssi < 0 || relative_rssi > 100)
394 		return -1;
395 	wpa_s->srp.relative_rssi = relative_rssi;
396 	wpa_s->srp.relative_rssi_set = 1;
397 	return 0;
398 }
399 
400 
wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant * wpa_s,const char * cmd)401 static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
402 					      const char *cmd)
403 {
404 	char *pos;
405 	int adjust_rssi;
406 
407 	/* <band>:adjust_value */
408 	pos = os_strchr(cmd, ':');
409 	if (!pos)
410 		return -1;
411 	pos++;
412 	adjust_rssi = atoi(pos);
413 	if (adjust_rssi < -100 || adjust_rssi > 100)
414 		return -1;
415 
416 	if (os_strncmp(cmd, "2G", 2) == 0)
417 		wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
418 	else if (os_strncmp(cmd, "5G", 2) == 0)
419 		wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
420 	else
421 		return -1;
422 
423 	wpa_s->srp.relative_adjust_rssi = adjust_rssi;
424 
425 	return 0;
426 }
427 
428 
wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant * wpa_s,const char * cmd)429 static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
430 				   const char *cmd)
431 {
432 	struct wpabuf *ric_ies;
433 
434 	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
435 		wpabuf_free(wpa_s->ric_ies);
436 		wpa_s->ric_ies = NULL;
437 		return 0;
438 	}
439 
440 	ric_ies = wpabuf_parse_bin(cmd);
441 	if (!ric_ies)
442 		return -1;
443 
444 	wpabuf_free(wpa_s->ric_ies);
445 	wpa_s->ric_ies = ric_ies;
446 
447 	return 0;
448 }
449 
450 
451 #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_iface_set_dso(struct wpa_supplicant * wpa_s,const char * val)452 static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
453 				   const char *val)
454 {
455 	u8 bssid[ETH_ALEN];
456 	const char *pos = val;
457 	struct driver_signal_override *dso = NULL, *tmp, parsed;
458 
459 	if (hwaddr_aton(pos, bssid))
460 		return -1;
461 	pos = os_strchr(pos, ' ');
462 
463 	dl_list_for_each(tmp, &wpa_s->drv_signal_override,
464 			 struct driver_signal_override, list) {
465 		if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
466 			dso = tmp;
467 			break;
468 		}
469 	}
470 
471 	if (!pos) {
472 		/* Remove existing entry */
473 		if (dso) {
474 			dl_list_del(&dso->list);
475 			os_free(dso);
476 		}
477 		return 0;
478 	}
479 	pos++;
480 
481 	/* Update an existing entry or add a new one */
482 	os_memset(&parsed, 0, sizeof(parsed));
483 	if (sscanf(pos, "%d %d %d %d %d",
484 		   &parsed.si_current_signal,
485 		   &parsed.si_avg_signal,
486 		   &parsed.si_avg_beacon_signal,
487 		   &parsed.si_current_noise,
488 		   &parsed.scan_level) != 5)
489 		return -1;
490 
491 	if (!dso) {
492 		dso = os_zalloc(sizeof(*dso));
493 		if (!dso)
494 			return -1;
495 		os_memcpy(dso->bssid, bssid, ETH_ALEN);
496 		dl_list_add(&wpa_s->drv_signal_override, &dso->list);
497 	}
498 	dso->si_current_signal = parsed.si_current_signal;
499 	dso->si_avg_signal = parsed.si_avg_signal;
500 	dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
501 	dso->si_current_noise = parsed.si_current_noise;
502 	dso->scan_level = parsed.scan_level;
503 
504 	return 0;
505 }
506 #endif /* CONFIG_TESTING_OPTIONS */
507 
508 
wpa_supplicant_ctrl_iface_set(struct wpa_supplicant * wpa_s,char * cmd)509 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
510 					 char *cmd)
511 {
512 	char *value;
513 	int ret = 0;
514 
515 	value = os_strchr(cmd, ' ');
516 	if (value == NULL)
517 		return -1;
518 	*value++ = '\0';
519 
520 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
521 	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
522 		eapol_sm_configure(wpa_s->eapol,
523 				   atoi(value), -1, -1, -1);
524 	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
525 		eapol_sm_configure(wpa_s->eapol,
526 				   -1, atoi(value), -1, -1);
527 	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
528 		eapol_sm_configure(wpa_s->eapol,
529 				   -1, -1, atoi(value), -1);
530 	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
531 		eapol_sm_configure(wpa_s->eapol,
532 				   -1, -1, -1, atoi(value));
533 #ifdef CONFIG_TESTING_OPTIONS
534 	} else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
535 		if (os_strcmp(value, "Auto") == 0)
536 			eapol_sm_notify_portControl(wpa_s->eapol, Auto);
537 		else if (os_strcmp(value, "ForceUnauthorized") == 0)
538 			eapol_sm_notify_portControl(wpa_s->eapol,
539 						    ForceUnauthorized);
540 		else if (os_strcmp(value, "ForceAuthorized") == 0)
541 			eapol_sm_notify_portControl(wpa_s->eapol,
542 						    ForceAuthorized);
543 		else
544 			ret = -1;
545 #endif /* CONFIG_TESTING_OPTIONS */
546 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
547 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
548 				     atoi(value))) {
549 			ret = -1;
550 		} else {
551 			value[-1] = '=';
552 			wpa_config_process_global(wpa_s->conf, cmd, -1);
553 		}
554 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
555 		   0) {
556 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
557 				     atoi(value))) {
558 			ret = -1;
559 		} else {
560 			value[-1] = '=';
561 			wpa_config_process_global(wpa_s->conf, cmd, -1);
562 		}
563 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
564 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
565 				     atoi(value))) {
566 			ret = -1;
567 		} else {
568 			value[-1] = '=';
569 			wpa_config_process_global(wpa_s->conf, cmd, -1);
570 		}
571 	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
572 		wpa_s->wps_fragment_size = atoi(value);
573 #ifdef CONFIG_WPS_TESTING
574 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
575 		long int val;
576 		val = strtol(value, NULL, 0);
577 		if (val < 0 || val > 0xff) {
578 			ret = -1;
579 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
580 				   "wps_version_number %ld", val);
581 		} else {
582 			wps_version_number = val;
583 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
584 				   "version %u.%u",
585 				   (wps_version_number & 0xf0) >> 4,
586 				   wps_version_number & 0x0f);
587 		}
588 	} else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
589 		wps_testing_stub_cred = atoi(value);
590 		wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
591 			   wps_testing_stub_cred);
592 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
593 		wps_corrupt_pkhash = atoi(value);
594 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
595 			   wps_corrupt_pkhash);
596 	} else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
597 		if (value[0] == '\0') {
598 			wps_force_auth_types_in_use = 0;
599 		} else {
600 			wps_force_auth_types = strtol(value, NULL, 0);
601 			wps_force_auth_types_in_use = 1;
602 		}
603 	} else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
604 		if (value[0] == '\0') {
605 			wps_force_encr_types_in_use = 0;
606 		} else {
607 			wps_force_encr_types = strtol(value, NULL, 0);
608 			wps_force_encr_types_in_use = 1;
609 		}
610 #endif /* CONFIG_WPS_TESTING */
611 	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
612 		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
613 			ret = -1;
614 #ifdef CONFIG_TDLS
615 #ifdef CONFIG_TDLS_TESTING
616 	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
617 		tdls_testing = strtol(value, NULL, 0);
618 		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
619 #endif /* CONFIG_TDLS_TESTING */
620 	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
621 		int disabled = atoi(value);
622 		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
623 		if (disabled) {
624 			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
625 				ret = -1;
626 		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
627 			ret = -1;
628 		wpa_tdls_enable(wpa_s->wpa, !disabled);
629 #endif /* CONFIG_TDLS */
630 	} else if (os_strcasecmp(cmd, "pno") == 0) {
631 		ret = wpas_ctrl_pno(wpa_s, value);
632 	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
633 		int disabled = atoi(value);
634 		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
635 			ret = -1;
636 		else if (disabled)
637 			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
638 	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
639 		if (os_strcmp(value, "disable") == 0)
640 			wpa_s->set_sta_uapsd = 0;
641 		else {
642 			int be, bk, vi, vo;
643 			char *pos;
644 			/* format: BE,BK,VI,VO;max SP Length */
645 			be = atoi(value);
646 			pos = os_strchr(value, ',');
647 			if (pos == NULL)
648 				return -1;
649 			pos++;
650 			bk = atoi(pos);
651 			pos = os_strchr(pos, ',');
652 			if (pos == NULL)
653 				return -1;
654 			pos++;
655 			vi = atoi(pos);
656 			pos = os_strchr(pos, ',');
657 			if (pos == NULL)
658 				return -1;
659 			pos++;
660 			vo = atoi(pos);
661 			/* ignore max SP Length for now */
662 
663 			wpa_s->set_sta_uapsd = 1;
664 			wpa_s->sta_uapsd = 0;
665 			if (be)
666 				wpa_s->sta_uapsd |= BIT(0);
667 			if (bk)
668 				wpa_s->sta_uapsd |= BIT(1);
669 			if (vi)
670 				wpa_s->sta_uapsd |= BIT(2);
671 			if (vo)
672 				wpa_s->sta_uapsd |= BIT(3);
673 		}
674 	} else if (os_strcasecmp(cmd, "ps") == 0) {
675 		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
676 #ifdef CONFIG_WIFI_DISPLAY
677 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
678 		int enabled = !!atoi(value);
679 		if (enabled && !wpa_s->global->p2p)
680 			ret = -1;
681 		else
682 			wifi_display_enable(wpa_s->global, enabled);
683 #endif /* CONFIG_WIFI_DISPLAY */
684 	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
685 		ret = set_bssid_filter(wpa_s, value);
686 	} else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
687 		ret = set_disallow_aps(wpa_s, value);
688 	} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
689 		wpa_s->no_keep_alive = !!atoi(value);
690 #ifdef CONFIG_DPP
691 	} else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
692 		os_free(wpa_s->dpp_configurator_params);
693 		wpa_s->dpp_configurator_params = os_strdup(value);
694 	} else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
695 		wpa_s->dpp_init_max_tries = atoi(value);
696 	} else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
697 		wpa_s->dpp_init_retry_time = atoi(value);
698 	} else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
699 		wpa_s->dpp_resp_wait_time = atoi(value);
700 	} else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
701 		wpa_s->dpp_resp_max_tries = atoi(value);
702 	} else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
703 		wpa_s->dpp_resp_retry_time = atoi(value);
704 #ifdef CONFIG_TESTING_OPTIONS
705 	} else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
706 		if (hwaddr_aton(value, dpp_pkex_own_mac_override))
707 			ret = -1;
708 	} else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
709 		if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
710 			ret = -1;
711 	} else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
712 		size_t hex_len = os_strlen(value);
713 
714 		if (hex_len >
715 		    2 * sizeof(dpp_pkex_ephemeral_key_override))
716 			ret = -1;
717 		else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
718 				    hex_len / 2))
719 			ret = -1;
720 		else
721 			dpp_pkex_ephemeral_key_override_len = hex_len / 2;
722 	} else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
723 		size_t hex_len = os_strlen(value);
724 
725 		if (hex_len > 2 * sizeof(dpp_protocol_key_override))
726 			ret = -1;
727 		else if (hexstr2bin(value, dpp_protocol_key_override,
728 				    hex_len / 2))
729 			ret = -1;
730 		else
731 			dpp_protocol_key_override_len = hex_len / 2;
732 	} else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
733 		size_t hex_len = os_strlen(value);
734 
735 		if (hex_len > 2 * sizeof(dpp_nonce_override))
736 			ret = -1;
737 		else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
738 			ret = -1;
739 		else
740 			dpp_nonce_override_len = hex_len / 2;
741 	} else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
742 		dpp_version_override = atoi(value);
743 #endif /* CONFIG_TESTING_OPTIONS */
744 #endif /* CONFIG_DPP */
745 #ifdef CONFIG_TESTING_OPTIONS
746 	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
747 		wpa_s->ext_mgmt_frame_handling = !!atoi(value);
748 	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
749 		wpa_s->ext_eapol_frame_io = !!atoi(value);
750 #ifdef CONFIG_AP
751 		if (wpa_s->ap_iface) {
752 			wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
753 				wpa_s->ext_eapol_frame_io;
754 		}
755 #endif /* CONFIG_AP */
756 	} else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
757 		wpa_s->extra_roc_dur = atoi(value);
758 	} else if (os_strcasecmp(cmd, "test_failure") == 0) {
759 		wpa_s->test_failure = atoi(value);
760 	} else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
761 		wpa_s->p2p_go_csa_on_inv = !!atoi(value);
762 	} else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
763 		wpa_s->ignore_auth_resp = !!atoi(value);
764 	} else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
765 		wpa_s->ignore_assoc_disallow = !!atoi(value);
766 		wpa_drv_ignore_assoc_disallow(wpa_s,
767 					      wpa_s->ignore_assoc_disallow);
768 	} else if (os_strcasecmp(cmd, "disable_sa_query") == 0) {
769 		wpa_s->disable_sa_query = !!atoi(value);
770 	} else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
771 		wpa_s->ignore_sae_h2e_only = !!atoi(value);
772 	} else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
773 		char *pos;
774 
775 		os_free(wpa_s->extra_sae_rejected_groups);
776 		wpa_s->extra_sae_rejected_groups = NULL;
777 		pos = value;
778 		while (pos && pos[0]) {
779 			int group;
780 
781 			group = atoi(pos);
782 			wpa_printf(MSG_DEBUG,
783 				   "TESTING: Extra rejection of SAE group %d",
784 				   group);
785 			if (group)
786 				int_array_add_unique(
787 					&wpa_s->extra_sae_rejected_groups,
788 					group);
789 			pos = os_strchr(pos, ' ');
790 			if (!pos)
791 				break;
792 			pos++;
793 		}
794 	} else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) {
795 		wpa_s->ft_rsnxe_used = atoi(value);
796 	} else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) {
797 		wpa_s->oci_freq_override_eapol = atoi(value);
798 	} else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) {
799 		wpa_s->oci_freq_override_saquery_req = atoi(value);
800 	} else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) {
801 		wpa_s->oci_freq_override_saquery_resp = atoi(value);
802 	} else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) {
803 		wpa_s->oci_freq_override_eapol_g2 = atoi(value);
804 		/* Populate value to wpa_sm if already associated. */
805 		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
806 				 wpa_s->oci_freq_override_eapol_g2);
807 	} else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) {
808 		wpa_s->oci_freq_override_ft_assoc = atoi(value);
809 		/* Populate value to wpa_sm if already associated. */
810 		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
811 				 wpa_s->oci_freq_override_ft_assoc);
812 	} else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) {
813 		wpa_s->oci_freq_override_fils_assoc = atoi(value);
814 	} else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) {
815 		wpa_s->oci_freq_override_wnm_sleep = atoi(value);
816 	} else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) {
817 		wpabuf_free(wpa_s->rsne_override_eapol);
818 		if (os_strcmp(value, "NULL") == 0)
819 			wpa_s->rsne_override_eapol = NULL;
820 		else
821 			wpa_s->rsne_override_eapol = wpabuf_parse_bin(value);
822 	} else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
823 		wpabuf_free(wpa_s->rsnxe_override_assoc);
824 		if (os_strcmp(value, "NULL") == 0)
825 			wpa_s->rsnxe_override_assoc = NULL;
826 		else
827 			wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
828 	} else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
829 		wpabuf_free(wpa_s->rsnxe_override_eapol);
830 		if (os_strcmp(value, "NULL") == 0)
831 			wpa_s->rsnxe_override_eapol = NULL;
832 		else
833 			wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
834 	} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
835 		wpa_s->reject_btm_req_reason = atoi(value);
836 	} else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
837 		os_free(wpa_s->get_pref_freq_list_override);
838 		if (!value[0])
839 			wpa_s->get_pref_freq_list_override = NULL;
840 		else
841 			wpa_s->get_pref_freq_list_override = os_strdup(value);
842 	} else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
843 		wpabuf_free(wpa_s->sae_commit_override);
844 		if (value[0] == '\0')
845 			wpa_s->sae_commit_override = NULL;
846 		else
847 			wpa_s->sae_commit_override = wpabuf_parse_bin(value);
848 	} else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
849 		ret = wpas_ctrl_iface_set_dso(wpa_s, value);
850 	} else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
851 		wpa_s->disable_scs_support = !!atoi(value);
852 	} else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
853 		wpa_s->disable_mscs_support = !!atoi(value);
854 #ifdef CONFIG_DPP
855 	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
856 		os_free(wpa_s->dpp_config_obj_override);
857 		if (value[0] == '\0')
858 			wpa_s->dpp_config_obj_override = NULL;
859 		else
860 			wpa_s->dpp_config_obj_override = os_strdup(value);
861 	} else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
862 		os_free(wpa_s->dpp_discovery_override);
863 		if (value[0] == '\0')
864 			wpa_s->dpp_discovery_override = NULL;
865 		else
866 			wpa_s->dpp_discovery_override = os_strdup(value);
867 	} else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
868 		os_free(wpa_s->dpp_groups_override);
869 		if (value[0] == '\0')
870 			wpa_s->dpp_groups_override = NULL;
871 		else
872 			wpa_s->dpp_groups_override = os_strdup(value);
873 	} else if (os_strcasecmp(cmd,
874 				 "dpp_ignore_netaccesskey_mismatch") == 0) {
875 		wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
876 	} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
877 		dpp_test = atoi(value);
878 #endif /* CONFIG_DPP */
879 #endif /* CONFIG_TESTING_OPTIONS */
880 #ifdef CONFIG_FILS
881 	} else if (os_strcasecmp(cmd, "disable_fils") == 0) {
882 		wpa_s->disable_fils = !!atoi(value);
883 		wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
884 		wpa_supplicant_set_default_scan_ies(wpa_s);
885 #endif /* CONFIG_FILS */
886 #ifndef CONFIG_NO_CONFIG_BLOBS
887 	} else if (os_strcmp(cmd, "blob") == 0) {
888 		ret = wpas_ctrl_set_blob(wpa_s, value);
889 #endif /* CONFIG_NO_CONFIG_BLOBS */
890 	} else if (os_strcasecmp(cmd, "setband") == 0) {
891 		ret = wpas_ctrl_set_band(wpa_s, value);
892 #ifdef CONFIG_MBO
893 	} else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
894 		ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
895 		if (ret == 0) {
896 			value[-1] = '=';
897 			wpa_config_process_global(wpa_s->conf, cmd, -1);
898 		}
899 	} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
900 		wpas_mbo_update_cell_capa(wpa_s, atoi(value));
901 	} else if (os_strcasecmp(cmd, "oce") == 0) {
902 		wpa_s->conf->oce = atoi(value);
903 		if (wpa_s->conf->oce) {
904 			if ((wpa_s->conf->oce & OCE_STA) &&
905 			    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
906 				wpa_s->enable_oce = OCE_STA;
907 
908 			if ((wpa_s->conf->oce & OCE_STA_CFON) &&
909 			    (wpa_s->drv_flags &
910 			     WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
911 				/* TODO: Need to add STA-CFON support */
912 				wpa_printf(MSG_ERROR,
913 					   "OCE STA-CFON feature is not yet supported");
914 				return -1;
915 			}
916 		} else {
917 			wpa_s->enable_oce = 0;
918 		}
919 		wpa_supplicant_set_default_scan_ies(wpa_s);
920 #endif /* CONFIG_MBO */
921 	} else if (os_strcasecmp(cmd, "lci") == 0) {
922 		ret = wpas_ctrl_iface_set_lci(wpa_s, value);
923 	} else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
924 		ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
925 	} else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
926 		ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
927 	} else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
928 		ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
929 	} else if (os_strcasecmp(cmd, "ric_ies") == 0) {
930 		ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
931 	} else if (os_strcasecmp(cmd, "roaming") == 0) {
932 		ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
933 #ifdef CONFIG_WNM
934 	} else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
935 		struct wpabuf *elems;
936 
937 		elems = wpabuf_parse_bin(value);
938 		if (!elems)
939 			return -1;
940 		wnm_set_coloc_intf_elems(wpa_s, elems);
941 #endif /* CONFIG_WNM */
942 	} else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
943 		wpa_s->enable_dscp_policy_capa = !!atoi(value);
944 	} else {
945 		value[-1] = '=';
946 		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
947 		if (ret == 0)
948 			wpa_supplicant_update_config(wpa_s);
949 		else if (ret == 1)
950 			ret = 0;
951 	}
952 
953 	return ret;
954 }
955 
956 
wpa_supplicant_ctrl_iface_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)957 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
958 					 char *cmd, char *buf, size_t buflen)
959 {
960 	int res = -1;
961 
962 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
963 
964 	if (os_strcmp(cmd, "version") == 0) {
965 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
966 	} else if (os_strcasecmp(cmd, "max_command_len") == 0) {
967 		res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN);
968 	} else if (os_strcasecmp(cmd, "country") == 0) {
969 		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
970 			res = os_snprintf(buf, buflen, "%c%c",
971 					  wpa_s->conf->country[0],
972 					  wpa_s->conf->country[1]);
973 #ifdef CONFIG_WIFI_DISPLAY
974 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
975 		int enabled;
976 		if (wpa_s->global->p2p == NULL ||
977 		    wpa_s->global->p2p_disabled)
978 			enabled = 0;
979 		else
980 			enabled = wpa_s->global->wifi_display;
981 		res = os_snprintf(buf, buflen, "%d", enabled);
982 #endif /* CONFIG_WIFI_DISPLAY */
983 #ifdef CONFIG_TESTING_GET_GTK
984 	} else if (os_strcmp(cmd, "gtk") == 0) {
985 		if (wpa_s->last_gtk_len == 0)
986 			return -1;
987 		res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
988 				       wpa_s->last_gtk_len);
989 		return res;
990 #endif /* CONFIG_TESTING_GET_GTK */
991 	} else if (os_strcmp(cmd, "tls_library") == 0) {
992 		res = tls_get_library_version(buf, buflen);
993 #ifdef CONFIG_TESTING_OPTIONS
994 	} else if (os_strcmp(cmd, "anonce") == 0) {
995 		return wpa_snprintf_hex(buf, buflen,
996 					wpa_sm_get_anonce(wpa_s->wpa),
997 					WPA_NONCE_LEN);
998 	} else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
999 		res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
1000 #endif /* CONFIG_TESTING_OPTIONS */
1001 	} else {
1002 		res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
1003 	}
1004 
1005 	if (os_snprintf_error(buflen, res))
1006 		return -1;
1007 	return res;
1008 }
1009 
1010 
1011 #ifdef IEEE8021X_EAPOL
wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant * wpa_s,char * addr)1012 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
1013 					     char *addr)
1014 {
1015 	u8 bssid[ETH_ALEN];
1016 	struct wpa_ssid *ssid = wpa_s->current_ssid;
1017 
1018 	if (hwaddr_aton(addr, bssid)) {
1019 		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
1020 			   "'%s'", addr);
1021 		return -1;
1022 	}
1023 
1024 	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
1025 	rsn_preauth_deinit(wpa_s->wpa);
1026 	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
1027 		return -1;
1028 
1029 	return 0;
1030 }
1031 #endif /* IEEE8021X_EAPOL */
1032 #endif  /* EXT_CODE_CROP */
1033 
1034 #ifdef CONFIG_TDLS
1035 
wpa_supplicant_ctrl_iface_tdls_discover(struct wpa_supplicant * wpa_s,char * addr)1036 static int wpa_supplicant_ctrl_iface_tdls_discover(
1037 	struct wpa_supplicant *wpa_s, char *addr)
1038 {
1039 	u8 peer[ETH_ALEN];
1040 	int ret;
1041 
1042 	if (hwaddr_aton(addr, peer)) {
1043 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
1044 			   "address '%s'", addr);
1045 		return -1;
1046 	}
1047 
1048 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
1049 		   MAC2STR(peer));
1050 
1051 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
1052 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
1053 	else
1054 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
1055 
1056 	return ret;
1057 }
1058 
1059 
wpa_supplicant_ctrl_iface_tdls_setup(struct wpa_supplicant * wpa_s,char * addr)1060 static int wpa_supplicant_ctrl_iface_tdls_setup(
1061 	struct wpa_supplicant *wpa_s, char *addr)
1062 {
1063 	u8 peer[ETH_ALEN];
1064 	int ret;
1065 
1066 	if (hwaddr_aton(addr, peer)) {
1067 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
1068 			   "address '%s'", addr);
1069 		return -1;
1070 	}
1071 
1072 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
1073 		   MAC2STR(peer));
1074 
1075 	if ((wpa_s->conf->tdls_external_control) &&
1076 	    wpa_tdls_is_external_setup(wpa_s->wpa))
1077 		return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1078 
1079 	wpa_tdls_remove(wpa_s->wpa, peer);
1080 
1081 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
1082 		ret = wpa_tdls_start(wpa_s->wpa, peer);
1083 	else
1084 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1085 
1086 	return ret;
1087 }
1088 
1089 
wpa_supplicant_ctrl_iface_tdls_teardown(struct wpa_supplicant * wpa_s,char * addr)1090 static int wpa_supplicant_ctrl_iface_tdls_teardown(
1091 	struct wpa_supplicant *wpa_s, char *addr)
1092 {
1093 	u8 peer[ETH_ALEN];
1094 	int ret;
1095 
1096 	if (os_strcmp(addr, "*") == 0) {
1097 		/* remove everyone */
1098 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
1099 		wpa_tdls_teardown_peers(wpa_s->wpa);
1100 		return 0;
1101 	}
1102 
1103 	if (hwaddr_aton(addr, peer)) {
1104 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
1105 			   "address '%s'", addr);
1106 		return -1;
1107 	}
1108 
1109 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
1110 		   MAC2STR(peer));
1111 
1112 	if ((wpa_s->conf->tdls_external_control) &&
1113 	    wpa_tdls_is_external_setup(wpa_s->wpa))
1114 		return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1115 
1116 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
1117 		ret = wpa_tdls_teardown_link(
1118 			wpa_s->wpa, peer,
1119 			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
1120 	else
1121 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1122 
1123 	return ret;
1124 }
1125 
1126 
ctrl_iface_get_capability_tdls(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1127 static int ctrl_iface_get_capability_tdls(
1128 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1129 {
1130 	int ret;
1131 
1132 	ret = os_snprintf(buf, buflen, "%s\n",
1133 			  wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
1134 			  (wpa_s->drv_flags &
1135 			   WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
1136 			   "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
1137 	if (os_snprintf_error(buflen, ret))
1138 		return -1;
1139 	return ret;
1140 }
1141 
1142 
wpa_supplicant_ctrl_iface_tdls_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1143 static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
1144 	struct wpa_supplicant *wpa_s, char *cmd)
1145 {
1146 	u8 peer[ETH_ALEN];
1147 	struct hostapd_freq_params freq_params;
1148 	u8 oper_class;
1149 	char *pos, *end;
1150 
1151 	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1152 		wpa_printf(MSG_INFO,
1153 			   "tdls_chanswitch: Only supported with external setup");
1154 		return -1;
1155 	}
1156 
1157 	os_memset(&freq_params, 0, sizeof(freq_params));
1158 
1159 	pos = os_strchr(cmd, ' ');
1160 	if (pos == NULL)
1161 		return -1;
1162 	*pos++ = '\0';
1163 
1164 	oper_class = strtol(pos, &end, 10);
1165 	if (pos == end) {
1166 		wpa_printf(MSG_INFO,
1167 			   "tdls_chanswitch: Invalid op class provided");
1168 		return -1;
1169 	}
1170 
1171 	pos = end;
1172 	freq_params.freq = atoi(pos);
1173 	if (freq_params.freq == 0) {
1174 		wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
1175 		return -1;
1176 	}
1177 
1178 #define SET_FREQ_SETTING(str) \
1179 	do { \
1180 		const char *pos2 = os_strstr(pos, " " #str "="); \
1181 		if (pos2) { \
1182 			pos2 += sizeof(" " #str "=") - 1; \
1183 			freq_params.str = atoi(pos2); \
1184 		} \
1185 	} while (0)
1186 
1187 	SET_FREQ_SETTING(center_freq1);
1188 	SET_FREQ_SETTING(center_freq2);
1189 	SET_FREQ_SETTING(bandwidth);
1190 	SET_FREQ_SETTING(sec_channel_offset);
1191 #undef SET_FREQ_SETTING
1192 
1193 	freq_params.ht_enabled = !!os_strstr(pos, " ht");
1194 	freq_params.vht_enabled = !!os_strstr(pos, " vht");
1195 
1196 	if (hwaddr_aton(cmd, peer)) {
1197 		wpa_printf(MSG_DEBUG,
1198 			   "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1199 			   cmd);
1200 		return -1;
1201 	}
1202 
1203 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1204 		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1205 		   MAC2STR(peer), oper_class, freq_params.freq,
1206 		   freq_params.center_freq1, freq_params.center_freq2,
1207 		   freq_params.bandwidth, freq_params.sec_channel_offset,
1208 		   freq_params.ht_enabled ? " HT" : "",
1209 		   freq_params.vht_enabled ? " VHT" : "");
1210 
1211 	return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1212 					   &freq_params);
1213 }
1214 
1215 
wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1216 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1217 	struct wpa_supplicant *wpa_s, char *cmd)
1218 {
1219 	u8 peer[ETH_ALEN];
1220 
1221 	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1222 		wpa_printf(MSG_INFO,
1223 			   "tdls_chanswitch: Only supported with external setup");
1224 		return -1;
1225 	}
1226 
1227 	if (hwaddr_aton(cmd, peer)) {
1228 		wpa_printf(MSG_DEBUG,
1229 			   "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1230 			   cmd);
1231 		return -1;
1232 	}
1233 
1234 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1235 		   MAC2STR(peer));
1236 
1237 	return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1238 }
1239 
1240 
wpa_supplicant_ctrl_iface_tdls_link_status(struct wpa_supplicant * wpa_s,const char * addr,char * buf,size_t buflen)1241 static int wpa_supplicant_ctrl_iface_tdls_link_status(
1242 	struct wpa_supplicant *wpa_s, const char *addr,
1243 	char *buf, size_t buflen)
1244 {
1245 	u8 peer[ETH_ALEN];
1246 	const char *tdls_status;
1247 	int ret;
1248 
1249 	if (hwaddr_aton(addr, peer)) {
1250 		wpa_printf(MSG_DEBUG,
1251 			   "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1252 			   addr);
1253 		return -1;
1254 	}
1255 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1256 		   MAC2STR(peer));
1257 
1258 	tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1259 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1260 	ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1261 	if (os_snprintf_error(buflen, ret))
1262 		return -1;
1263 
1264 	return ret;
1265 }
1266 
1267 #endif /* CONFIG_TDLS */
1268 
1269 #ifdef CONFIG_WMM_AC
wmm_ac_ctrl_addts(struct wpa_supplicant * wpa_s,char * cmd)1270 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1271 {
1272 	char *token, *context = NULL;
1273 	struct wmm_ac_ts_setup_params params = {
1274 		.tsid = 0xff,
1275 		.direction = 0xff,
1276 	};
1277 
1278 	while ((token = str_token(cmd, " ", &context))) {
1279 		if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
1280 		    sscanf(token, "up=%i", &params.user_priority) == 1 ||
1281 		    sscanf(token, "nominal_msdu_size=%i",
1282 			   &params.nominal_msdu_size) == 1 ||
1283 		    sscanf(token, "mean_data_rate=%i",
1284 			   &params.mean_data_rate) == 1 ||
1285 		    sscanf(token, "min_phy_rate=%i",
1286 			   &params.minimum_phy_rate) == 1 ||
1287 		    sscanf(token, "sba=%i",
1288 			   &params.surplus_bandwidth_allowance) == 1)
1289 			continue;
1290 
1291 		if (os_strcasecmp(token, "downlink") == 0) {
1292 			params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1293 		} else if (os_strcasecmp(token, "uplink") == 0) {
1294 			params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1295 		} else if (os_strcasecmp(token, "bidi") == 0) {
1296 			params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1297 		} else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1298 			params.fixed_nominal_msdu = 1;
1299 		} else {
1300 			wpa_printf(MSG_DEBUG,
1301 				   "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1302 				   token);
1303 			return -1;
1304 		}
1305 
1306 	}
1307 
1308 	return wpas_wmm_ac_addts(wpa_s, &params);
1309 }
1310 
1311 
wmm_ac_ctrl_delts(struct wpa_supplicant * wpa_s,char * cmd)1312 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1313 {
1314 	u8 tsid = atoi(cmd);
1315 
1316 	return wpas_wmm_ac_delts(wpa_s, tsid);
1317 }
1318 #endif /* CONFIG_WMM_AC */
1319 
1320 #ifdef CONFIG_IEEE80211R
wpa_supplicant_ctrl_iface_ft_ds(struct wpa_supplicant * wpa_s,char * addr)1321 __attribute__((weak)) int wpa_supplicant_ctrl_iface_ft_ds(
1322 	struct wpa_supplicant *wpa_s, char *addr)
1323 {
1324 	u8 target_ap[ETH_ALEN];
1325 	struct wpa_bss *bss;
1326 	const u8 *mdie;
1327 	int ret;
1328 
1329 	if (hwaddr_aton(addr, target_ap)) {
1330 		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1331 			   "address '%s'", addr);
1332 		return -1;
1333 	}
1334 
1335 	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1336 
1337 	bss = wpa_bss_get_bssid(wpa_s, target_ap);
1338 	if (bss)
1339 		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1340 	else
1341 		mdie = NULL;
1342 
1343 	ret = wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
1344 	os_free_drv_scan_bss(bss);
1345 	return ret;
1346 }
1347 #endif /* CONFIG_IEEE80211R */
1348 
1349 
1350 #ifdef CONFIG_WPS
wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant * wpa_s,char * cmd)1351 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1352 					     char *cmd)
1353 {
1354 	u8 bssid[ETH_ALEN], *_bssid = bssid;
1355 #ifdef CONFIG_P2P
1356 	u8 p2p_dev_addr[ETH_ALEN];
1357 #endif /* CONFIG_P2P */
1358 #ifdef CONFIG_WPS_AP
1359 	u8 *_p2p_dev_addr = NULL;
1360 #endif /* CONFIG_WPS_AP */
1361 #ifdef CONFIG_MULTI_AP
1362 	char *pos;
1363 	int multi_ap = 0;
1364 #endif /* CONFIG_MULTI_AP */
1365 
1366 #ifdef CONFIG_MULTI_AP
1367 	if (!cmd || os_strcmp(cmd, "any") == 0 ||
1368 	    os_strncmp(cmd, "any ", 4) == 0) {
1369 #else
1370 	if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
1371 #endif /* CONFIG_MULTI_AP */
1372 		_bssid = NULL;
1373 #ifdef CONFIG_P2P
1374 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1375 		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1376 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1377 				   "P2P Device Address '%s'",
1378 				   cmd + 13);
1379 			return -1;
1380 		}
1381 		_p2p_dev_addr = p2p_dev_addr;
1382 #endif /* CONFIG_P2P */
1383 #ifdef CONFIG_MULTI_AP
1384 	} else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1385 		_bssid = NULL;
1386 		multi_ap = atoi(cmd + 9);
1387 #endif /* CONFIG_MULTI_AP */
1388 	} else if (hwaddr_aton(cmd, bssid)) {
1389 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1390 			   cmd);
1391 		return -1;
1392 	}
1393 
1394 #ifdef CONFIG_MULTI_AP
1395 	if (cmd) {
1396 		pos = os_strstr(cmd, " multi_ap=");
1397 		if (pos) {
1398 			pos += 10;
1399 			multi_ap = atoi(pos);
1400 		}
1401 	}
1402 #endif /* CONFIG_MULTI_AP */
1403 #ifdef CONFIG_WPS_AP
1404 	if (wpa_s->ap_iface)
1405 		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1406 #endif /* CONFIG_AP */
1407 
1408 #ifdef CONFIG_MULTI_AP
1409 	return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
1410 #else
1411 	return wpas_wps_start_pbc(wpa_s, _bssid, 0, 0);
1412 #endif /* CONFIG_MULTI_AP */
1413 }
1414 
1415 
1416 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1417 					     char *cmd, char *buf,
1418 					     size_t buflen)
1419 {
1420 	u8 bssid[ETH_ALEN], *_bssid = bssid;
1421 	char *pin;
1422 	int ret;
1423 
1424 	pin = os_strchr(cmd, ' ');
1425 	if (pin)
1426 		*pin++ = '\0';
1427 
1428 	if (os_strcmp(cmd, "any") == 0)
1429 		_bssid = NULL;
1430 	else if (os_strcmp(cmd, "get") == 0) {
1431 		if (wps_generate_pin((unsigned int *) &ret) < 0)
1432 			return -1;
1433 		goto done;
1434 	} else if (hwaddr_aton(cmd, bssid)) {
1435 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1436 			   cmd);
1437 		return -1;
1438 	}
1439 
1440 #ifndef LOS_WPS_REG_NON_PBC_CROP
1441 #ifdef CONFIG_WPS_AP
1442 	if (wpa_s->ap_iface) {
1443 		int timeout = 0;
1444 		char *pos;
1445 
1446 		if (pin) {
1447 			pos = os_strchr(pin, ' ');
1448 			if (pos) {
1449 				*pos++ = '\0';
1450 				timeout = atoi(pos);
1451 			}
1452 		}
1453 
1454 		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
1455 						 buf, buflen, timeout);
1456 	}
1457 #endif /* CONFIG_WPS_AP */
1458 #endif /* LOS_WPS_REG_NON_PBC_CROP */
1459 
1460 	if (pin) {
1461 		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1462 					 DEV_PW_DEFAULT);
1463 		if (ret < 0)
1464 			return -1;
1465 #ifndef EXT_CODE_CROP
1466 		ret = os_snprintf(buf, buflen, "%s", pin);
1467 		if (os_snprintf_error(buflen, ret))
1468 			return -1;
1469 #endif /* EXT_CODE_CROP */
1470 		return ret;
1471 	}
1472 
1473 	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1474 	if (ret < 0)
1475 		return -1;
1476 
1477 done:
1478 #ifndef EXT_CODE_CROP
1479 	/* Return the generated PIN */
1480 	ret = os_snprintf(buf, buflen, "%08d", ret);
1481 	if (os_snprintf_error(buflen, ret))
1482 		return -1;
1483 #endif /* EXT_CODE_CROP */
1484 	return ret;
1485 }
1486 
1487 
1488 #ifndef EXT_CODE_CROP
1489 static int wpa_supplicant_ctrl_iface_wps_check_pin(
1490 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1491 {
1492 	char pin[9];
1493 	size_t len;
1494 	char *pos;
1495 	int ret;
1496 
1497 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1498 			      (u8 *) cmd, os_strlen(cmd));
1499 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1500 		if (*pos < '0' || *pos > '9')
1501 			continue;
1502 		pin[len++] = *pos;
1503 		if (len == 9) {
1504 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1505 			return -1;
1506 		}
1507 	}
1508 	if (len != 4 && len != 8) {
1509 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1510 		return -1;
1511 	}
1512 	pin[len] = '\0';
1513 
1514 	if (len == 8) {
1515 		unsigned int pin_val;
1516 		pin_val = atoi(pin);
1517 		if (!wps_pin_valid(pin_val)) {
1518 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1519 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
1520 			if (os_snprintf_error(buflen, ret))
1521 				return -1;
1522 			return ret;
1523 		}
1524 	}
1525 
1526 	ret = os_snprintf(buf, buflen, "%s", pin);
1527 	if (os_snprintf_error(buflen, ret))
1528 		return -1;
1529 
1530 	return ret;
1531 }
1532 
1533 
1534 #ifdef CONFIG_WPS_NFC
1535 
1536 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1537 					     char *cmd)
1538 {
1539 	u8 bssid[ETH_ALEN], *_bssid = bssid;
1540 
1541 	if (cmd == NULL || cmd[0] == '\0')
1542 		_bssid = NULL;
1543 	else if (hwaddr_aton(cmd, bssid))
1544 		return -1;
1545 
1546 	return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1547 				  0, 0);
1548 }
1549 
1550 
1551 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1552 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1553 {
1554 	int ndef;
1555 	struct wpabuf *buf;
1556 	int res;
1557 	char *pos;
1558 
1559 	pos = os_strchr(cmd, ' ');
1560 	if (pos)
1561 		*pos++ = '\0';
1562 	if (os_strcmp(cmd, "WPS") == 0)
1563 		ndef = 0;
1564 	else if (os_strcmp(cmd, "NDEF") == 0)
1565 		ndef = 1;
1566 	else
1567 		return -1;
1568 
1569 	buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
1570 	if (buf == NULL)
1571 		return -1;
1572 
1573 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1574 					 wpabuf_len(buf));
1575 	reply[res++] = '\n';
1576 	reply[res] = '\0';
1577 
1578 	wpabuf_free(buf);
1579 
1580 	return res;
1581 }
1582 
1583 
1584 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1585 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1586 {
1587 	int ndef;
1588 	struct wpabuf *buf;
1589 	int res;
1590 
1591 	if (os_strcmp(cmd, "WPS") == 0)
1592 		ndef = 0;
1593 	else if (os_strcmp(cmd, "NDEF") == 0)
1594 		ndef = 1;
1595 	else
1596 		return -1;
1597 
1598 	buf = wpas_wps_nfc_token(wpa_s, ndef);
1599 	if (buf == NULL)
1600 		return -1;
1601 
1602 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1603 					 wpabuf_len(buf));
1604 	reply[res++] = '\n';
1605 	reply[res] = '\0';
1606 
1607 	wpabuf_free(buf);
1608 
1609 	return res;
1610 }
1611 
1612 
1613 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1614 	struct wpa_supplicant *wpa_s, char *pos)
1615 {
1616 	size_t len;
1617 	struct wpabuf *buf;
1618 	int ret;
1619 	char *freq;
1620 	int forced_freq = 0;
1621 
1622 	freq = strstr(pos, " freq=");
1623 	if (freq) {
1624 		*freq = '\0';
1625 		freq += 6;
1626 		forced_freq = atoi(freq);
1627 	}
1628 
1629 	len = os_strlen(pos);
1630 	if (len & 0x01)
1631 		return -1;
1632 	len /= 2;
1633 
1634 	buf = wpabuf_alloc(len);
1635 	if (buf == NULL)
1636 		return -1;
1637 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1638 		wpabuf_free(buf);
1639 		return -1;
1640 	}
1641 
1642 	ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
1643 	wpabuf_free(buf);
1644 
1645 	return ret;
1646 }
1647 
1648 
1649 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
1650 					      char *reply, size_t max_len,
1651 					      int ndef)
1652 {
1653 	struct wpabuf *buf;
1654 	int res;
1655 
1656 	buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
1657 	if (buf == NULL)
1658 		return -1;
1659 
1660 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1661 					 wpabuf_len(buf));
1662 	reply[res++] = '\n';
1663 	reply[res] = '\0';
1664 
1665 	wpabuf_free(buf);
1666 
1667 	return res;
1668 }
1669 
1670 
1671 #ifdef CONFIG_P2P
1672 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1673 					      char *reply, size_t max_len,
1674 					      int ndef)
1675 {
1676 	struct wpabuf *buf;
1677 	int res;
1678 
1679 	buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1680 	if (buf == NULL) {
1681 		wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1682 		return -1;
1683 	}
1684 
1685 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1686 					 wpabuf_len(buf));
1687 	reply[res++] = '\n';
1688 	reply[res] = '\0';
1689 
1690 	wpabuf_free(buf);
1691 
1692 	return res;
1693 }
1694 #endif /* CONFIG_P2P */
1695 
1696 
1697 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1698 					  char *cmd, char *reply,
1699 					  size_t max_len)
1700 {
1701 	char *pos;
1702 	int ndef;
1703 
1704 	pos = os_strchr(cmd, ' ');
1705 	if (pos == NULL)
1706 		return -1;
1707 	*pos++ = '\0';
1708 
1709 	if (os_strcmp(cmd, "WPS") == 0)
1710 		ndef = 0;
1711 	else if (os_strcmp(cmd, "NDEF") == 0)
1712 		ndef = 1;
1713 	else
1714 		return -1;
1715 
1716 	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1717 		if (!ndef)
1718 			return -1;
1719 		return wpas_ctrl_nfc_get_handover_req_wps(
1720 			wpa_s, reply, max_len, ndef);
1721 	}
1722 
1723 #ifdef CONFIG_P2P
1724 	if (os_strcmp(pos, "P2P-CR") == 0) {
1725 		return wpas_ctrl_nfc_get_handover_req_p2p(
1726 			wpa_s, reply, max_len, ndef);
1727 	}
1728 #endif /* CONFIG_P2P */
1729 
1730 	return -1;
1731 }
1732 
1733 
1734 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1735 					      char *reply, size_t max_len,
1736 					      int ndef, int cr, char *uuid)
1737 {
1738 	struct wpabuf *buf;
1739 	int res;
1740 
1741 	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1742 	if (buf == NULL)
1743 		return -1;
1744 
1745 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1746 					 wpabuf_len(buf));
1747 	reply[res++] = '\n';
1748 	reply[res] = '\0';
1749 
1750 	wpabuf_free(buf);
1751 
1752 	return res;
1753 }
1754 
1755 
1756 #ifdef CONFIG_P2P
1757 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1758 					      char *reply, size_t max_len,
1759 					      int ndef, int tag)
1760 {
1761 	struct wpabuf *buf;
1762 	int res;
1763 
1764 	buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1765 	if (buf == NULL)
1766 		return -1;
1767 
1768 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1769 					 wpabuf_len(buf));
1770 	reply[res++] = '\n';
1771 	reply[res] = '\0';
1772 
1773 	wpabuf_free(buf);
1774 
1775 	return res;
1776 }
1777 #endif /* CONFIG_P2P */
1778 
1779 
1780 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1781 					  char *cmd, char *reply,
1782 					  size_t max_len)
1783 {
1784 	char *pos, *pos2;
1785 	int ndef;
1786 
1787 	pos = os_strchr(cmd, ' ');
1788 	if (pos == NULL)
1789 		return -1;
1790 	*pos++ = '\0';
1791 
1792 	if (os_strcmp(cmd, "WPS") == 0)
1793 		ndef = 0;
1794 	else if (os_strcmp(cmd, "NDEF") == 0)
1795 		ndef = 1;
1796 	else
1797 		return -1;
1798 
1799 	pos2 = os_strchr(pos, ' ');
1800 	if (pos2)
1801 		*pos2++ = '\0';
1802 	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1803 		if (!ndef)
1804 			return -1;
1805 		return wpas_ctrl_nfc_get_handover_sel_wps(
1806 			wpa_s, reply, max_len, ndef,
1807 			os_strcmp(pos, "WPS-CR") == 0, pos2);
1808 	}
1809 
1810 #ifdef CONFIG_P2P
1811 	if (os_strcmp(pos, "P2P-CR") == 0) {
1812 		return wpas_ctrl_nfc_get_handover_sel_p2p(
1813 			wpa_s, reply, max_len, ndef, 0);
1814 	}
1815 
1816 	if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1817 		return wpas_ctrl_nfc_get_handover_sel_p2p(
1818 			wpa_s, reply, max_len, ndef, 1);
1819 	}
1820 #endif /* CONFIG_P2P */
1821 
1822 	return -1;
1823 }
1824 
1825 
1826 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1827 					 char *cmd)
1828 {
1829 	size_t len;
1830 	struct wpabuf *req, *sel;
1831 	int ret;
1832 	char *pos, *role, *type, *pos2;
1833 #ifdef CONFIG_P2P
1834 	char *freq;
1835 	int forced_freq = 0;
1836 
1837 	freq = strstr(cmd, " freq=");
1838 	if (freq) {
1839 		*freq = '\0';
1840 		freq += 6;
1841 		forced_freq = atoi(freq);
1842 	}
1843 #endif /* CONFIG_P2P */
1844 
1845 	role = cmd;
1846 	pos = os_strchr(role, ' ');
1847 	if (pos == NULL) {
1848 		wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1849 		return -1;
1850 	}
1851 	*pos++ = '\0';
1852 
1853 	type = pos;
1854 	pos = os_strchr(type, ' ');
1855 	if (pos == NULL) {
1856 		wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1857 		return -1;
1858 	}
1859 	*pos++ = '\0';
1860 
1861 	pos2 = os_strchr(pos, ' ');
1862 	if (pos2 == NULL) {
1863 		wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1864 		return -1;
1865 	}
1866 	*pos2++ = '\0';
1867 
1868 	len = os_strlen(pos);
1869 	if (len & 0x01) {
1870 		wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1871 		return -1;
1872 	}
1873 	len /= 2;
1874 
1875 	req = wpabuf_alloc(len);
1876 	if (req == NULL) {
1877 		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1878 		return -1;
1879 	}
1880 	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1881 		wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1882 		wpabuf_free(req);
1883 		return -1;
1884 	}
1885 
1886 	len = os_strlen(pos2);
1887 	if (len & 0x01) {
1888 		wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1889 		wpabuf_free(req);
1890 		return -1;
1891 	}
1892 	len /= 2;
1893 
1894 	sel = wpabuf_alloc(len);
1895 	if (sel == NULL) {
1896 		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1897 		wpabuf_free(req);
1898 		return -1;
1899 	}
1900 	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1901 		wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1902 		wpabuf_free(req);
1903 		wpabuf_free(sel);
1904 		return -1;
1905 	}
1906 
1907 	wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1908 		   role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1909 
1910 	if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1911 		ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1912 #ifdef CONFIG_AP
1913 	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1914 	{
1915 		ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1916 		if (ret < 0)
1917 			ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1918 #endif /* CONFIG_AP */
1919 #ifdef CONFIG_P2P
1920 	} else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1921 	{
1922 		ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1923 	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1924 	{
1925 		ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1926 						   forced_freq);
1927 #endif /* CONFIG_P2P */
1928 	} else {
1929 		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1930 			   "reported: role=%s type=%s", role, type);
1931 		ret = -1;
1932 	}
1933 	wpabuf_free(req);
1934 	wpabuf_free(sel);
1935 
1936 	if (ret)
1937 		wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1938 
1939 	return ret;
1940 }
1941 
1942 #endif /* CONFIG_WPS_NFC */
1943 
1944 
1945 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1946 					     char *cmd)
1947 {
1948 	u8 bssid[ETH_ALEN];
1949 	char *pin;
1950 	char *new_ssid;
1951 	char *new_auth;
1952 	char *new_encr;
1953 	char *new_key;
1954 	struct wps_new_ap_settings ap;
1955 
1956 	pin = os_strchr(cmd, ' ');
1957 	if (pin == NULL)
1958 		return -1;
1959 	*pin++ = '\0';
1960 
1961 	if (hwaddr_aton(cmd, bssid)) {
1962 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1963 			   cmd);
1964 		return -1;
1965 	}
1966 
1967 	new_ssid = os_strchr(pin, ' ');
1968 	if (new_ssid == NULL)
1969 		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1970 	*new_ssid++ = '\0';
1971 
1972 	new_auth = os_strchr(new_ssid, ' ');
1973 	if (new_auth == NULL)
1974 		return -1;
1975 	*new_auth++ = '\0';
1976 
1977 	new_encr = os_strchr(new_auth, ' ');
1978 	if (new_encr == NULL)
1979 		return -1;
1980 	*new_encr++ = '\0';
1981 
1982 	new_key = os_strchr(new_encr, ' ');
1983 	if (new_key == NULL)
1984 		return -1;
1985 	*new_key++ = '\0';
1986 
1987 	os_memset(&ap, 0, sizeof(ap));
1988 	ap.ssid_hex = new_ssid;
1989 	ap.auth = new_auth;
1990 	ap.encr = new_encr;
1991 	ap.key_hex = new_key;
1992 	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1993 }
1994 
1995 
1996 #ifdef CONFIG_WPS_AP
1997 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1998 						char *cmd, char *buf,
1999 						size_t buflen)
2000 {
2001 	int timeout = 300;
2002 	char *pos;
2003 	const char *pin_txt;
2004 
2005 	if (!wpa_s->ap_iface)
2006 		return -1;
2007 
2008 	pos = os_strchr(cmd, ' ');
2009 	if (pos)
2010 		*pos++ = '\0';
2011 
2012 	if (os_strcmp(cmd, "disable") == 0) {
2013 		wpas_wps_ap_pin_disable(wpa_s);
2014 		return os_snprintf(buf, buflen, "OK\n");
2015 	}
2016 
2017 	if (os_strcmp(cmd, "random") == 0) {
2018 		if (pos)
2019 			timeout = atoi(pos);
2020 		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
2021 		if (pin_txt == NULL)
2022 			return -1;
2023 		return os_snprintf(buf, buflen, "%s", pin_txt);
2024 	}
2025 
2026 	if (os_strcmp(cmd, "get") == 0) {
2027 		pin_txt = wpas_wps_ap_pin_get(wpa_s);
2028 		if (pin_txt == NULL)
2029 			return -1;
2030 		return os_snprintf(buf, buflen, "%s", pin_txt);
2031 	}
2032 
2033 	if (os_strcmp(cmd, "set") == 0) {
2034 		char *pin;
2035 		if (pos == NULL)
2036 			return -1;
2037 		pin = pos;
2038 		pos = os_strchr(pos, ' ');
2039 		if (pos) {
2040 			*pos++ = '\0';
2041 			timeout = atoi(pos);
2042 		}
2043 		if (os_strlen(pin) > buflen)
2044 			return -1;
2045 		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
2046 			return -1;
2047 		return os_snprintf(buf, buflen, "%s", pin);
2048 	}
2049 
2050 	return -1;
2051 }
2052 #endif /* CONFIG_WPS_AP */
2053 #endif /* EXT_CODE_CROP */
2054 
2055 
2056 #ifdef CONFIG_WPS_ER
2057 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
2058 						char *cmd)
2059 {
2060 	char *uuid = cmd, *pin, *pos;
2061 	u8 addr_buf[ETH_ALEN], *addr = NULL;
2062 	pin = os_strchr(uuid, ' ');
2063 	if (pin == NULL)
2064 		return -1;
2065 	*pin++ = '\0';
2066 	pos = os_strchr(pin, ' ');
2067 	if (pos) {
2068 		*pos++ = '\0';
2069 		if (hwaddr_aton(pos, addr_buf) == 0)
2070 			addr = addr_buf;
2071 	}
2072 	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
2073 }
2074 
2075 
2076 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
2077 						  char *cmd)
2078 {
2079 	char *uuid = cmd, *pin;
2080 	pin = os_strchr(uuid, ' ');
2081 	if (pin == NULL)
2082 		return -1;
2083 	*pin++ = '\0';
2084 	return wpas_wps_er_learn(wpa_s, uuid, pin);
2085 }
2086 
2087 
2088 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
2089 	struct wpa_supplicant *wpa_s, char *cmd)
2090 {
2091 	char *uuid = cmd, *id;
2092 	id = os_strchr(uuid, ' ');
2093 	if (id == NULL)
2094 		return -1;
2095 	*id++ = '\0';
2096 	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
2097 }
2098 
2099 
2100 static int wpa_supplicant_ctrl_iface_wps_er_config(
2101 	struct wpa_supplicant *wpa_s, char *cmd)
2102 {
2103 	char *pin;
2104 	char *new_ssid;
2105 	char *new_auth;
2106 	char *new_encr;
2107 	char *new_key;
2108 	struct wps_new_ap_settings ap;
2109 
2110 	pin = os_strchr(cmd, ' ');
2111 	if (pin == NULL)
2112 		return -1;
2113 	*pin++ = '\0';
2114 
2115 	new_ssid = os_strchr(pin, ' ');
2116 	if (new_ssid == NULL)
2117 		return -1;
2118 	*new_ssid++ = '\0';
2119 
2120 	new_auth = os_strchr(new_ssid, ' ');
2121 	if (new_auth == NULL)
2122 		return -1;
2123 	*new_auth++ = '\0';
2124 
2125 	new_encr = os_strchr(new_auth, ' ');
2126 	if (new_encr == NULL)
2127 		return -1;
2128 	*new_encr++ = '\0';
2129 
2130 	new_key = os_strchr(new_encr, ' ');
2131 	if (new_key == NULL)
2132 		return -1;
2133 	*new_key++ = '\0';
2134 
2135 	os_memset(&ap, 0, sizeof(ap));
2136 	ap.ssid_hex = new_ssid;
2137 	ap.auth = new_auth;
2138 	ap.encr = new_encr;
2139 	ap.key_hex = new_key;
2140 	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
2141 }
2142 
2143 
2144 #ifdef CONFIG_WPS_NFC
2145 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
2146 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2147 {
2148 	int ndef;
2149 	struct wpabuf *buf;
2150 	int res;
2151 	char *uuid;
2152 
2153 	uuid = os_strchr(cmd, ' ');
2154 	if (uuid == NULL)
2155 		return -1;
2156 	*uuid++ = '\0';
2157 
2158 	if (os_strcmp(cmd, "WPS") == 0)
2159 		ndef = 0;
2160 	else if (os_strcmp(cmd, "NDEF") == 0)
2161 		ndef = 1;
2162 	else
2163 		return -1;
2164 
2165 	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
2166 	if (buf == NULL)
2167 		return -1;
2168 
2169 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
2170 					 wpabuf_len(buf));
2171 	reply[res++] = '\n';
2172 	reply[res] = '\0';
2173 
2174 	wpabuf_free(buf);
2175 
2176 	return res;
2177 }
2178 #endif /* CONFIG_WPS_NFC */
2179 #endif /* CONFIG_WPS_ER */
2180 
2181 #endif /* CONFIG_WPS */
2182 
2183 
2184 #ifdef CONFIG_IBSS_RSN
2185 static int wpa_supplicant_ctrl_iface_ibss_rsn(
2186 	struct wpa_supplicant *wpa_s, char *addr)
2187 {
2188 	u8 peer[ETH_ALEN];
2189 
2190 	if (hwaddr_aton(addr, peer)) {
2191 		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
2192 			   "address '%s'", addr);
2193 		return -1;
2194 	}
2195 
2196 	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
2197 		   MAC2STR(peer));
2198 
2199 	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
2200 }
2201 #endif /* CONFIG_IBSS_RSN */
2202 
2203 #ifndef EXT_CODE_CROP
2204 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
2205 					      char *rsp)
2206 {
2207 #ifdef IEEE8021X_EAPOL
2208 	char *pos, *id_pos;
2209 	int id;
2210 	struct wpa_ssid *ssid;
2211 
2212 	pos = os_strchr(rsp, '-');
2213 	if (pos == NULL)
2214 		return -1;
2215 	*pos++ = '\0';
2216 	id_pos = pos;
2217 	pos = os_strchr(pos, ':');
2218 	if (pos == NULL)
2219 		return -1;
2220 	*pos++ = '\0';
2221 	id = atoi(id_pos);
2222 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2223 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2224 			      (u8 *) pos, os_strlen(pos));
2225 
2226 	ssid = wpa_config_get_network(wpa_s->conf, id);
2227 	if (ssid == NULL) {
2228 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2229 			   "to update", id);
2230 		return -1;
2231 	}
2232 
2233 	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2234 							 pos);
2235 #else /* IEEE8021X_EAPOL */
2236 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2237 	return -1;
2238 #endif /* IEEE8021X_EAPOL */
2239 }
2240 
2241 
2242 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2243 					    const char *params,
2244 					    char *buf, size_t buflen)
2245 {
2246 	char *pos, *end, tmp[30];
2247 	int res, verbose, wps, ret;
2248 #ifdef CONFIG_HS20
2249 	const u8 *hs20;
2250 #endif /* CONFIG_HS20 */
2251 	const u8 *sess_id;
2252 	size_t sess_id_len;
2253 
2254 	if (os_strcmp(params, "-DRIVER") == 0)
2255 		return wpa_drv_status(wpa_s, buf, buflen);
2256 	verbose = os_strcmp(params, "-VERBOSE") == 0;
2257 	wps = os_strcmp(params, "-WPS") == 0;
2258 	pos = buf;
2259 	end = buf + buflen;
2260 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2261 		struct wpa_ssid *ssid = wpa_s->current_ssid;
2262 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2263 				  MAC2STR(wpa_s->bssid));
2264 		if (os_snprintf_error(end - pos, ret))
2265 			return pos - buf;
2266 		pos += ret;
2267 		ret = os_snprintf(pos, end - pos, "freq=%u\n",
2268 				  wpa_s->assoc_freq);
2269 		if (os_snprintf_error(end - pos, ret))
2270 			return pos - buf;
2271 		pos += ret;
2272 		if (ssid) {
2273 			u8 *_ssid = ssid->ssid;
2274 			size_t ssid_len = ssid->ssid_len;
2275 			u8 ssid_buf[SSID_MAX_LEN];
2276 			if (ssid_len == 0) {
2277 				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2278 				if (_res < 0)
2279 					ssid_len = 0;
2280 				else
2281 					ssid_len = _res;
2282 				_ssid = ssid_buf;
2283 			}
2284 			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2285 					  wpa_ssid_txt(_ssid, ssid_len),
2286 					  ssid->id);
2287 			if (os_snprintf_error(end - pos, ret))
2288 				return pos - buf;
2289 			pos += ret;
2290 
2291 			if (wps && ssid->passphrase &&
2292 			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2293 			    (ssid->mode == WPAS_MODE_AP ||
2294 			     ssid->mode == WPAS_MODE_P2P_GO)) {
2295 				ret = os_snprintf(pos, end - pos,
2296 						  "passphrase=%s\n",
2297 						  ssid->passphrase);
2298 				if (os_snprintf_error(end - pos, ret))
2299 					return pos - buf;
2300 				pos += ret;
2301 			}
2302 			if (ssid->id_str) {
2303 				ret = os_snprintf(pos, end - pos,
2304 						  "id_str=%s\n",
2305 						  ssid->id_str);
2306 				if (os_snprintf_error(end - pos, ret))
2307 					return pos - buf;
2308 				pos += ret;
2309 			}
2310 
2311 			switch (ssid->mode) {
2312 			case WPAS_MODE_INFRA:
2313 				ret = os_snprintf(pos, end - pos,
2314 						  "mode=station\n");
2315 				break;
2316 			case WPAS_MODE_IBSS:
2317 				ret = os_snprintf(pos, end - pos,
2318 						  "mode=IBSS\n");
2319 				break;
2320 			case WPAS_MODE_AP:
2321 				ret = os_snprintf(pos, end - pos,
2322 						  "mode=AP\n");
2323 				break;
2324 			case WPAS_MODE_P2P_GO:
2325 				ret = os_snprintf(pos, end - pos,
2326 						  "mode=P2P GO\n");
2327 				break;
2328 			case WPAS_MODE_P2P_GROUP_FORMATION:
2329 				ret = os_snprintf(pos, end - pos,
2330 						  "mode=P2P GO - group "
2331 						  "formation\n");
2332 				break;
2333 			case WPAS_MODE_MESH:
2334 				ret = os_snprintf(pos, end - pos,
2335 						  "mode=mesh\n");
2336 				break;
2337 			default:
2338 				ret = 0;
2339 				break;
2340 			}
2341 			if (os_snprintf_error(end - pos, ret))
2342 				return pos - buf;
2343 			pos += ret;
2344 		}
2345 
2346 		if (wpa_s->connection_set &&
2347 		    (wpa_s->connection_ht || wpa_s->connection_vht ||
2348 		     wpa_s->connection_he)) {
2349 			ret = os_snprintf(pos, end - pos,
2350 					  "wifi_generation=%u\n",
2351 					  wpa_s->connection_he ? 6 :
2352 					  (wpa_s->connection_vht ? 5 : 4));
2353 			if (os_snprintf_error(end - pos, ret))
2354 				return pos - buf;
2355 			pos += ret;
2356 		}
2357 
2358 #ifdef CONFIG_AP
2359 		if (wpa_s->ap_iface) {
2360 			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2361 							    end - pos,
2362 							    verbose);
2363 		} else
2364 #endif /* CONFIG_AP */
2365 		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2366 	}
2367 #ifdef CONFIG_SME
2368 #ifdef CONFIG_SAE
2369 	if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
2370 #ifdef CONFIG_AP
2371 	    !wpa_s->ap_iface &&
2372 #endif /* CONFIG_AP */
2373 	    wpa_s->sme.sae.state == SAE_ACCEPTED) {
2374 		ret = os_snprintf(pos, end - pos, "sae_group=%d\n"
2375 				  "sae_h2e=%d\n"
2376 				  "sae_pk=%d\n",
2377 				  wpa_s->sme.sae.group,
2378 				  wpa_s->sme.sae.h2e,
2379 				  wpa_s->sme.sae.pk);
2380 		if (os_snprintf_error(end - pos, ret))
2381 			return pos - buf;
2382 		pos += ret;
2383 	}
2384 #endif /* CONFIG_SAE */
2385 #endif /* CONFIG_SME */
2386 	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2387 			  wpa_supplicant_state_txt(wpa_s->wpa_state));
2388 	if (os_snprintf_error(end - pos, ret))
2389 		return pos - buf;
2390 	pos += ret;
2391 
2392 	if (wpa_s->l2 &&
2393 	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2394 		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
2395 		if (os_snprintf_error(end - pos, ret))
2396 			return pos - buf;
2397 		pos += ret;
2398 	}
2399 
2400 #ifdef CONFIG_P2P
2401 	if (wpa_s->global->p2p) {
2402 		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2403 				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
2404 		if (os_snprintf_error(end - pos, ret))
2405 			return pos - buf;
2406 		pos += ret;
2407 	}
2408 #endif /* CONFIG_P2P */
2409 
2410 	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2411 			  MAC2STR(wpa_s->own_addr));
2412 	if (os_snprintf_error(end - pos, ret))
2413 		return pos - buf;
2414 	pos += ret;
2415 
2416 #ifdef CONFIG_HS20
2417 	if (wpa_s->current_bss &&
2418 	    (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2419 					  HS20_IE_VENDOR_TYPE)) &&
2420 	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
2421 	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2422 		int release = 1;
2423 		if (hs20[1] >= 5) {
2424 			u8 rel_num = (hs20[6] & 0xf0) >> 4;
2425 			release = rel_num + 1;
2426 		}
2427 		ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
2428 		if (os_snprintf_error(end - pos, ret))
2429 			return pos - buf;
2430 		pos += ret;
2431 	}
2432 
2433 	if (wpa_s->current_ssid) {
2434 		struct wpa_cred *cred;
2435 		char *type;
2436 
2437 		for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
2438 			size_t i;
2439 
2440 			if (wpa_s->current_ssid->parent_cred != cred)
2441 				continue;
2442 
2443 			if (cred->provisioning_sp) {
2444 				ret = os_snprintf(pos, end - pos,
2445 						  "provisioning_sp=%s\n",
2446 						  cred->provisioning_sp);
2447 				if (os_snprintf_error(end - pos, ret))
2448 					return pos - buf;
2449 				pos += ret;
2450 			}
2451 
2452 			if (!cred->domain)
2453 				goto no_domain;
2454 
2455 			i = 0;
2456 			if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2457 				struct wpabuf *names =
2458 					wpa_s->current_bss->anqp->domain_name;
2459 				for (i = 0; names && i < cred->num_domain; i++)
2460 				{
2461 					if (domain_name_list_contains(
2462 						    names, cred->domain[i], 1))
2463 						break;
2464 				}
2465 				if (i == cred->num_domain)
2466 					i = 0; /* show first entry by default */
2467 			}
2468 			ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2469 					  cred->domain[i]);
2470 			if (os_snprintf_error(end - pos, ret))
2471 				return pos - buf;
2472 			pos += ret;
2473 
2474 		no_domain:
2475 			if (wpa_s->current_bss == NULL ||
2476 			    wpa_s->current_bss->anqp == NULL)
2477 				res = -1;
2478 			else
2479 				res = interworking_home_sp_cred(
2480 					wpa_s, cred,
2481 					wpa_s->current_bss->anqp->domain_name);
2482 			if (res > 0)
2483 				type = "home";
2484 			else if (res == 0)
2485 				type = "roaming";
2486 			else
2487 				type = "unknown";
2488 
2489 			ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
2490 			if (os_snprintf_error(end - pos, ret))
2491 				return pos - buf;
2492 			pos += ret;
2493 
2494 			break;
2495 		}
2496 	}
2497 #endif /* CONFIG_HS20 */
2498 
2499 	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2500 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2501 		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2502 					  verbose);
2503 		if (res >= 0)
2504 			pos += res;
2505 	}
2506 
2507 #ifdef CONFIG_MACSEC
2508 	res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2509 	if (res > 0)
2510 		pos += res;
2511 #endif /* CONFIG_MACSEC */
2512 
2513 	sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2514 	if (sess_id) {
2515 		char *start = pos;
2516 
2517 		ret = os_snprintf(pos, end - pos, "eap_session_id=");
2518 		if (os_snprintf_error(end - pos, ret))
2519 			return start - buf;
2520 		pos += ret;
2521 		ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2522 		if (ret <= 0)
2523 			return start - buf;
2524 		pos += ret;
2525 		ret = os_snprintf(pos, end - pos, "\n");
2526 		if (os_snprintf_error(end - pos, ret))
2527 			return start - buf;
2528 		pos += ret;
2529 	}
2530 
2531 	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2532 	if (res >= 0)
2533 		pos += res;
2534 
2535 #ifdef CONFIG_WPS
2536 	{
2537 		char uuid_str[100];
2538 		uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2539 		ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
2540 		if (os_snprintf_error(end - pos, ret))
2541 			return pos - buf;
2542 		pos += ret;
2543 	}
2544 #endif /* CONFIG_WPS */
2545 
2546 	if (wpa_s->ieee80211ac) {
2547 		ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2548 		if (os_snprintf_error(end - pos, ret))
2549 			return pos - buf;
2550 		pos += ret;
2551 	}
2552 
2553 #ifdef ANDROID
2554 	/*
2555 	 * Allow using the STATUS command with default behavior, say for debug,
2556 	 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2557 	 * events with STATUS-NO_EVENTS.
2558 	 */
2559 	if (os_strcmp(params, "-NO_EVENTS")) {
2560 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2561 			     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2562 			     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2563 			     wpa_s->wpa_state,
2564 			     MAC2STR(wpa_s->bssid),
2565 			     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2566 			     wpa_ssid_txt(wpa_s->current_ssid->ssid,
2567 					  wpa_s->current_ssid->ssid_len) : "");
2568 		if (wpa_s->wpa_state == WPA_COMPLETED) {
2569 			struct wpa_ssid *ssid = wpa_s->current_ssid;
2570 			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2571 				     "- connection to " MACSTR
2572 				     " completed %s [id=%d id_str=%s]",
2573 				     MAC2STR(wpa_s->bssid), "(auth)",
2574 				     ssid ? ssid->id : -1,
2575 				     ssid && ssid->id_str ? ssid->id_str : "");
2576 		}
2577 	}
2578 #endif /* ANDROID */
2579 
2580 	return pos - buf;
2581 }
2582 #else
2583 #ifdef LOS_CONFIG_P2P
2584 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2585 					    const char *params,
2586 					    char *buf, size_t buflen)
2587 {
2588 	(void) params;
2589 	(void) buf;
2590 	(void) buflen;
2591 	int fail = 0;
2592 	unsigned int int_save;
2593 
2594 	os_task_lock(&int_save);
2595 	if (wpa_s == NULL || g_p2p_status_buf == NULL) {
2596 		os_task_unlock(int_save);
2597 		(void)os_event_write(g_p2p_event, WPA_EVENT_P2P_GET_STATUS_ERROR);
2598 		return -1;
2599 	}
2600 	g_p2p_status_buf->mode =EXT_WIFI_P2P_DEVICE_ONLY;
2601 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2602 		if (wpa_s->current_ssid == NULL) {
2603 			os_task_unlock(int_save);
2604 			(void)os_event_write(g_p2p_event, WPA_EVENT_P2P_GET_STATUS_ERROR);
2605 			return -1;
2606 		}
2607 		if (wpa_s->current_ssid->ssid_len)
2608 			(void)os_memcpy(g_p2p_status_buf->ssid, wpa_s->current_ssid->ssid, wpa_s->current_ssid->ssid_len);
2609 
2610 		(void)os_memcpy(g_p2p_status_buf->bssid, wpa_s->bssid, ETH_ALEN);
2611 		g_p2p_status_buf->op_freq = wpa_s->assoc_freq;
2612 		if (wpa_s->current_ssid->mode == WPAS_MODE_INFRA)
2613 			g_p2p_status_buf->mode = EXT_WIFI_P2P_MODE_GC;
2614 		else if (wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
2615 			g_p2p_status_buf->mode = EXT_WIFI_P2P_MODE_GO;
2616 		else
2617 			g_p2p_status_buf->mode = EXT_WIFI_P2P_DEVICE_ONLY;
2618 	}
2619 
2620 	if (wpa_s->wpa_state < WPA_AUTHENTICATING)
2621 		g_p2p_status_buf->p2p_state = EXT_WIFI_P2P_DISCONNECTED;
2622 	else if ((wpa_s->wpa_state >= WPA_AUTHENTICATING) && (wpa_s->wpa_state < WPA_COMPLETED))
2623 		g_p2p_status_buf->p2p_state = EXT_WIFI_P2P_CONNECTING;
2624 	else if (wpa_s->wpa_state == WPA_COMPLETED)
2625 		g_p2p_status_buf->p2p_state = EXT_WIFI_P2P_CONNECTED;
2626 	else
2627 		fail = 1;
2628 	g_p2p_status_buf = NULL;
2629 	os_task_unlock(int_save);
2630 
2631 	if (fail != 0)
2632 		(void)os_event_write(g_p2p_event, WPA_EVENT_P2P_GET_STATUS_ERROR);
2633 	else
2634 		(void)os_event_write(g_p2p_event, WPA_EVENT_P2P_GET_STATUS_OK);
2635 
2636 	return 0;
2637 }
2638 #endif /* LOS_CONFIG_P2P */
2639 
2640 #endif /* EXT_CODE_CROP */
2641 
2642 
2643 #ifndef EXT_CODE_CROP
2644 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2645 					   char *cmd)
2646 {
2647 	char *pos;
2648 	int id;
2649 	struct wpa_ssid *ssid;
2650 	u8 bssid[ETH_ALEN];
2651 
2652 	/* cmd: "<network id> <BSSID>" */
2653 	pos = os_strchr(cmd, ' ');
2654 	if (pos == NULL)
2655 		return -1;
2656 	*pos++ = '\0';
2657 	id = atoi(cmd);
2658 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2659 	if (hwaddr_aton(pos, bssid)) {
2660 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2661 		return -1;
2662 	}
2663 
2664 	ssid = wpa_config_get_network(wpa_s->conf, id);
2665 	if (ssid == NULL) {
2666 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2667 			   "to update", id);
2668 		return -1;
2669 	}
2670 
2671 	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2672 	ssid->bssid_set = !is_zero_ether_addr(bssid);
2673 
2674 	return 0;
2675 }
2676 
2677 
2678 static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
2679 						  char *cmd, char *buf,
2680 						  size_t buflen)
2681 {
2682 	u8 bssid[ETH_ALEN];
2683 	struct wpa_bssid_ignore *e;
2684 	char *pos, *end;
2685 	int ret;
2686 
2687 	/* cmd: "BSSID_IGNORE [<BSSID>]" */
2688 	if (*cmd == '\0') {
2689 		pos = buf;
2690 		end = buf + buflen;
2691 		e = wpa_s->bssid_ignore;
2692 		while (e) {
2693 			ret = os_snprintf(pos, end - pos, MACSTR "\n",
2694 					  MAC2STR(e->bssid));
2695 			if (os_snprintf_error(end - pos, ret))
2696 				return pos - buf;
2697 			pos += ret;
2698 			e = e->next;
2699 		}
2700 		return pos - buf;
2701 	}
2702 
2703 	cmd++;
2704 	if (os_strncmp(cmd, "clear", 5) == 0) {
2705 		wpa_bssid_ignore_clear(wpa_s);
2706 		os_memcpy(buf, "OK\n", 3);
2707 		return 3;
2708 	}
2709 
2710 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
2711 	if (hwaddr_aton(cmd, bssid)) {
2712 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
2713 		return -1;
2714 	}
2715 
2716 	/*
2717 	 * Add the BSSID twice, so its count will be 2, causing it to be
2718 	 * skipped when processing scan results.
2719 	 */
2720 	ret = wpa_bssid_ignore_add(wpa_s, bssid);
2721 	if (ret < 0)
2722 		return -1;
2723 	ret = wpa_bssid_ignore_add(wpa_s, bssid);
2724 	if (ret < 0)
2725 		return -1;
2726 	os_memcpy(buf, "OK\n", 3);
2727 	return 3;
2728 }
2729 #endif /* EXT_CODE_CROP */
2730 
2731 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2732 					       char *cmd, char *buf,
2733 					       size_t buflen)
2734 {
2735 	char *pos, *end, *stamp;
2736 	int ret;
2737 
2738 	/* cmd: "LOG_LEVEL [<level>]" */
2739 	if (*cmd == '\0') {
2740 		pos = buf;
2741 		end = buf + buflen;
2742 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2743 				  "Timestamp: %d\n",
2744 				  debug_level_str(wpa_debug_level),
2745 				  wpa_debug_timestamp);
2746 		if (os_snprintf_error(end - pos, ret))
2747 			ret = 0;
2748 
2749 		return ret;
2750 	}
2751 
2752 	while (*cmd == ' ')
2753 		cmd++;
2754 
2755 	stamp = os_strchr(cmd, ' ');
2756 	if (stamp) {
2757 		*stamp++ = '\0';
2758 		while (*stamp == ' ') {
2759 			stamp++;
2760 		}
2761 	}
2762 
2763 	if (os_strlen(cmd)) {
2764 		int level = str_to_debug_level(cmd);
2765 		if (level < 0)
2766 			return -1;
2767 		wpa_debug_level = level;
2768 	}
2769 
2770 	if (stamp && os_strlen(stamp))
2771 		wpa_debug_timestamp = atoi(stamp);
2772 
2773 	os_memcpy(buf, "OK\n", 3);
2774 	return 3;
2775 }
2776 
2777 #ifndef EXT_CODE_CROP
2778 static int wpa_supplicant_ctrl_iface_list_networks(
2779 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2780 {
2781 	char *pos, *end, *prev;
2782 	struct wpa_ssid *ssid;
2783 	int ret;
2784 
2785 	pos = buf;
2786 	end = buf + buflen;
2787 	ret = os_snprintf(pos, end - pos,
2788 			  "network id / ssid / bssid / flags\n");
2789 	if (os_snprintf_error(end - pos, ret))
2790 		return pos - buf;
2791 	pos += ret;
2792 
2793 	ssid = wpa_s->conf->ssid;
2794 
2795 	/* skip over ssids until we find next one */
2796 	if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2797 		int last_id = atoi(cmd + 8);
2798 		if (last_id != -1) {
2799 			while (ssid != NULL && ssid->id <= last_id) {
2800 				ssid = ssid->next;
2801 			}
2802 		}
2803 	}
2804 
2805 	while (ssid) {
2806 		prev = pos;
2807 		ret = os_snprintf(pos, end - pos, "%d\t%s",
2808 				  ssid->id,
2809 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2810 		if (os_snprintf_error(end - pos, ret))
2811 			return prev - buf;
2812 		pos += ret;
2813 		if (ssid->bssid_set) {
2814 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2815 					  MAC2STR(ssid->bssid));
2816 		} else {
2817 			ret = os_snprintf(pos, end - pos, "\tany");
2818 		}
2819 		if (os_snprintf_error(end - pos, ret))
2820 			return prev - buf;
2821 		pos += ret;
2822 		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2823 				  ssid == wpa_s->current_ssid ?
2824 				  "[CURRENT]" : "",
2825 				  ssid->disabled ? "[DISABLED]" : "",
2826 				  ssid->disabled_until.sec ?
2827 				  "[TEMP-DISABLED]" : "",
2828 				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2829 				  "");
2830 		if (os_snprintf_error(end - pos, ret))
2831 			return prev - buf;
2832 		pos += ret;
2833 		ret = os_snprintf(pos, end - pos, "\n");
2834 		if (os_snprintf_error(end - pos, ret))
2835 			return prev - buf;
2836 		pos += ret;
2837 
2838 		ssid = ssid->next;
2839 	}
2840 
2841 	return pos - buf;
2842 }
2843 #else
2844 #ifdef LOS_CONFIG_P2P
2845 static int wpa_supplicant_ctrl_iface_list_networks(struct wpa_supplicant *wpa_s)
2846 {
2847 	struct wpa_ssid *ssid = NULL;
2848 	int i = 0;
2849 
2850 	if ((wpa_s == NULL) || (wpa_s->conf == NULL) ||
2851 	    (g_persistent_group_num == 0) || (g_p2p_persistent_group == NULL))
2852 		return -1;
2853 
2854 	g_persistent_group_num = WPA_MIN(g_persistent_group_num, P2P_MAX_PERSISTENT_CNT);
2855 	ssid = wpa_s->conf->ssid;
2856 	while (ssid) {
2857 		/* 2: this network block includes parameters for a persistent P2P */
2858 		if (ssid->disabled == 2) {
2859 			g_p2p_persistent_group[i].network_id = ssid->id;
2860 			os_memcpy(g_p2p_persistent_group[i].network_name, ssid->ssid, ssid->ssid_len);
2861 			if (ssid->bssid_set)
2862 				os_memcpy(g_p2p_persistent_group[i].go_bssid, ssid->bssid, ETH_ALEN);
2863 			i++;
2864 		}
2865 		if ((unsigned int)i == g_persistent_group_num)
2866 			return 0;
2867 
2868 		ssid = ssid->next;
2869 	}
2870 	g_persistent_group_num = (unsigned int)i;
2871 	g_p2p_persistent_group = NULL;
2872 
2873 	return 0;
2874 }
2875 #endif /* LOS_CONFIG_P2P */
2876 #endif /* EXT_CODE_CROP */
2877 
2878 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2879 {
2880 	int ret;
2881 	ret = os_snprintf(pos, end - pos, "-");
2882 	if (os_snprintf_error(end - pos, ret))
2883 		return pos;
2884 	pos += ret;
2885 	ret = wpa_write_ciphers(pos, end, cipher, "+");
2886 	if (ret < 0)
2887 		return pos;
2888 	pos += ret;
2889 	return pos;
2890 }
2891 
2892 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2893 				    const u8 *ie, size_t ie_len)
2894 {
2895 	struct wpa_ie_data data;
2896 	char *start;
2897 	int ret;
2898 
2899 	ret = os_snprintf(pos, end - pos, "[%s-", proto);
2900 	if (os_snprintf_error(end - pos, ret))
2901 		return pos;
2902 	pos += ret;
2903 
2904 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2905 		ret = os_snprintf(pos, end - pos, "?]");
2906 		if (os_snprintf_error(end - pos, ret))
2907 			return pos;
2908 		pos += ret;
2909 		return pos;
2910 	}
2911 
2912 	start = pos;
2913 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2914 		ret = os_snprintf(pos, end - pos, "%sEAP",
2915 				  pos == start ? "" : "+");
2916 		if (os_snprintf_error(end - pos, ret))
2917 			return pos;
2918 		pos += ret;
2919 	}
2920 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2921 		ret = os_snprintf(pos, end - pos, "%sPSK",
2922 				  pos == start ? "" : "+");
2923 		if (os_snprintf_error(end - pos, ret))
2924 			return pos;
2925 		pos += ret;
2926 	}
2927 #ifndef EXT_WPA_KEY_MGMT_CROP
2928 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2929 		ret = os_snprintf(pos, end - pos, "%sNone",
2930 				  pos == start ? "" : "+");
2931 		if (os_snprintf_error(end - pos, ret))
2932 			return pos;
2933 		pos += ret;
2934 	}
2935 #endif /* EXT_WPA_KEY_MGMT_CROP */
2936 	if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2937 		ret = os_snprintf(pos, end - pos, "%sSAE",
2938 				  pos == start ? "" : "+");
2939 		if (os_snprintf_error(end - pos, ret))
2940 			return pos;
2941 		pos += ret;
2942 	}
2943 #ifdef CONFIG_IEEE80211R
2944 	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2945 		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2946 				  pos == start ? "" : "+");
2947 		if (os_snprintf_error(end - pos, ret))
2948 			return pos;
2949 		pos += ret;
2950 	}
2951 	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2952 		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2953 				  pos == start ? "" : "+");
2954 		if (os_snprintf_error(end - pos, ret))
2955 			return pos;
2956 		pos += ret;
2957 	}
2958 	if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2959 		ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2960 				  pos == start ? "" : "+");
2961 		if (os_snprintf_error(end - pos, ret))
2962 			return pos;
2963 		pos += ret;
2964 	}
2965 #endif /* CONFIG_IEEE80211R */
2966 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2967 		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2968 				  pos == start ? "" : "+");
2969 		if (os_snprintf_error(end - pos, ret))
2970 			return pos;
2971 		pos += ret;
2972 	}
2973 	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2974 		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2975 				  pos == start ? "" : "+");
2976 		if (os_snprintf_error(end - pos, ret))
2977 			return pos;
2978 		pos += ret;
2979 	}
2980 
2981 #ifdef CONFIG_SUITEB
2982 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2983 		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2984 				  pos == start ? "" : "+");
2985 		if (os_snprintf_error(end - pos, ret))
2986 			return pos;
2987 		pos += ret;
2988 	}
2989 #endif /* CONFIG_SUITEB */
2990 
2991 #ifdef CONFIG_SUITEB192
2992 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2993 		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2994 				  pos == start ? "" : "+");
2995 		if (os_snprintf_error(end - pos, ret))
2996 			return pos;
2997 		pos += ret;
2998 	}
2999 #endif /* CONFIG_SUITEB192 */
3000 
3001 #ifdef CONFIG_FILS
3002 	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
3003 		ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
3004 				  pos == start ? "" : "+");
3005 		if (os_snprintf_error(end - pos, ret))
3006 			return pos;
3007 		pos += ret;
3008 	}
3009 	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
3010 		ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
3011 				  pos == start ? "" : "+");
3012 		if (os_snprintf_error(end - pos, ret))
3013 			return pos;
3014 		pos += ret;
3015 	}
3016 #ifdef CONFIG_IEEE80211R
3017 	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
3018 		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
3019 				  pos == start ? "" : "+");
3020 		if (os_snprintf_error(end - pos, ret))
3021 			return pos;
3022 		pos += ret;
3023 	}
3024 	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
3025 		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
3026 				  pos == start ? "" : "+");
3027 		if (os_snprintf_error(end - pos, ret))
3028 			return pos;
3029 		pos += ret;
3030 	}
3031 #endif /* CONFIG_IEEE80211R */
3032 #endif /* CONFIG_FILS */
3033 
3034 #ifdef CONFIG_OWE
3035 	if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
3036 		ret = os_snprintf(pos, end - pos, "%sOWE",
3037 				  pos == start ? "" : "+");
3038 		if (os_snprintf_error(end - pos, ret))
3039 			return pos;
3040 		pos += ret;
3041 	}
3042 #endif /* CONFIG_OWE */
3043 
3044 #ifdef CONFIG_DPP
3045 	if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
3046 		ret = os_snprintf(pos, end - pos, "%sDPP",
3047 				  pos == start ? "" : "+");
3048 		if (os_snprintf_error(end - pos, ret))
3049 			return pos;
3050 		pos += ret;
3051 	}
3052 #endif /* CONFIG_DPP */
3053 
3054 	if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
3055 		ret = os_snprintf(pos, end - pos, "%sOSEN",
3056 				  pos == start ? "" : "+");
3057 		if (os_snprintf_error(end - pos, ret))
3058 			return pos;
3059 		pos += ret;
3060 	}
3061 
3062 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
3063 #ifndef EXT_WPA_KEY_MGMT_CROP
3064 	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
3065 		ret = os_snprintf(pos, end - pos, "-preauth");
3066 		if (os_snprintf_error(end - pos, ret))
3067 			return pos;
3068 		pos += ret;
3069 	}
3070 #endif /* EXT_WPA_KEY_MGMT_CROP */
3071 	ret = os_snprintf(pos, end - pos, "]");
3072 	if (os_snprintf_error(end - pos, ret))
3073 		return pos;
3074 	pos += ret;
3075 
3076 	return pos;
3077 }
3078 
3079 
3080 #ifdef CONFIG_WPS
3081 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
3082 					    char *pos, char *end,
3083 					    struct wpabuf *wps_ie)
3084 {
3085 	int ret;
3086 	const char *txt;
3087 
3088 	if (wps_ie == NULL)
3089 		return pos;
3090 	if (wps_is_selected_pbc_registrar(wps_ie))
3091 		txt = "[WPS-PBC]";
3092 	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
3093 		txt = "[WPS-AUTH]";
3094 	else if (wps_is_selected_pin_registrar(wps_ie))
3095 		txt = "[WPS-PIN]";
3096 	else
3097 		txt = "[WPS]";
3098 
3099 	ret = os_snprintf(pos, end - pos, "%s", txt);
3100 	if (!os_snprintf_error(end - pos, ret))
3101 		pos += ret;
3102 	wpabuf_free(wps_ie);
3103 	return pos;
3104 }
3105 #endif /* CONFIG_WPS */
3106 
3107 
3108 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
3109 					char *pos, char *end,
3110 					const struct wpa_bss *bss)
3111 {
3112 #ifdef CONFIG_WPS
3113 	struct wpabuf *wps_ie;
3114 	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
3115 	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
3116 #else /* CONFIG_WPS */
3117 	return pos;
3118 #endif /* CONFIG_WPS */
3119 }
3120 
3121 
3122 /* Format one result on one text line into a buffer. */
3123 static int wpa_supplicant_ctrl_iface_scan_result(
3124 	struct wpa_supplicant *wpa_s,
3125 	const struct wpa_bss *bss, char *buf, size_t buflen)
3126 {
3127 	char *pos, *end;
3128 	int ret;
3129 	const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe;
3130 
3131 #ifdef CONFIG_WAPI
3132 	const u8 *ie3;
3133 #endif /* CONFIG_WAPI */
3134 #ifdef LOS_WPA_PATCH
3135 	const u8 *wmm_ie;
3136 	char tmp_ssid[SSID_MAX_LEN + 1] = {0};
3137 #endif /* LOS_WPA_PATCH */
3138 	mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
3139 	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
3140 	if (!p2p)
3141 		p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
3142 	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
3143 	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
3144 	    0)
3145 		return 0; /* Do not show P2P listen discovery results here */
3146 
3147 	pos = buf;
3148 	end = buf + buflen;
3149 
3150 	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
3151 			  MAC2STR(bss->bssid), bss->freq, bss->level);
3152 	if (os_snprintf_error(end - pos, ret))
3153 		return -1;
3154 	pos += ret;
3155 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3156 	if (ie)
3157 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
3158 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3159 	if (ie2) {
3160 		pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
3161 					    ie2, 2 + ie2[1]);
3162 	}
3163 #ifdef LOS_WPA_PATCH
3164 	wmm_ie = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
3165 	if (wmm_ie)
3166 		pos = wpa_supplicant_ie_txt(pos, end, "WMM", wmm_ie, 2 + wmm_ie[1]);
3167 #endif /* LOS_WPA_PATCH */
3168 #ifdef CONFIG_WAPI
3169 	ie3 = wpa_bss_get_ie(bss, WLAN_EID_WAPI);
3170 	if (ie3)
3171 		pos = wpa_supplicant_wapi_ie_txt(pos, end, ie3, 2 + ie3[1]);
3172 #endif /* CONFIG_WAPI */
3173 	rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
3174 	if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
3175 		ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
3176 		if (os_snprintf_error(end - pos, ret))
3177 			return -1;
3178 		pos += ret;
3179 	}
3180 	if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
3181 		ret = os_snprintf(pos, end - pos, "[SAE-PK]");
3182 		if (os_snprintf_error(end - pos, ret))
3183 			return -1;
3184 		pos += ret;
3185 	}
3186 	osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
3187 	if (osen_ie)
3188 		pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
3189 					    osen_ie, 2 + osen_ie[1]);
3190 	owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3191 	if (owe) {
3192 		ret = os_snprintf(pos, end - pos,
3193 				  ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
3194 		if (os_snprintf_error(end - pos, ret))
3195 			return -1;
3196 		pos += ret;
3197 	}
3198 #ifdef CONFIG_WPS
3199 	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3200 #endif /* CONFIG_WPS */
3201 	if (!ie && !ie2 && !osen_ie &&
3202 #ifdef CONFIG_WAPI
3203 	!ie3 &&
3204 #endif /* CONFIG_WAPI */
3205     (bss->caps & IEEE80211_CAP_PRIVACY)) {
3206 		ret = os_snprintf(pos, end - pos, "[WEP]");
3207 		if (os_snprintf_error(end - pos, ret))
3208 			return -1;
3209 		pos += ret;
3210 	}
3211 #ifdef LOS_WPA_PATCH
3212 	if (!(bss->caps & IEEE80211_CAP_PRIVACY)) {
3213 		ret = os_snprintf(pos, end - pos, "[OPEN]");
3214 		if (os_snprintf_error(end - pos, ret))
3215 			return -1;
3216 		pos += ret;
3217 	}
3218 #endif /* LOS_WPA_PATCH */
3219 	if (mesh) {
3220 		ret = os_snprintf(pos, end - pos, "[MESH]");
3221 		if (os_snprintf_error(end - pos, ret))
3222 			return -1;
3223 		pos += ret;
3224 	}
3225 	if (bss_is_dmg(bss)) {
3226 		const char *s;
3227 
3228 		if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
3229 			ret = os_snprintf(pos, end - pos, "[EDMG]");
3230 			if (os_snprintf_error(end - pos, ret))
3231 				return -1;
3232 			pos += ret;
3233 		}
3234 
3235 		ret = os_snprintf(pos, end - pos, "[DMG]");
3236 		if (os_snprintf_error(end - pos, ret))
3237 			return -1;
3238 		pos += ret;
3239 		switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
3240 		case IEEE80211_CAP_DMG_IBSS:
3241 			s = "[IBSS]";
3242 			break;
3243 		case IEEE80211_CAP_DMG_AP:
3244 			s = "[ESS]";
3245 			break;
3246 		case IEEE80211_CAP_DMG_PBSS:
3247 			s = "[PBSS]";
3248 			break;
3249 		default:
3250 			s = "";
3251 			break;
3252 		}
3253 		ret = os_snprintf(pos, end - pos, "%s", s);
3254 		if (os_snprintf_error(end - pos, ret))
3255 			return -1;
3256 		pos += ret;
3257 	} else {
3258 		if (bss->caps & IEEE80211_CAP_IBSS) {
3259 			ret = os_snprintf(pos, end - pos, "[IBSS]");
3260 			if (os_snprintf_error(end - pos, ret))
3261 				return -1;
3262 			pos += ret;
3263 		}
3264 		if (bss->caps & IEEE80211_CAP_ESS) {
3265 			ret = os_snprintf(pos, end - pos, "[ESS]");
3266 			if (os_snprintf_error(end - pos, ret))
3267 				return -1;
3268 			pos += ret;
3269 		}
3270 	}
3271 	if (p2p) {
3272 		ret = os_snprintf(pos, end - pos, "[P2P]");
3273 		if (os_snprintf_error(end - pos, ret))
3274 			return -1;
3275 		pos += ret;
3276 	}
3277 #ifdef CONFIG_HS20
3278 	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
3279 		ret = os_snprintf(pos, end - pos, "[HS20]");
3280 		if (os_snprintf_error(end - pos, ret))
3281 			return -1;
3282 		pos += ret;
3283 	}
3284 #endif /* CONFIG_HS20 */
3285 #ifdef CONFIG_FILS
3286 	if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
3287 		ret = os_snprintf(pos, end - pos, "[FILS]");
3288 		if (os_snprintf_error(end - pos, ret))
3289 			return -1;
3290 		pos += ret;
3291 	}
3292 #endif /* CONFIG_FILS */
3293 #ifdef CONFIG_FST
3294 	if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
3295 		ret = os_snprintf(pos, end - pos, "[FST]");
3296 		if (os_snprintf_error(end - pos, ret))
3297 			return -1;
3298 		pos += ret;
3299 	}
3300 #endif /* CONFIG_FST */
3301 #ifndef EXT_CODE_CROP
3302 	if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
3303 		ret = os_snprintf(pos, end - pos, "[UTF-8]");
3304 		if (os_snprintf_error(end - pos, ret))
3305 			return -1;
3306 		pos += ret;
3307 	}
3308 #endif /* EXT_CODE_CROP */
3309 
3310 #ifndef EXT_CODE_CROP
3311 	ret = os_snprintf(pos, end - pos, "\t%s",
3312 			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
3313 #else
3314 	os_memcpy(tmp_ssid, bss->ssid, bss->ssid_len);
3315 	ret = os_snprintf(pos, end - pos, "\t%s",
3316 			  tmp_ssid);
3317 #endif
3318 	if (os_snprintf_error(end - pos, ret))
3319 		return -1;
3320 	pos += ret;
3321 
3322 	ret = os_snprintf(pos, end - pos, "\n");
3323 	if (os_snprintf_error(end - pos, ret))
3324 		return -1;
3325 	pos += ret;
3326 
3327 	return pos - buf;
3328 }
3329 
3330 
3331 static int wpa_supplicant_ctrl_iface_scan_results(
3332 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3333 {
3334 	char *pos, *end;
3335 	struct wpa_bss *bss;
3336 	int ret;
3337 
3338 	pos = buf;
3339 	end = buf + buflen;
3340 	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
3341 			  "flags / ssid\n");
3342 	if (os_snprintf_error(end - pos, ret))
3343 		return pos - buf;
3344 	pos += ret;
3345 
3346 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3347 		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
3348 							    end - pos);
3349 		if (ret < 0 || ret >= end - pos)
3350 			return pos - buf;
3351 		pos += ret;
3352 	}
3353 
3354 	return pos - buf;
3355 }
3356 
3357 
3358 #ifdef CONFIG_MESH
3359 
3360 static int wpa_supplicant_ctrl_iface_mesh_interface_add(
3361 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
3362 {
3363 	char *pos, ifname[IFNAMSIZ + 1];
3364 
3365 	ifname[0] = '\0';
3366 
3367 	pos = os_strstr(cmd, "ifname=");
3368 	if (pos) {
3369 		pos += 7;
3370 		os_strlcpy(ifname, pos, sizeof(ifname));
3371 	}
3372 
3373 	if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3374 		return -1;
3375 
3376 	os_strlcpy(reply, ifname, max_len);
3377 	return os_strlen(ifname);
3378 }
3379 
3380 
3381 static int wpa_supplicant_ctrl_iface_mesh_group_add(
3382 	struct wpa_supplicant *wpa_s, char *cmd)
3383 {
3384 	int id;
3385 	struct wpa_ssid *ssid;
3386 
3387 	id = atoi(cmd);
3388 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3389 
3390 	ssid = wpa_config_get_network(wpa_s->conf, id);
3391 	if (ssid == NULL) {
3392 		wpa_printf(MSG_DEBUG,
3393 			   "CTRL_IFACE: Could not find network id=%d", id);
3394 		return -1;
3395 	}
3396 	if (ssid->mode != WPAS_MODE_MESH) {
3397 		wpa_printf(MSG_DEBUG,
3398 			   "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3399 		return -1;
3400 	}
3401 	if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
3402 	    ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
3403 		wpa_printf(MSG_ERROR,
3404 			   "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3405 		return -1;
3406 	}
3407 
3408 	/*
3409 	 * TODO: If necessary write our own group_add function,
3410 	 * for now we can reuse select_network
3411 	 */
3412 	wpa_supplicant_select_network(wpa_s, ssid);
3413 
3414 	return 0;
3415 }
3416 
3417 
3418 static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3419 	struct wpa_supplicant *wpa_s, char *cmd)
3420 {
3421 	struct wpa_supplicant *orig;
3422 	struct wpa_global *global;
3423 	int found = 0;
3424 
3425 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3426 
3427 	global = wpa_s->global;
3428 	orig = wpa_s;
3429 
3430 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3431 		if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3432 			found = 1;
3433 			break;
3434 		}
3435 	}
3436 	if (!found) {
3437 		wpa_printf(MSG_ERROR,
3438 			   "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3439 			   cmd);
3440 		return -1;
3441 	}
3442 	if (wpa_s->mesh_if_created && wpa_s == orig) {
3443 		wpa_printf(MSG_ERROR,
3444 			   "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3445 		return -1;
3446 	}
3447 
3448 	wpa_s->reassociate = 0;
3449 	wpa_s->disconnected = 1;
3450 	wpa_supplicant_cancel_sched_scan(wpa_s);
3451 	wpa_supplicant_cancel_scan(wpa_s);
3452 
3453 	/*
3454 	 * TODO: If necessary write our own group_remove function,
3455 	 * for now we can reuse deauthenticate
3456 	 */
3457 	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3458 
3459 	if (wpa_s->mesh_if_created)
3460 		wpa_supplicant_remove_iface(global, wpa_s, 0);
3461 
3462 	return 0;
3463 }
3464 
3465 
3466 static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3467 	struct wpa_supplicant *wpa_s, char *cmd)
3468 {
3469 	u8 addr[ETH_ALEN];
3470 
3471 	if (hwaddr_aton(cmd, addr) < 0)
3472 		return -1;
3473 
3474 	return wpas_mesh_peer_remove(wpa_s, addr);
3475 }
3476 
3477 
3478 static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3479 	struct wpa_supplicant *wpa_s, char *cmd)
3480 {
3481 	u8 addr[ETH_ALEN];
3482 	int duration;
3483 	char *pos;
3484 
3485 	pos = os_strstr(cmd, " duration=");
3486 	if (pos) {
3487 		*pos = '\0';
3488 		duration = atoi(pos + 10);
3489 	} else {
3490 		duration = -1;
3491 	}
3492 
3493 	if (hwaddr_aton(cmd, addr))
3494 		return -1;
3495 
3496 	return wpas_mesh_peer_add(wpa_s, addr, duration);
3497 }
3498 
3499 
3500 static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3501 	struct wpa_supplicant *wpa_s, char *cmd)
3502 {
3503 	struct ether_header *eth;
3504 	u8 addr[ETH_ALEN];
3505 	u8 *buf;
3506 	char *pos;
3507 	size_t payload_len = 0, len;
3508 	int ret = -1;
3509 
3510 	if (hwaddr_aton(cmd, addr))
3511 		return -1;
3512 
3513 	pos = os_strstr(cmd, " payload=");
3514 	if (pos) {
3515 		pos = pos + 9;
3516 		payload_len = os_strlen(pos);
3517 		if (payload_len & 1)
3518 			return -1;
3519 
3520 		payload_len /= 2;
3521 	}
3522 
3523 	len = ETH_HLEN + payload_len;
3524 	buf = os_malloc(len);
3525 	if (!buf)
3526 		return -1;
3527 
3528 	eth = (struct ether_header *) buf;
3529 	os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3530 	os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3531 	eth->ether_type = htons(ETH_P_802_3);
3532 
3533 	if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3534 		goto fail;
3535 
3536 	ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3537 fail:
3538 	os_free(buf);
3539 	return -ret;
3540 }
3541 
3542 #endif /* CONFIG_MESH */
3543 
3544 
3545 static int wpa_supplicant_ctrl_iface_select_network(
3546 	struct wpa_supplicant *wpa_s, char *cmd)
3547 {
3548 	int id;
3549 	struct wpa_ssid *ssid;
3550 	char *pos;
3551 
3552 	/* cmd: "<network id>" or "any" */
3553 	if (os_strncmp(cmd, "any", 3) == 0) {
3554 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3555 		ssid = NULL;
3556 	} else {
3557 		id = atoi(cmd);
3558 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3559 
3560 		ssid = wpa_config_get_network(wpa_s->conf, id);
3561 		if (ssid == NULL) {
3562 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3563 				   "network id=%d", id);
3564 			return -1;
3565 		}
3566 		if (ssid->disabled == 2) {
3567 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3568 				   "SELECT_NETWORK with persistent P2P group");
3569 			return -1;
3570 		}
3571 	}
3572 
3573 	pos = os_strstr(cmd, " freq=");
3574 	if (pos) {
3575 		int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3576 		if (freqs) {
3577 			os_free(wpa_s->select_network_scan_freqs);
3578 			wpa_s->select_network_scan_freqs = freqs;
3579 		}
3580 	}
3581 #ifdef LOS_WPA_PATCH
3582 	if (ssid && (wpa_is_sta(wpa_s) == WPA_FLAG_ON))
3583 		g_connecting_ssid = ssid;
3584 #endif /* LOS_WPA_PATCH */
3585 
3586 	wpa_s->scan_min_time.sec = 0;
3587 	wpa_s->scan_min_time.usec = 0;
3588 	wpa_supplicant_select_network(wpa_s, ssid);
3589 
3590 	return 0;
3591 }
3592 
3593 #ifndef EXT_CODE_CROP
3594 static int wpa_supplicant_ctrl_iface_enable_network(
3595 	struct wpa_supplicant *wpa_s, char *cmd)
3596 {
3597 	int id;
3598 	struct wpa_ssid *ssid;
3599 
3600 	/* cmd: "<network id>" or "all" */
3601 	if (os_strcmp(cmd, "all") == 0) {
3602 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3603 		ssid = NULL;
3604 	} else {
3605 		id = atoi(cmd);
3606 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3607 
3608 		ssid = wpa_config_get_network(wpa_s->conf, id);
3609 		if (ssid == NULL) {
3610 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3611 				   "network id=%d", id);
3612 			return -1;
3613 		}
3614 		if (ssid->disabled == 2) {
3615 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3616 				   "ENABLE_NETWORK with persistent P2P group");
3617 			return -1;
3618 		}
3619 
3620 		if (os_strstr(cmd, " no-connect")) {
3621 			ssid->disabled = 0;
3622 			return 0;
3623 		}
3624 	}
3625 	wpa_s->scan_min_time.sec = 0;
3626 	wpa_s->scan_min_time.usec = 0;
3627 	wpa_supplicant_enable_network(wpa_s, ssid);
3628 
3629 	return 0;
3630 }
3631 
3632 
3633 static int wpa_supplicant_ctrl_iface_disable_network(
3634 	struct wpa_supplicant *wpa_s, char *cmd)
3635 {
3636 	int id;
3637 	struct wpa_ssid *ssid;
3638 
3639 	/* cmd: "<network id>" or "all" */
3640 	if (os_strcmp(cmd, "all") == 0) {
3641 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3642 		ssid = NULL;
3643 	} else {
3644 		id = atoi(cmd);
3645 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3646 
3647 		ssid = wpa_config_get_network(wpa_s->conf, id);
3648 		if (ssid == NULL) {
3649 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3650 				   "network id=%d", id);
3651 			return -1;
3652 		}
3653 		if (ssid->disabled == 2) {
3654 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3655 				   "DISABLE_NETWORK with persistent P2P "
3656 				   "group");
3657 			return -1;
3658 		}
3659 	}
3660 	wpa_supplicant_disable_network(wpa_s, ssid);
3661 
3662 	return 0;
3663 }
3664 #endif /* EXT_CODE_CROP */
3665 
3666 static int wpa_supplicant_ctrl_iface_add_network(
3667 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3668 {
3669 	struct wpa_ssid *ssid = NULL;
3670 #ifdef LOS_WPA_PATCH
3671 	struct ext_wifi_dev *wifi_dev = NULL;
3672 	int ret = 0;
3673 #endif /* LOS_WPA_PATCH */
3674 	wpa_warning_log0(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3675 #ifdef LOS_WPA_PATCH
3676 	wifi_dev = los_get_wifi_dev_by_name(wpa_s->ifname);
3677 	if (wifi_dev == NULL)
3678 		return -1;
3679 #endif /* LOS_WPA_PATCH */
3680 	ssid = wpa_supplicant_add_network(wpa_s);
3681 	if (ssid == NULL)
3682 		return -1;
3683 #ifdef LOS_WPA_PATCH
3684 	ssid->id = wifi_dev->network_id;
3685 #endif /* LOS_WPA_PATCH */
3686 #ifndef EXT_CODE_CROP
3687 	wpa_error_log1(MSG_ERROR, "wpa_supplicant_ctrl_iface_add_network: add network id : %d\n", ssid->id);
3688 	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
3689 	if (os_snprintf_error(buflen, ret))
3690 		return -1;
3691 #else
3692 	(void)buf;
3693 #endif /* EXT_CODE_CROP */
3694 	return ret;
3695 }
3696 
3697 
3698 static int wpa_supplicant_ctrl_iface_remove_network(
3699 	struct wpa_supplicant *wpa_s, char *cmd)
3700 {
3701 	int id;
3702 	int result;
3703 
3704 	/* cmd: "<network id>" or "all" */
3705 	if (os_strcmp(cmd, "all") == 0) {
3706 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
3707 		return wpa_supplicant_remove_all_networks(wpa_s);
3708 	}
3709 
3710 	id = atoi(cmd);
3711 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3712 
3713 	result = wpa_supplicant_remove_network(wpa_s, id);
3714 	if (result == -1) {
3715 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3716 			   "id=%d", id);
3717 		return -1;
3718 	}
3719 	if (result == -2) {
3720 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3721 			   "network id=%d", id);
3722 		return -1;
3723 	}
3724 	return 0;
3725 }
3726 
3727 
3728 static int wpa_supplicant_ctrl_iface_update_network(
3729 	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3730 	char *name, char *value)
3731 {
3732 	int ret;
3733 #ifdef LOS_WPA_PATCH
3734 	if (os_strcmp(name, "ssid") == 0) {
3735 		if (los_wpa_ssid_config_set(ssid, name, value) == EXT_WIFI_OK)
3736 			goto SSID_SET;
3737 		else
3738 			return -1;
3739 	}
3740 	/* just for fast connect set psk without password */
3741 	if ((os_strcmp(name, "set_psk") == 0) && (strtol(value, NULL, 10) != 0)) {
3742 		wpa_config_update_psk(ssid);
3743 		return 0;
3744 	}
3745 #endif /* LOS_WPA_PATCH */
3746 	ret = wpa_config_set(ssid, name, value, 0);
3747 	if (ret < 0) {
3748 #ifndef CONFIG_PRINT_NOUSE
3749 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3750 			   "variable '%s'", name);
3751 #endif
3752 		return -1;
3753 	}
3754 	if (ret == 1)
3755 		return 0; /* No change to the previously configured value */
3756 
3757 #ifdef CONFIG_BGSCAN
3758 	if (os_strcmp(name, "bgscan") == 0) {
3759 		/*
3760 		 * Reset the bgscan parameters for the current network and
3761 		 * return. There's no need to flush caches for bgscan parameter
3762 		 * changes.
3763 		 */
3764 		if (wpa_s->current_ssid == ssid &&
3765 		    wpa_s->wpa_state == WPA_COMPLETED)
3766 			wpa_supplicant_reset_bgscan(wpa_s);
3767 		return 0;
3768 	}
3769 #endif /* CONFIG_BGSCAN */
3770 
3771 	if (os_strcmp(name, "bssid") != 0 &&
3772 #ifndef EXT_CODE_CROP
3773 	    os_strcmp(name, "bssid_hint") != 0 &&
3774 #endif /* EXT_CODE_CROP */
3775 	    os_strcmp(name, "priority") != 0) {
3776 #ifndef EXT_CODE_CROP
3777 		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3778 #endif /* EXT_CODE_CROP */
3779 		if (wpa_s->current_ssid == ssid ||
3780 		    wpa_s->current_ssid == NULL) {
3781 			/*
3782 			 * Invalidate the EAP session cache if anything in the
3783 			 * current or previously used configuration changes.
3784 			 */
3785 			eapol_sm_invalidate_cached_session(wpa_s->eapol);
3786 		}
3787 	}
3788 #ifdef LOS_WPA_PATCH
3789 SSID_SET:
3790 #endif /* LOS_WPA_PATCH */
3791 	if ((os_strcmp(name, "psk") == 0 &&
3792 	     value[0] == '"' && ssid->ssid_len) ||
3793 	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3794 		wpa_config_update_psk(ssid);
3795 #ifndef EXT_CODE_CROP
3796 	else if (os_strcmp(name, "priority") == 0)
3797 		wpa_config_update_prio_list(wpa_s->conf);
3798 #endif /* EXT_CODE_CROP */
3799 
3800 	return 0;
3801 }
3802 
3803 
3804 static int wpa_supplicant_ctrl_iface_set_network(
3805 	struct wpa_supplicant *wpa_s, char *cmd)
3806 {
3807 	int id, ret, prev_bssid_set, prev_disabled;
3808 	struct wpa_ssid *ssid;
3809 	char *name, *value;
3810 	u8 prev_bssid[ETH_ALEN];
3811 
3812 	/* cmd: "<network id> <variable name> <value>" */
3813 	name = os_strchr(cmd, ' ');
3814 	if (name == NULL)
3815 		return -1;
3816 	*name++ = '\0';
3817 
3818 	value = os_strchr(name, ' ');
3819 	if (value == NULL)
3820 		return -1;
3821 	*value++ = '\0';
3822 
3823 	id = atoi(cmd);
3824 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3825 		   id, name);
3826 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3827 			      (u8 *) value, os_strlen(value));
3828 
3829 	ssid = wpa_config_get_network(wpa_s->conf, id);
3830 	if (ssid == NULL) {
3831 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3832 			   "id=%d", id);
3833 		return -1;
3834 	}
3835 
3836 	prev_bssid_set = ssid->bssid_set;
3837 	prev_disabled = ssid->disabled;
3838 	os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3839 	ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3840 						       value);
3841 #ifndef EXT_CODE_CROP
3842 	if (ret == 0 &&
3843 	    (ssid->bssid_set != prev_bssid_set ||
3844 	     os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
3845 		wpas_notify_network_bssid_set_changed(wpa_s, ssid);
3846 
3847 	if (prev_disabled != ssid->disabled &&
3848 	    (prev_disabled == 2 || ssid->disabled == 2))
3849 		wpas_notify_network_type_changed(wpa_s, ssid);
3850 #endif /* EXT_CODE_CROP */
3851 	return ret;
3852 }
3853 
3854 #ifndef EXT_CODE_CROP
3855 static int wpa_supplicant_ctrl_iface_get_network(
3856 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3857 {
3858 	int id;
3859 	size_t res;
3860 	struct wpa_ssid *ssid;
3861 	char *name, *value;
3862 
3863 	/* cmd: "<network id> <variable name>" */
3864 	name = os_strchr(cmd, ' ');
3865 	if (name == NULL || buflen == 0)
3866 		return -1;
3867 	*name++ = '\0';
3868 
3869 	id = atoi(cmd);
3870 	wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
3871 		   id, name);
3872 
3873 	ssid = wpa_config_get_network(wpa_s->conf, id);
3874 	if (ssid == NULL) {
3875 		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
3876 			   "id=%d", id);
3877 		return -1;
3878 	}
3879 
3880 	value = wpa_config_get_no_key(ssid, name);
3881 	if (value == NULL) {
3882 		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
3883 			   "variable '%s'", name);
3884 		return -1;
3885 	}
3886 
3887 	res = os_strlcpy(buf, value, buflen);
3888 	if (res >= buflen) {
3889 		os_free(value);
3890 		return -1;
3891 	}
3892 
3893 	os_free(value);
3894 
3895 	return res;
3896 }
3897 
3898 
3899 static int wpa_supplicant_ctrl_iface_dup_network(
3900 	struct wpa_supplicant *wpa_s, char *cmd,
3901 	struct wpa_supplicant *dst_wpa_s)
3902 {
3903 	struct wpa_ssid *ssid_s, *ssid_d;
3904 	char *name, *id, *value;
3905 	int id_s, id_d, ret;
3906 
3907 	/* cmd: "<src network id> <dst network id> <variable name>" */
3908 	id = os_strchr(cmd, ' ');
3909 	if (id == NULL)
3910 		return -1;
3911 	*id++ = '\0';
3912 
3913 	name = os_strchr(id, ' ');
3914 	if (name == NULL)
3915 		return -1;
3916 	*name++ = '\0';
3917 
3918 	id_s = atoi(cmd);
3919 	id_d = atoi(id);
3920 
3921 	wpa_printf(MSG_DEBUG,
3922 		   "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3923 		   wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
3924 
3925 	ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3926 	if (ssid_s == NULL) {
3927 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3928 			   "network id=%d", id_s);
3929 		return -1;
3930 	}
3931 
3932 	ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
3933 	if (ssid_d == NULL) {
3934 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3935 			   "network id=%d", id_d);
3936 		return -1;
3937 	}
3938 
3939 	value = wpa_config_get(ssid_s, name);
3940 	if (value == NULL) {
3941 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3942 			   "variable '%s'", name);
3943 		return -1;
3944 	}
3945 
3946 	ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
3947 						       value);
3948 
3949 	os_free(value);
3950 
3951 	return ret;
3952 }
3953 
3954 
3955 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3956 						char *buf, size_t buflen)
3957 {
3958 	char *pos, *end;
3959 	struct wpa_cred *cred;
3960 	int ret;
3961 
3962 	pos = buf;
3963 	end = buf + buflen;
3964 	ret = os_snprintf(pos, end - pos,
3965 			  "cred id / realm / username / domain / imsi\n");
3966 	if (os_snprintf_error(end - pos, ret))
3967 		return pos - buf;
3968 	pos += ret;
3969 
3970 	cred = wpa_s->conf->cred;
3971 	while (cred) {
3972 		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3973 				  cred->id, cred->realm ? cred->realm : "",
3974 				  cred->username ? cred->username : "",
3975 				  cred->domain ? cred->domain[0] : "",
3976 				  cred->imsi ? cred->imsi : "");
3977 		if (os_snprintf_error(end - pos, ret))
3978 			return pos - buf;
3979 		pos += ret;
3980 
3981 		cred = cred->next;
3982 	}
3983 
3984 	return pos - buf;
3985 }
3986 
3987 
3988 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3989 					      char *buf, size_t buflen)
3990 {
3991 	struct wpa_cred *cred;
3992 	int ret;
3993 
3994 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3995 
3996 	cred = wpa_config_add_cred(wpa_s->conf);
3997 	if (cred == NULL)
3998 		return -1;
3999 
4000 	wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
4001 
4002 	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
4003 	if (os_snprintf_error(buflen, ret))
4004 		return -1;
4005 	return ret;
4006 }
4007 
4008 
4009 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
4010 						 char *cmd)
4011 {
4012 	int id;
4013 	struct wpa_cred *cred, *prev;
4014 
4015 	/* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
4016 	 * "provisioning_sp=<FQDN> */
4017 	if (os_strcmp(cmd, "all") == 0) {
4018 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
4019 		return wpas_remove_all_creds(wpa_s);
4020 	}
4021 
4022 	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
4023 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
4024 			   cmd + 8);
4025 		cred = wpa_s->conf->cred;
4026 		while (cred) {
4027 			prev = cred;
4028 			cred = cred->next;
4029 			if (prev->domain) {
4030 				size_t i;
4031 				for (i = 0; i < prev->num_domain; i++) {
4032 					if (os_strcmp(prev->domain[i], cmd + 8)
4033 					    != 0)
4034 						continue;
4035 					wpas_remove_cred(wpa_s, prev);
4036 					break;
4037 				}
4038 			}
4039 		}
4040 		return 0;
4041 	}
4042 
4043 	if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
4044 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
4045 			   cmd + 16);
4046 		cred = wpa_s->conf->cred;
4047 		while (cred) {
4048 			prev = cred;
4049 			cred = cred->next;
4050 			if (prev->provisioning_sp &&
4051 			    os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
4052 				wpas_remove_cred(wpa_s, prev);
4053 		}
4054 		return 0;
4055 	}
4056 
4057 	id = atoi(cmd);
4058 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
4059 
4060 	cred = wpa_config_get_cred(wpa_s->conf, id);
4061 	return wpas_remove_cred(wpa_s, cred);
4062 }
4063 
4064 
4065 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
4066 					      char *cmd)
4067 {
4068 	int id;
4069 	struct wpa_cred *cred;
4070 	char *name, *value;
4071 
4072 	/* cmd: "<cred id> <variable name> <value>" */
4073 	name = os_strchr(cmd, ' ');
4074 	if (name == NULL)
4075 		return -1;
4076 	*name++ = '\0';
4077 
4078 	value = os_strchr(name, ' ');
4079 	if (value == NULL)
4080 		return -1;
4081 	*value++ = '\0';
4082 
4083 	id = atoi(cmd);
4084 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
4085 		   id, name);
4086 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
4087 			      (u8 *) value, os_strlen(value));
4088 
4089 	cred = wpa_config_get_cred(wpa_s->conf, id);
4090 	if (cred == NULL) {
4091 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
4092 			   id);
4093 		return -1;
4094 	}
4095 
4096 	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
4097 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
4098 			   "variable '%s'", name);
4099 		return -1;
4100 	}
4101 
4102 	wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
4103 
4104 	return 0;
4105 }
4106 
4107 
4108 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
4109 					      char *cmd, char *buf,
4110 					      size_t buflen)
4111 {
4112 	int id;
4113 	size_t res;
4114 	struct wpa_cred *cred;
4115 	char *name, *value;
4116 
4117 	/* cmd: "<cred id> <variable name>" */
4118 	name = os_strchr(cmd, ' ');
4119 	if (name == NULL)
4120 		return -1;
4121 	*name++ = '\0';
4122 
4123 	id = atoi(cmd);
4124 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
4125 		   id, name);
4126 
4127 	cred = wpa_config_get_cred(wpa_s->conf, id);
4128 	if (cred == NULL) {
4129 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
4130 			   id);
4131 		return -1;
4132 	}
4133 
4134 	value = wpa_config_get_cred_no_key(cred, name);
4135 	if (value == NULL) {
4136 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
4137 			   name);
4138 		return -1;
4139 	}
4140 
4141 	res = os_strlcpy(buf, value, buflen);
4142 	if (res >= buflen) {
4143 		os_free(value);
4144 		return -1;
4145 	}
4146 
4147 	os_free(value);
4148 
4149 	return res;
4150 }
4151 
4152 
4153 #ifndef CONFIG_NO_CONFIG_WRITE
4154 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
4155 {
4156 	int ret;
4157 
4158 	if (!wpa_s->conf->update_config) {
4159 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
4160 			   "to update configuration (update_config=0)");
4161 		return -1;
4162 	}
4163 
4164 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
4165 	if (ret) {
4166 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
4167 			   "update configuration");
4168 	} else {
4169 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
4170 			   " updated");
4171 	}
4172 
4173 	return ret;
4174 }
4175 #endif /* CONFIG_NO_CONFIG_WRITE */
4176 
4177 
4178 struct cipher_info {
4179 	unsigned int capa;
4180 	const char *name;
4181 	int group_only;
4182 };
4183 
4184 static const struct cipher_info ciphers[] = {
4185 	{ WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
4186 	{ WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
4187 	{ WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
4188 	{ WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
4189 #ifndef CONFIG_NO_TKIP
4190 	{ WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
4191 #endif /* CONFIG_NO_TKIP */
4192 	{ WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
4193 #ifdef CONFIG_WEP
4194 	{ WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
4195 	{ WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
4196 #endif /* CONFIG_WEP */
4197 };
4198 
4199 static const struct cipher_info ciphers_group_mgmt[] = {
4200 	{ WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
4201 	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
4202 	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
4203 	{ WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
4204 };
4205 
4206 
4207 static int ctrl_iface_get_capability_pairwise(int res, bool strict,
4208 					      struct wpa_driver_capa *capa,
4209 					      char *buf, size_t buflen)
4210 {
4211 	int ret;
4212 	char *pos, *end;
4213 	size_t len;
4214 	unsigned int i;
4215 
4216 	pos = buf;
4217 	end = pos + buflen;
4218 
4219 	if (res < 0) {
4220 		if (strict)
4221 			return 0;
4222 #ifdef CONFIG_NO_TKIP
4223 		len = os_strlcpy(buf, "CCMP NONE", buflen);
4224 #else /* CONFIG_NO_TKIP */
4225 		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
4226 #endif /* CONFIG_NO_TKIP */
4227 		if (len >= buflen)
4228 			return -1;
4229 		return len;
4230 	}
4231 
4232 	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4233 		if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
4234 			ret = os_snprintf(pos, end - pos, "%s%s",
4235 					  pos == buf ? "" : " ",
4236 					  ciphers[i].name);
4237 			if (os_snprintf_error(end - pos, ret))
4238 				return pos - buf;
4239 			pos += ret;
4240 		}
4241 	}
4242 
4243 	return pos - buf;
4244 }
4245 
4246 
4247 static int ctrl_iface_get_capability_group(int res, bool strict,
4248 					   struct wpa_driver_capa *capa,
4249 					   char *buf, size_t buflen)
4250 {
4251 	int ret;
4252 	char *pos, *end;
4253 	size_t len;
4254 	unsigned int i;
4255 
4256 	pos = buf;
4257 	end = pos + buflen;
4258 
4259 	if (res < 0) {
4260 		if (strict)
4261 			return 0;
4262 #ifdef CONFIG_WEP
4263 #ifdef CONFIG_NO_TKIP
4264 		len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen);
4265 #else /* CONFIG_NO_TKIP */
4266 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
4267 #endif /* CONFIG_NO_TKIP */
4268 #else /* CONFIG_WEP */
4269 #ifdef CONFIG_NO_TKIP
4270 		len = os_strlcpy(buf, "CCMP", buflen);
4271 #else /* CONFIG_NO_TKIP */
4272 		len = os_strlcpy(buf, "CCMP TKIP", buflen);
4273 #endif /* CONFIG_NO_TKIP */
4274 #endif /* CONFIG_WEP */
4275 		if (len >= buflen)
4276 			return -1;
4277 		return len;
4278 	}
4279 
4280 	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4281 		if (capa->enc & ciphers[i].capa) {
4282 			ret = os_snprintf(pos, end - pos, "%s%s",
4283 					  pos == buf ? "" : " ",
4284 					  ciphers[i].name);
4285 			if (os_snprintf_error(end - pos, ret))
4286 				return pos - buf;
4287 			pos += ret;
4288 		}
4289 	}
4290 
4291 	return pos - buf;
4292 }
4293 
4294 
4295 static int ctrl_iface_get_capability_group_mgmt(int res, bool strict,
4296 						struct wpa_driver_capa *capa,
4297 						char *buf, size_t buflen)
4298 {
4299 	int ret;
4300 	char *pos, *end;
4301 	unsigned int i;
4302 
4303 	pos = buf;
4304 	end = pos + buflen;
4305 
4306 	if (res < 0)
4307 		return 0;
4308 
4309 	for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
4310 		if (capa->enc & ciphers_group_mgmt[i].capa) {
4311 			ret = os_snprintf(pos, end - pos, "%s%s",
4312 					  pos == buf ? "" : " ",
4313 					  ciphers_group_mgmt[i].name);
4314 			if (os_snprintf_error(end - pos, ret))
4315 				return pos - buf;
4316 			pos += ret;
4317 		}
4318 	}
4319 
4320 	return pos - buf;
4321 }
4322 
4323 
4324 static int iftype_str_to_index(const char *iftype_str)
4325 {
4326 	if (!iftype_str)
4327 		return WPA_IF_MAX;
4328 
4329 	if (os_strcmp(iftype_str, "STATION") == 0)
4330 		return WPA_IF_STATION;
4331 
4332 	if (os_strcmp(iftype_str, "AP_VLAN") == 0)
4333 		return WPA_IF_AP_VLAN;
4334 
4335 	if (os_strcmp(iftype_str, "AP") == 0)
4336 		return WPA_IF_AP_BSS;
4337 
4338 	if (os_strcmp(iftype_str, "P2P_GO") == 0)
4339 		return WPA_IF_P2P_GO;
4340 
4341 	if (os_strcmp(iftype_str, "P2P_CLIENT") == 0)
4342 		return WPA_IF_P2P_CLIENT;
4343 
4344 	if (os_strcmp(iftype_str, "P2P_DEVICE") == 0)
4345 		return WPA_IF_P2P_DEVICE;
4346 
4347 	if (os_strcmp(iftype_str, "MESH") == 0)
4348 		return WPA_IF_MESH;
4349 
4350 	if (os_strcmp(iftype_str, "IBSS") == 0)
4351 		return WPA_IF_IBSS;
4352 
4353 	if (os_strcmp(iftype_str, "NAN") == 0)
4354 		return WPA_IF_NAN;
4355 
4356 	return WPA_IF_MAX;
4357 }
4358 
4359 
4360 static int ctrl_iface_get_capability_key_mgmt(int res, bool strict,
4361 					      struct wpa_driver_capa *capa,
4362 					      const char *iftype_str,
4363 					      char *buf, size_t buflen)
4364 {
4365 	int ret;
4366 	unsigned int key_mgmt;
4367 	char *pos, *end;
4368 	size_t len;
4369 
4370 	pos = buf;
4371 	end = pos + buflen;
4372 
4373 	if (res < 0) {
4374 		if (strict)
4375 			return 0;
4376 		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
4377 				 "NONE", buflen);
4378 		if (len >= buflen)
4379 			return -1;
4380 		return len;
4381 	}
4382 
4383 	if (iftype_str) {
4384 		enum wpa_driver_if_type iftype;
4385 
4386 		iftype = iftype_str_to_index(iftype_str);
4387 		if (iftype == WPA_IF_MAX)
4388 			return -1;
4389 		key_mgmt = capa->key_mgmt_iftype[iftype];
4390 	} else {
4391 		key_mgmt = capa->key_mgmt;
4392 	}
4393 
4394 	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
4395 	if (os_snprintf_error(end - pos, ret))
4396 		return pos - buf;
4397 	pos += ret;
4398 
4399 	if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4400 			WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
4401 		ret = os_snprintf(pos, end - pos, " WPA-EAP");
4402 		if (os_snprintf_error(end - pos, ret))
4403 			return pos - buf;
4404 		pos += ret;
4405 	}
4406 
4407 	if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
4408 			WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4409 		ret = os_snprintf(pos, end - pos, " WPA-PSK");
4410 		if (os_snprintf_error(end - pos, ret))
4411 			return pos - buf;
4412 		pos += ret;
4413 	}
4414 
4415 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
4416 		ret = os_snprintf(pos, end - pos, " WPA-NONE");
4417 		if (os_snprintf_error(end - pos, ret))
4418 			return pos - buf;
4419 		pos += ret;
4420 	}
4421 
4422 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) {
4423 		ret = os_snprintf(pos, end - pos, " WAPI-PSK");
4424 		if (os_snprintf_error(end - pos, ret))
4425 			return pos - buf;
4426 		pos += ret;
4427 	}
4428 
4429 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) {
4430 		ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE");
4431 		if (os_snprintf_error(end - pos, ret))
4432 			return pos - buf;
4433 		pos += ret;
4434 	}
4435 
4436 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) {
4437 		ret = os_snprintf(pos, end - pos, " CCKM");
4438 		if (os_snprintf_error(end - pos, ret))
4439 			return pos - buf;
4440 		pos += ret;
4441 	}
4442 
4443 #ifdef CONFIG_SUITEB
4444 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
4445 		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4446 		if (os_snprintf_error(end - pos, ret))
4447 			return pos - buf;
4448 		pos += ret;
4449 	}
4450 #endif /* CONFIG_SUITEB */
4451 #ifdef CONFIG_SUITEB192
4452 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
4453 		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4454 		if (os_snprintf_error(end - pos, ret))
4455 			return pos - buf;
4456 		pos += ret;
4457 	}
4458 #endif /* CONFIG_SUITEB192 */
4459 #ifdef CONFIG_OWE
4460 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
4461 		ret = os_snprintf(pos, end - pos, " OWE");
4462 		if (os_snprintf_error(end - pos, ret))
4463 			return pos - buf;
4464 		pos += ret;
4465 	}
4466 #endif /* CONFIG_OWE */
4467 #ifdef CONFIG_DPP
4468 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
4469 		ret = os_snprintf(pos, end - pos, " DPP");
4470 		if (os_snprintf_error(end - pos, ret))
4471 			return pos - buf;
4472 		pos += ret;
4473 	}
4474 #endif /* CONFIG_DPP */
4475 #ifdef CONFIG_FILS
4476 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
4477 		ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4478 		if (os_snprintf_error(end - pos, ret))
4479 			return pos - buf;
4480 		pos += ret;
4481 	}
4482 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
4483 		ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4484 		if (os_snprintf_error(end - pos, ret))
4485 			return pos - buf;
4486 		pos += ret;
4487 	}
4488 #ifdef CONFIG_IEEE80211R
4489 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
4490 		ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4491 		if (os_snprintf_error(end - pos, ret))
4492 			return pos - buf;
4493 		pos += ret;
4494 	}
4495 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
4496 		ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4497 		if (os_snprintf_error(end - pos, ret))
4498 			return pos - buf;
4499 		pos += ret;
4500 	}
4501 #endif /* CONFIG_IEEE80211R */
4502 #endif /* CONFIG_FILS */
4503 #ifdef CONFIG_IEEE80211R
4504 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
4505 		ret = os_snprintf(pos, end - pos, " FT-PSK");
4506 		if (os_snprintf_error(end - pos, ret))
4507 			return pos - buf;
4508 		pos += ret;
4509 	}
4510 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) {
4511 		ret = os_snprintf(pos, end - pos, " FT-EAP");
4512 		if (os_snprintf_error(end - pos, ret))
4513 			return pos - buf;
4514 		pos += ret;
4515 	}
4516 #ifdef CONFIG_SAE
4517 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) {
4518 		ret = os_snprintf(pos, end - pos, " FT-SAE");
4519 		if (os_snprintf_error(end - pos, ret))
4520 			return pos - buf;
4521 		pos += ret;
4522 	}
4523 #endif /* CONFIG_SAE */
4524 #ifdef CONFIG_SHA384
4525 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) {
4526 		ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384");
4527 		if (os_snprintf_error(end - pos, ret))
4528 			return pos - buf;
4529 		pos += ret;
4530 	}
4531 #endif /* CONFIG_SHA384 */
4532 #endif /* CONFIG_IEEE80211R */
4533 #ifdef CONFIG_SAE
4534 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
4535 		ret = os_snprintf(pos, end - pos, " SAE");
4536 		if (os_snprintf_error(end - pos, ret))
4537 			return pos - buf;
4538 		pos += ret;
4539 	}
4540 #endif /* CONFIG_SAE */
4541 #ifdef CONFIG_SHA256
4542 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) {
4543 		ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256");
4544 		if (os_snprintf_error(end - pos, ret))
4545 			return pos - buf;
4546 		pos += ret;
4547 	}
4548 
4549 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) {
4550 		ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256");
4551 		if (os_snprintf_error(end - pos, ret))
4552 			return pos - buf;
4553 		pos += ret;
4554 	}
4555 #endif /* CONFIG_SHA256 */
4556 #ifdef CONFIG_HS20
4557 	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) {
4558 		ret = os_snprintf(pos, end - pos, " OSEN");
4559 		if (os_snprintf_error(end - pos, ret))
4560 			return pos - buf;
4561 		pos += ret;
4562 	}
4563 #endif /* CONFIG_HS20 */
4564 
4565 	return pos - buf;
4566 }
4567 
4568 
4569 static int ctrl_iface_get_capability_proto(int res, bool strict,
4570 					   struct wpa_driver_capa *capa,
4571 					   char *buf, size_t buflen)
4572 {
4573 	int ret;
4574 	char *pos, *end;
4575 	size_t len;
4576 
4577 	pos = buf;
4578 	end = pos + buflen;
4579 
4580 	if (res < 0) {
4581 		if (strict)
4582 			return 0;
4583 		len = os_strlcpy(buf, "RSN WPA", buflen);
4584 		if (len >= buflen)
4585 			return -1;
4586 		return len;
4587 	}
4588 
4589 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4590 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4591 		ret = os_snprintf(pos, end - pos, "%sRSN",
4592 				  pos == buf ? "" : " ");
4593 		if (os_snprintf_error(end - pos, ret))
4594 			return pos - buf;
4595 		pos += ret;
4596 	}
4597 
4598 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4599 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
4600 		ret = os_snprintf(pos, end - pos, "%sWPA",
4601 				  pos == buf ? "" : " ");
4602 		if (os_snprintf_error(end - pos, ret))
4603 			return pos - buf;
4604 		pos += ret;
4605 	}
4606 
4607 	return pos - buf;
4608 }
4609 
4610 
4611 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
4612 					      int res, bool strict,
4613 					      struct wpa_driver_capa *capa,
4614 					      char *buf, size_t buflen)
4615 {
4616 	int ret;
4617 	char *pos, *end;
4618 	size_t len;
4619 
4620 	pos = buf;
4621 	end = pos + buflen;
4622 
4623 	if (res < 0) {
4624 		if (strict)
4625 			return 0;
4626 		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4627 		if (len >= buflen)
4628 			return -1;
4629 		return len;
4630 	}
4631 
4632 	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
4633 		ret = os_snprintf(pos, end - pos, "%sOPEN",
4634 				  pos == buf ? "" : " ");
4635 		if (os_snprintf_error(end - pos, ret))
4636 			return pos - buf;
4637 		pos += ret;
4638 	}
4639 
4640 	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4641 		ret = os_snprintf(pos, end - pos, "%sSHARED",
4642 				  pos == buf ? "" : " ");
4643 		if (os_snprintf_error(end - pos, ret))
4644 			return pos - buf;
4645 		pos += ret;
4646 	}
4647 
4648 	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
4649 		ret = os_snprintf(pos, end - pos, "%sLEAP",
4650 				  pos == buf ? "" : " ");
4651 		if (os_snprintf_error(end - pos, ret))
4652 			return pos - buf;
4653 		pos += ret;
4654 	}
4655 
4656 #ifdef CONFIG_SAE
4657 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4658 		ret = os_snprintf(pos, end - pos, "%sSAE",
4659 				  pos == buf ? "" : " ");
4660 		if (os_snprintf_error(end - pos, ret))
4661 			return pos - buf;
4662 		pos += ret;
4663 	}
4664 #endif /* CONFIG_SAE */
4665 
4666 #ifdef CONFIG_FILS
4667 	if (wpa_is_fils_supported(wpa_s)) {
4668 		ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4669 				  pos == buf ? "" : " ");
4670 		if (os_snprintf_error(end - pos, ret))
4671 			return pos - buf;
4672 		pos += ret;
4673 	}
4674 
4675 #ifdef CONFIG_FILS_SK_PFS
4676 	if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4677 		ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4678 				  pos == buf ? "" : " ");
4679 		if (os_snprintf_error(end - pos, ret))
4680 			return pos - buf;
4681 		pos += ret;
4682 	}
4683 #endif /* CONFIG_FILS_SK_PFS */
4684 #endif /* CONFIG_FILS */
4685 
4686 #ifdef CONFIG_PASN
4687 	ret = os_snprintf(pos, end - pos, "%sPASN",
4688 			  pos == buf ? "" : " ");
4689 	if (os_snprintf_error(end - pos, ret))
4690 		return pos - buf;
4691 	pos += ret;
4692 
4693 #endif /* CONFIG_PASN */
4694 
4695 	return pos - buf;
4696 }
4697 
4698 
4699 static int ctrl_iface_get_capability_modes(int res, bool strict,
4700 					   struct wpa_driver_capa *capa,
4701 					   char *buf, size_t buflen)
4702 {
4703 	int ret;
4704 	char *pos, *end;
4705 	size_t len;
4706 
4707 	pos = buf;
4708 	end = pos + buflen;
4709 
4710 	if (res < 0) {
4711 		if (strict)
4712 			return 0;
4713 		len = os_strlcpy(buf, "IBSS AP", buflen);
4714 		if (len >= buflen)
4715 			return -1;
4716 		return len;
4717 	}
4718 
4719 	if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
4720 		ret = os_snprintf(pos, end - pos, "%sIBSS",
4721 				  pos == buf ? "" : " ");
4722 		if (os_snprintf_error(end - pos, ret))
4723 			return pos - buf;
4724 		pos += ret;
4725 	}
4726 
4727 	if (capa->flags & WPA_DRIVER_FLAGS_AP) {
4728 		ret = os_snprintf(pos, end - pos, "%sAP",
4729 				  pos == buf ? "" : " ");
4730 		if (os_snprintf_error(end - pos, ret))
4731 			return pos - buf;
4732 		pos += ret;
4733 	}
4734 
4735 #ifdef CONFIG_MESH
4736 	if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4737 		ret = os_snprintf(pos, end - pos, "%sMESH",
4738 				  pos == buf ? "" : " ");
4739 		if (os_snprintf_error(end - pos, ret))
4740 			return pos - buf;
4741 		pos += ret;
4742 	}
4743 #endif /* CONFIG_MESH */
4744 
4745 	return pos - buf;
4746 }
4747 
4748 
4749 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4750 					      char *buf, size_t buflen)
4751 {
4752 	struct hostapd_channel_data *chnl;
4753 	int ret, i, j;
4754 	char *pos, *end, *hmode;
4755 
4756 	pos = buf;
4757 	end = pos + buflen;
4758 
4759 	for (j = 0; j < wpa_s->hw.num_modes; j++) {
4760 		switch (wpa_s->hw.modes[j].mode) {
4761 		case HOSTAPD_MODE_IEEE80211B:
4762 			hmode = "B";
4763 			break;
4764 		case HOSTAPD_MODE_IEEE80211G:
4765 			hmode = "G";
4766 			break;
4767 		case HOSTAPD_MODE_IEEE80211A:
4768 			hmode = "A";
4769 			break;
4770 		case HOSTAPD_MODE_IEEE80211AD:
4771 			hmode = "AD";
4772 			break;
4773 		default:
4774 			continue;
4775 		}
4776 		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
4777 		if (os_snprintf_error(end - pos, ret))
4778 			return pos - buf;
4779 		pos += ret;
4780 		chnl = wpa_s->hw.modes[j].channels;
4781 		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4782 			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4783 				continue;
4784 			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
4785 			if (os_snprintf_error(end - pos, ret))
4786 				return pos - buf;
4787 			pos += ret;
4788 		}
4789 		ret = os_snprintf(pos, end - pos, "\n");
4790 		if (os_snprintf_error(end - pos, ret))
4791 			return pos - buf;
4792 		pos += ret;
4793 	}
4794 
4795 	return pos - buf;
4796 }
4797 
4798 
4799 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4800 					  char *buf, size_t buflen)
4801 {
4802 	struct hostapd_channel_data *chnl;
4803 	int ret, i, j;
4804 	char *pos, *end, *hmode;
4805 
4806 	pos = buf;
4807 	end = pos + buflen;
4808 
4809 	for (j = 0; j < wpa_s->hw.num_modes; j++) {
4810 		switch (wpa_s->hw.modes[j].mode) {
4811 		case HOSTAPD_MODE_IEEE80211B:
4812 			hmode = "B";
4813 			break;
4814 		case HOSTAPD_MODE_IEEE80211G:
4815 			hmode = "G";
4816 			break;
4817 		case HOSTAPD_MODE_IEEE80211A:
4818 			hmode = "A";
4819 			break;
4820 		case HOSTAPD_MODE_IEEE80211AD:
4821 			hmode = "AD";
4822 			break;
4823 		default:
4824 			continue;
4825 		}
4826 		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4827 				  hmode);
4828 		if (os_snprintf_error(end - pos, ret))
4829 			return pos - buf;
4830 		pos += ret;
4831 		chnl = wpa_s->hw.modes[j].channels;
4832 		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4833 			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4834 				continue;
4835 			ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
4836 					  chnl[i].chan, chnl[i].freq,
4837 					  chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4838 					  " (NO_IR)" : "",
4839 					  chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4840 					  " (DFS)" : "");
4841 
4842 			if (os_snprintf_error(end - pos, ret))
4843 				return pos - buf;
4844 			pos += ret;
4845 		}
4846 		ret = os_snprintf(pos, end - pos, "\n");
4847 		if (os_snprintf_error(end - pos, ret))
4848 			return pos - buf;
4849 		pos += ret;
4850 	}
4851 
4852 	return pos - buf;
4853 }
4854 
4855 
4856 static int wpa_supplicant_ctrl_iface_get_capability(
4857 	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4858 	size_t buflen)
4859 {
4860 	struct wpa_driver_capa capa;
4861 	int res;
4862 	char *next_param, *curr_param, *iftype = NULL;
4863 	bool strict = false;
4864 	char field[50];
4865 	size_t len;
4866 
4867 	/* Determine whether or not strict checking was requested */
4868 	len = os_strlcpy(field, _field, sizeof(field));
4869 	if (len >= sizeof(field))
4870 		return -1;
4871 
4872 	next_param = os_strchr(field, ' ');
4873 	while (next_param) {
4874 		*next_param++ = '\0';
4875 		curr_param = next_param;
4876 		next_param = os_strchr(next_param, ' ');
4877 
4878 		if (next_param)
4879 			*next_param = '\0';
4880 
4881 		if (os_strcmp(curr_param, "strict") == 0)
4882 			strict = true;
4883 		else if (os_strncmp(curr_param, "iftype=", 7) == 0)
4884 			iftype = curr_param + 7;
4885 		else
4886 			return -1;
4887 	}
4888 
4889 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s",
4890 		   field, iftype ? " iftype=" : "", iftype ? iftype : "",
4891 		   strict ? " strict" : "");
4892 
4893 	if (os_strcmp(field, "eap") == 0) {
4894 		return eap_get_names(buf, buflen);
4895 	}
4896 
4897 	res = wpa_drv_get_capa(wpa_s, &capa);
4898 
4899 	if (os_strcmp(field, "pairwise") == 0)
4900 		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4901 							  buf, buflen);
4902 
4903 	if (os_strcmp(field, "group") == 0)
4904 		return ctrl_iface_get_capability_group(res, strict, &capa,
4905 						       buf, buflen);
4906 
4907 	if (os_strcmp(field, "group_mgmt") == 0)
4908 		return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4909 							    buf, buflen);
4910 
4911 	if (os_strcmp(field, "key_mgmt") == 0)
4912 		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
4913 							  iftype, buf, buflen);
4914 
4915 	if (os_strcmp(field, "proto") == 0)
4916 		return ctrl_iface_get_capability_proto(res, strict, &capa,
4917 						       buf, buflen);
4918 
4919 	if (os_strcmp(field, "auth_alg") == 0)
4920 		return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4921 							  &capa, buf, buflen);
4922 
4923 	if (os_strcmp(field, "modes") == 0)
4924 		return ctrl_iface_get_capability_modes(res, strict, &capa,
4925 						       buf, buflen);
4926 
4927 	if (os_strcmp(field, "channels") == 0)
4928 		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4929 
4930 	if (os_strcmp(field, "freq") == 0)
4931 		return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4932 
4933 #ifdef CONFIG_TDLS
4934 	if (os_strcmp(field, "tdls") == 0)
4935 		return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4936 #endif /* CONFIG_TDLS */
4937 
4938 #ifdef CONFIG_ERP
4939 	if (os_strcmp(field, "erp") == 0) {
4940 		res = os_snprintf(buf, buflen, "ERP");
4941 		if (os_snprintf_error(buflen, res))
4942 			return -1;
4943 		return res;
4944 	}
4945 #endif /* CONFIG_EPR */
4946 
4947 #ifdef CONFIG_FIPS
4948 	if (os_strcmp(field, "fips") == 0) {
4949 		res = os_snprintf(buf, buflen, "FIPS");
4950 		if (os_snprintf_error(buflen, res))
4951 			return -1;
4952 		return res;
4953 	}
4954 #endif /* CONFIG_FIPS */
4955 
4956 #ifdef CONFIG_ACS
4957 	if (os_strcmp(field, "acs") == 0) {
4958 		res = os_snprintf(buf, buflen, "ACS");
4959 		if (os_snprintf_error(buflen, res))
4960 			return -1;
4961 		return res;
4962 	}
4963 #endif /* CONFIG_ACS */
4964 
4965 #ifdef CONFIG_FILS
4966 	if (os_strcmp(field, "fils") == 0) {
4967 #ifdef CONFIG_FILS_SK_PFS
4968 		if (wpa_is_fils_supported(wpa_s) &&
4969 		    wpa_is_fils_sk_pfs_supported(wpa_s)) {
4970 			res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4971 			if (os_snprintf_error(buflen, res))
4972 				return -1;
4973 			return res;
4974 		}
4975 #endif /* CONFIG_FILS_SK_PFS */
4976 
4977 		if (wpa_is_fils_supported(wpa_s)) {
4978 			res = os_snprintf(buf, buflen, "FILS");
4979 			if (os_snprintf_error(buflen, res))
4980 				return -1;
4981 			return res;
4982 		}
4983 	}
4984 #endif /* CONFIG_FILS */
4985 
4986 	if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4987 		res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4988 		if (os_snprintf_error(buflen, res))
4989 			return -1;
4990 		return res;
4991 	}
4992 
4993 #ifdef CONFIG_DPP
4994 	if (os_strcmp(field, "dpp") == 0) {
4995 #ifdef CONFIG_DPP3
4996 		res = os_snprintf(buf, buflen, "DPP=3");
4997 #elif defined(CONFIG_DPP2)
4998 		res = os_snprintf(buf, buflen, "DPP=2");
4999 #else /* CONFIG_DPP2 */
5000 		res = os_snprintf(buf, buflen, "DPP=1");
5001 #endif /* CONFIG_DPP2 */
5002 		if (os_snprintf_error(buflen, res))
5003 			return -1;
5004 		return res;
5005 	}
5006 #endif /* CONFIG_DPP */
5007 
5008 #ifdef CONFIG_SAE
5009 	if (os_strcmp(field, "sae") == 0 &&
5010 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
5011 #ifdef CONFIG_SAE_PK
5012 		res = os_snprintf(buf, buflen, "H2E PK");
5013 #else /* CONFIG_SAE_PK */
5014 		res = os_snprintf(buf, buflen, "H2E");
5015 #endif /* CONFIG_SAE_PK */
5016 		if (os_snprintf_error(buflen, res))
5017 			return -1;
5018 		return res;
5019 	}
5020 #endif /* CONFIG_SAE */
5021 
5022 #ifdef CONFIG_OCV
5023 	if (os_strcmp(field, "ocv") == 0) {
5024 		if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
5025 		    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
5026 			res = os_snprintf(buf, buflen, "supported");
5027 		else
5028 			res = os_snprintf(buf, buflen, "not supported");
5029 		if (os_snprintf_error(buflen, res))
5030 			return -1;
5031 		return res;
5032 	}
5033 #endif /* CONFIG_OCV */
5034 
5035 	if (os_strcmp(field, "beacon_prot") == 0) {
5036 		if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
5037 		    (wpa_s->drv_flags2 &
5038 		     WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
5039 			res = os_snprintf(buf, buflen, "supported");
5040 		else
5041 			res = os_snprintf(buf, buflen, "not supported");
5042 		if (os_snprintf_error(buflen, res))
5043 			return -1;
5044 		return res;
5045 	}
5046 
5047 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
5048 		   field);
5049 
5050 	return -1;
5051 }
5052 
5053 
5054 #ifdef CONFIG_INTERWORKING
5055 static char * anqp_add_hex(char *pos, char *end, const char *title,
5056 			   struct wpabuf *data)
5057 {
5058 	char *start = pos;
5059 	size_t i;
5060 	int ret;
5061 	const u8 *d;
5062 
5063 	if (data == NULL)
5064 		return start;
5065 
5066 	ret = os_snprintf(pos, end - pos, "%s=", title);
5067 	if (os_snprintf_error(end - pos, ret))
5068 		return start;
5069 	pos += ret;
5070 
5071 	d = wpabuf_head_u8(data);
5072 	for (i = 0; i < wpabuf_len(data); i++) {
5073 		ret = os_snprintf(pos, end - pos, "%02x", *d++);
5074 		if (os_snprintf_error(end - pos, ret))
5075 			return start;
5076 		pos += ret;
5077 	}
5078 
5079 	ret = os_snprintf(pos, end - pos, "\n");
5080 	if (os_snprintf_error(end - pos, ret))
5081 		return start;
5082 	pos += ret;
5083 
5084 	return pos;
5085 }
5086 #endif /* CONFIG_INTERWORKING */
5087 #endif /* EXT_CODE_CROP */
5088 
5089 #ifdef CONFIG_FILS
5090 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
5091 {
5092 	char *start = pos;
5093 	const u8 *ie, *ie_end;
5094 	u16 info, realms;
5095 	int ret;
5096 
5097 	ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
5098 	if (!ie)
5099 		return 0;
5100 	ie_end = ie + 2 + ie[1];
5101 	ie += 2;
5102 	if (ie_end - ie < 2)
5103 		return -1;
5104 
5105 	info = WPA_GET_LE16(ie);
5106 	ie += 2;
5107 	ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
5108 	if (os_snprintf_error(end - pos, ret))
5109 		return 0;
5110 	pos += ret;
5111 
5112 	if (info & BIT(7)) {
5113 		/* Cache Identifier Included */
5114 		if (ie_end - ie < 2)
5115 			return -1;
5116 		ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
5117 				  ie[0], ie[1]);
5118 		if (os_snprintf_error(end - pos, ret))
5119 			return 0;
5120 		pos += ret;
5121 		ie += 2;
5122 	}
5123 
5124 	if (info & BIT(8)) {
5125 		/* HESSID Included */
5126 		if (ie_end - ie < ETH_ALEN)
5127 			return -1;
5128 		ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
5129 				  MAC2STR(ie));
5130 		if (os_snprintf_error(end - pos, ret))
5131 			return 0;
5132 		pos += ret;
5133 		ie += ETH_ALEN;
5134 	}
5135 
5136 	realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
5137 	if (realms) {
5138 		if (ie_end - ie < realms * 2)
5139 			return -1;
5140 		ret = os_snprintf(pos, end - pos, "fils_realms=");
5141 		if (os_snprintf_error(end - pos, ret))
5142 			return 0;
5143 		pos += ret;
5144 
5145 		ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
5146 		if (ret <= 0)
5147 			return 0;
5148 		pos += ret;
5149 		ie += realms * 2;
5150 		ret = os_snprintf(pos, end - pos, "\n");
5151 		if (os_snprintf_error(end - pos, ret))
5152 			return 0;
5153 		pos += ret;
5154 	}
5155 
5156 	return pos - start;
5157 }
5158 #endif /* CONFIG_FILS */
5159 
5160 #ifndef EXT_CODE_CROP
5161 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
5162 			  unsigned long mask, char *buf, size_t buflen)
5163 {
5164 	size_t i;
5165 	int ret;
5166 	char *pos, *end;
5167 	const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe;
5168 
5169 	pos = buf;
5170 	end = buf + buflen;
5171 
5172 	if (mask & WPA_BSS_MASK_ID) {
5173 		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
5174 		if (os_snprintf_error(end - pos, ret))
5175 			return 0;
5176 		pos += ret;
5177 	}
5178 
5179 	if (mask & WPA_BSS_MASK_BSSID) {
5180 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
5181 				  MAC2STR(bss->bssid));
5182 		if (os_snprintf_error(end - pos, ret))
5183 			return 0;
5184 		pos += ret;
5185 	}
5186 
5187 	if (mask & WPA_BSS_MASK_FREQ) {
5188 		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
5189 		if (os_snprintf_error(end - pos, ret))
5190 			return 0;
5191 		pos += ret;
5192 	}
5193 
5194 	if (mask & WPA_BSS_MASK_BEACON_INT) {
5195 		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
5196 				  bss->beacon_int);
5197 		if (os_snprintf_error(end - pos, ret))
5198 			return 0;
5199 		pos += ret;
5200 	}
5201 
5202 	if (mask & WPA_BSS_MASK_CAPABILITIES) {
5203 		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
5204 				  bss->caps);
5205 		if (os_snprintf_error(end - pos, ret))
5206 			return 0;
5207 		pos += ret;
5208 	}
5209 
5210 	if (mask & WPA_BSS_MASK_QUAL) {
5211 		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
5212 		if (os_snprintf_error(end - pos, ret))
5213 			return 0;
5214 		pos += ret;
5215 	}
5216 
5217 	if (mask & WPA_BSS_MASK_NOISE) {
5218 		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
5219 		if (os_snprintf_error(end - pos, ret))
5220 			return 0;
5221 		pos += ret;
5222 	}
5223 
5224 	if (mask & WPA_BSS_MASK_LEVEL) {
5225 		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
5226 		if (os_snprintf_error(end - pos, ret))
5227 			return 0;
5228 		pos += ret;
5229 	}
5230 
5231 	if (mask & WPA_BSS_MASK_TSF) {
5232 		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
5233 				  (unsigned long long) bss->tsf);
5234 		if (os_snprintf_error(end - pos, ret))
5235 			return 0;
5236 		pos += ret;
5237 	}
5238 
5239 	if (mask & WPA_BSS_MASK_AGE) {
5240 		struct os_reltime now;
5241 
5242 		os_get_reltime(&now);
5243 		ret = os_snprintf(pos, end - pos, "age=%d\n",
5244 				  (int) (now.sec - bss->last_update.sec));
5245 		if (os_snprintf_error(end - pos, ret))
5246 			return 0;
5247 		pos += ret;
5248 	}
5249 
5250 	if (mask & WPA_BSS_MASK_IE) {
5251 		ret = os_snprintf(pos, end - pos, "ie=");
5252 		if (os_snprintf_error(end - pos, ret))
5253 			return 0;
5254 		pos += ret;
5255 
5256 		ie = wpa_bss_ie_ptr(bss);
5257 		for (i = 0; i < bss->ie_len; i++) {
5258 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5259 			if (os_snprintf_error(end - pos, ret))
5260 				return 0;
5261 			pos += ret;
5262 		}
5263 
5264 		ret = os_snprintf(pos, end - pos, "\n");
5265 		if (os_snprintf_error(end - pos, ret))
5266 			return 0;
5267 		pos += ret;
5268 	}
5269 
5270 	if (mask & WPA_BSS_MASK_FLAGS) {
5271 		ret = os_snprintf(pos, end - pos, "flags=");
5272 		if (os_snprintf_error(end - pos, ret))
5273 			return 0;
5274 		pos += ret;
5275 
5276 		mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
5277 
5278 		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
5279 		if (ie)
5280 			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
5281 						    2 + ie[1]);
5282 		ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
5283 		if (ie2)
5284 			pos = wpa_supplicant_ie_txt(pos, end,
5285 						    mesh ? "RSN" : "WPA2", ie2,
5286 						    2 + ie2[1]);
5287 		rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
5288 		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
5289 			ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
5290 			if (os_snprintf_error(end - pos, ret))
5291 				return -1;
5292 			pos += ret;
5293 		}
5294 		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
5295 			ret = os_snprintf(pos, end - pos, "[SAE-PK]");
5296 			if (os_snprintf_error(end - pos, ret))
5297 				return -1;
5298 			pos += ret;
5299 		}
5300 		osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
5301 		if (osen_ie)
5302 			pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
5303 						    osen_ie, 2 + osen_ie[1]);
5304 		owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5305 		if (owe) {
5306 			ret = os_snprintf(
5307 				pos, end - pos,
5308 				ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
5309 			if (os_snprintf_error(end - pos, ret))
5310 				return 0;
5311 			pos += ret;
5312 		}
5313 		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
5314 		if (!ie && !ie2 && !osen_ie &&
5315 		    (bss->caps & IEEE80211_CAP_PRIVACY)) {
5316 			ret = os_snprintf(pos, end - pos, "[WEP]");
5317 			if (os_snprintf_error(end - pos, ret))
5318 				return 0;
5319 			pos += ret;
5320 		}
5321 
5322 		if (mesh) {
5323 			ret = os_snprintf(pos, end - pos, "[MESH]");
5324 			if (os_snprintf_error(end - pos, ret))
5325 				return 0;
5326 			pos += ret;
5327 		}
5328 
5329 		if (bss_is_dmg(bss)) {
5330 			const char *s;
5331 			ret = os_snprintf(pos, end - pos, "[DMG]");
5332 			if (os_snprintf_error(end - pos, ret))
5333 				return 0;
5334 			pos += ret;
5335 			switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
5336 			case IEEE80211_CAP_DMG_IBSS:
5337 				s = "[IBSS]";
5338 				break;
5339 			case IEEE80211_CAP_DMG_AP:
5340 				s = "[ESS]";
5341 				break;
5342 			case IEEE80211_CAP_DMG_PBSS:
5343 				s = "[PBSS]";
5344 				break;
5345 			default:
5346 				s = "";
5347 				break;
5348 			}
5349 			ret = os_snprintf(pos, end - pos, "%s", s);
5350 			if (os_snprintf_error(end - pos, ret))
5351 				return 0;
5352 			pos += ret;
5353 		} else {
5354 			if (bss->caps & IEEE80211_CAP_IBSS) {
5355 				ret = os_snprintf(pos, end - pos, "[IBSS]");
5356 				if (os_snprintf_error(end - pos, ret))
5357 					return 0;
5358 				pos += ret;
5359 			}
5360 			if (bss->caps & IEEE80211_CAP_ESS) {
5361 				ret = os_snprintf(pos, end - pos, "[ESS]");
5362 				if (os_snprintf_error(end - pos, ret))
5363 					return 0;
5364 				pos += ret;
5365 			}
5366 		}
5367 		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
5368 		    wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
5369 			ret = os_snprintf(pos, end - pos, "[P2P]");
5370 			if (os_snprintf_error(end - pos, ret))
5371 				return 0;
5372 			pos += ret;
5373 		}
5374 #ifdef CONFIG_HS20
5375 		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
5376 			ret = os_snprintf(pos, end - pos, "[HS20]");
5377 			if (os_snprintf_error(end - pos, ret))
5378 				return 0;
5379 			pos += ret;
5380 		}
5381 #endif /* CONFIG_HS20 */
5382 #ifdef CONFIG_FILS
5383 		if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
5384 			ret = os_snprintf(pos, end - pos, "[FILS]");
5385 			if (os_snprintf_error(end - pos, ret))
5386 				return 0;
5387 			pos += ret;
5388 		}
5389 #endif /* CONFIG_FILS */
5390 #ifdef CONFIG_FST
5391 		if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
5392 			ret = os_snprintf(pos, end - pos, "[FST]");
5393 			if (os_snprintf_error(end - pos, ret))
5394 				return 0;
5395 			pos += ret;
5396 		}
5397 #endif /* CONFIG_FST */
5398 		if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
5399 			ret = os_snprintf(pos, end - pos, "[UTF-8]");
5400 			if (os_snprintf_error(end - pos, ret))
5401 				return 0;
5402 			pos += ret;
5403 		}
5404 
5405 		ret = os_snprintf(pos, end - pos, "\n");
5406 		if (os_snprintf_error(end - pos, ret))
5407 			return 0;
5408 		pos += ret;
5409 	}
5410 
5411 	if (mask & WPA_BSS_MASK_SSID) {
5412 		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
5413 				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
5414 		if (os_snprintf_error(end - pos, ret))
5415 			return 0;
5416 		pos += ret;
5417 	}
5418 
5419 #ifdef CONFIG_WPS
5420 	if (mask & WPA_BSS_MASK_WPS_SCAN) {
5421 		ie = wpa_bss_ie_ptr(bss);
5422 		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
5423 		if (ret >= end - pos)
5424 			return 0;
5425 		if (ret > 0)
5426 			pos += ret;
5427 	}
5428 #endif /* CONFIG_WPS */
5429 
5430 #ifdef CONFIG_P2P
5431 	if (mask & WPA_BSS_MASK_P2P_SCAN) {
5432 		ie = wpa_bss_ie_ptr(bss);
5433 		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
5434 		if (ret >= end - pos)
5435 			return 0;
5436 		if (ret > 0)
5437 			pos += ret;
5438 	}
5439 #endif /* CONFIG_P2P */
5440 
5441 #ifdef CONFIG_WIFI_DISPLAY
5442 	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
5443 		struct wpabuf *wfd;
5444 
5445 		ie = wpa_bss_ie_ptr(bss);
5446 		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
5447 						  WFD_IE_VENDOR_TYPE);
5448 		if (wfd) {
5449 			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
5450 			if (os_snprintf_error(end - pos, ret)) {
5451 				wpabuf_free(wfd);
5452 				return 0;
5453 			}
5454 			pos += ret;
5455 
5456 			pos += wpa_snprintf_hex(pos, end - pos,
5457 						wpabuf_head(wfd),
5458 						wpabuf_len(wfd));
5459 			wpabuf_free(wfd);
5460 
5461 			ret = os_snprintf(pos, end - pos, "\n");
5462 			if (os_snprintf_error(end - pos, ret))
5463 				return 0;
5464 			pos += ret;
5465 		}
5466 	}
5467 #endif /* CONFIG_WIFI_DISPLAY */
5468 
5469 #ifdef CONFIG_INTERWORKING
5470 	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
5471 		struct wpa_bss_anqp *anqp = bss->anqp;
5472 		struct wpa_bss_anqp_elem *elem;
5473 
5474 		pos = anqp_add_hex(pos, end, "anqp_capability_list",
5475 				   anqp->capability_list);
5476 		pos = anqp_add_hex(pos, end, "anqp_venue_name",
5477 				   anqp->venue_name);
5478 		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
5479 				   anqp->network_auth_type);
5480 		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
5481 				   anqp->roaming_consortium);
5482 		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
5483 				   anqp->ip_addr_type_availability);
5484 		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
5485 				   anqp->nai_realm);
5486 		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
5487 		pos = anqp_add_hex(pos, end, "anqp_domain_name",
5488 				   anqp->domain_name);
5489 		pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
5490 				   anqp->fils_realm_info);
5491 #ifdef CONFIG_HS20
5492 		pos = anqp_add_hex(pos, end, "hs20_capability_list",
5493 				   anqp->hs20_capability_list);
5494 		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
5495 				   anqp->hs20_operator_friendly_name);
5496 		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
5497 				   anqp->hs20_wan_metrics);
5498 		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
5499 				   anqp->hs20_connection_capability);
5500 		pos = anqp_add_hex(pos, end, "hs20_operating_class",
5501 				   anqp->hs20_operating_class);
5502 		pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
5503 				   anqp->hs20_osu_providers_list);
5504 		pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
5505 				   anqp->hs20_operator_icon_metadata);
5506 		pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
5507 				   anqp->hs20_osu_providers_nai_list);
5508 #endif /* CONFIG_HS20 */
5509 
5510 		dl_list_for_each(elem, &anqp->anqp_elems,
5511 				 struct wpa_bss_anqp_elem, list) {
5512 			char title[20];
5513 
5514 			os_snprintf(title, sizeof(title), "anqp[%u]",
5515 				    elem->infoid);
5516 			pos = anqp_add_hex(pos, end, title, elem->payload);
5517 			if (elem->protected_response) {
5518 				ret = os_snprintf(pos, end - pos,
5519 						  "protected-anqp-info[%u]=1\n",
5520 						  elem->infoid);
5521 				if (os_snprintf_error(end - pos, ret))
5522 					return 0;
5523 				pos += ret;
5524 			}
5525 		}
5526 	}
5527 #endif /* CONFIG_INTERWORKING */
5528 
5529 #ifdef CONFIG_MESH
5530 	if (mask & WPA_BSS_MASK_MESH_SCAN) {
5531 		ie = wpa_bss_ie_ptr(bss);
5532 		ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
5533 		if (ret >= end - pos)
5534 			return 0;
5535 		if (ret > 0)
5536 			pos += ret;
5537 	}
5538 #endif /* CONFIG_MESH */
5539 
5540 	if (mask & WPA_BSS_MASK_SNR) {
5541 		ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
5542 		if (os_snprintf_error(end - pos, ret))
5543 			return 0;
5544 		pos += ret;
5545 	}
5546 
5547 	if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
5548 		ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
5549 				  bss->est_throughput);
5550 		if (os_snprintf_error(end - pos, ret))
5551 			return 0;
5552 		pos += ret;
5553 	}
5554 
5555 #ifdef CONFIG_FST
5556 	if (mask & WPA_BSS_MASK_FST) {
5557 		ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
5558 		if (ret < 0 || ret >= end - pos)
5559 			return 0;
5560 		pos += ret;
5561 	}
5562 #endif /* CONFIG_FST */
5563 
5564 	if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5565 		ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5566 				  bss->last_update_idx);
5567 		if (os_snprintf_error(end - pos, ret))
5568 			return 0;
5569 		pos += ret;
5570 	}
5571 
5572 	if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5573 		ret = os_snprintf(pos, end - pos, "beacon_ie=");
5574 		if (os_snprintf_error(end - pos, ret))
5575 			return 0;
5576 		pos += ret;
5577 
5578 		ie = wpa_bss_ie_ptr(bss);
5579 		ie += bss->ie_len;
5580 		for (i = 0; i < bss->beacon_ie_len; i++) {
5581 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5582 			if (os_snprintf_error(end - pos, ret))
5583 				return 0;
5584 			pos += ret;
5585 		}
5586 
5587 		ret = os_snprintf(pos, end - pos, "\n");
5588 		if (os_snprintf_error(end - pos, ret))
5589 			return 0;
5590 		pos += ret;
5591 	}
5592 
5593 #ifdef CONFIG_FILS
5594 	if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5595 		ret = print_fils_indication(bss, pos, end);
5596 		if (ret < 0)
5597 			return 0;
5598 		pos += ret;
5599 	}
5600 #endif /* CONFIG_FILS */
5601 
5602 	if (mask & WPA_BSS_MASK_DELIM) {
5603 		ret = os_snprintf(pos, end - pos, "====\n");
5604 		if (os_snprintf_error(end - pos, ret))
5605 			return 0;
5606 		pos += ret;
5607 	}
5608 
5609 	return pos - buf;
5610 }
5611 
5612 
5613 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5614 					 const char *cmd, char *buf,
5615 					 size_t buflen)
5616 {
5617 	u8 bssid[ETH_ALEN];
5618 	size_t i;
5619 	struct wpa_bss *bss;
5620 	struct wpa_bss *bsslast = NULL;
5621 	struct dl_list *next;
5622 	int ret = 0;
5623 	int len;
5624 	char *ctmp, *end = buf + buflen;
5625 	unsigned long mask = WPA_BSS_MASK_ALL;
5626 
5627 	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5628 		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5629 			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
5630 					    list_id);
5631 			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5632 					       list_id);
5633 		} else { /* N1-N2 */
5634 			unsigned int id1, id2;
5635 
5636 			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5637 				wpa_printf(MSG_INFO, "Wrong BSS range "
5638 					   "format");
5639 				return 0;
5640 			}
5641 
5642 			if (*(cmd + 6) == '-')
5643 				id1 = 0;
5644 			else
5645 				id1 = atoi(cmd + 6);
5646 			ctmp++;
5647 			if (*ctmp >= '0' && *ctmp <= '9')
5648 				id2 = atoi(ctmp);
5649 			else
5650 				id2 = (unsigned int) -1;
5651 			bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5652 			if (id2 == (unsigned int) -1)
5653 				bsslast = dl_list_last(&wpa_s->bss_id,
5654 						       struct wpa_bss,
5655 						       list_id);
5656 			else {
5657 				bsslast = wpa_bss_get_id(wpa_s, id2);
5658 				if (bsslast == NULL && bss && id2 > id1) {
5659 					struct wpa_bss *tmp = bss;
5660 					for (;;) {
5661 						next = tmp->list_id.next;
5662 						if (next == &wpa_s->bss_id)
5663 							break;
5664 						tmp = dl_list_entry(
5665 							next, struct wpa_bss,
5666 							list_id);
5667 						if (tmp->id > id2)
5668 							break;
5669 						bsslast = tmp;
5670 					}
5671 				}
5672 			}
5673 		}
5674 	} else if (os_strncmp(cmd, "FIRST", 5) == 0)
5675 		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
5676 	else if (os_strncmp(cmd, "LAST", 4) == 0)
5677 		bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
5678 	else if (os_strncmp(cmd, "ID-", 3) == 0) {
5679 		i = atoi(cmd + 3);
5680 		bss = wpa_bss_get_id(wpa_s, i);
5681 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5682 		i = atoi(cmd + 5);
5683 		bss = wpa_bss_get_id(wpa_s, i);
5684 		if (bss) {
5685 			next = bss->list_id.next;
5686 			if (next == &wpa_s->bss_id)
5687 				bss = NULL;
5688 			else
5689 				bss = dl_list_entry(next, struct wpa_bss,
5690 						    list_id);
5691 		}
5692 	} else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5693 		bss = wpa_s->current_bss;
5694 #ifdef CONFIG_P2P
5695 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5696 		if (hwaddr_aton(cmd + 13, bssid) == 0)
5697 			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5698 		else
5699 			bss = NULL;
5700 #endif /* CONFIG_P2P */
5701 	} else if (hwaddr_aton(cmd, bssid) == 0)
5702 		bss = wpa_bss_get_bssid(wpa_s, bssid);
5703 	else {
5704 		struct wpa_bss *tmp;
5705 		i = atoi(cmd);
5706 		bss = NULL;
5707 		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5708 		{
5709 			if (i == 0) {
5710 				bss = tmp;
5711 				break;
5712 			}
5713 			i--;
5714 		}
5715 	}
5716 
5717 	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5718 		mask = strtoul(ctmp + 5, NULL, 0x10);
5719 		if (mask == 0)
5720 			mask = WPA_BSS_MASK_ALL;
5721 	}
5722 
5723 	if (bss == NULL)
5724 		return 0;
5725 
5726 	if (bsslast == NULL)
5727 		bsslast = bss;
5728 	do {
5729 		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5730 		ret += len;
5731 		buf += len;
5732 		buflen -= len;
5733 		if (bss == bsslast) {
5734 			if ((mask & WPA_BSS_MASK_DELIM) && len &&
5735 			    (bss == dl_list_last(&wpa_s->bss_id,
5736 						 struct wpa_bss, list_id))) {
5737 				int res;
5738 
5739 				res = os_snprintf(buf - 5, end - buf + 5,
5740 						  "####\n");
5741 				if (os_snprintf_error(end - buf + 5, res)) {
5742 					wpa_printf(MSG_DEBUG,
5743 						   "Could not add end delim");
5744 				}
5745 			}
5746 			break;
5747 		}
5748 		next = bss->list_id.next;
5749 		if (next == &wpa_s->bss_id)
5750 			break;
5751 		bss = dl_list_entry(next, struct wpa_bss, list_id);
5752 	} while (bss && len);
5753 
5754 	os_free_drv_scan_bss(bss);
5755 	return ret;
5756 }
5757 
5758 
5759 static int wpa_supplicant_ctrl_iface_ap_scan(
5760 	struct wpa_supplicant *wpa_s, char *cmd)
5761 {
5762 	int ap_scan = atoi(cmd);
5763 	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5764 }
5765 
5766 
5767 static int wpa_supplicant_ctrl_iface_scan_interval(
5768 	struct wpa_supplicant *wpa_s, char *cmd)
5769 {
5770 	int scan_int = atoi(cmd);
5771 	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
5772 }
5773 
5774 
5775 static int wpa_supplicant_ctrl_iface_bss_expire_age(
5776 	struct wpa_supplicant *wpa_s, char *cmd)
5777 {
5778 	int expire_age = atoi(cmd);
5779 	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5780 }
5781 
5782 
5783 static int wpa_supplicant_ctrl_iface_bss_expire_count(
5784 	struct wpa_supplicant *wpa_s, char *cmd)
5785 {
5786 	int expire_count = atoi(cmd);
5787 	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5788 }
5789 #endif /* EXT_CODE_CROP */
5790 
5791 static void wpa_supplicant_ctrl_iface_bss_flush(
5792 	struct wpa_supplicant *wpa_s, char *cmd)
5793 {
5794 	int flush_age = atoi(cmd);
5795 
5796 	if (flush_age == 0)
5797 		wpa_bss_flush(wpa_s);
5798 	else
5799 		wpa_bss_flush_by_age(wpa_s, flush_age);
5800 }
5801 
5802 #ifdef CONFIG_TESTING_OPTIONS
5803 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5804 {
5805 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5806 	/* MLME-DELETEKEYS.request */
5807 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
5808 			0, KEY_FLAG_GROUP);
5809 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
5810 			0, KEY_FLAG_GROUP);
5811 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
5812 			0, KEY_FLAG_GROUP);
5813 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
5814 			0, KEY_FLAG_GROUP);
5815 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
5816 			0, KEY_FLAG_GROUP);
5817 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
5818 			0, KEY_FLAG_GROUP);
5819 
5820 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
5821 			0, KEY_FLAG_PAIRWISE);
5822 	if (wpa_sm_ext_key_id(wpa_s->wpa))
5823 		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
5824 				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
5825 	/* MLME-SETPROTECTION.request(None) */
5826 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
5827 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
5828 				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
5829 	wpa_sm_drop_sa(wpa_s->wpa);
5830 }
5831 #endif /* CONFIG_TESTING_OPTIONS */
5832 
5833 
5834 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
5835 					  char *addr)
5836 {
5837 #ifdef CONFIG_NO_SCAN_PROCESSING
5838 	return -1;
5839 #else /* CONFIG_NO_SCAN_PROCESSING */
5840 	u8 bssid[ETH_ALEN];
5841 	struct wpa_bss *bss;
5842 	struct wpa_ssid *ssid = wpa_s->current_ssid;
5843 	struct wpa_radio_work *already_connecting;
5844 
5845 	if (hwaddr_aton(addr, bssid)) {
5846 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
5847 			   "address '%s'", addr);
5848 		return -1;
5849 	}
5850 
5851 	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
5852 
5853 	if (!ssid) {
5854 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
5855 			   "configuration known for the target AP");
5856 		return -1;
5857 	}
5858 
5859 	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
5860 	if (!bss) {
5861 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
5862 			   "from BSS table");
5863 		return -1;
5864 	}
5865 
5866 	/*
5867 	 * TODO: Find best network configuration block from configuration to
5868 	 * allow roaming to other networks
5869 	 */
5870 
5871 	already_connecting = radio_work_pending(wpa_s, "sme-connect");
5872 	wpa_s->reassociate = 1;
5873 	wpa_supplicant_connect(wpa_s, bss, ssid);
5874 
5875 	/*
5876 	 * Indicate that an explicitly requested roam is in progress so scan
5877 	 * results that come in before the 'sme-connect' radio work gets
5878 	 * executed do not override the original connection attempt.
5879 	 */
5880 	if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
5881 		wpa_s->roam_in_progress = true;
5882 
5883 	return 0;
5884 #endif /* CONFIG_NO_SCAN_PROCESSING */
5885 }
5886 
5887 
5888 #ifdef CONFIG_P2P
5889 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
5890 {
5891 	unsigned int timeout = atoi(cmd);
5892 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
5893 	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
5894 	u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
5895 	char *pos;
5896 	unsigned int search_delay;
5897 	const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
5898 	u8 seek_count = 0;
5899 	int freq = 0;
5900 	bool include_6ghz = false;
5901 
5902 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5903 		wpa_dbg(wpa_s, MSG_INFO,
5904 			"Reject P2P_FIND since interface is disabled");
5905 		return -1;
5906 	}
5907 #ifndef LOS_P2P_CROP
5908 	if (os_strstr(cmd, " include_6ghz"))
5909 		include_6ghz = true;
5910 	if (os_strstr(cmd, "type=social"))
5911 		type = P2P_FIND_ONLY_SOCIAL;
5912 	else if (os_strstr(cmd, "type=progressive"))
5913 		type = P2P_FIND_PROGRESSIVE;
5914 
5915 	pos = os_strstr(cmd, "dev_id=");
5916 	if (pos) {
5917 		pos += 7;
5918 		if (hwaddr_aton(pos, dev_id))
5919 			return -1;
5920 		_dev_id = dev_id;
5921 	}
5922 
5923 	pos = os_strstr(cmd, "dev_type=");
5924 	if (pos) {
5925 		pos += 9;
5926 		if (wps_dev_type_str2bin(pos, dev_type) < 0)
5927 			return -1;
5928 		_dev_type = dev_type;
5929 	}
5930 
5931 	pos = os_strstr(cmd, "delay=");
5932 	if (pos) {
5933 		pos += 6;
5934 		search_delay = atoi(pos);
5935 	} else
5936 #endif /* LOS_P2P_CROP */
5937 		search_delay = wpas_p2p_search_delay(wpa_s);
5938 
5939 #ifndef LOS_P2P_CROP
5940 	pos = os_strstr(cmd, "freq=");
5941 	if (pos) {
5942 		pos += 5;
5943 		freq = atoi(pos);
5944 		if (freq <= 0)
5945 			return -1;
5946 	}
5947 
5948 	/* Must be searched for last, because it adds nul termination */
5949 	pos = os_strstr(cmd, " seek=");
5950 	if (pos)
5951 		pos += 6;
5952 	while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
5953 		char *term;
5954 
5955 		_seek[seek_count++] = pos;
5956 		seek = _seek;
5957 		term = os_strchr(pos, ' ');
5958 		if (!term)
5959 			break;
5960 		*term = '\0';
5961 		pos = os_strstr(term + 1, "seek=");
5962 		if (pos)
5963 			pos += 5;
5964 	}
5965 	if (seek_count > P2P_MAX_QUERY_HASH) {
5966 		seek[0] = NULL;
5967 		seek_count = 1;
5968 	}
5969 #endif /* LOS_P2P_CROP */
5970 
5971 	return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
5972 			     _dev_id, search_delay, seek_count, seek, freq,
5973 			     include_6ghz);
5974 }
5975 
5976 
5977 #ifndef LOS_P2P_CROP
5978 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
5979 {
5980 	const char *last = NULL;
5981 	const char *token;
5982 	long int token_len;
5983 	unsigned int i;
5984 
5985 	/* Expected predefined CPT names delimited by ':' */
5986 	for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
5987 		if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
5988 			wpa_printf(MSG_ERROR,
5989 				   "P2PS: CPT name list is too long, expected up to %d names",
5990 				   P2PS_FEATURE_CAPAB_CPT_MAX);
5991 			cpt[0] = 0;
5992 			return -1;
5993 		}
5994 
5995 		token_len = last - token;
5996 
5997 		if (token_len  == 3 &&
5998 		    os_memcmp(token, "UDP", token_len) == 0) {
5999 			cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6000 		} else if (token_len == 3 &&
6001 			   os_memcmp(token, "MAC", token_len) == 0) {
6002 			cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
6003 		} else {
6004 			wpa_printf(MSG_ERROR,
6005 				   "P2PS: Unsupported CPT name '%s'", token);
6006 			cpt[0] = 0;
6007 			return -1;
6008 		}
6009 
6010 		if (isblank((unsigned char) *last)) {
6011 			i++;
6012 			break;
6013 		}
6014 	}
6015 	cpt[i] = 0;
6016 	return 0;
6017 }
6018 
6019 
6020 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
6021 {
6022 	struct p2ps_provision *p2ps_prov;
6023 	char *pos;
6024 	size_t info_len = 0;
6025 	char *info = NULL;
6026 	u8 role = P2PS_SETUP_NONE;
6027 	long long unsigned val;
6028 	int i;
6029 
6030 	pos = os_strstr(cmd, "info=");
6031 	if (pos) {
6032 		pos += 5;
6033 		info_len = os_strlen(pos);
6034 
6035 		if (info_len) {
6036 			info = os_malloc(info_len + 1);
6037 			if (info) {
6038 				info_len = utf8_unescape(pos, info_len,
6039 							 info, info_len + 1);
6040 			} else
6041 				info_len = 0;
6042 		}
6043 	}
6044 
6045 	p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
6046 	if (p2ps_prov == NULL) {
6047 		os_free(info);
6048 		return NULL;
6049 	}
6050 
6051 	if (info) {
6052 		os_memcpy(p2ps_prov->info, info, info_len);
6053 		p2ps_prov->info[info_len] = '\0';
6054 		os_free(info);
6055 	}
6056 
6057 	pos = os_strstr(cmd, "status=");
6058 	if (pos)
6059 		p2ps_prov->status = atoi(pos + 7);
6060 	else
6061 		p2ps_prov->status = -1;
6062 
6063 	pos = os_strstr(cmd, "adv_id=");
6064 	if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
6065 		goto invalid_args;
6066 	p2ps_prov->adv_id = val;
6067 
6068 	pos = os_strstr(cmd, "method=");
6069 	if (pos)
6070 		p2ps_prov->method = strtol(pos + 7, NULL, 16);
6071 	else
6072 		p2ps_prov->method = 0;
6073 
6074 	pos = os_strstr(cmd, "session=");
6075 	if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
6076 		goto invalid_args;
6077 	p2ps_prov->session_id = val;
6078 
6079 	pos = os_strstr(cmd, "adv_mac=");
6080 	if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
6081 		goto invalid_args;
6082 
6083 	pos = os_strstr(cmd, "session_mac=");
6084 	if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
6085 		goto invalid_args;
6086 
6087 	pos = os_strstr(cmd, "cpt=");
6088 	if (pos) {
6089 		if (p2ps_ctrl_parse_cpt_priority(pos + 4,
6090 						 p2ps_prov->cpt_priority))
6091 			goto invalid_args;
6092 	} else {
6093 		p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6094 	}
6095 
6096 	for (i = 0; p2ps_prov->cpt_priority[i]; i++)
6097 		p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
6098 
6099 	/* force conncap with tstCap (no validity checks) */
6100 	pos = os_strstr(cmd, "tstCap=");
6101 	if (pos) {
6102 		role = strtol(pos + 7, NULL, 16);
6103 	} else {
6104 		pos = os_strstr(cmd, "role=");
6105 		if (pos) {
6106 			role = strtol(pos + 5, NULL, 16);
6107 			if (role != P2PS_SETUP_CLIENT &&
6108 			    role != P2PS_SETUP_GROUP_OWNER)
6109 				role = P2PS_SETUP_NONE;
6110 		}
6111 	}
6112 	p2ps_prov->role = role;
6113 
6114 	return p2ps_prov;
6115 
6116 invalid_args:
6117 	os_free(p2ps_prov);
6118 	return NULL;
6119 }
6120 
6121 
6122 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
6123 {
6124 	u8 addr[ETH_ALEN];
6125 	struct p2ps_provision *p2ps_prov;
6126 	char *pos;
6127 
6128 	/* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
6129 
6130 	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6131 
6132 	if (hwaddr_aton(cmd, addr))
6133 		return -1;
6134 
6135 	pos = cmd + 17;
6136 	if (*pos != ' ')
6137 		return -1;
6138 
6139 	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6140 	if (!p2ps_prov)
6141 		return -1;
6142 
6143 	if (p2ps_prov->status < 0) {
6144 		os_free(p2ps_prov);
6145 		return -1;
6146 	}
6147 
6148 	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6149 				  p2ps_prov);
6150 }
6151 
6152 
6153 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
6154 {
6155 	u8 addr[ETH_ALEN];
6156 	struct p2ps_provision *p2ps_prov;
6157 	char *pos;
6158 
6159 	/* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
6160 	 *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
6161 	 */
6162 
6163 	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6164 	if (hwaddr_aton(cmd, addr))
6165 		return -1;
6166 
6167 	pos = cmd + 17;
6168 	if (*pos != ' ')
6169 		return -1;
6170 
6171 	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6172 	if (!p2ps_prov)
6173 		return -1;
6174 
6175 	p2ps_prov->pd_seeker = 1;
6176 
6177 	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6178 				  p2ps_prov);
6179 }
6180 #endif /* LOS_P2P_CROP */
6181 
6182 #ifndef EXT_CODE_CROP
6183 static int parse_freq(int chwidth, int freq2)
6184 {
6185 	if (freq2 < 0)
6186 		return -1;
6187 	if (freq2)
6188 		return CHANWIDTH_80P80MHZ;
6189 
6190 	switch (chwidth) {
6191 	case 0:
6192 	case 20:
6193 	case 40:
6194 		return CHANWIDTH_USE_HT;
6195 	case 80:
6196 		return CHANWIDTH_80MHZ;
6197 	case 160:
6198 		return CHANWIDTH_160MHZ;
6199 	default:
6200 		wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
6201 			   chwidth);
6202 		return -1;
6203 	}
6204 }
6205 #endif /* EXT_CODE_CROP */
6206 
6207 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
6208 			    char *buf, size_t buflen)
6209 {
6210 	u8 addr[ETH_ALEN];
6211 	char *pos, *pos2;
6212 	char *pin = NULL;
6213 	enum p2p_wps_method wps_method;
6214 	int new_pin;
6215 	int ret;
6216 	int persistent_group, persistent_id = -1;
6217 	int join;
6218 	int auth;
6219 	int automatic;
6220 	int go_intent = -1;
6221 	int freq = 0;
6222 	int pd;
6223 	int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
6224 	int edmg;
6225 	u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
6226 	size_t group_ssid_len = 0;
6227 	int he;
6228 	bool allow_6ghz;
6229 
6230 	if (!wpa_s->global->p2p_init_wpa_s)
6231 		return -1;
6232 	if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
6233 		wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
6234 			wpa_s->global->p2p_init_wpa_s->ifname);
6235 		wpa_s = wpa_s->global->p2p_init_wpa_s;
6236 	}
6237 
6238 	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
6239 	 * [persistent|persistent=<network id>]
6240 	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
6241 	 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */
6242 
6243 	if (hwaddr_aton(cmd, addr))
6244 		return -1;
6245 
6246 	pos = cmd + 17;
6247 	if (*pos != ' ')
6248 		return -1;
6249 	pos++;
6250 
6251 	persistent_group = os_strstr(pos, " persistent") != NULL;
6252 	pos2 = os_strstr(pos, " persistent=");
6253 	if (pos2) {
6254 		struct wpa_ssid *ssid;
6255 		persistent_id = atoi(pos2 + 12);
6256 		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6257 		if (ssid == NULL || ssid->disabled != 2 ||
6258 		    ssid->mode != WPAS_MODE_P2P_GO) {
6259 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
6260 				   "SSID id=%d for persistent P2P group (GO)",
6261 				   persistent_id);
6262 			return -1;
6263 		}
6264 	}
6265 	join = os_strstr(pos, " join") != NULL;
6266 	allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
6267 	auth = os_strstr(pos, " auth") != NULL;
6268 	automatic = os_strstr(pos, " auto") != NULL;
6269 	pd = os_strstr(pos, " provdisc") != NULL;
6270 	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6271 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6272 		vht;
6273 	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
6274 	edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
6275 
6276 	pos2 = os_strstr(pos, " go_intent=");
6277 	if (pos2) {
6278 		pos2 += 11;
6279 		go_intent = atoi(pos2);
6280 		if (go_intent < 0 || go_intent > 15)
6281 			return -1;
6282 	}
6283 #ifndef LOS_P2P_CROP
6284 	pos2 = os_strstr(pos, " freq=");
6285 	if (pos2) {
6286 		pos2 += 6;
6287 		freq = atoi(pos2);
6288 		if (freq <= 0)
6289 			return -1;
6290 	}
6291 
6292 	pos2 = os_strstr(pos, " freq2=");
6293 	if (pos2)
6294 		freq2 = atoi(pos2 + 7);
6295 
6296 	pos2 = os_strstr(pos, " max_oper_chwidth=");
6297 	if (pos2)
6298 		chwidth = atoi(pos2 + 18);
6299 
6300 	max_oper_chwidth = parse_freq(chwidth, freq2);
6301 	if (max_oper_chwidth < 0)
6302 		return -1;
6303 
6304 	if (allow_6ghz && chwidth == 40)
6305 		max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
6306 
6307 	pos2 = os_strstr(pos, " ssid=");
6308 	if (pos2) {
6309 		char *end;
6310 
6311 		pos2 += 6;
6312 		end = os_strchr(pos2, ' ');
6313 		if (!end)
6314 			group_ssid_len = os_strlen(pos2) / 2;
6315 		else
6316 			group_ssid_len = (end - pos2) / 2;
6317 		if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
6318 		    hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
6319 			return -1;
6320 		group_ssid = _group_ssid;
6321 	}
6322 #endif /* LOS_P2P_CROP */
6323 
6324 #ifdef LOS_CONFIG_P2P
6325 	if (os_strncmp(pos, "pin", 3) == 0) {
6326 		/* Request random PIN (to be displayed) and enable the PIN */
6327 		wps_method = WPS_PIN_DISPLAY;
6328 	} else if (os_strncmp(pos, "pbc", 3) == 0) {
6329 		wps_method = WPS_PBC;
6330 	} else if (os_strstr(pos, "p2ps") != NULL) {
6331 		wps_method = WPS_P2PS;
6332 	} else {
6333 		pin = pos;
6334 		pos = os_strchr(pin, ' ');
6335 		wps_method = WPS_PIN_KEYPAD;
6336 		if (pos) {
6337 			*pos++ = '\0';
6338 			if (os_strncmp(pos, "display", 7) == 0)
6339 				wps_method = WPS_PIN_DISPLAY;
6340 		}
6341 		if (!wps_pin_str_valid(pin)) {
6342 			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
6343 			return 17;
6344 		}
6345 	}
6346 #endif /* LOS_CONFIG_P2P */
6347 #ifndef LOS_P2P_CROP
6348 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
6349 				   persistent_group, automatic, join,
6350 				   auth, go_intent, freq, freq2, persistent_id,
6351 				   pd, ht40, vht, max_oper_chwidth, he, edmg,
6352 				   group_ssid, group_ssid_len, allow_6ghz);
6353 #else
6354 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
6355 				   persistent_group, automatic, join,
6356 				   auth, go_intent, freq, persistent_id,
6357 				   pd, he, group_ssid, group_ssid_len);
6358 #endif
6359 	if (new_pin == -2) {
6360 		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
6361 		return 25;
6362 	}
6363 	if (new_pin == -3) {
6364 		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
6365 		return 25;
6366 	}
6367 	if (new_pin < 0)
6368 		return -1;
6369 	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
6370 		ret = os_snprintf(buf, buflen, "%08d", new_pin);
6371 		if (os_snprintf_error(buflen, ret))
6372 			return -1;
6373 		printf("\r\n P2P: *************p2p_ctrl_connect pin_code[%s] \r\n", buf);
6374 		return ret;
6375 	}
6376 
6377 	os_memcpy(buf, "OK\n", 3);
6378 	return 3;
6379 }
6380 
6381 #ifndef LOS_P2P_CROP
6382 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
6383 {
6384 	unsigned int timeout = atoi(cmd);
6385 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6386 		wpa_dbg(wpa_s, MSG_INFO,
6387 			"Reject P2P_LISTEN since interface is disabled");
6388 		return -1;
6389 	}
6390 	return wpas_p2p_listen(wpa_s, timeout);
6391 }
6392 
6393 
6394 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
6395 {
6396 	u8 addr[ETH_ALEN];
6397 	char *pos;
6398 	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
6399 
6400 	/* <addr> <config method> [join|auto] */
6401 
6402 	if (hwaddr_aton(cmd, addr))
6403 		return -1;
6404 
6405 	pos = cmd + 17;
6406 	if (*pos != ' ')
6407 		return -1;
6408 	pos++;
6409 
6410 	if (os_strstr(pos, " join") != NULL)
6411 		use = WPAS_P2P_PD_FOR_JOIN;
6412 	else if (os_strstr(pos, " auto") != NULL)
6413 		use = WPAS_P2P_PD_AUTO;
6414 
6415 	return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
6416 }
6417 
6418 
6419 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
6420 			      size_t buflen)
6421 {
6422 	struct wpa_ssid *ssid = wpa_s->current_ssid;
6423 
6424 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6425 	    ssid->passphrase == NULL)
6426 		return -1;
6427 
6428 	os_strlcpy(buf, ssid->passphrase, buflen);
6429 	return os_strlen(buf);
6430 }
6431 #endif /* LOS_P2P_CROP */
6432 
6433 #ifdef LOS_CONFIG_P2P_SERVICE
6434 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
6435 				  char *buf, size_t buflen)
6436 {
6437 	u64 ref;
6438 	int res;
6439 	u8 dst_buf[ETH_ALEN], *dst;
6440 	struct wpabuf *tlvs;
6441 	char *pos;
6442 	size_t len;
6443 
6444 	if (hwaddr_aton(cmd, dst_buf))
6445 		return -1;
6446 	dst = dst_buf;
6447 	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
6448 	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
6449 		dst = NULL;
6450 	pos = cmd + 17;
6451 	if (*pos != ' ')
6452 		return -1;
6453 	pos++;
6454 
6455 	if (os_strncmp(pos, "upnp ", 5) == 0) {
6456 		u8 version;
6457 		pos += 5;
6458 		if (hexstr2bin(pos, &version, 1) < 0)
6459 			return -1;
6460 		pos += 2;
6461 		if (*pos != ' ')
6462 			return -1;
6463 		pos++;
6464 		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
6465 #ifdef CONFIG_WIFI_DISPLAY
6466 	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
6467 		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
6468 #endif /* CONFIG_WIFI_DISPLAY */
6469 	} else if (os_strncmp(pos, "asp ", 4) == 0) {
6470 		char *svc_str;
6471 		char *svc_info = NULL;
6472 		u32 id;
6473 
6474 		pos += 4;
6475 		if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
6476 			return -1;
6477 
6478 		pos = os_strchr(pos, ' ');
6479 		if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
6480 			return -1;
6481 
6482 		svc_str = pos + 1;
6483 
6484 		pos = os_strchr(svc_str, ' ');
6485 
6486 		if (pos)
6487 			*pos++ = '\0';
6488 
6489 		/* All remaining data is the svc_info string */
6490 		if (pos && pos[0] && pos[0] != ' ') {
6491 			len = os_strlen(pos);
6492 
6493 			/* Unescape in place */
6494 			len = utf8_unescape(pos, len, pos, len);
6495 			if (len > 0xff)
6496 				return -1;
6497 
6498 			svc_info = pos;
6499 		}
6500 
6501 		ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
6502 					      svc_str, svc_info);
6503 	} else {
6504 		len = os_strlen(pos);
6505 		if (len & 1)
6506 			return -1;
6507 		len /= 2;
6508 		tlvs = wpabuf_alloc(len);
6509 		if (tlvs == NULL)
6510 			return -1;
6511 		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
6512 			wpabuf_free(tlvs);
6513 			return -1;
6514 		}
6515 
6516 		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
6517 		wpabuf_free(tlvs);
6518 	}
6519 	if (ref == 0)
6520 		return -1;
6521 	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
6522 	if (os_snprintf_error(buflen, res))
6523 		return -1;
6524 	return res;
6525 }
6526 
6527 
6528 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
6529 					 char *cmd)
6530 {
6531 	long long unsigned val;
6532 	u64 req;
6533 	if (sscanf(cmd, "%llx", &val) != 1)
6534 		return -1;
6535 	req = val;
6536 	return wpas_p2p_sd_cancel_request(wpa_s, req);
6537 }
6538 
6539 
6540 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
6541 {
6542 	int freq;
6543 	u8 dst[ETH_ALEN];
6544 	u8 dialog_token;
6545 	struct wpabuf *resp_tlvs;
6546 	char *pos, *pos2;
6547 	size_t len;
6548 
6549 	pos = os_strchr(cmd, ' ');
6550 	if (pos == NULL)
6551 		return -1;
6552 	*pos++ = '\0';
6553 	freq = atoi(cmd);
6554 	if (freq == 0)
6555 		return -1;
6556 
6557 	if (hwaddr_aton(pos, dst))
6558 		return -1;
6559 	pos += 17;
6560 	if (*pos != ' ')
6561 		return -1;
6562 	pos++;
6563 
6564 	pos2 = os_strchr(pos, ' ');
6565 	if (pos2 == NULL)
6566 		return -1;
6567 	*pos2++ = '\0';
6568 	dialog_token = atoi(pos);
6569 
6570 	len = os_strlen(pos2);
6571 	if (len & 1)
6572 		return -1;
6573 	len /= 2;
6574 	resp_tlvs = wpabuf_alloc(len);
6575 	if (resp_tlvs == NULL)
6576 		return -1;
6577 	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
6578 		wpabuf_free(resp_tlvs);
6579 		return -1;
6580 	}
6581 
6582 	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
6583 	wpabuf_free(resp_tlvs);
6584 	return 0;
6585 }
6586 
6587 
6588 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
6589 				       char *cmd)
6590 {
6591 	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
6592 		return -1;
6593 	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
6594 	return 0;
6595 }
6596 
6597 
6598 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
6599 					char *cmd)
6600 {
6601 	char *pos;
6602 	size_t len;
6603 	struct wpabuf *query, *resp;
6604 
6605 	pos = os_strchr(cmd, ' ');
6606 	if (pos == NULL)
6607 		return -1;
6608 	*pos++ = '\0';
6609 
6610 	len = os_strlen(cmd);
6611 	if (len & 1)
6612 		return -1;
6613 	len /= 2;
6614 	query = wpabuf_alloc(len);
6615 	if (query == NULL)
6616 		return -1;
6617 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6618 		wpabuf_free(query);
6619 		return -1;
6620 	}
6621 
6622 	len = os_strlen(pos);
6623 	if (len & 1) {
6624 		wpabuf_free(query);
6625 		return -1;
6626 	}
6627 	len /= 2;
6628 	resp = wpabuf_alloc(len);
6629 	if (resp == NULL) {
6630 		wpabuf_free(query);
6631 		return -1;
6632 	}
6633 	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
6634 		wpabuf_free(query);
6635 		wpabuf_free(resp);
6636 		return -1;
6637 	}
6638 
6639 	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
6640 		wpabuf_free(query);
6641 		wpabuf_free(resp);
6642 		return -1;
6643 	}
6644 	return 0;
6645 }
6646 
6647 
6648 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6649 {
6650 	char *pos;
6651 	u8 version;
6652 
6653 	pos = os_strchr(cmd, ' ');
6654 	if (pos == NULL)
6655 		return -1;
6656 	*pos++ = '\0';
6657 
6658 	if (hexstr2bin(cmd, &version, 1) < 0)
6659 		return -1;
6660 
6661 	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6662 }
6663 
6664 
6665 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6666 				    u8 replace, char *cmd)
6667 {
6668 	char *pos;
6669 	char *adv_str;
6670 	u32 auto_accept, adv_id, svc_state, config_methods;
6671 	char *svc_info = NULL;
6672 	char *cpt_prio_str;
6673 	u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
6674 
6675 	pos = os_strchr(cmd, ' ');
6676 	if (pos == NULL)
6677 		return -1;
6678 	*pos++ = '\0';
6679 
6680 	/* Auto-Accept value is mandatory, and must be one of the
6681 	 * single values (0, 1, 2, 4) */
6682 	auto_accept = atoi(cmd);
6683 	switch (auto_accept) {
6684 	case P2PS_SETUP_NONE: /* No auto-accept */
6685 	case P2PS_SETUP_NEW:
6686 	case P2PS_SETUP_CLIENT:
6687 	case P2PS_SETUP_GROUP_OWNER:
6688 		break;
6689 	default:
6690 		return -1;
6691 	}
6692 
6693 	/* Advertisement ID is mandatory */
6694 	cmd = pos;
6695 	pos = os_strchr(cmd, ' ');
6696 	if (pos == NULL)
6697 		return -1;
6698 	*pos++ = '\0';
6699 
6700 	/* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6701 	if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6702 		return -1;
6703 
6704 	/* Only allow replacements if exist, and adds if not */
6705 	if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6706 		if (!replace)
6707 			return -1;
6708 	} else {
6709 		if (replace)
6710 			return -1;
6711 	}
6712 
6713 	/* svc_state between 0 - 0xff is mandatory */
6714 	if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6715 		return -1;
6716 
6717 	pos = os_strchr(pos, ' ');
6718 	if (pos == NULL)
6719 		return -1;
6720 
6721 	/* config_methods is mandatory */
6722 	pos++;
6723 	if (sscanf(pos, "%x", &config_methods) != 1)
6724 		return -1;
6725 
6726 	if (!(config_methods &
6727 	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6728 		return -1;
6729 
6730 	pos = os_strchr(pos, ' ');
6731 	if (pos == NULL)
6732 		return -1;
6733 
6734 	pos++;
6735 	adv_str = pos;
6736 
6737 	/* Advertisement string is mandatory */
6738 	if (!pos[0] || pos[0] == ' ')
6739 		return -1;
6740 
6741 	/* Terminate svc string */
6742 	pos = os_strchr(pos, ' ');
6743 	if (pos != NULL)
6744 		*pos++ = '\0';
6745 
6746 	cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6747 	if (cpt_prio_str) {
6748 		pos = os_strchr(pos, ' ');
6749 		if (pos != NULL)
6750 			*pos++ = '\0';
6751 #ifndef LOS_P2P_CROP
6752 		if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6753 			return -1;
6754 #endif /* LOS_P2P_CROP */
6755 	} else {
6756 		cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6757 		cpt_prio[1] = 0;
6758 	}
6759 
6760 	/* Service and Response Information are optional */
6761 	if (pos && pos[0]) {
6762 		size_t len;
6763 
6764 		/* Note the bare ' included, which cannot exist legally
6765 		 * in unescaped string. */
6766 		svc_info = os_strstr(pos, "svc_info='");
6767 
6768 		if (svc_info) {
6769 			svc_info += 9;
6770 			len = os_strlen(svc_info);
6771 			utf8_unescape(svc_info, len, svc_info, len);
6772 		}
6773 	}
6774 
6775 	return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
6776 					(u8) svc_state, (u16) config_methods,
6777 					svc_info, cpt_prio);
6778 }
6779 
6780 
6781 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
6782 {
6783 	char *pos;
6784 
6785 	pos = os_strchr(cmd, ' ');
6786 	if (pos == NULL)
6787 		return -1;
6788 	*pos++ = '\0';
6789 
6790 	if (os_strcmp(cmd, "bonjour") == 0)
6791 		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
6792 	if (os_strcmp(cmd, "upnp") == 0)
6793 		return p2p_ctrl_service_add_upnp(wpa_s, pos);
6794 	if (os_strcmp(cmd, "asp") == 0)
6795 		return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
6796 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6797 	return -1;
6798 }
6799 
6800 
6801 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
6802 					char *cmd)
6803 {
6804 	size_t len;
6805 	struct wpabuf *query;
6806 	int ret;
6807 
6808 	len = os_strlen(cmd);
6809 	if (len & 1)
6810 		return -1;
6811 	len /= 2;
6812 	query = wpabuf_alloc(len);
6813 	if (query == NULL)
6814 		return -1;
6815 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6816 		wpabuf_free(query);
6817 		return -1;
6818 	}
6819 
6820 	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
6821 	wpabuf_free(query);
6822 	return ret;
6823 }
6824 
6825 
6826 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6827 {
6828 	char *pos;
6829 	u8 version;
6830 
6831 	pos = os_strchr(cmd, ' ');
6832 	if (pos == NULL)
6833 		return -1;
6834 	*pos++ = '\0';
6835 
6836 	if (hexstr2bin(cmd, &version, 1) < 0)
6837 		return -1;
6838 
6839 	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
6840 }
6841 
6842 
6843 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
6844 {
6845 	u32 adv_id;
6846 
6847 	if (os_strcmp(cmd, "all") == 0) {
6848 		wpas_p2p_service_flush_asp(wpa_s);
6849 		return 0;
6850 	}
6851 
6852 	if (sscanf(cmd, "%x", &adv_id) != 1)
6853 		return -1;
6854 
6855 	return wpas_p2p_service_del_asp(wpa_s, adv_id);
6856 }
6857 
6858 
6859 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
6860 {
6861 	char *pos;
6862 
6863 	pos = os_strchr(cmd, ' ');
6864 	if (pos == NULL)
6865 		return -1;
6866 	*pos++ = '\0';
6867 
6868 	if (os_strcmp(cmd, "bonjour") == 0)
6869 		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
6870 	if (os_strcmp(cmd, "upnp") == 0)
6871 		return p2p_ctrl_service_del_upnp(wpa_s, pos);
6872 	if (os_strcmp(cmd, "asp") == 0)
6873 		return p2p_ctrl_service_del_asp(wpa_s, pos);
6874 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6875 	return -1;
6876 }
6877 
6878 
6879 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
6880 {
6881 	char *pos;
6882 
6883 	pos = os_strchr(cmd, ' ');
6884 	if (pos == NULL)
6885 		return -1;
6886 	*pos++ = '\0';
6887 
6888 	if (os_strcmp(cmd, "asp") == 0)
6889 		return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
6890 
6891 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6892 	return -1;
6893 }
6894 #endif /* LOS_CONFIG_P2P_SERVICE */
6895 
6896 
6897 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
6898 {
6899 	u8 addr[ETH_ALEN];
6900 
6901 	/* <addr> */
6902 
6903 	if (hwaddr_aton(cmd, addr))
6904 		return -1;
6905 
6906 	return wpas_p2p_reject(wpa_s, addr);
6907 }
6908 
6909 
6910 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
6911 {
6912 	char *pos;
6913 	int id;
6914 	struct wpa_ssid *ssid;
6915 	u8 *_peer = NULL, peer[ETH_ALEN];
6916 	int freq = 0, pref_freq = 0;
6917 	int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
6918 	int edmg;
6919 	bool allow_6ghz;
6920 
6921 	id = atoi(cmd);
6922 	pos = os_strstr(cmd, " peer=");
6923 	if (pos) {
6924 		pos += 6;
6925 		if (hwaddr_aton(pos, peer))
6926 			return -1;
6927 		_peer = peer;
6928 	}
6929 	ssid = wpa_config_get_network(wpa_s->conf, id);
6930 	if (ssid == NULL || ssid->disabled != 2) {
6931 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
6932 			   "for persistent P2P group",
6933 			   id);
6934 		return -1;
6935 	}
6936 #ifndef LOS_P2P_CROP
6937 	pos = os_strstr(cmd, " freq=");
6938 	if (pos) {
6939 		pos += 6;
6940 		freq = atoi(pos);
6941 		if (freq <= 0)
6942 			return -1;
6943 	}
6944 
6945 	pos = os_strstr(cmd, " pref=");
6946 	if (pos) {
6947 		pos += 6;
6948 		pref_freq = atoi(pos);
6949 		if (pref_freq <= 0)
6950 			return -1;
6951 	}
6952 
6953 	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6954 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6955 		vht;
6956 	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
6957 	edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
6958 
6959 	pos = os_strstr(cmd, "freq2=");
6960 	if (pos)
6961 		freq2 = atoi(pos + 6);
6962 
6963 	pos = os_strstr(cmd, " max_oper_chwidth=");
6964 	if (pos)
6965 		chwidth = atoi(pos + 18);
6966 
6967 	max_oper_chwidth = parse_freq(chwidth, freq2);
6968 	if (max_oper_chwidth < 0)
6969 		return -1;
6970 
6971 	allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
6972 
6973 	if (allow_6ghz && chwidth == 40)
6974 		max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
6975 
6976 	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
6977 			       max_oper_chwidth, pref_freq, he, edmg,
6978 			       allow_6ghz);
6979 #else
6980 	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, pref_freq, he);
6981 #endif
6982 }
6983 
6984 
6985 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
6986 {
6987 	char *pos;
6988 	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
6989 	bool allow_6ghz;
6990 
6991 	pos = os_strstr(cmd, " peer=");
6992 	if (!pos)
6993 		return -1;
6994 
6995 	*pos = '\0';
6996 	pos += 6;
6997 	if (hwaddr_aton(pos, peer)) {
6998 		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
6999 		return -1;
7000 	}
7001 
7002 	allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
7003 
7004 	pos = os_strstr(pos, " go_dev_addr=");
7005 	if (pos) {
7006 		pos += 13;
7007 		if (hwaddr_aton(pos, go_dev_addr)) {
7008 			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
7009 				   pos);
7010 			return -1;
7011 		}
7012 		go_dev = go_dev_addr;
7013 	}
7014 
7015 	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
7016 }
7017 
7018 
7019 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
7020 {
7021 	if (os_strncmp(cmd, "persistent=", 11) == 0)
7022 		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
7023 	if (os_strncmp(cmd, "group=", 6) == 0)
7024 		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
7025 
7026 	return -1;
7027 }
7028 
7029 
7030 #ifndef LOS_P2P_CROP
7031 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
7032 					 int id, int freq, int vht_center_freq2,
7033 					 int ht40, int vht, int vht_chwidth,
7034 					 int he, int edmg, bool allow_6ghz)
7035 {
7036 	struct wpa_ssid *ssid;
7037 
7038 	ssid = wpa_config_get_network(wpa_s->conf, id);
7039 	if (ssid == NULL || ssid->disabled != 2) {
7040 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7041 			   "for persistent P2P group",
7042 			   id);
7043 		return -1;
7044 	}
7045 
7046 	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
7047 					     vht_center_freq2, 0, ht40, vht,
7048 					     vht_chwidth, he, edmg,
7049 					     NULL, 0, 0, allow_6ghz);
7050 }
7051 
7052 
7053 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
7054 {
7055 	int freq = 0, persistent = 0, group_id = -1;
7056 	bool allow_6ghz = false;
7057 	int vht = wpa_s->conf->p2p_go_vht;
7058 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
7059 	int he = wpa_s->conf->p2p_go_he;
7060 	int edmg = wpa_s->conf->p2p_go_edmg;
7061 	int max_oper_chwidth, chwidth = 0, freq2 = 0;
7062 	char *token, *context = NULL;
7063 #ifdef CONFIG_ACS
7064 	int acs = 0;
7065 #endif /* CONFIG_ACS */
7066 
7067 	while ((token = str_token(cmd, " ", &context))) {
7068 		if (sscanf(token, "freq2=%d", &freq2) == 1 ||
7069 		    sscanf(token, "persistent=%d", &group_id) == 1 ||
7070 		    sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
7071 			continue;
7072 #ifdef CONFIG_ACS
7073 		} else if (os_strcmp(token, "freq=acs") == 0) {
7074 			acs = 1;
7075 #endif /* CONFIG_ACS */
7076 		} else if (sscanf(token, "freq=%d", &freq) == 1) {
7077 			continue;
7078 		} else if (os_strcmp(token, "ht40") == 0) {
7079 			ht40 = 1;
7080 		} else if (os_strcmp(token, "vht") == 0) {
7081 			vht = 1;
7082 			ht40 = 1;
7083 		} else if (os_strcmp(token, "he") == 0) {
7084 			he = 1;
7085 		} else if (os_strcmp(token, "edmg") == 0) {
7086 			edmg = 1;
7087 		} else if (os_strcmp(token, "persistent") == 0) {
7088 			persistent = 1;
7089 		} else if (os_strcmp(token, "allow_6ghz") == 0) {
7090 			allow_6ghz = true;
7091 		} else {
7092 			wpa_printf(MSG_DEBUG,
7093 				   "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
7094 				   token);
7095 			return -1;
7096 		}
7097 	}
7098 
7099 #ifdef CONFIG_ACS
7100 	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
7101 	    (acs || freq == 2 || freq == 5)) {
7102 		if (freq == 2 && wpa_s->best_24_freq <= 0) {
7103 			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
7104 			wpa_s->p2p_go_do_acs = 1;
7105 			freq = 0;
7106 		} else if (freq == 5 && wpa_s->best_5_freq <= 0) {
7107 			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
7108 			wpa_s->p2p_go_do_acs = 1;
7109 			freq = 0;
7110 		} else {
7111 			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
7112 			wpa_s->p2p_go_do_acs = 1;
7113 		}
7114 	} else {
7115 		wpa_s->p2p_go_do_acs = 0;
7116 	}
7117 #endif /* CONFIG_ACS */
7118 #ifndef EXT_CODE_CROP
7119 	max_oper_chwidth = parse_freq(chwidth, freq2);
7120 	if (max_oper_chwidth < 0)
7121 		return -1;
7122 
7123 	if (allow_6ghz && chwidth == 40)
7124 		max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
7125 
7126 	/* Allow DFS to be used for Autonomous GO */
7127 	wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
7128 				     WPA_DRIVER_FLAGS_DFS_OFFLOAD);
7129 
7130 	if (group_id >= 0)
7131 		return p2p_ctrl_group_add_persistent(wpa_s, group_id,
7132 						     freq, freq2, ht40, vht,
7133 						     max_oper_chwidth, he,
7134 						     edmg, allow_6ghz);
7135 
7136 	return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
7137 				  max_oper_chwidth, he, edmg, allow_6ghz);
7138 #else
7139 	if (group_id >= 0)
7140 		return p2p_ctrl_group_add_persistent(wpa_s, group_id,
7141 							 freq, he);
7142 
7143 	return wpas_p2p_group_add(wpa_s, persistent, freq, he);
7144 #endif /* EXT_CODE_CROP */
7145 }
7146 
7147 
7148 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
7149 				 char *buf, size_t buflen)
7150 {
7151 	u8 dev_addr[ETH_ALEN];
7152 	struct wpa_ssid *ssid;
7153 	int res;
7154 	const u8 *iaddr;
7155 
7156 	ssid = wpa_s->current_ssid;
7157 	if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
7158 	    hwaddr_aton(cmd, dev_addr))
7159 		return -1;
7160 
7161 	iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
7162 	if (!iaddr)
7163 		return -1;
7164 	res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
7165 	if (os_snprintf_error(buflen, res))
7166 		return -1;
7167 	return res;
7168 }
7169 #endif /* LOS_P2P_CROP */
7170 
7171 
7172 #ifndef EXT_CODE_CROP
7173 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
7174 				      const u8 *p2p_dev_addr)
7175 {
7176 	struct wpa_supplicant *wpa_s;
7177 
7178 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7179 		if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
7180 			return 1;
7181 	}
7182 
7183 	return 0;
7184 }
7185 
7186 
7187 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
7188 			 char *buf, size_t buflen)
7189 {
7190 	u8 addr[ETH_ALEN], *addr_ptr, group_capab;
7191 	int next, res;
7192 	const struct p2p_peer_info *info;
7193 	char *pos, *end;
7194 	char devtype[WPS_DEV_TYPE_BUFSIZE];
7195 	struct wpa_ssid *ssid;
7196 	size_t i;
7197 
7198 	if (!wpa_s->global->p2p)
7199 		return -1;
7200 
7201 	if (os_strcmp(cmd, "FIRST") == 0) {
7202 		addr_ptr = NULL;
7203 		next = 0;
7204 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
7205 		if (hwaddr_aton(cmd + 5, addr) < 0)
7206 			return -1;
7207 		addr_ptr = addr;
7208 		next = 1;
7209 	} else {
7210 		if (hwaddr_aton(cmd, addr) < 0)
7211 			return -1;
7212 		addr_ptr = addr;
7213 		next = 0;
7214 	}
7215 
7216 	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
7217 	if (info == NULL)
7218 		return -1;
7219 	group_capab = info->group_capab;
7220 
7221 	if (group_capab &&
7222 	    !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
7223 		wpa_printf(MSG_DEBUG,
7224 			   "P2P: Could not find any BSS with p2p_dev_addr "
7225 			   MACSTR ", hence override group_capab from 0x%x to 0",
7226 			   MAC2STR(info->p2p_device_addr), group_capab);
7227 		group_capab = 0;
7228 	}
7229 
7230 	pos = buf;
7231 	end = buf + buflen;
7232 
7233 	res = os_snprintf(pos, end - pos, MACSTR "\n"
7234 			  "pri_dev_type=%s\n"
7235 			  "device_name=%s\n"
7236 			  "manufacturer=%s\n"
7237 			  "model_name=%s\n"
7238 			  "model_number=%s\n"
7239 			  "serial_number=%s\n"
7240 			  "config_methods=0x%x\n"
7241 			  "dev_capab=0x%x\n"
7242 			  "group_capab=0x%x\n"
7243 			  "level=%d\n",
7244 			  MAC2STR(info->p2p_device_addr),
7245 			  wps_dev_type_bin2str(info->pri_dev_type,
7246 					       devtype, sizeof(devtype)),
7247 			  info->device_name,
7248 			  info->manufacturer,
7249 			  info->model_name,
7250 			  info->model_number,
7251 			  info->serial_number,
7252 			  info->config_methods,
7253 			  info->dev_capab,
7254 			  group_capab,
7255 			  info->level);
7256 	if (os_snprintf_error(end - pos, res))
7257 		return pos - buf;
7258 	pos += res;
7259 
7260 	for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
7261 	{
7262 		const u8 *t;
7263 		t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
7264 		res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
7265 				  wps_dev_type_bin2str(t, devtype,
7266 						       sizeof(devtype)));
7267 		if (os_snprintf_error(end - pos, res))
7268 			return pos - buf;
7269 		pos += res;
7270 	}
7271 
7272 	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
7273 	if (ssid) {
7274 		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
7275 		if (os_snprintf_error(end - pos, res))
7276 			return pos - buf;
7277 		pos += res;
7278 	}
7279 
7280 	res = p2p_get_peer_info_txt(info, pos, end - pos);
7281 	if (res < 0)
7282 		return pos - buf;
7283 	pos += res;
7284 
7285 	if (info->vendor_elems) {
7286 		res = os_snprintf(pos, end - pos, "vendor_elems=");
7287 		if (os_snprintf_error(end - pos, res))
7288 			return pos - buf;
7289 		pos += res;
7290 
7291 		pos += wpa_snprintf_hex(pos, end - pos,
7292 					wpabuf_head(info->vendor_elems),
7293 					wpabuf_len(info->vendor_elems));
7294 
7295 		res = os_snprintf(pos, end - pos, "\n");
7296 		if (os_snprintf_error(end - pos, res))
7297 			return pos - buf;
7298 		pos += res;
7299 	}
7300 
7301 	return pos - buf;
7302 }
7303 #else
7304 #ifdef LOS_CONFIG_P2P
7305 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
7306 			 char *buf, size_t buflen)
7307 {
7308 	size_t i = 0;
7309 	u8 *addr_ptr = NULL;
7310 	u8 addr[ETH_ALEN];
7311 	int next = 0;
7312 	const struct p2p_peer_info *info;
7313 	int res;
7314 	struct wpa_ssid *ssid;
7315 	(void)cmd;
7316 	(void)buf;
7317 	(void)buflen;
7318 
7319 	if (g_p2p_peers_discoverd == 0 || g_p2p_peers == NULL)
7320 		return -1;
7321 
7322 	g_p2p_peers_discoverd = WPA_MIN(g_p2p_peers_discoverd, P2P_SCAN_DEVICE_LIMIT);
7323 	while (i < g_p2p_peers_discoverd) {
7324 		info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
7325 		if (info == NULL)
7326 			break;
7327 
7328 		(void)os_memcpy(g_p2p_peers[i].device_addr, info->p2p_device_addr, ETH_ALEN);
7329 		res = os_snprintf(g_p2p_peers[i].device_name , sizeof(g_p2p_peers[i].device_name), "%s", info->device_name);
7330 		if (res < 0)
7331 			return -1;
7332 
7333 		g_p2p_peers[i].config_methods = info->config_methods;
7334 		g_p2p_peers[i].group_capab = info->group_capab;
7335 
7336 		(void)os_memcpy(addr, info->p2p_device_addr, ETH_ALEN);
7337 		ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
7338 		if (ssid)
7339 			g_p2p_peers[i].persistent_id = ssid->id;
7340 		else
7341 			g_p2p_peers[i].persistent_id = -1;
7342 
7343 		addr_ptr = addr;
7344 		next = 1;
7345 		i++;
7346 	}
7347 	g_p2p_peers_discoverd = i;
7348 	g_p2p_peers = NULL;
7349 
7350 	return 0;
7351 }
7352 #endif /* LOS_CONFIG_P2P */
7353 #endif /* EXT_CODE_CROP */
7354 
7355 #ifndef LOS_P2P_CROP
7356 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
7357 				  const char *param)
7358 {
7359 	unsigned int i;
7360 
7361 	if (wpa_s->global->p2p == NULL)
7362 		return -1;
7363 
7364 	if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
7365 		return -1;
7366 
7367 	for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
7368 		struct wpa_freq_range *freq;
7369 		freq = &wpa_s->global->p2p_disallow_freq.range[i];
7370 		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
7371 			   freq->min, freq->max);
7372 	}
7373 
7374 	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
7375 	return 0;
7376 }
7377 
7378 
7379 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
7380 {
7381 	char *param;
7382 
7383 	if (wpa_s->global->p2p == NULL)
7384 		return -1;
7385 
7386 	param = os_strchr(cmd, ' ');
7387 	if (param == NULL)
7388 		return -1;
7389 	*param++ = '\0';
7390 
7391 	if (os_strcmp(cmd, "discoverability") == 0) {
7392 		p2p_set_client_discoverability(wpa_s->global->p2p,
7393 					       atoi(param));
7394 		return 0;
7395 	}
7396 
7397 	if (os_strcmp(cmd, "managed") == 0) {
7398 		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
7399 		return 0;
7400 	}
7401 
7402 	if (os_strcmp(cmd, "listen_channel") == 0) {
7403 		char *pos;
7404 		u8 channel, op_class;
7405 
7406 		channel = atoi(param);
7407 		pos = os_strchr(param, ' ');
7408 		op_class = pos ? atoi(pos) : 81;
7409 
7410 		return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
7411 					      channel, 1);
7412 	}
7413 
7414 	if (os_strcmp(cmd, "ssid_postfix") == 0) {
7415 		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
7416 					    os_strlen(param));
7417 	}
7418 
7419 	if (os_strcmp(cmd, "noa") == 0) {
7420 		char *pos;
7421 		int count, start, duration;
7422 		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
7423 		count = atoi(param);
7424 		pos = os_strchr(param, ',');
7425 		if (pos == NULL)
7426 			return -1;
7427 		pos++;
7428 		start = atoi(pos);
7429 		pos = os_strchr(pos, ',');
7430 		if (pos == NULL)
7431 			return -1;
7432 		pos++;
7433 		duration = atoi(pos);
7434 		if (count < 0 || count > 255 || start < 0 || duration < 0)
7435 			return -1;
7436 		if (count == 0 && duration > 0)
7437 			return -1;
7438 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
7439 			   "start=%d duration=%d", count, start, duration);
7440 		return wpas_p2p_set_noa(wpa_s, count, start, duration);
7441 	}
7442 
7443 	if (os_strcmp(cmd, "ps") == 0)
7444 		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
7445 
7446 	if (os_strcmp(cmd, "oppps") == 0)
7447 		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
7448 
7449 	if (os_strcmp(cmd, "ctwindow") == 0)
7450 		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
7451 
7452 	if (os_strcmp(cmd, "disabled") == 0) {
7453 		wpa_s->global->p2p_disabled = atoi(param);
7454 		wpa_printf(MSG_DEBUG, "P2P functionality %s",
7455 			   wpa_s->global->p2p_disabled ?
7456 			   "disabled" : "enabled");
7457 		if (wpa_s->global->p2p_disabled) {
7458 			wpas_p2p_stop_find(wpa_s);
7459 			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7460 			p2p_flush(wpa_s->global->p2p);
7461 		}
7462 		return 0;
7463 	}
7464 
7465 	if (os_strcmp(cmd, "conc_pref") == 0) {
7466 		if (os_strcmp(param, "sta") == 0)
7467 			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
7468 		else if (os_strcmp(param, "p2p") == 0)
7469 			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
7470 		else {
7471 			wpa_printf(MSG_INFO, "Invalid conc_pref value");
7472 			return -1;
7473 		}
7474 		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
7475 			   "%s", param);
7476 		return 0;
7477 	}
7478 
7479 	if (os_strcmp(cmd, "force_long_sd") == 0) {
7480 		wpa_s->force_long_sd = atoi(param);
7481 		return 0;
7482 	}
7483 
7484 	if (os_strcmp(cmd, "peer_filter") == 0) {
7485 		u8 addr[ETH_ALEN];
7486 		if (hwaddr_aton(param, addr))
7487 			return -1;
7488 		p2p_set_peer_filter(wpa_s->global->p2p, addr);
7489 		return 0;
7490 	}
7491 
7492 	if (os_strcmp(cmd, "cross_connect") == 0)
7493 		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
7494 
7495 	if (os_strcmp(cmd, "go_apsd") == 0) {
7496 		if (os_strcmp(param, "disable") == 0)
7497 			wpa_s->set_ap_uapsd = 0;
7498 		else {
7499 			wpa_s->set_ap_uapsd = 1;
7500 			wpa_s->ap_uapsd = atoi(param);
7501 		}
7502 		return 0;
7503 	}
7504 
7505 	if (os_strcmp(cmd, "client_apsd") == 0) {
7506 		if (os_strcmp(param, "disable") == 0)
7507 			wpa_s->set_sta_uapsd = 0;
7508 		else {
7509 			int be, bk, vi, vo;
7510 			char *pos;
7511 			/* format: BE,BK,VI,VO;max SP Length */
7512 			be = atoi(param);
7513 			pos = os_strchr(param, ',');
7514 			if (pos == NULL)
7515 				return -1;
7516 			pos++;
7517 			bk = atoi(pos);
7518 			pos = os_strchr(pos, ',');
7519 			if (pos == NULL)
7520 				return -1;
7521 			pos++;
7522 			vi = atoi(pos);
7523 			pos = os_strchr(pos, ',');
7524 			if (pos == NULL)
7525 				return -1;
7526 			pos++;
7527 			vo = atoi(pos);
7528 			/* ignore max SP Length for now */
7529 
7530 			wpa_s->set_sta_uapsd = 1;
7531 			wpa_s->sta_uapsd = 0;
7532 			if (be)
7533 				wpa_s->sta_uapsd |= BIT(0);
7534 			if (bk)
7535 				wpa_s->sta_uapsd |= BIT(1);
7536 			if (vi)
7537 				wpa_s->sta_uapsd |= BIT(2);
7538 			if (vo)
7539 				wpa_s->sta_uapsd |= BIT(3);
7540 		}
7541 		return 0;
7542 	}
7543 
7544 	if (os_strcmp(cmd, "disallow_freq") == 0)
7545 		return p2p_ctrl_disallow_freq(wpa_s, param);
7546 
7547 	if (os_strcmp(cmd, "disc_int") == 0) {
7548 		int min_disc_int, max_disc_int, max_disc_tu;
7549 		char *pos;
7550 
7551 		pos = param;
7552 
7553 		min_disc_int = atoi(pos);
7554 		pos = os_strchr(pos, ' ');
7555 		if (pos == NULL)
7556 			return -1;
7557 		*pos++ = '\0';
7558 
7559 		max_disc_int = atoi(pos);
7560 		pos = os_strchr(pos, ' ');
7561 		if (pos == NULL)
7562 			return -1;
7563 		*pos++ = '\0';
7564 
7565 		max_disc_tu = atoi(pos);
7566 
7567 		return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
7568 					max_disc_int, max_disc_tu);
7569 	}
7570 
7571 	if (os_strcmp(cmd, "per_sta_psk") == 0) {
7572 		wpa_s->global->p2p_per_sta_psk = !!atoi(param);
7573 		return 0;
7574 	}
7575 
7576 #ifdef CONFIG_WPS_NFC
7577 	if (os_strcmp(cmd, "nfc_tag") == 0)
7578 		return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
7579 #endif /* CONFIG_WPS_NFC */
7580 
7581 	if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
7582 		wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
7583 		return 0;
7584 	}
7585 
7586 	if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
7587 		int op_class, chan;
7588 
7589 		op_class = atoi(param);
7590 		param = os_strchr(param, ':');
7591 		if (!param)
7592 			return -1;
7593 		param++;
7594 		chan = atoi(param);
7595 		p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
7596 					      chan);
7597 		return 0;
7598 	}
7599 
7600 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
7601 		   cmd);
7602 
7603 	return -1;
7604 }
7605 
7606 
7607 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
7608 {
7609 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7610 	wpa_s->force_long_sd = 0;
7611 
7612 #ifdef CONFIG_TESTING_OPTIONS
7613 	os_free(wpa_s->get_pref_freq_list_override);
7614 	wpa_s->get_pref_freq_list_override = NULL;
7615 #endif /* CONFIG_TESTING_OPTIONS */
7616 
7617 	wpas_p2p_stop_find(wpa_s);
7618 	wpa_s->parent->p2ps_method_config_any = 0;
7619 	if (wpa_s->global->p2p)
7620 		p2p_flush(wpa_s->global->p2p);
7621 }
7622 
7623 
7624 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
7625 {
7626 	char *pos, *pos2;
7627 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
7628 
7629 	if (cmd[0]) {
7630 		pos = os_strchr(cmd, ' ');
7631 		if (pos == NULL)
7632 			return -1;
7633 		*pos++ = '\0';
7634 		dur1 = atoi(cmd);
7635 
7636 		pos2 = os_strchr(pos, ' ');
7637 		if (pos2)
7638 			*pos2++ = '\0';
7639 		int1 = atoi(pos);
7640 	} else
7641 		pos2 = NULL;
7642 
7643 	if (pos2) {
7644 		pos = os_strchr(pos2, ' ');
7645 		if (pos == NULL)
7646 			return -1;
7647 		*pos++ = '\0';
7648 		dur2 = atoi(pos2);
7649 		int2 = atoi(pos);
7650 	}
7651 
7652 	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
7653 }
7654 #endif /* LOS_P2P_CROP */
7655 
7656 
7657 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
7658 {
7659 	char *pos;
7660 	unsigned int period = 0, interval = 0;
7661 
7662 	if (cmd[0]) {
7663 		pos = os_strchr(cmd, ' ');
7664 		if (pos == NULL)
7665 			return -1;
7666 		*pos++ = '\0';
7667 		period = atoi(cmd);
7668 		interval = atoi(pos);
7669 	}
7670 
7671 	return wpas_p2p_ext_listen(wpa_s, period, interval);
7672 }
7673 
7674 
7675 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
7676 {
7677 	const char *pos;
7678 	u8 peer[ETH_ALEN];
7679 	int iface_addr = 0;
7680 
7681 	pos = cmd;
7682 	if (os_strncmp(pos, "iface=", 6) == 0) {
7683 		iface_addr = 1;
7684 		pos += 6;
7685 	}
7686 	if (hwaddr_aton(pos, peer))
7687 		return -1;
7688 
7689 	wpas_p2p_remove_client(wpa_s, peer, iface_addr);
7690 	return 0;
7691 }
7692 
7693 #ifdef LOS_CONFIG_P2P
7694 static int p2p_update_str(char **dst, const char *src, size_t len)
7695 {
7696 	if ((dst == NULL) || (src == NULL) || (len == 0))
7697 		return -1;
7698 	char *tmp = os_zalloc(len + 1);
7699 	if (tmp == NULL) {
7700 		wpa_error_log0(MSG_ERROR, "p2p_update_str: os_zalloc failed.");
7701 		return -1;
7702 	}
7703 	os_memcpy(tmp, src, len);
7704 	os_free(*dst);
7705 	*dst = tmp;
7706 	return 0;
7707 }
7708 
7709 static int p2p_ctrl_update_config(struct wpa_supplicant *wpa_s, const char *cmd)
7710 {
7711 	char *pos = NULL;
7712 	char *cmd_walk = NULL;
7713 	int size, len, i;
7714 	int intent = -1;
7715 	int opchan = -1;
7716 	int listenchan = -1;
7717     int wps_method = -1;
7718 
7719 	if ((wpa_s == NULL) || (wpa_s->conf == NULL) || (cmd == NULL))
7720 		return -1;
7721 
7722 	struct p2p_user_cfg_pos cfg_str[] = {
7723 		{"devname=",    NULL, NULL, &wpa_s->conf->device_name,   CFG_CHANGED_DEVICE_NAME},
7724 		{"manufact=",   NULL, NULL, &wpa_s->conf->manufacturer,  CFG_CHANGED_WPS_STRING},
7725 		{"modname=",    NULL, NULL, &wpa_s->conf->model_name,    CFG_CHANGED_WPS_STRING},
7726 		{"modnum=",     NULL, NULL, &wpa_s->conf->model_number,  CFG_CHANGED_WPS_STRING},
7727 		{"sernum=",     NULL, NULL, &wpa_s->conf->serial_number, CFG_CHANGED_WPS_STRING},
7728 		{"intent=",     NULL, NULL, NULL,                        0x0},
7729 		{"opchan=",     NULL, NULL, NULL,                        0x0},
7730 		{"listenchan=", NULL, NULL, NULL,                        0x0},
7731 		{"wps_method=", NULL, NULL, NULL,                        0x0},
7732 	};
7733 
7734 	cmd_walk = (char *)cmd;
7735 	size = sizeof(cfg_str) / sizeof(*cfg_str);
7736 	/* Get every position from target string. */
7737 	for (i = 0; i < size; ++i) {
7738 		pos = os_strstr(cmd_walk, cfg_str[i].name);
7739 		if (pos == NULL)
7740 			continue;
7741 
7742 		pos += os_strlen(cfg_str[i].name);
7743 
7744 		if (os_strcmp(cfg_str[i].name, "intent=") == 0) {
7745 			intent = atoi(pos);
7746 			/* intent: 0-15 */
7747 			if (intent < 0 || intent > 15)
7748 				return -1;
7749 		} else if (os_strcmp(cfg_str[i].name, "opchan=") == 0) {
7750 			opchan = atoi(pos);
7751 			/* ch: 1-13 */
7752 			if (opchan < 1 || opchan >= 14)
7753 				return -1;
7754 		} else if (os_strcmp(cfg_str[i].name, "listenchan=") == 0) {
7755 			listenchan = atoi(pos);
7756 			/* ch: 1-13 */
7757 			if (listenchan < 1 || listenchan >= 14)
7758 				return -1;
7759 		} else if (os_strcmp(cfg_str[i].name, "wps_method=") == 0) {
7760 			wps_method = atoi(pos);
7761 			/* wps_method: 0-1 */
7762 			if (wps_method < 0 || wps_method > 1)
7763 				return -1;
7764 		} else {
7765 			len = atoi(pos);
7766 			/* 64: manufacturer has the maximum length. */
7767 			if (len < 0 || len > 64)
7768 				return -1;
7769 			pos = os_strchr(pos, ',');
7770 			if (pos == NULL)
7771 				return -1;
7772 
7773 			cfg_str[i].pos_start = pos + 1;
7774 			cfg_str[i].pos_end = cfg_str[i].pos_start + len;
7775 			pos = cfg_str[i].pos_end + 1;
7776 		}
7777 
7778 		cmd_walk = pos;
7779 	}
7780 
7781 	/* Filter the valid character string and update config. */
7782 	for (i = 0; i < size; ++i) {
7783 		if (cfg_str[i].pos_start == NULL || cfg_str[i].pos_end == NULL || cfg_str[i].dst == NULL ||
7784 			(cfg_str[i].pos_end <= cfg_str[i].pos_start))
7785 			continue;
7786 		(void)p2p_update_str(cfg_str[i].dst, cfg_str[i].pos_start, cfg_str[i].pos_end - cfg_str[i].pos_start);
7787 		wpa_s->conf->changed_parameters |= cfg_str[i].changed;
7788 	}
7789 
7790 	if (intent != -1)
7791 		wpa_s->conf->p2p_go_intent = intent;
7792 
7793 	if (opchan != -1) {
7794 		/* 81: operating class */
7795 		wpa_s->conf->p2p_oper_reg_class = 81;
7796 		wpa_s->conf->p2p_oper_channel = opchan;
7797 		wpa_s->conf->changed_parameters |= CFG_CHANGED_P2P_OPER_CHANNEL;
7798 	}
7799 
7800 	if (listenchan != -1) {
7801 		/* 81: operating class */
7802 		wpa_s->conf->p2p_listen_reg_class = 81;
7803 		wpa_s->conf->p2p_listen_channel = listenchan;
7804 		wpa_s->conf->changed_parameters |= CFG_CHANGED_P2P_LISTEN_CHANNEL;
7805 	}
7806 
7807 	if (wps_method != -1) {
7808 		if (wps_method == 0) {
7809 			os_memcpy(wpa_s->conf->config_methods, "push_button", sizeof("push_button"));
7810 		} else if (wps_method == 1) {
7811 			os_memcpy(wpa_s->conf->config_methods, "display", sizeof("display"));
7812 		}
7813 		wpa_s->conf->changed_parameters |= CFG_CHANGED_CONFIG_METHODS;
7814 	}
7815 
7816 	wpa_supplicant_update_config(wpa_s);
7817 	return 0;
7818 }
7819 #endif /* LOS_CONFIG_P2P */
7820 
7821 #ifndef LOS_CONFIG_EXT_DRIVER_NOT_SUPPORT
7822 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
7823 {
7824 	int freq = 0, period = 0, interval = 0, count = 0;
7825 
7826 	if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
7827 	{
7828 		wpa_printf(MSG_DEBUG,
7829 			   "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
7830 		return -1;
7831 	}
7832 
7833 	return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7834 }
7835 #endif /* LOS_CONFIG_EXT_DRIVER_NOT_SUPPORT */
7836 #endif /* CONFIG_P2P */
7837 
7838 
7839 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7840 {
7841 	struct wpa_freq_range_list ranges;
7842 	int *freqs = NULL;
7843 	struct hostapd_hw_modes *mode;
7844 	u16 i;
7845 
7846 	if (wpa_s->hw.modes == NULL)
7847 		return NULL;
7848 
7849 	os_memset(&ranges, 0, sizeof(ranges));
7850 	if (freq_range_list_parse(&ranges, val) < 0)
7851 		return NULL;
7852 
7853 	for (i = 0; i < wpa_s->hw.num_modes; i++) {
7854 		int j;
7855 
7856 		mode = &wpa_s->hw.modes[i];
7857 		for (j = 0; j < mode->num_channels; j++) {
7858 			unsigned int freq;
7859 
7860 			if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7861 				continue;
7862 
7863 			freq = mode->channels[j].freq;
7864 			if (!freq_range_list_includes(&ranges, freq))
7865 				continue;
7866 
7867 			int_array_add_unique(&freqs, freq);
7868 		}
7869 	}
7870 
7871 	os_free(ranges.range);
7872 	return freqs;
7873 }
7874 
7875 
7876 #ifdef CONFIG_INTERWORKING
7877 
7878 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
7879 {
7880 	int auto_sel = 0;
7881 	int *freqs = NULL;
7882 
7883 	if (param) {
7884 		char *pos;
7885 
7886 		auto_sel = os_strstr(param, "auto") != NULL;
7887 
7888 		pos = os_strstr(param, "freq=");
7889 		if (pos) {
7890 			freqs = freq_range_to_channel_list(wpa_s, pos + 5);
7891 			if (freqs == NULL)
7892 				return -1;
7893 		}
7894 
7895 	}
7896 
7897 	return interworking_select(wpa_s, auto_sel, freqs);
7898 }
7899 
7900 
7901 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
7902 				     int only_add)
7903 {
7904 	u8 bssid[ETH_ALEN];
7905 	struct wpa_bss *bss;
7906 
7907 	if (hwaddr_aton(dst, bssid)) {
7908 		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
7909 		return -1;
7910 	}
7911 
7912 	bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
7913 	if (bss == NULL) {
7914 		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
7915 			   MAC2STR(bssid));
7916 		return -1;
7917 	}
7918 
7919 	if (bss->ssid_len == 0) {
7920 		int found = 0;
7921 
7922 		wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
7923 			   " does not have SSID information", MAC2STR(bssid));
7924 
7925 		dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
7926 					 list) {
7927 			if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
7928 			    bss->ssid_len > 0) {
7929 				found = 1;
7930 				break;
7931 			}
7932 		}
7933 
7934 		if (!found)
7935 			return -1;
7936 		wpa_printf(MSG_DEBUG,
7937 			   "Found another matching BSS entry with SSID");
7938 	}
7939 
7940 	return interworking_connect(wpa_s, bss, only_add);
7941 }
7942 
7943 
7944 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
7945 {
7946 	u8 dst_addr[ETH_ALEN];
7947 	int used, freq = 0;
7948 	char *pos;
7949 #define MAX_ANQP_INFO_ID 100
7950 	u16 id[MAX_ANQP_INFO_ID];
7951 	size_t num_id = 0;
7952 	u32 subtypes = 0;
7953 	u32 mbo_subtypes = 0;
7954 
7955 	used = hwaddr_aton2(dst, dst_addr);
7956 	if (used < 0)
7957 		return -1;
7958 	pos = dst + used;
7959 	if (*pos == ' ')
7960 		pos++;
7961 
7962 	if (os_strncmp(pos, "freq=", 5) == 0) {
7963 		freq = atoi(pos + 5);
7964 		pos = os_strchr(pos, ' ');
7965 		if (!pos)
7966 			return -1;
7967 		pos++;
7968 	}
7969 
7970 	while (num_id < MAX_ANQP_INFO_ID) {
7971 		if (os_strncmp(pos, "hs20:", 5) == 0) {
7972 #ifdef CONFIG_HS20
7973 			int num = atoi(pos + 5);
7974 			if (num <= 0 || num > 31)
7975 				return -1;
7976 			subtypes |= BIT(num);
7977 #else /* CONFIG_HS20 */
7978 			return -1;
7979 #endif /* CONFIG_HS20 */
7980 		} else if (os_strncmp(pos, "mbo:", 4) == 0) {
7981 #ifdef CONFIG_MBO
7982 			int num = atoi(pos + 4);
7983 
7984 			if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
7985 				return -1;
7986 			mbo_subtypes |= BIT(num);
7987 #else /* CONFIG_MBO */
7988 			return -1;
7989 #endif /* CONFIG_MBO */
7990 		} else {
7991 			id[num_id] = atoi(pos);
7992 			if (id[num_id])
7993 				num_id++;
7994 		}
7995 		pos = os_strchr(pos + 1, ',');
7996 		if (pos == NULL)
7997 			break;
7998 		pos++;
7999 	}
8000 
8001 	if (num_id == 0 && !subtypes && !mbo_subtypes)
8002 		return -1;
8003 
8004 	return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
8005 			     mbo_subtypes);
8006 }
8007 
8008 
8009 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
8010 {
8011 	u8 dst_addr[ETH_ALEN];
8012 	struct wpabuf *advproto, *query = NULL;
8013 	int used, ret = -1;
8014 	char *pos, *end;
8015 	size_t len;
8016 
8017 	used = hwaddr_aton2(cmd, dst_addr);
8018 	if (used < 0)
8019 		return -1;
8020 
8021 	pos = cmd + used;
8022 	while (*pos == ' ')
8023 		pos++;
8024 
8025 	/* Advertisement Protocol ID */
8026 	end = os_strchr(pos, ' ');
8027 	if (end)
8028 		len = end - pos;
8029 	else
8030 		len = os_strlen(pos);
8031 	if (len & 0x01)
8032 		return -1;
8033 	len /= 2;
8034 	if (len == 0)
8035 		return -1;
8036 	advproto = wpabuf_alloc(len);
8037 	if (advproto == NULL)
8038 		return -1;
8039 	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
8040 		goto fail;
8041 
8042 	if (end) {
8043 		/* Optional Query Request */
8044 		pos = end + 1;
8045 		while (*pos == ' ')
8046 			pos++;
8047 
8048 		len = os_strlen(pos);
8049 		if (len) {
8050 			if (len & 0x01)
8051 				goto fail;
8052 			len /= 2;
8053 			if (len == 0)
8054 				goto fail;
8055 			query = wpabuf_alloc(len);
8056 			if (query == NULL)
8057 				goto fail;
8058 			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
8059 				goto fail;
8060 		}
8061 	}
8062 
8063 	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
8064 
8065 fail:
8066 	wpabuf_free(advproto);
8067 	wpabuf_free(query);
8068 
8069 	return ret;
8070 }
8071 
8072 
8073 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
8074 			    size_t buflen)
8075 {
8076 	u8 addr[ETH_ALEN];
8077 	int dialog_token;
8078 	int used;
8079 	char *pos;
8080 	size_t resp_len, start, requested_len;
8081 	struct wpabuf *resp;
8082 	int ret;
8083 
8084 	used = hwaddr_aton2(cmd, addr);
8085 	if (used < 0)
8086 		return -1;
8087 
8088 	pos = cmd + used;
8089 	while (*pos == ' ')
8090 		pos++;
8091 	dialog_token = atoi(pos);
8092 
8093 	if (wpa_s->last_gas_resp &&
8094 	    os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
8095 	    dialog_token == wpa_s->last_gas_dialog_token)
8096 		resp = wpa_s->last_gas_resp;
8097 	else if (wpa_s->prev_gas_resp &&
8098 		 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
8099 		 dialog_token == wpa_s->prev_gas_dialog_token)
8100 		resp = wpa_s->prev_gas_resp;
8101 	else
8102 		return -1;
8103 
8104 	resp_len = wpabuf_len(resp);
8105 	start = 0;
8106 	requested_len = resp_len;
8107 
8108 	pos = os_strchr(pos, ' ');
8109 	if (pos) {
8110 		start = atoi(pos);
8111 		if (start > resp_len)
8112 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
8113 		pos = os_strchr(pos, ',');
8114 		if (pos == NULL)
8115 			return -1;
8116 		pos++;
8117 		requested_len = atoi(pos);
8118 		if (start + requested_len > resp_len)
8119 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
8120 	}
8121 
8122 	if (requested_len * 2 + 1 > buflen)
8123 		return os_snprintf(buf, buflen, "FAIL-Too long response");
8124 
8125 	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
8126 			       requested_len);
8127 
8128 	if (start + requested_len == resp_len) {
8129 		/*
8130 		 * Free memory by dropping the response after it has been
8131 		 * fetched.
8132 		 */
8133 		if (resp == wpa_s->prev_gas_resp) {
8134 			wpabuf_free(wpa_s->prev_gas_resp);
8135 			wpa_s->prev_gas_resp = NULL;
8136 		} else {
8137 			wpabuf_free(wpa_s->last_gas_resp);
8138 			wpa_s->last_gas_resp = NULL;
8139 		}
8140 	}
8141 
8142 	return ret;
8143 }
8144 #endif /* CONFIG_INTERWORKING */
8145 
8146 
8147 #ifdef CONFIG_HS20
8148 
8149 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
8150 {
8151 	u8 dst_addr[ETH_ALEN];
8152 	int used;
8153 	char *pos;
8154 	u32 subtypes = 0;
8155 
8156 	used = hwaddr_aton2(dst, dst_addr);
8157 	if (used < 0)
8158 		return -1;
8159 	pos = dst + used;
8160 	if (*pos == ' ')
8161 		pos++;
8162 	for (;;) {
8163 		int num = atoi(pos);
8164 		if (num <= 0 || num > 31)
8165 			return -1;
8166 		subtypes |= BIT(num);
8167 		pos = os_strchr(pos + 1, ',');
8168 		if (pos == NULL)
8169 			break;
8170 		pos++;
8171 	}
8172 
8173 	if (subtypes == 0)
8174 		return -1;
8175 
8176 	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
8177 }
8178 
8179 
8180 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8181 				    const u8 *addr, const char *realm)
8182 {
8183 	u8 *buf;
8184 	size_t rlen, len;
8185 	int ret;
8186 
8187 	rlen = os_strlen(realm);
8188 	len = 3 + rlen;
8189 	buf = os_malloc(len);
8190 	if (buf == NULL)
8191 		return -1;
8192 	buf[0] = 1; /* NAI Home Realm Count */
8193 	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
8194 	buf[2] = rlen;
8195 	os_memcpy(buf + 3, realm, rlen);
8196 
8197 	ret = hs20_anqp_send_req(wpa_s, addr,
8198 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
8199 				 buf, len, 0);
8200 
8201 	os_free(buf);
8202 
8203 	return ret;
8204 }
8205 
8206 
8207 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8208 					char *dst)
8209 {
8210 	struct wpa_cred *cred = wpa_s->conf->cred;
8211 	u8 dst_addr[ETH_ALEN];
8212 	int used;
8213 	u8 *buf;
8214 	size_t len;
8215 	int ret;
8216 
8217 	used = hwaddr_aton2(dst, dst_addr);
8218 	if (used < 0)
8219 		return -1;
8220 
8221 	while (dst[used] == ' ')
8222 		used++;
8223 	if (os_strncmp(dst + used, "realm=", 6) == 0)
8224 		return hs20_nai_home_realm_list(wpa_s, dst_addr,
8225 						dst + used + 6);
8226 
8227 	len = os_strlen(dst + used);
8228 
8229 	if (len == 0 && cred && cred->realm)
8230 		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
8231 
8232 	if (len & 1)
8233 		return -1;
8234 	len /= 2;
8235 	buf = os_malloc(len);
8236 	if (buf == NULL)
8237 		return -1;
8238 	if (hexstr2bin(dst + used, buf, len) < 0) {
8239 		os_free(buf);
8240 		return -1;
8241 	}
8242 
8243 	ret = hs20_anqp_send_req(wpa_s, dst_addr,
8244 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
8245 				 buf, len, 0);
8246 	os_free(buf);
8247 
8248 	return ret;
8249 }
8250 
8251 
8252 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
8253 			 int buflen)
8254 {
8255 	u8 dst_addr[ETH_ALEN];
8256 	int used;
8257 	char *ctx = NULL, *icon, *poffset, *psize;
8258 
8259 	used = hwaddr_aton2(cmd, dst_addr);
8260 	if (used < 0)
8261 		return -1;
8262 	cmd += used;
8263 
8264 	icon = str_token(cmd, " ", &ctx);
8265 	poffset = str_token(cmd, " ", &ctx);
8266 	psize = str_token(cmd, " ", &ctx);
8267 	if (!icon || !poffset || !psize)
8268 		return -1;
8269 
8270 	wpa_s->fetch_osu_icon_in_progress = 0;
8271 	return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
8272 			     reply, buflen);
8273 }
8274 
8275 
8276 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
8277 {
8278 	u8 dst_addr[ETH_ALEN];
8279 	int used;
8280 	char *icon;
8281 
8282 	if (!cmd[0])
8283 		return hs20_del_icon(wpa_s, NULL, NULL);
8284 
8285 	used = hwaddr_aton2(cmd, dst_addr);
8286 	if (used < 0)
8287 		return -1;
8288 
8289 	while (cmd[used] == ' ')
8290 		used++;
8291 	icon = cmd[used] ? &cmd[used] : NULL;
8292 
8293 	return hs20_del_icon(wpa_s, dst_addr, icon);
8294 }
8295 
8296 
8297 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
8298 {
8299 	u8 dst_addr[ETH_ALEN];
8300 	int used;
8301 	char *icon;
8302 
8303 	used = hwaddr_aton2(cmd, dst_addr);
8304 	if (used < 0)
8305 		return -1;
8306 
8307 	while (cmd[used] == ' ')
8308 		used++;
8309 	icon = &cmd[used];
8310 
8311 	wpa_s->fetch_osu_icon_in_progress = 0;
8312 	return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
8313 				  (u8 *) icon, os_strlen(icon), inmem);
8314 }
8315 
8316 #endif /* CONFIG_HS20 */
8317 
8318 
8319 #ifdef CONFIG_AUTOSCAN
8320 
8321 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
8322 					      char *cmd)
8323 {
8324 	enum wpa_states state = wpa_s->wpa_state;
8325 	char *new_params = NULL;
8326 
8327 	if (os_strlen(cmd) > 0) {
8328 		new_params = os_strdup(cmd);
8329 		if (new_params == NULL)
8330 			return -1;
8331 	}
8332 
8333 	os_free(wpa_s->conf->autoscan);
8334 	wpa_s->conf->autoscan = new_params;
8335 
8336 	if (wpa_s->conf->autoscan == NULL)
8337 		autoscan_deinit(wpa_s);
8338 	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
8339 		autoscan_init(wpa_s, 1);
8340 	else if (state == WPA_SCANNING)
8341 		wpa_supplicant_reinit_autoscan(wpa_s);
8342 	else
8343 		wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
8344 			   wpa_supplicant_state_txt(state));
8345 
8346 	return 0;
8347 }
8348 
8349 #endif /* CONFIG_AUTOSCAN */
8350 
8351 
8352 #ifdef CONFIG_WNM
8353 
8354 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
8355 {
8356 	int enter;
8357 	int intval = 0;
8358 	char *pos;
8359 	int ret;
8360 	struct wpabuf *tfs_req = NULL;
8361 
8362 	if (os_strncmp(cmd, "enter", 5) == 0)
8363 		enter = 1;
8364 	else if (os_strncmp(cmd, "exit", 4) == 0)
8365 		enter = 0;
8366 	else
8367 		return -1;
8368 
8369 	pos = os_strstr(cmd, " interval=");
8370 	if (pos)
8371 		intval = atoi(pos + 10);
8372 
8373 	pos = os_strstr(cmd, " tfs_req=");
8374 	if (pos) {
8375 		char *end;
8376 		size_t len;
8377 		pos += 9;
8378 		end = os_strchr(pos, ' ');
8379 		if (end)
8380 			len = end - pos;
8381 		else
8382 			len = os_strlen(pos);
8383 		if (len & 1)
8384 			return -1;
8385 		len /= 2;
8386 		tfs_req = wpabuf_alloc(len);
8387 		if (tfs_req == NULL)
8388 			return -1;
8389 		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
8390 			wpabuf_free(tfs_req);
8391 			return -1;
8392 		}
8393 	}
8394 
8395 	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
8396 					   WNM_SLEEP_MODE_EXIT, intval,
8397 					   tfs_req);
8398 	wpabuf_free(tfs_req);
8399 
8400 	return ret;
8401 }
8402 
8403 
8404 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
8405 {
8406 	int query_reason, list = 0;
8407 	char *btm_candidates = NULL;
8408 
8409 	query_reason = atoi(cmd);
8410 
8411 	cmd = os_strchr(cmd, ' ');
8412 	if (cmd) {
8413 		if (os_strncmp(cmd, " list", 5) == 0)
8414 			list = 1;
8415 		else
8416 			btm_candidates = cmd;
8417 	}
8418 
8419 	wpa_printf(MSG_DEBUG,
8420 		   "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
8421 		   query_reason, list ? " candidate list" : "");
8422 
8423 	return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
8424 						  btm_candidates,
8425 						  list);
8426 }
8427 
8428 
8429 static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
8430 					     char *cmd)
8431 {
8432 	struct wpabuf *elems;
8433 	int ret;
8434 
8435 	elems = wpabuf_parse_bin(cmd);
8436 	if (!elems)
8437 		return -1;
8438 
8439 	ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
8440 	wpabuf_free(elems);
8441 	return ret;
8442 }
8443 
8444 #endif /* CONFIG_WNM */
8445 
8446 #ifndef EXT_CODE_CROP
8447 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
8448 				      size_t buflen)
8449 {
8450 	struct wpa_signal_info si;
8451 	int ret;
8452 	char *pos, *end;
8453 
8454 	ret = wpa_drv_signal_poll(wpa_s, &si);
8455 	if (ret)
8456 		return -1;
8457 
8458 	pos = buf;
8459 	end = buf + buflen;
8460 
8461 	ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
8462 			  "NOISE=%d\nFREQUENCY=%u\n",
8463 			  si.current_signal, si.current_txrate / 1000,
8464 			  si.current_noise, si.frequency);
8465 	if (os_snprintf_error(end - pos, ret))
8466 		return -1;
8467 	pos += ret;
8468 
8469 	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
8470 		ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
8471 				  channel_width_to_string(si.chanwidth));
8472 		if (os_snprintf_error(end - pos, ret))
8473 			return -1;
8474 		pos += ret;
8475 	}
8476 
8477 	if (si.center_frq1 > 0) {
8478 		ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
8479 				  si.center_frq1);
8480 		if (os_snprintf_error(end - pos, ret))
8481 			return -1;
8482 		pos += ret;
8483 	}
8484 
8485 	if (si.center_frq2 > 0) {
8486 		ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
8487 				  si.center_frq2);
8488 		if (os_snprintf_error(end - pos, ret))
8489 			return -1;
8490 		pos += ret;
8491 	}
8492 
8493 	if (si.avg_signal) {
8494 		ret = os_snprintf(pos, end - pos,
8495 				  "AVG_RSSI=%d\n", si.avg_signal);
8496 		if (os_snprintf_error(end - pos, ret))
8497 			return -1;
8498 		pos += ret;
8499 	}
8500 
8501 	if (si.avg_beacon_signal) {
8502 		ret = os_snprintf(pos, end - pos,
8503 				  "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal);
8504 		if (os_snprintf_error(end - pos, ret))
8505 			return -1;
8506 		pos += ret;
8507 	}
8508 
8509 	return pos - buf;
8510 }
8511 
8512 
8513 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
8514 					  const char *cmd)
8515 {
8516 	const char *pos;
8517 	int threshold = 0;
8518 	int hysteresis = 0;
8519 
8520 	if (wpa_s->bgscan && wpa_s->bgscan_priv) {
8521 		wpa_printf(MSG_DEBUG,
8522 			   "Reject SIGNAL_MONITOR command - bgscan is active");
8523 		return -1;
8524 	}
8525 	pos = os_strstr(cmd, "THRESHOLD=");
8526 	if (pos)
8527 		threshold = atoi(pos + 10);
8528 	pos = os_strstr(cmd, "HYSTERESIS=");
8529 	if (pos)
8530 		hysteresis = atoi(pos + 11);
8531 	return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
8532 }
8533 
8534 
8535 #ifdef CONFIG_TESTING_OPTIONS
8536 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
8537 						enum wpa_driver_if_type if_type,
8538 						unsigned int *num,
8539 						unsigned int *freq_list)
8540 {
8541 	char *pos = wpa_s->get_pref_freq_list_override;
8542 	char *end;
8543 	unsigned int count = 0;
8544 
8545 	/* Override string format:
8546 	 *  <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
8547 
8548 	while (pos) {
8549 		if (atoi(pos) == (int) if_type)
8550 			break;
8551 		pos = os_strchr(pos, ' ');
8552 		if (pos)
8553 			pos++;
8554 	}
8555 	if (!pos)
8556 		return -1;
8557 	pos = os_strchr(pos, ':');
8558 	if (!pos)
8559 		return -1;
8560 	pos++;
8561 	end = os_strchr(pos, ' ');
8562 	while (pos && (!end || pos < end) && count < *num) {
8563 		freq_list[count++] = atoi(pos);
8564 		pos = os_strchr(pos, ',');
8565 		if (pos)
8566 			pos++;
8567 	}
8568 
8569 	*num = count;
8570 	return 0;
8571 }
8572 #endif /* CONFIG_TESTING_OPTIONS */
8573 
8574 
8575 static int wpas_ctrl_iface_get_pref_freq_list(
8576 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
8577 {
8578 	unsigned int freq_list[100], num = 100, i;
8579 	int ret;
8580 	enum wpa_driver_if_type iface_type;
8581 	char *pos, *end;
8582 
8583 	pos = buf;
8584 	end = buf + buflen;
8585 
8586 	/* buf: "<interface_type>" */
8587 	if (os_strcmp(cmd, "STATION") == 0)
8588 		iface_type = WPA_IF_STATION;
8589 	else if (os_strcmp(cmd, "AP") == 0)
8590 		iface_type = WPA_IF_AP_BSS;
8591 	else if (os_strcmp(cmd, "P2P_GO") == 0)
8592 		iface_type = WPA_IF_P2P_GO;
8593 	else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
8594 		iface_type = WPA_IF_P2P_CLIENT;
8595 	else if (os_strcmp(cmd, "IBSS") == 0)
8596 		iface_type = WPA_IF_IBSS;
8597 	else if (os_strcmp(cmd, "TDLS") == 0)
8598 		iface_type = WPA_IF_TDLS;
8599 	else
8600 		return -1;
8601 
8602 	wpa_printf(MSG_DEBUG,
8603 		   "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
8604 		   iface_type, cmd);
8605 
8606 	ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
8607 	if (ret)
8608 		return -1;
8609 
8610 	for (i = 0; i < num; i++) {
8611 		ret = os_snprintf(pos, end - pos, "%s%u",
8612 				  i > 0 ? "," : "", freq_list[i]);
8613 		if (os_snprintf_error(end - pos, ret))
8614 			return -1;
8615 		pos += ret;
8616 	}
8617 
8618 	return pos - buf;
8619 }
8620 
8621 
8622 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
8623 					char *buf, size_t buflen)
8624 {
8625 	int ret, i;
8626 	char *pos, *end;
8627 
8628 	ret = os_snprintf(buf, buflen, "%016llX:\n",
8629 			  (long long unsigned) wpa_s->drv_flags);
8630 	if (os_snprintf_error(buflen, ret))
8631 		return -1;
8632 
8633 	pos = buf + ret;
8634 	end = buf + buflen;
8635 
8636 	for (i = 0; i < 64; i++) {
8637 		if (wpa_s->drv_flags & (1LLU << i)) {
8638 			ret = os_snprintf(pos, end - pos, "%s\n",
8639 					  driver_flag_to_string(1LLU << i));
8640 			if (os_snprintf_error(end - pos, ret))
8641 				return -1;
8642 			pos += ret;
8643 		}
8644 	}
8645 
8646 	return pos - buf;
8647 }
8648 
8649 
8650 static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s,
8651 					 char *buf, size_t buflen)
8652 {
8653 	int ret, i;
8654 	char *pos, *end;
8655 
8656 	ret = os_snprintf(buf, buflen, "%016llX:\n",
8657 			  (long long unsigned) wpa_s->drv_flags2);
8658 	if (os_snprintf_error(buflen, ret))
8659 		return -1;
8660 
8661 	pos = buf + ret;
8662 	end = buf + buflen;
8663 
8664 	for (i = 0; i < 64; i++) {
8665 		if (wpa_s->drv_flags2 & (1LLU << i)) {
8666 			ret = os_snprintf(pos, end - pos, "%s\n",
8667 					  driver_flag2_to_string(1LLU << i));
8668 			if (os_snprintf_error(end - pos, ret))
8669 				return -1;
8670 			pos += ret;
8671 		}
8672 	}
8673 
8674 	return pos - buf;
8675 }
8676 
8677 
8678 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
8679 				      size_t buflen)
8680 {
8681 	struct hostap_sta_driver_data sta;
8682 	int ret;
8683 
8684 	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
8685 	if (ret)
8686 		return -1;
8687 
8688 	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
8689 			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
8690 	if (os_snprintf_error(buflen, ret))
8691 		return -1;
8692 	return ret;
8693 }
8694 #endif /* EXT_CODE_CROP */
8695 
8696 #ifdef ANDROID
8697 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8698 				     char *buf, size_t buflen)
8699 {
8700 	int ret;
8701 
8702 	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
8703 	if (ret == 0) {
8704 		if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
8705 			struct p2p_data *p2p = wpa_s->global->p2p;
8706 			if (p2p) {
8707 				char country[3];
8708 				country[0] = cmd[8];
8709 				country[1] = cmd[9];
8710 				country[2] = 0x04;
8711 				p2p_set_country(p2p, country);
8712 			}
8713 		}
8714 		ret = os_snprintf(buf, buflen, "%s\n", "OK");
8715 		if (os_snprintf_error(buflen, ret))
8716 			ret = -1;
8717 	}
8718 	return ret;
8719 }
8720 #endif /* ANDROID */
8721 
8722 #ifndef EXT_CODE_CROP
8723 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8724 				     char *buf, size_t buflen)
8725 {
8726 	int ret;
8727 	char *pos, *temp = NULL;
8728 	u8 *data = NULL;
8729 	unsigned int vendor_id, subcmd;
8730 	enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
8731 	struct wpabuf *reply;
8732 	size_t data_len = 0;
8733 
8734 	/**
8735 	 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
8736 	 * [nested=<0|1>]
8737 	 */
8738 	vendor_id = strtoul(cmd, &pos, 16);
8739 	if (!isblank((unsigned char) *pos))
8740 		return -EINVAL;
8741 
8742 	subcmd = strtoul(pos, &pos, 10);
8743 
8744 	if (*pos != '\0') {
8745 		if (!isblank((unsigned char) *pos++))
8746 			return -EINVAL;
8747 
8748 		temp = os_strchr(pos, ' ');
8749 		data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
8750 	}
8751 
8752 	if (data_len) {
8753 		data_len /= 2;
8754 		data = os_malloc(data_len);
8755 		if (!data)
8756 			return -1;
8757 
8758 		if (hexstr2bin(pos, data, data_len)) {
8759 			wpa_printf(MSG_DEBUG,
8760 				   "Vendor command: wrong parameter format");
8761 			os_free(data);
8762 			return -EINVAL;
8763 		}
8764 	}
8765 
8766 	pos = os_strstr(cmd, "nested=");
8767 	if (pos)
8768 		nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
8769 			NESTED_ATTR_NOT_USED;
8770 
8771 	reply = wpabuf_alloc((buflen - 1) / 2);
8772 	if (!reply) {
8773 		os_free(data);
8774 		return -1;
8775 	}
8776 
8777 	ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
8778 				 nested_attr_flag, reply);
8779 
8780 	if (ret == 0)
8781 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
8782 				       wpabuf_len(reply));
8783 
8784 	wpabuf_free(reply);
8785 	os_free(data);
8786 
8787 	return ret;
8788 }
8789 
8790 
8791 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
8792 {
8793 #ifdef CONFIG_P2P
8794 	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
8795 		wpa_s->global->p2p_init_wpa_s : wpa_s;
8796 #endif /* CONFIG_P2P */
8797 
8798 	wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
8799 
8800 	if (wpas_abort_ongoing_scan(wpa_s) == 0)
8801 		wpa_s->ignore_post_flush_scan_res = 1;
8802 
8803 	if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
8804 		/*
8805 		 * Avoid possible auto connect re-connection on getting
8806 		 * disconnected due to state flush.
8807 		 */
8808 		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
8809 	}
8810 
8811 #ifdef CONFIG_P2P
8812 	wpas_p2p_group_remove(p2p_wpa_s, "*");
8813 	wpas_p2p_cancel(p2p_wpa_s);
8814 	p2p_ctrl_flush(p2p_wpa_s);
8815 	wpas_p2p_service_flush(p2p_wpa_s);
8816 	p2p_wpa_s->global->p2p_disabled = 0;
8817 	p2p_wpa_s->global->p2p_per_sta_psk = 0;
8818 	p2p_wpa_s->conf->num_sec_device_types = 0;
8819 	p2p_wpa_s->p2p_disable_ip_addr_req = 0;
8820 	os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
8821 	p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
8822 	p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
8823 	p2p_wpa_s->global->pending_p2ps_group = 0;
8824 	p2p_wpa_s->global->pending_p2ps_group_freq = 0;
8825 #endif /* CONFIG_P2P */
8826 
8827 #ifdef CONFIG_WPS_TESTING
8828 	wps_version_number = 0x20;
8829 	wps_testing_stub_cred = 0;
8830 	wps_corrupt_pkhash = 0;
8831 	wps_force_auth_types_in_use = 0;
8832 	wps_force_encr_types_in_use = 0;
8833 #endif /* CONFIG_WPS_TESTING */
8834 #ifdef CONFIG_WPS
8835 	wpa_s->wps_fragment_size = 0;
8836 	wpas_wps_cancel(wpa_s);
8837 	wps_registrar_flush(wpa_s->wps->registrar);
8838 #endif /* CONFIG_WPS */
8839 	wpa_s->after_wps = 0;
8840 	wpa_s->known_wps_freq = 0;
8841 
8842 #ifdef CONFIG_DPP
8843 	wpas_dpp_deinit(wpa_s);
8844 	wpa_s->dpp_init_max_tries = 0;
8845 	wpa_s->dpp_init_retry_time = 0;
8846 	wpa_s->dpp_resp_wait_time = 0;
8847 	wpa_s->dpp_resp_max_tries = 0;
8848 	wpa_s->dpp_resp_retry_time = 0;
8849 #ifdef CONFIG_DPP2
8850 	wpas_dpp_chirp_stop(wpa_s);
8851 	wpa_s->dpp_pfs_fallback = 0;
8852 #endif /* CONFIG_DPP2 */
8853 #ifdef CONFIG_TESTING_OPTIONS
8854 	os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
8855 	os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
8856 	dpp_pkex_ephemeral_key_override_len = 0;
8857 	dpp_protocol_key_override_len = 0;
8858 	dpp_nonce_override_len = 0;
8859 #ifdef CONFIG_DPP3
8860 	dpp_version_override = 3;
8861 #elif defined(CONFIG_DPP2)
8862 	dpp_version_override = 2;
8863 #else /* CONFIG_DPP2 */
8864 	dpp_version_override = 1;
8865 #endif /* CONFIG_DPP2 */
8866 #endif /* CONFIG_TESTING_OPTIONS */
8867 #endif /* CONFIG_DPP */
8868 
8869 #ifdef CONFIG_TDLS
8870 #ifdef CONFIG_TDLS_TESTING
8871 	tdls_testing = 0;
8872 #endif /* CONFIG_TDLS_TESTING */
8873 	wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
8874 	wpa_tdls_enable(wpa_s->wpa, 1);
8875 #endif /* CONFIG_TDLS */
8876 
8877 	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
8878 	wpa_supplicant_stop_countermeasures(wpa_s, NULL);
8879 	wpa_s->last_michael_mic_error.sec = 0;
8880 
8881 	wpa_s->no_keep_alive = 0;
8882 	wpa_s->own_disconnect_req = 0;
8883 	wpa_s->own_reconnect_req = 0;
8884 	wpa_s->deny_ptk0_rekey = 0;
8885 
8886 	os_free(wpa_s->disallow_aps_bssid);
8887 	wpa_s->disallow_aps_bssid = NULL;
8888 	wpa_s->disallow_aps_bssid_count = 0;
8889 	os_free(wpa_s->disallow_aps_ssid);
8890 	wpa_s->disallow_aps_ssid = NULL;
8891 	wpa_s->disallow_aps_ssid_count = 0;
8892 
8893 	wpa_s->set_sta_uapsd = 0;
8894 	wpa_s->sta_uapsd = 0;
8895 
8896 	wpa_s->consecutive_conn_failures = 0;
8897 
8898 	wpa_drv_radio_disable(wpa_s, 0);
8899 	wpa_bssid_ignore_clear(wpa_s);
8900 	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
8901 	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
8902 	wpa_config_flush_blobs(wpa_s->conf);
8903 	wpa_s->conf->auto_interworking = 0;
8904 	wpa_s->conf->okc = 0;
8905 
8906 	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
8907 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
8908 	rsn_preauth_deinit(wpa_s->wpa);
8909 
8910 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
8911 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
8912 	wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
8913 	eapol_sm_notify_logoff(wpa_s->eapol, false);
8914 
8915 	radio_remove_works(wpa_s, NULL, 1);
8916 	wpa_s->ext_work_in_progress = 0;
8917 
8918 	wpa_s->next_ssid = NULL;
8919 
8920 #ifdef CONFIG_INTERWORKING
8921 #ifdef CONFIG_HS20
8922 	hs20_cancel_fetch_osu(wpa_s);
8923 	hs20_del_icon(wpa_s, NULL, NULL);
8924 #endif /* CONFIG_HS20 */
8925 #endif /* CONFIG_INTERWORKING */
8926 
8927 	wpa_s->ext_mgmt_frame_handling = 0;
8928 	wpa_s->ext_eapol_frame_io = 0;
8929 #ifdef CONFIG_TESTING_OPTIONS
8930 	wpa_s->extra_roc_dur = 0;
8931 	wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
8932 	wpa_s->p2p_go_csa_on_inv = 0;
8933 	wpa_s->ignore_auth_resp = 0;
8934 	wpa_s->ignore_assoc_disallow = 0;
8935 	wpa_s->disable_sa_query = 0;
8936 	wpa_s->testing_resend_assoc = 0;
8937 	wpa_s->ignore_sae_h2e_only = 0;
8938 	wpa_s->ft_rsnxe_used = 0;
8939 	wpa_s->reject_btm_req_reason = 0;
8940 	wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
8941 	os_free(wpa_s->get_pref_freq_list_override);
8942 	wpa_s->get_pref_freq_list_override = NULL;
8943 	wpabuf_free(wpa_s->sae_commit_override);
8944 	wpa_s->sae_commit_override = NULL;
8945 	os_free(wpa_s->extra_sae_rejected_groups);
8946 	wpa_s->extra_sae_rejected_groups = NULL;
8947 	wpabuf_free(wpa_s->rsne_override_eapol);
8948 	wpa_s->rsne_override_eapol = NULL;
8949 	wpabuf_free(wpa_s->rsnxe_override_assoc);
8950 	wpa_s->rsnxe_override_assoc = NULL;
8951 	wpabuf_free(wpa_s->rsnxe_override_eapol);
8952 	wpa_s->rsnxe_override_eapol = NULL;
8953 	wpas_clear_driver_signal_override(wpa_s);
8954 	wpa_s->disable_scs_support = 0;
8955 	wpa_s->disable_mscs_support = 0;
8956 	wpa_s->enable_dscp_policy_capa = 0;
8957 	wpa_s->oci_freq_override_eapol = 0;
8958 	wpa_s->oci_freq_override_saquery_req = 0;
8959 	wpa_s->oci_freq_override_saquery_resp = 0;
8960 	wpa_s->oci_freq_override_eapol_g2 = 0;
8961 	wpa_s->oci_freq_override_ft_assoc = 0;
8962 	wpa_s->oci_freq_override_fils_assoc = 0;
8963 	wpa_s->oci_freq_override_wnm_sleep = 0;
8964 #ifdef CONFIG_DPP
8965 	os_free(wpa_s->dpp_config_obj_override);
8966 	wpa_s->dpp_config_obj_override = NULL;
8967 	os_free(wpa_s->dpp_discovery_override);
8968 	wpa_s->dpp_discovery_override = NULL;
8969 	os_free(wpa_s->dpp_groups_override);
8970 	wpa_s->dpp_groups_override = NULL;
8971 	dpp_test = DPP_TEST_DISABLED;
8972 #endif /* CONFIG_DPP */
8973 #endif /* CONFIG_TESTING_OPTIONS */
8974 
8975 	wpa_s->disconnected = 0;
8976 	os_free(wpa_s->next_scan_freqs);
8977 	wpa_s->next_scan_freqs = NULL;
8978 	os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
8979 	wpa_s->next_scan_bssid_wildcard_ssid = 0;
8980 	os_free(wpa_s->select_network_scan_freqs);
8981 	wpa_s->select_network_scan_freqs = NULL;
8982 	os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
8983 
8984 	wpa_bss_flush(wpa_s);
8985 	if (!dl_list_empty(&wpa_s->bss)) {
8986 		wpa_printf(MSG_DEBUG,
8987 			   "BSS table not empty after flush: %u entries, current_bss=%p bssid="
8988 			   MACSTR " pending_bssid=" MACSTR,
8989 			   dl_list_len(&wpa_s->bss), wpa_s->current_bss,
8990 			   MAC2STR(wpa_s->bssid),
8991 			   MAC2STR(wpa_s->pending_bssid));
8992 	}
8993 
8994 	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
8995 	wpa_s->wnmsleep_used = 0;
8996 
8997 #ifdef CONFIG_SME
8998 	wpa_s->sme.last_unprot_disconnect.sec = 0;
8999 	wpa_s->sme.auth_alg = 0;
9000 #endif /* CONFIG_SME */
9001 
9002 	wpabuf_free(wpa_s->ric_ies);
9003 	wpa_s->ric_ies = NULL;
9004 
9005 	wpa_supplicant_update_channel_list(wpa_s, NULL);
9006 
9007 	free_bss_tmp_disallowed(wpa_s);
9008 
9009 	os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
9010 
9011 #ifdef CONFIG_PASN
9012 	wpas_pasn_auth_stop(wpa_s);
9013 #endif /* CONFIG_PASN */
9014 
9015 	if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
9016 		wpas_restore_permanent_mac_addr(wpa_s);
9017 }
9018 
9019 
9020 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
9021 				     char *buf, size_t buflen)
9022 {
9023 	struct wpa_radio_work *work;
9024 	char *pos, *end;
9025 	struct os_reltime now, diff;
9026 
9027 	pos = buf;
9028 	end = buf + buflen;
9029 
9030 	os_get_reltime(&now);
9031 
9032 	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9033 	{
9034 		int ret;
9035 
9036 		os_reltime_sub(&now, &work->time, &diff);
9037 		ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
9038 				  work->type, work->wpa_s->ifname, work->freq,
9039 				  work->started, diff.sec, diff.usec);
9040 		if (os_snprintf_error(end - pos, ret))
9041 			break;
9042 		pos += ret;
9043 	}
9044 
9045 	return pos - buf;
9046 }
9047 
9048 
9049 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
9050 {
9051 	struct wpa_radio_work *work = eloop_ctx;
9052 	struct wpa_external_work *ework = work->ctx;
9053 
9054 	wpa_dbg(work->wpa_s, MSG_DEBUG,
9055 		"Timing out external radio work %u (%s)",
9056 		ework->id, work->type);
9057 	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
9058 	work->wpa_s->ext_work_in_progress = 0;
9059 	radio_work_done(work);
9060 	os_free(ework);
9061 }
9062 
9063 
9064 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
9065 {
9066 	struct wpa_external_work *ework = work->ctx;
9067 
9068 	if (deinit) {
9069 		if (work->started)
9070 			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9071 					     work, NULL);
9072 
9073 		/*
9074 		 * work->type points to a buffer in ework, so need to replace
9075 		 * that here with a fixed string to avoid use of freed memory
9076 		 * in debug prints.
9077 		 */
9078 		work->type = "freed-ext-work";
9079 		work->ctx = NULL;
9080 		os_free(ework);
9081 		return;
9082 	}
9083 
9084 	wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
9085 		ework->id, ework->type);
9086 	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
9087 	work->wpa_s->ext_work_in_progress = 1;
9088 	if (!ework->timeout)
9089 		ework->timeout = 10;
9090 	eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
9091 			       work, NULL);
9092 }
9093 
9094 
9095 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
9096 				    char *buf, size_t buflen)
9097 {
9098 	struct wpa_external_work *ework;
9099 	char *pos, *pos2;
9100 	size_t type_len;
9101 	int ret;
9102 	unsigned int freq = 0;
9103 
9104 	/* format: <name> [freq=<MHz>] [timeout=<seconds>] */
9105 
9106 	ework = os_zalloc(sizeof(*ework));
9107 	if (ework == NULL)
9108 		return -1;
9109 
9110 	pos = os_strchr(cmd, ' ');
9111 	if (pos) {
9112 		type_len = pos - cmd;
9113 		pos++;
9114 
9115 		pos2 = os_strstr(pos, "freq=");
9116 		if (pos2)
9117 			freq = atoi(pos2 + 5);
9118 
9119 		pos2 = os_strstr(pos, "timeout=");
9120 		if (pos2)
9121 			ework->timeout = atoi(pos2 + 8);
9122 	} else {
9123 		type_len = os_strlen(cmd);
9124 	}
9125 	if (4 + type_len >= sizeof(ework->type))
9126 		type_len = sizeof(ework->type) - 4 - 1;
9127 	os_strlcpy(ework->type, "ext:", sizeof(ework->type));
9128 	os_memcpy(ework->type + 4, cmd, type_len);
9129 	ework->type[4 + type_len] = '\0';
9130 
9131 	wpa_s->ext_work_id++;
9132 	if (wpa_s->ext_work_id == 0)
9133 		wpa_s->ext_work_id++;
9134 	ework->id = wpa_s->ext_work_id;
9135 
9136 	if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
9137 			   ework) < 0) {
9138 		os_free(ework);
9139 		return -1;
9140 	}
9141 
9142 	ret = os_snprintf(buf, buflen, "%u", ework->id);
9143 	if (os_snprintf_error(buflen, ret))
9144 		return -1;
9145 	return ret;
9146 }
9147 
9148 
9149 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
9150 {
9151 	struct wpa_radio_work *work;
9152 	unsigned int id = atoi(cmd);
9153 
9154 	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9155 	{
9156 		struct wpa_external_work *ework;
9157 
9158 		if (os_strncmp(work->type, "ext:", 4) != 0)
9159 			continue;
9160 		ework = work->ctx;
9161 		if (id && ework->id != id)
9162 			continue;
9163 		wpa_dbg(wpa_s, MSG_DEBUG,
9164 			"Completed external radio work %u (%s)",
9165 			ework->id, ework->type);
9166 		eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
9167 		wpa_s->ext_work_in_progress = 0;
9168 		radio_work_done(work);
9169 		os_free(ework);
9170 		return 3; /* "OK\n" */
9171 	}
9172 
9173 	return -1;
9174 }
9175 
9176 
9177 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
9178 				char *buf, size_t buflen)
9179 {
9180 	if (os_strcmp(cmd, "show") == 0)
9181 		return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
9182 	if (os_strncmp(cmd, "add ", 4) == 0)
9183 		return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
9184 	if (os_strncmp(cmd, "done ", 5) == 0)
9185 		return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
9186 	return -1;
9187 }
9188 
9189 
9190 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
9191 {
9192 	struct wpa_radio_work *work, *tmp;
9193 
9194 	if (!wpa_s || !wpa_s->radio)
9195 		return;
9196 
9197 	dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
9198 			      struct wpa_radio_work, list) {
9199 		struct wpa_external_work *ework;
9200 
9201 		if (os_strncmp(work->type, "ext:", 4) != 0)
9202 			continue;
9203 		ework = work->ctx;
9204 		wpa_dbg(wpa_s, MSG_DEBUG,
9205 			"Flushing%s external radio work %u (%s)",
9206 			work->started ? " started" : "", ework->id,
9207 			ework->type);
9208 		if (work->started)
9209 			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9210 					     work, NULL);
9211 		radio_work_done(work);
9212 		os_free(ework);
9213 	}
9214 }
9215 
9216 
9217 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
9218 {
9219 	struct wpa_supplicant *wpa_s = eloop_ctx;
9220 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
9221 }
9222 
9223 
9224 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
9225 			      unsigned int *scan_id_count, int scan_id[])
9226 {
9227 	const char *pos = value;
9228 
9229 	while (pos) {
9230 		if (*pos == ' ' || *pos == '\0')
9231 			break;
9232 		if (*scan_id_count == MAX_SCAN_ID)
9233 			return -1;
9234 		scan_id[(*scan_id_count)++] = atoi(pos);
9235 		pos = os_strchr(pos, ',');
9236 		if (pos)
9237 			pos++;
9238 	}
9239 
9240 	return 0;
9241 }
9242 #endif /* EXT_CODE_CROP */
9243 
9244 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
9245 			   char *reply, int reply_size, int *reply_len)
9246 {
9247 #ifndef EXT_CODE_CROP
9248 	char *pos;
9249 	unsigned int manual_scan_passive = 0;
9250 	unsigned int manual_scan_use_id = 0;
9251 	unsigned int manual_scan_only_new = 0;
9252 	unsigned int scan_only = 0;
9253 	unsigned int scan_id_count = 0;
9254 	int scan_id[MAX_SCAN_ID];
9255 #endif /* EXT_CODE_CROP */
9256 	void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
9257 				 struct wpa_scan_results *scan_res);
9258 	int *manual_scan_freqs = NULL;
9259 	struct wpa_ssid_value *ssid	 = NULL;
9260 	struct wpa_ssid_value *ns	 = NULL;
9261 	char *pos					 = NULL;
9262 	unsigned int ssid_count = 0;
9263 
9264 #ifndef EXT_CODE_CROP
9265 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
9266 		*reply_len = -1;
9267 		(void)os_event_write(g_wpa_event, WPA_EVENT_SCAN_OK);
9268 		return;
9269 	}
9270 #else
9271 	(void)reply;
9272 #endif /* EXT_CODE_CROP */
9273 
9274 	if (radio_work_pending(wpa_s, "scan")) {
9275 #ifndef EXT_CODE_CROP
9276 		wpa_warning_log0(MSG_DEBUG,
9277 			   "Pending scan scheduled - reject new request");
9278 		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9279 #endif /* EXT_CODE_CROP */
9280 		*reply_len = -1;
9281 		(void)os_event_write(g_wpa_event, WPA_EVENT_SCAN_OK);
9282 		return;
9283 	}
9284 
9285 #ifdef CONFIG_INTERWORKING
9286 	if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
9287 		wpa_printf(MSG_DEBUG,
9288 			   "Interworking select in progress - reject new scan");
9289 		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9290 		return;
9291 	}
9292 #endif /* CONFIG_INTERWORKING */
9293 
9294 	if (params) {
9295 #ifndef EXT_CODE_CROP
9296 		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
9297 			scan_only = 1;
9298 #endif /* LOS_WPA_PATCH */
9299 		pos = os_strstr(params, "freq=");
9300 		if (pos) {
9301 			manual_scan_freqs = freq_range_to_channel_list(wpa_s,
9302 								       pos + 5);
9303 			if (manual_scan_freqs == NULL) {
9304 				*reply_len = -1;
9305 				goto done;
9306 			}
9307 		}
9308 #ifndef EXT_CODE_CROP
9309 		pos = os_strstr(params, "passive=");
9310 		if (pos)
9311 			manual_scan_passive = !!atoi(pos + 8);
9312 
9313 		pos = os_strstr(params, "use_id=");
9314 		if (pos)
9315 			manual_scan_use_id = atoi(pos + 7);
9316 
9317 		pos = os_strstr(params, "only_new=1");
9318 		if (pos)
9319 			manual_scan_only_new = 1;
9320 
9321 		pos = os_strstr(params, "scan_id=");
9322 		if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
9323 					      scan_id) < 0) {
9324 			*reply_len = -1;
9325 			goto done;
9326 		}
9327 #endif /* LOS_WPA_PATCH */
9328 
9329 		pos = os_strstr(params, "bssid=");
9330 		if (pos) {
9331 			u8 bssid[ETH_ALEN];
9332 
9333 			pos += 6;
9334 			if (hwaddr_aton(pos, bssid)) {
9335 #ifndef EXT_CODE_CROP
9336 				wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
9337 #endif /* EXT_CODE_CROP */
9338 				*reply_len = -1;
9339 				goto done;
9340 			}
9341 			os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
9342 
9343 			wpa_s->next_scan_bssid_wildcard_ssid =
9344 				os_strstr(params, "wildcard_ssid=1") != NULL;
9345 		}
9346 
9347 		pos = params;
9348 		while (pos && *pos != '\0') {
9349 			if (os_strncmp(pos, "ssid ", 5) == 0) {
9350 				char *end;
9351 
9352 				pos += 5;
9353 				end = pos;
9354 				while (*end) {
9355 #ifndef EXT_CODE_CROP
9356 					if (*end == '\0' || *end == ' ')
9357 						break;
9358 #else
9359 					if (*end == '\0')
9360 						break;
9361 #endif /* EXT_CODE_CROP */
9362 					end++;
9363 				}
9364 
9365 				ns = os_realloc_array(
9366 					ssid, ssid_count + 1,
9367 					sizeof(struct wpa_ssid_value));
9368 				if (ns == NULL) {
9369 					*reply_len = -1;
9370 					goto done;
9371 				}
9372 				ssid = ns;
9373 
9374 #ifndef EXT_CODE_CROP
9375 				if ((end - pos) & 0x01 ||
9376 				    end - pos > 2 * SSID_MAX_LEN ||
9377 				    hexstr2bin(pos, ssid[ssid_count].ssid,
9378 					       (end - pos) / 2) < 0) {
9379 					wpa_printf(MSG_DEBUG,
9380 						   "Invalid SSID value '%s'",
9381 						   pos);
9382 					*reply_len = -1;
9383 					goto done;
9384 				}
9385 #else
9386 				if ((end - pos) <= SSID_MAX_LEN) {
9387 					ssid[ssid_count].ssid_len = end - pos;
9388 					os_memcpy(ssid[ssid_count].ssid, pos, ssid[ssid_count].ssid_len);
9389 				} else {
9390 					*reply_len = -1;
9391 					goto done;
9392 				}
9393 #endif
9394 #ifndef EXT_CODE_CROP
9395 				ssid[ssid_count].ssid_len = (end - pos) / 2;
9396 				wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
9397 						  ssid[ssid_count].ssid,
9398 						  ssid[ssid_count].ssid_len);
9399 #endif /* EXT_CODE_CROP */
9400 				ssid_count++;
9401 #ifndef EXT_CODE_CROP
9402 				pos = end;
9403 #endif
9404 			}
9405 
9406 			pos = os_strchr(pos, ' ');
9407 			if (pos)
9408 				pos++;
9409 		}
9410 	}
9411 #ifndef LOS_WPA_PATCH
9412 	wpa_bss_flush(wpa_s);
9413 #endif /* LOS_WPA_PATCH */
9414 
9415 	wpa_s->num_ssids_from_scan_req = ssid_count;
9416 	os_free(wpa_s->ssids_from_scan_req);
9417 	if (ssid_count) {
9418 		wpa_s->ssids_from_scan_req = ssid;
9419 		ssid = NULL;
9420 	} else {
9421 		wpa_s->ssids_from_scan_req = NULL;
9422 	}
9423 
9424 #ifndef LOS_WPA_PATCH
9425 	if (scan_only)
9426 		scan_res_handler = scan_only_handler;
9427 	else if (wpa_s->scan_res_handler == scan_only_handler)
9428 		scan_res_handler = NULL;
9429 	else
9430 		scan_res_handler = wpa_s->scan_res_handler;
9431 #endif /* LOS_WPA_PATCH */
9432 	if (!wpa_s->sched_scanning && !wpa_s->scanning &&
9433 	    ((wpa_s->wpa_state <= WPA_SCANNING) ||
9434 	     (wpa_s->wpa_state == WPA_COMPLETED))) {
9435 #ifndef LOS_WPA_PATCH
9436 		wpa_s->manual_scan_passive = manual_scan_passive;
9437 		wpa_s->manual_scan_use_id = manual_scan_use_id;
9438 		wpa_s->manual_scan_only_new = manual_scan_only_new;
9439 		wpa_s->scan_id_count = scan_id_count;
9440 		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9441 #endif /* LOS_WPA_PATCH */
9442 		wpa_s->scan_res_handler = scan_res_handler;
9443 		os_free(wpa_s->manual_scan_freqs);
9444 		wpa_s->manual_scan_freqs = manual_scan_freqs;
9445 		manual_scan_freqs = NULL;
9446 #ifndef LOS_WPA_PATCH
9447 		wpa_s->normal_scans = 0;
9448 #endif /* LOS_WPA_PATCH */
9449 		wpa_s->scan_req = MANUAL_SCAN_REQ;
9450 		wpa_s->after_wps = 0;
9451 		wpa_s->known_wps_freq = 0;
9452 		wpa_supplicant_req_scan(wpa_s, 0, 0);
9453 #ifndef LOS_WPA_PATCH
9454 		if (wpa_s->manual_scan_use_id) {
9455 			wpa_s->manual_scan_id++;
9456 			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9457 				wpa_s->manual_scan_id);
9458 			*reply_len = os_snprintf(reply, reply_size, "%u\n",
9459 						 wpa_s->manual_scan_id);
9460 		}
9461 #endif /* LOS_WPA_PATCH */
9462 	}
9463 #ifndef LOS_WPA_PATCH
9464 	else if (wpa_s->sched_scanning) {
9465 		wpa_s->manual_scan_passive = manual_scan_passive;
9466 		wpa_s->manual_scan_use_id = manual_scan_use_id;
9467 		wpa_s->manual_scan_only_new = manual_scan_only_new;
9468 		wpa_s->scan_id_count = scan_id_count;
9469 		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9470 		wpa_s->scan_res_handler = scan_res_handler;
9471 		os_free(wpa_s->manual_scan_freqs);
9472 		wpa_s->manual_scan_freqs = manual_scan_freqs;
9473 		manual_scan_freqs = NULL;
9474 #ifndef EXT_CODE_CROP
9475 		wpa_s->normal_scans = 0;
9476 		wpa_s->scan_req = MANUAL_SCAN_REQ;
9477 		wpa_s->after_wps = 0;
9478 		wpa_s->known_wps_freq = 0;
9479 		wpa_supplicant_req_scan(wpa_s, 0, 0);
9480 		if (wpa_s->manual_scan_use_id) {
9481 			wpa_s->manual_scan_id++;
9482 			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9483 				wpa_s->manual_scan_id);
9484 			*reply_len = os_snprintf(reply, reply_size, "%u\n",
9485 						 wpa_s->manual_scan_id);
9486 		}
9487 	} else if (wpa_s->sched_scanning) {
9488 		wpa_s->manual_scan_passive = manual_scan_passive;
9489 		wpa_s->manual_scan_use_id = manual_scan_use_id;
9490 		wpa_s->manual_scan_only_new = manual_scan_only_new;
9491 		wpa_s->scan_id_count = scan_id_count;
9492 		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9493 		wpa_s->scan_res_handler = scan_res_handler;
9494 		os_free(wpa_s->manual_scan_freqs);
9495 		wpa_s->manual_scan_freqs = manual_scan_freqs;
9496 		manual_scan_freqs = NULL;
9497 
9498 		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
9499 		wpa_supplicant_cancel_sched_scan(wpa_s);
9500 #endif /* EXT_CODE_CROP */
9501 		wpa_s->scan_req = MANUAL_SCAN_REQ;
9502 		wpa_supplicant_req_scan(wpa_s, 0, 0);
9503 		if (wpa_s->manual_scan_use_id) {
9504 			wpa_s->manual_scan_id++;
9505 			*reply_len = os_snprintf(reply, reply_size, "%u\n",
9506 						 wpa_s->manual_scan_id);
9507 			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9508 				wpa_s->manual_scan_id);
9509 		}
9510 	}
9511 #endif /* LOS_WPA_PATCH */
9512 	else {
9513 #ifndef EXT_CODE_CROP
9514 		wpa_warning_log0(MSG_DEBUG, "Ongoing scan action - reject new request");
9515 		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9516 #endif /* EXT_CODE_CROP */
9517 		*reply_len = -1;
9518 	}
9519 
9520 done:
9521 	os_free(manual_scan_freqs);
9522 	os_free(ssid);
9523 	if (*reply_len == -1)
9524 		(void)os_event_write(g_wpa_event, WPA_EVENT_SCAN_OK);
9525 }
9526 
9527 
9528 #ifdef LOS_WPA_PATCH
9529 void wpa_mesh_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
9530 			   char *reply, int reply_size, int *reply_len)
9531 {
9532 	wpas_ctrl_scan(wpa_s, params, reply, reply_size, reply_len);
9533 }
9534 #endif /* LOS_WPA_PATCH */
9535 
9536 
9537 #ifdef CONFIG_TESTING_OPTIONS
9538 
9539 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
9540 				       unsigned int freq, const u8 *dst,
9541 				       const u8 *src, const u8 *bssid,
9542 				       const u8 *data, size_t data_len,
9543 				       enum offchannel_send_action_result
9544 				       result)
9545 {
9546 	wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
9547 		" src=" MACSTR " bssid=" MACSTR " result=%s",
9548 		freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
9549 		result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
9550 		"SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
9551 			     "NO_ACK" : "FAILED"));
9552 }
9553 
9554 
9555 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
9556 {
9557 	char *pos, *param;
9558 	size_t len;
9559 	u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
9560 	int res, used;
9561 	int freq = 0, no_cck = 0, wait_time = 0;
9562 
9563 	/* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
9564 	 *    <action=Action frame payload> */
9565 
9566 	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
9567 
9568 	pos = cmd;
9569 	used = hwaddr_aton2(pos, da);
9570 	if (used < 0)
9571 		return -1;
9572 	pos += used;
9573 	while (*pos == ' ')
9574 		pos++;
9575 	used = hwaddr_aton2(pos, bssid);
9576 	if (used < 0)
9577 		return -1;
9578 	pos += used;
9579 
9580 	param = os_strstr(pos, " freq=");
9581 	if (param) {
9582 		param += 6;
9583 		freq = atoi(param);
9584 	}
9585 
9586 	param = os_strstr(pos, " no_cck=");
9587 	if (param) {
9588 		param += 8;
9589 		no_cck = atoi(param);
9590 	}
9591 
9592 	param = os_strstr(pos, " wait_time=");
9593 	if (param) {
9594 		param += 11;
9595 		wait_time = atoi(param);
9596 	}
9597 
9598 	param = os_strstr(pos, " action=");
9599 	if (param == NULL)
9600 		return -1;
9601 	param += 8;
9602 
9603 	len = os_strlen(param);
9604 	if (len & 1)
9605 		return -1;
9606 	len /= 2;
9607 
9608 	buf = os_malloc(len);
9609 	if (buf == NULL)
9610 		return -1;
9611 
9612 	if (hexstr2bin(param, buf, len) < 0) {
9613 		os_free(buf);
9614 		return -1;
9615 	}
9616 
9617 	res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
9618 				     buf, len, wait_time,
9619 				     wpas_ctrl_iface_mgmt_tx_cb, no_cck);
9620 	os_free(buf);
9621 	return res;
9622 }
9623 
9624 
9625 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
9626 {
9627 	wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
9628 	offchannel_send_action_done(wpa_s);
9629 }
9630 
9631 
9632 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
9633 					   char *cmd)
9634 {
9635 	char *pos, *param;
9636 	size_t len;
9637 	u8 *buf;
9638 	int freq = 0, datarate = 0, ssi_signal = 0;
9639 	union wpa_event_data event;
9640 
9641 	if (!wpa_s->ext_mgmt_frame_handling)
9642 		return -1;
9643 
9644 	/* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
9645 
9646 	wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
9647 
9648 	pos = cmd;
9649 	param = os_strstr(pos, "freq=");
9650 	if (param) {
9651 		param += 5;
9652 		freq = atoi(param);
9653 	}
9654 
9655 	param = os_strstr(pos, " datarate=");
9656 	if (param) {
9657 		param += 10;
9658 		datarate = atoi(param);
9659 	}
9660 
9661 	param = os_strstr(pos, " ssi_signal=");
9662 	if (param) {
9663 		param += 12;
9664 		ssi_signal = atoi(param);
9665 	}
9666 
9667 	param = os_strstr(pos, " frame=");
9668 	if (param == NULL)
9669 		return -1;
9670 	param += 7;
9671 
9672 	len = os_strlen(param);
9673 	if (len & 1)
9674 		return -1;
9675 	len /= 2;
9676 
9677 	buf = os_malloc(len);
9678 	if (buf == NULL)
9679 		return -1;
9680 
9681 	if (hexstr2bin(param, buf, len) < 0) {
9682 		os_free(buf);
9683 		return -1;
9684 	}
9685 
9686 	os_memset(&event, 0, sizeof(event));
9687 	event.rx_mgmt.freq = freq;
9688 	event.rx_mgmt.frame = buf;
9689 	event.rx_mgmt.frame_len = len;
9690 	event.rx_mgmt.ssi_signal = ssi_signal;
9691 	event.rx_mgmt.datarate = datarate;
9692 	wpa_s->ext_mgmt_frame_handling = 0;
9693 	wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
9694 	wpa_s->ext_mgmt_frame_handling = 1;
9695 
9696 	os_free(buf);
9697 
9698 	return 0;
9699 }
9700 
9701 
9702 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
9703 					   char *param)
9704 {
9705 	struct wpa_scan_res *res;
9706 	struct os_reltime now;
9707 	char *pos, *end;
9708 	int ret = -1;
9709 
9710 	if (!param)
9711 		return -1;
9712 
9713 	if (os_strcmp(param, "START") == 0) {
9714 		wpa_bss_update_start(wpa_s);
9715 		return 0;
9716 	}
9717 
9718 	if (os_strcmp(param, "END") == 0) {
9719 		wpa_bss_update_end(wpa_s, NULL, 1);
9720 		return 0;
9721 	}
9722 
9723 	if (os_strncmp(param, "BSS ", 4) != 0)
9724 		return -1;
9725 	param += 3;
9726 
9727 	res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
9728 	if (!res)
9729 		return -1;
9730 
9731 	pos = os_strstr(param, " flags=");
9732 	if (pos)
9733 		res->flags = strtol(pos + 7, NULL, 16);
9734 
9735 	pos = os_strstr(param, " bssid=");
9736 	if (pos && hwaddr_aton(pos + 7, res->bssid))
9737 		goto fail;
9738 
9739 	pos = os_strstr(param, " freq=");
9740 	if (pos)
9741 		res->freq = atoi(pos + 6);
9742 
9743 	pos = os_strstr(param, " beacon_int=");
9744 	if (pos)
9745 		res->beacon_int = atoi(pos + 12);
9746 
9747 	pos = os_strstr(param, " caps=");
9748 	if (pos)
9749 		res->caps = strtol(pos + 6, NULL, 16);
9750 
9751 	pos = os_strstr(param, " qual=");
9752 	if (pos)
9753 		res->qual = atoi(pos + 6);
9754 
9755 	pos = os_strstr(param, " noise=");
9756 	if (pos)
9757 		res->noise = atoi(pos + 7);
9758 
9759 	pos = os_strstr(param, " level=");
9760 	if (pos)
9761 		res->level = atoi(pos + 7);
9762 
9763 	pos = os_strstr(param, " tsf=");
9764 	if (pos)
9765 		res->tsf = strtoll(pos + 5, NULL, 16);
9766 
9767 	pos = os_strstr(param, " age=");
9768 	if (pos)
9769 		res->age = atoi(pos + 5);
9770 
9771 	pos = os_strstr(param, " est_throughput=");
9772 	if (pos)
9773 		res->est_throughput = atoi(pos + 16);
9774 
9775 	pos = os_strstr(param, " snr=");
9776 	if (pos)
9777 		res->snr = atoi(pos + 5);
9778 
9779 	pos = os_strstr(param, " parent_tsf=");
9780 	if (pos)
9781 		res->parent_tsf = strtoll(pos + 7, NULL, 16);
9782 
9783 	pos = os_strstr(param, " tsf_bssid=");
9784 	if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
9785 		goto fail;
9786 
9787 	pos = os_strstr(param, " ie=");
9788 	if (pos) {
9789 		pos += 4;
9790 		end = os_strchr(pos, ' ');
9791 		if (!end)
9792 			end = pos + os_strlen(pos);
9793 		res->ie_len = (end - pos) / 2;
9794 		if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
9795 			goto fail;
9796 	}
9797 
9798 	pos = os_strstr(param, " beacon_ie=");
9799 	if (pos) {
9800 		pos += 11;
9801 		end = os_strchr(pos, ' ');
9802 		if (!end)
9803 			end = pos + os_strlen(pos);
9804 		res->beacon_ie_len = (end - pos) / 2;
9805 		if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
9806 			       res->beacon_ie_len))
9807 			goto fail;
9808 	}
9809 
9810 	os_get_reltime(&now);
9811 	wpa_bss_update_scan_res(wpa_s, res, &now);
9812 	ret = 0;
9813 fail:
9814 	os_free(res);
9815 
9816 	return ret;
9817 }
9818 
9819 
9820 static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
9821 					      char *param)
9822 {
9823 	union wpa_event_data event;
9824 	struct assoc_info *ai;
9825 	char *ctx = NULL;
9826 	int ret = -1;
9827 	struct wpabuf *req_ies = NULL;
9828 	struct wpabuf *resp_ies = NULL;
9829 	struct wpabuf *resp_frame = NULL;
9830 	struct wpabuf *beacon_ies = NULL;
9831 	struct wpabuf *key_replay_ctr = NULL;
9832 	struct wpabuf *ptk_kck = NULL;
9833 	struct wpabuf *ptk_kek = NULL;
9834 	struct wpabuf *fils_pmk = NULL;
9835 	char *str, *pos;
9836 	u8 addr[ETH_ALEN];
9837 	u8 fils_pmkid[PMKID_LEN];
9838 
9839 	os_memset(&event, 0, sizeof(event));
9840 	ai = &event.assoc_info;
9841 
9842 	while ((str = str_token(param, " ", &ctx))) {
9843 		pos = os_strchr(str, '=');
9844 		if (!pos)
9845 			goto fail;
9846 		*pos++ = '\0';
9847 
9848 		if (os_strcmp(str, "reassoc") == 0) {
9849 			ai->reassoc = atoi(pos);
9850 		} else if (os_strcmp(str, "req_ies") == 0) {
9851 			wpabuf_free(req_ies);
9852 			req_ies = wpabuf_parse_bin(pos);
9853 			if (!req_ies)
9854 				goto fail;
9855 			ai->req_ies = wpabuf_head(req_ies);
9856 			ai->req_ies_len = wpabuf_len(req_ies);
9857 		} else if (os_strcmp(str, "resp_ies") == 0) {
9858 			wpabuf_free(resp_ies);
9859 			resp_ies = wpabuf_parse_bin(pos);
9860 			if (!resp_ies)
9861 				goto fail;
9862 			ai->resp_ies = wpabuf_head(resp_ies);
9863 			ai->resp_ies_len = wpabuf_len(resp_ies);
9864 		} else if (os_strcmp(str, "resp_frame") == 0) {
9865 			wpabuf_free(resp_frame);
9866 			resp_frame = wpabuf_parse_bin(pos);
9867 			if (!resp_frame)
9868 				goto fail;
9869 			ai->resp_frame = wpabuf_head(resp_frame);
9870 			ai->resp_frame_len = wpabuf_len(resp_frame);
9871 		} else if (os_strcmp(str, "beacon_ies") == 0) {
9872 			wpabuf_free(beacon_ies);
9873 			beacon_ies = wpabuf_parse_bin(pos);
9874 			if (!beacon_ies)
9875 				goto fail;
9876 			ai->beacon_ies = wpabuf_head(beacon_ies);
9877 			ai->beacon_ies_len = wpabuf_len(beacon_ies);
9878 		} else if (os_strcmp(str, "freq") == 0) {
9879 			ai->freq = atoi(pos);
9880 		} else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
9881 			ai->wmm_params.info_bitmap = atoi(pos);
9882 		} else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
9883 			ai->wmm_params.uapsd_queues = atoi(pos);
9884 		} else if (os_strcmp(str, "addr") == 0) {
9885 			if (hwaddr_aton(pos, addr))
9886 				goto fail;
9887 			ai->addr = addr;
9888 		} else if (os_strcmp(str, "authorized") == 0) {
9889 			ai->authorized = atoi(pos);
9890 		} else if (os_strcmp(str, "key_replay_ctr") == 0) {
9891 			wpabuf_free(key_replay_ctr);
9892 			key_replay_ctr = wpabuf_parse_bin(pos);
9893 			if (!key_replay_ctr)
9894 				goto fail;
9895 			ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
9896 			ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
9897 		} else if (os_strcmp(str, "ptk_kck") == 0) {
9898 			wpabuf_free(ptk_kck);
9899 			ptk_kck = wpabuf_parse_bin(pos);
9900 			if (!ptk_kck)
9901 				goto fail;
9902 			ai->ptk_kck = wpabuf_head(ptk_kck);
9903 			ai->ptk_kck_len = wpabuf_len(ptk_kck);
9904 		} else if (os_strcmp(str, "ptk_kek") == 0) {
9905 			wpabuf_free(ptk_kek);
9906 			ptk_kek = wpabuf_parse_bin(pos);
9907 			if (!ptk_kek)
9908 				goto fail;
9909 			ai->ptk_kek = wpabuf_head(ptk_kek);
9910 			ai->ptk_kek_len = wpabuf_len(ptk_kek);
9911 		} else if (os_strcmp(str, "subnet_status") == 0) {
9912 			ai->subnet_status = atoi(pos);
9913 		} else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
9914 			ai->fils_erp_next_seq_num = atoi(pos);
9915 		} else if (os_strcmp(str, "fils_pmk") == 0) {
9916 			wpabuf_free(fils_pmk);
9917 			fils_pmk = wpabuf_parse_bin(pos);
9918 			if (!fils_pmk)
9919 				goto fail;
9920 			ai->fils_pmk = wpabuf_head(fils_pmk);
9921 			ai->fils_pmk_len = wpabuf_len(fils_pmk);
9922 		} else if (os_strcmp(str, "fils_pmkid") == 0) {
9923 			if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
9924 				goto fail;
9925 			ai->fils_pmkid = fils_pmkid;
9926 		} else {
9927 			goto fail;
9928 		}
9929 	}
9930 
9931 	wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
9932 	ret = 0;
9933 fail:
9934 	wpabuf_free(req_ies);
9935 	wpabuf_free(resp_ies);
9936 	wpabuf_free(resp_frame);
9937 	wpabuf_free(beacon_ies);
9938 	wpabuf_free(key_replay_ctr);
9939 	wpabuf_free(ptk_kck);
9940 	wpabuf_free(ptk_kek);
9941 	wpabuf_free(fils_pmk);
9942 	return ret;
9943 }
9944 
9945 
9946 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
9947 {
9948 	char *pos, *param;
9949 	union wpa_event_data event;
9950 	enum wpa_event_type ev;
9951 
9952 	/* <event name> [parameters..] */
9953 
9954 	wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
9955 
9956 	pos = cmd;
9957 	param = os_strchr(pos, ' ');
9958 	if (param)
9959 		*param++ = '\0';
9960 
9961 	os_memset(&event, 0, sizeof(event));
9962 
9963 	if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
9964 		ev = EVENT_INTERFACE_ENABLED;
9965 	} else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
9966 		ev = EVENT_INTERFACE_DISABLED;
9967 	} else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
9968 		ev = EVENT_AVOID_FREQUENCIES;
9969 		if (param == NULL)
9970 			param = "";
9971 		if (freq_range_list_parse(&event.freq_range, param) < 0)
9972 			return -1;
9973 		wpa_supplicant_event(wpa_s, ev, &event);
9974 		os_free(event.freq_range.range);
9975 		return 0;
9976 	} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
9977 		return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
9978 	} else if (os_strcmp(cmd, "ASSOC") == 0) {
9979 		return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
9980 	} else {
9981 		wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
9982 			cmd);
9983 		return -1;
9984 	}
9985 
9986 	wpa_supplicant_event(wpa_s, ev, &event);
9987 
9988 	return 0;
9989 }
9990 
9991 
9992 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
9993 {
9994 	char *pos;
9995 	u8 src[ETH_ALEN], *buf;
9996 	int used;
9997 	size_t len;
9998 
9999 	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
10000 
10001 	pos = cmd;
10002 	used = hwaddr_aton2(pos, src);
10003 	if (used < 0)
10004 		return -1;
10005 	pos += used;
10006 	while (*pos == ' ')
10007 		pos++;
10008 
10009 	len = os_strlen(pos);
10010 	if (len & 1)
10011 		return -1;
10012 	len /= 2;
10013 
10014 	buf = os_malloc(len);
10015 	if (buf == NULL)
10016 		return -1;
10017 
10018 	if (hexstr2bin(pos, buf, len) < 0) {
10019 		os_free(buf);
10020 		return -1;
10021 	}
10022 
10023 	wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
10024 	os_free(buf);
10025 
10026 	return 0;
10027 }
10028 
10029 
10030 static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
10031 {
10032 	char *pos;
10033 	u8 dst[ETH_ALEN], *buf;
10034 	int used, ret;
10035 	size_t len;
10036 	unsigned int prev;
10037 
10038 	wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
10039 
10040 	pos = cmd;
10041 	used = hwaddr_aton2(pos, dst);
10042 	if (used < 0)
10043 		return -1;
10044 	pos += used;
10045 	while (*pos == ' ')
10046 		pos++;
10047 
10048 	len = os_strlen(pos);
10049 	if (len & 1)
10050 		return -1;
10051 	len /= 2;
10052 
10053 	buf = os_malloc(len);
10054 	if (!buf || hexstr2bin(pos, buf, len) < 0) {
10055 		os_free(buf);
10056 		return -1;
10057 	}
10058 
10059 	prev = wpa_s->ext_eapol_frame_io;
10060 	wpa_s->ext_eapol_frame_io = 0;
10061 	ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
10062 	wpa_s->ext_eapol_frame_io = prev;
10063 	os_free(buf);
10064 
10065 	return ret;
10066 }
10067 
10068 
10069 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
10070 {
10071 	size_t i;
10072 	u32 sum = 0;
10073 	const u16 *pos = buf;
10074 
10075 	for (i = 0; i < len / 2; i++)
10076 		sum += *pos++;
10077 
10078 	while (sum >> 16)
10079 		sum = (sum & 0xffff) + (sum >> 16);
10080 
10081 	return sum ^ 0xffff;
10082 }
10083 
10084 
10085 #define HWSIM_PACKETLEN 1500
10086 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
10087 
10088 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
10089 			      size_t len)
10090 {
10091 	struct wpa_supplicant *wpa_s = ctx;
10092 	const struct ether_header *eth;
10093 	struct ip ip;
10094 	const u8 *pos;
10095 	unsigned int i;
10096 	char extra[30];
10097 
10098 	if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
10099 		wpa_printf(MSG_DEBUG,
10100 			   "test data: RX - ignore unexpected length %d",
10101 			   (int) len);
10102 		return;
10103 	}
10104 
10105 	eth = (const struct ether_header *) buf;
10106 	os_memcpy(&ip, eth + 1, sizeof(ip));
10107 	pos = &buf[sizeof(*eth) + sizeof(ip)];
10108 
10109 	if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
10110 		wpa_printf(MSG_DEBUG,
10111 			   "test data: RX - ignore unexpected IP header");
10112 		return;
10113 	}
10114 
10115 	for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
10116 		if (*pos != (u8) i) {
10117 			wpa_printf(MSG_DEBUG,
10118 				   "test data: RX - ignore mismatching payload");
10119 			return;
10120 		}
10121 		pos++;
10122 	}
10123 	extra[0] = '\0';
10124 	if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
10125 		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
10126 	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
10127 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
10128 }
10129 
10130 
10131 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
10132 					    char *cmd)
10133 {
10134 	int enabled = atoi(cmd);
10135 	char *pos;
10136 	const char *ifname;
10137 
10138 	if (!enabled) {
10139 		if (wpa_s->l2_test) {
10140 			l2_packet_deinit(wpa_s->l2_test);
10141 			wpa_s->l2_test = NULL;
10142 			wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
10143 		}
10144 		return 0;
10145 	}
10146 
10147 	if (wpa_s->l2_test)
10148 		return 0;
10149 
10150 	pos = os_strstr(cmd, " ifname=");
10151 	if (pos)
10152 		ifname = pos + 8;
10153 	else
10154 		ifname = wpa_s->ifname;
10155 
10156 	wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
10157 					ETHERTYPE_IP, wpas_data_test_rx,
10158 					wpa_s, 1);
10159 	if (wpa_s->l2_test == NULL)
10160 		return -1;
10161 
10162 	wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
10163 
10164 	return 0;
10165 }
10166 
10167 
10168 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
10169 {
10170 	u8 dst[ETH_ALEN], src[ETH_ALEN];
10171 	char *pos, *pos2;
10172 	int used;
10173 	long int val;
10174 	u8 tos;
10175 	u8 buf[2 + HWSIM_PACKETLEN];
10176 	struct ether_header *eth;
10177 	struct ip *ip;
10178 	u8 *dpos;
10179 	unsigned int i;
10180 	size_t send_len = HWSIM_IP_LEN;
10181 
10182 	if (wpa_s->l2_test == NULL)
10183 		return -1;
10184 
10185 	/* format: <dst> <src> <tos> [len=<length>] */
10186 
10187 	pos = cmd;
10188 	used = hwaddr_aton2(pos, dst);
10189 	if (used < 0)
10190 		return -1;
10191 	pos += used;
10192 	while (*pos == ' ')
10193 		pos++;
10194 	used = hwaddr_aton2(pos, src);
10195 	if (used < 0)
10196 		return -1;
10197 	pos += used;
10198 
10199 	val = strtol(pos, &pos2, 0);
10200 	if (val < 0 || val > 0xff)
10201 		return -1;
10202 	tos = val;
10203 
10204 	pos = os_strstr(pos2, " len=");
10205 	if (pos) {
10206 		i = atoi(pos + 5);
10207 		if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
10208 			return -1;
10209 		send_len = i;
10210 	}
10211 
10212 	eth = (struct ether_header *) &buf[2];
10213 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
10214 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
10215 	eth->ether_type = htons(ETHERTYPE_IP);
10216 	ip = (struct ip *) (eth + 1);
10217 	os_memset(ip, 0, sizeof(*ip));
10218 	ip->ip_hl = 5;
10219 	ip->ip_v = 4;
10220 	ip->ip_ttl = 64;
10221 	ip->ip_tos = tos;
10222 	ip->ip_len = htons(send_len);
10223 	ip->ip_p = 1;
10224 	ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
10225 	ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
10226 	ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
10227 	dpos = (u8 *) (ip + 1);
10228 	for (i = 0; i < send_len - sizeof(*ip); i++)
10229 		*dpos++ = i;
10230 
10231 	if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
10232 			   sizeof(struct ether_header) + send_len) < 0)
10233 		return -1;
10234 
10235 	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
10236 		" tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
10237 
10238 	return 0;
10239 }
10240 
10241 
10242 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
10243 					   char *cmd)
10244 {
10245 	u8 *buf;
10246 	struct ether_header *eth;
10247 	struct l2_packet_data *l2 = NULL;
10248 	size_t len;
10249 	u16 ethertype;
10250 	int res = -1;
10251 
10252 	len = os_strlen(cmd);
10253 	if (len & 1 || len < ETH_HLEN * 2)
10254 		return -1;
10255 	len /= 2;
10256 
10257 	buf = os_malloc(len);
10258 	if (buf == NULL)
10259 		return -1;
10260 
10261 	if (hexstr2bin(cmd, buf, len) < 0)
10262 		goto done;
10263 
10264 	eth = (struct ether_header *) buf;
10265 	ethertype = ntohs(eth->ether_type);
10266 
10267 	l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
10268 			    wpas_data_test_rx, wpa_s, 1);
10269 	if (l2 == NULL)
10270 		goto done;
10271 
10272 	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
10273 	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
10274 done:
10275 	if (l2)
10276 		l2_packet_deinit(l2);
10277 	os_free(buf);
10278 
10279 	return res < 0 ? -1 : 0;
10280 }
10281 
10282 
10283 static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
10284 {
10285 #ifdef WPA_TRACE_BFD
10286 	char *pos;
10287 
10288 	wpa_trace_fail_after = atoi(cmd);
10289 	pos = os_strchr(cmd, ':');
10290 	if (pos) {
10291 		pos++;
10292 		os_strlcpy(wpa_trace_fail_func, pos,
10293 			   sizeof(wpa_trace_fail_func));
10294 	} else {
10295 		wpa_trace_fail_after = 0;
10296 	}
10297 	return 0;
10298 #else /* WPA_TRACE_BFD */
10299 	return -1;
10300 #endif /* WPA_TRACE_BFD */
10301 }
10302 
10303 
10304 static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
10305 				    char *buf, size_t buflen)
10306 {
10307 #ifdef WPA_TRACE_BFD
10308 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
10309 			   wpa_trace_fail_func);
10310 #else /* WPA_TRACE_BFD */
10311 	return -1;
10312 #endif /* WPA_TRACE_BFD */
10313 }
10314 
10315 
10316 static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
10317 {
10318 #ifdef WPA_TRACE_BFD
10319 	char *pos;
10320 
10321 	wpa_trace_test_fail_after = atoi(cmd);
10322 	pos = os_strchr(cmd, ':');
10323 	if (pos) {
10324 		pos++;
10325 		os_strlcpy(wpa_trace_test_fail_func, pos,
10326 			   sizeof(wpa_trace_test_fail_func));
10327 	} else {
10328 		wpa_trace_test_fail_after = 0;
10329 	}
10330 	return 0;
10331 #else /* WPA_TRACE_BFD */
10332 	return -1;
10333 #endif /* WPA_TRACE_BFD */
10334 }
10335 
10336 
10337 static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
10338 				    char *buf, size_t buflen)
10339 {
10340 #ifdef WPA_TRACE_BFD
10341 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
10342 			   wpa_trace_test_fail_func);
10343 #else /* WPA_TRACE_BFD */
10344 	return -1;
10345 #endif /* WPA_TRACE_BFD */
10346 }
10347 
10348 
10349 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
10350 {
10351 	struct wpa_supplicant *wpa_s = eloop_ctx;
10352 	int i, count = (intptr_t) timeout_ctx;
10353 
10354 	wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
10355 		   count);
10356 	for (i = 0; i < count; i++) {
10357 		wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
10358 			     i + 1, count);
10359 	}
10360 }
10361 
10362 
10363 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
10364 {
10365 	int count;
10366 
10367 	count = atoi(cmd);
10368 	if (count <= 0)
10369 		return -1;
10370 
10371 	return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
10372 				      (void *) (intptr_t) count);
10373 }
10374 
10375 
10376 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
10377 				   const char *cmd)
10378 {
10379 	struct wpabuf *buf;
10380 	size_t len;
10381 
10382 	len = os_strlen(cmd);
10383 	if (len & 1)
10384 		return -1;
10385 	len /= 2;
10386 
10387 	if (len == 0) {
10388 		buf = NULL;
10389 	} else {
10390 		buf = wpabuf_alloc(len);
10391 		if (buf == NULL)
10392 			return -1;
10393 
10394 		if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
10395 			wpabuf_free(buf);
10396 			return -1;
10397 		}
10398 	}
10399 
10400 	wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
10401 	return 0;
10402 }
10403 
10404 
10405 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
10406 {
10407 	u8 zero[WPA_TK_MAX_LEN];
10408 
10409 	if (wpa_s->last_tk_alg == WPA_ALG_NONE)
10410 		return -1;
10411 
10412 	wpa_printf(MSG_INFO, "TESTING: Reset PN");
10413 	os_memset(zero, 0, sizeof(zero));
10414 
10415 	/* First, use a zero key to avoid any possible duplicate key avoidance
10416 	 * in the driver. */
10417 	if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
10418 			    wpa_s->last_tk_key_idx, 1, zero, 6,
10419 			    zero, wpa_s->last_tk_len,
10420 			    KEY_FLAG_PAIRWISE_RX_TX) < 0)
10421 		return -1;
10422 
10423 	/* Set the previously configured key to reset its TSC/RSC */
10424 	return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
10425 			       wpa_s->last_tk_key_idx, 1, zero, 6,
10426 			       wpa_s->last_tk, wpa_s->last_tk_len,
10427 			       KEY_FLAG_PAIRWISE_RX_TX);
10428 }
10429 
10430 
10431 static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
10432 {
10433 	const char *pos = cmd;
10434 	int error, pairwise;
10435 
10436 	error = atoi(pos);
10437 	pos = os_strchr(pos, ' ');
10438 	if (!pos)
10439 		return -1;
10440 	pairwise = atoi(pos);
10441 	wpa_sm_key_request(wpa_s->wpa, error, pairwise);
10442 	return 0;
10443 }
10444 
10445 
10446 static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
10447 {
10448 #ifdef CONFIG_SME
10449 	struct wpa_driver_associate_params params;
10450 	int ret;
10451 
10452 	os_memset(&params, 0, sizeof(params));
10453 	params.bssid = wpa_s->bssid;
10454 	params.ssid = wpa_s->sme.ssid;
10455 	params.ssid_len = wpa_s->sme.ssid_len;
10456 	params.freq.freq = wpa_s->sme.freq;
10457 	if (wpa_s->last_assoc_req_wpa_ie) {
10458 		params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
10459 		params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
10460 	}
10461 	params.pairwise_suite = wpa_s->pairwise_cipher;
10462 	params.group_suite = wpa_s->group_cipher;
10463 	params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
10464 	params.key_mgmt_suite = wpa_s->key_mgmt;
10465 	params.wpa_proto = wpa_s->wpa_proto;
10466 	params.mgmt_frame_protection = wpa_s->sme.mfp;
10467 	params.rrm_used = wpa_s->rrm.rrm_used;
10468 	if (wpa_s->sme.prev_bssid_set)
10469 		params.prev_bssid = wpa_s->sme.prev_bssid;
10470 	wpa_printf(MSG_INFO, "TESTING: Resend association request");
10471 	ret = wpa_drv_associate(wpa_s, &params);
10472 	wpa_s->testing_resend_assoc = 1;
10473 	return ret;
10474 #else /* CONFIG_SME */
10475 	return -1;
10476 #endif /* CONFIG_SME */
10477 }
10478 
10479 
10480 static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s,
10481 					  const char *cmd)
10482 {
10483 	u8 dtok = 1;
10484 	int exponent = 10;
10485 	int mantissa = 8192;
10486 	u8 min_twt = 255;
10487 	unsigned long long twt = 0;
10488 	bool requestor = true;
10489 	int setup_cmd = 0;
10490 	bool trigger = true;
10491 	bool implicit = true;
10492 	bool flow_type = true;
10493 	int flow_id = 0;
10494 	bool protection = false;
10495 	u8 twt_channel = 0;
10496 	u8 control = BIT(4); /* Control field (IEEE P802.11ax/D8.0 Figure
10497 			      * 9-687): B4 = TWT Information Frame Disabled */
10498 	const char *tok_s;
10499 
10500 	tok_s = os_strstr(cmd, " dialog=");
10501 	if (tok_s)
10502 		dtok = atoi(tok_s + os_strlen(" dialog="));
10503 
10504 	tok_s = os_strstr(cmd, " exponent=");
10505 	if (tok_s)
10506 		exponent = atoi(tok_s + os_strlen(" exponent="));
10507 
10508 	tok_s = os_strstr(cmd, " mantissa=");
10509 	if (tok_s)
10510 		mantissa = atoi(tok_s + os_strlen(" mantissa="));
10511 
10512 	tok_s = os_strstr(cmd, " min_twt=");
10513 	if (tok_s)
10514 		min_twt = atoi(tok_s + os_strlen(" min_twt="));
10515 
10516 	tok_s = os_strstr(cmd, " setup_cmd=");
10517 	if (tok_s)
10518 		setup_cmd = atoi(tok_s + os_strlen(" setup_cmd="));
10519 
10520 	tok_s = os_strstr(cmd, " twt=");
10521 	if (tok_s)
10522 		sscanf(tok_s + os_strlen(" twt="), "%llu", &twt);
10523 
10524 	tok_s = os_strstr(cmd, " requestor=");
10525 	if (tok_s)
10526 		requestor = atoi(tok_s + os_strlen(" requestor="));
10527 
10528 	tok_s = os_strstr(cmd, " trigger=");
10529 	if (tok_s)
10530 		trigger = atoi(tok_s + os_strlen(" trigger="));
10531 
10532 	tok_s = os_strstr(cmd, " implicit=");
10533 	if (tok_s)
10534 		implicit = atoi(tok_s + os_strlen(" implicit="));
10535 
10536 	tok_s = os_strstr(cmd, " flow_type=");
10537 	if (tok_s)
10538 		flow_type = atoi(tok_s + os_strlen(" flow_type="));
10539 
10540 	tok_s = os_strstr(cmd, " flow_id=");
10541 	if (tok_s)
10542 		flow_id = atoi(tok_s + os_strlen(" flow_id="));
10543 
10544 	tok_s = os_strstr(cmd, " protection=");
10545 	if (tok_s)
10546 		protection = atoi(tok_s + os_strlen(" protection="));
10547 
10548 	tok_s = os_strstr(cmd, " twt_channel=");
10549 	if (tok_s)
10550 		twt_channel = atoi(tok_s + os_strlen(" twt_channel="));
10551 
10552 	tok_s = os_strstr(cmd, " control=");
10553 	if (tok_s)
10554 		control = atoi(tok_s + os_strlen(" control="));
10555 
10556 	return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt,
10557 				   setup_cmd, twt, requestor, trigger, implicit,
10558 				   flow_type, flow_id, protection, twt_channel,
10559 				   control);
10560 }
10561 
10562 
10563 static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
10564 					     const char *cmd)
10565 {
10566 	u8 flags = 0x1;
10567 	const char *tok_s;
10568 
10569 	tok_s = os_strstr(cmd, " flags=");
10570 	if (tok_s)
10571 		flags = atoi(tok_s + os_strlen(" flags="));
10572 
10573 	return wpas_twt_send_teardown(wpa_s, flags);
10574 }
10575 
10576 #endif /* CONFIG_TESTING_OPTIONS */
10577 
10578 #ifndef EXT_CODE_CROP
10579 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
10580 {
10581 	char *pos = cmd;
10582 	int frame;
10583 	size_t len;
10584 	struct wpabuf *buf;
10585 	struct ieee802_11_elems elems;
10586 
10587 	frame = atoi(pos);
10588 	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10589 		return -1;
10590 	wpa_s = wpas_vendor_elem(wpa_s, frame);
10591 
10592 	pos = os_strchr(pos, ' ');
10593 	if (pos == NULL)
10594 		return -1;
10595 	pos++;
10596 
10597 	len = os_strlen(pos);
10598 	if (len == 0)
10599 		return 0;
10600 	if (len & 1)
10601 		return -1;
10602 	len /= 2;
10603 
10604 	buf = wpabuf_alloc(len);
10605 	if (buf == NULL)
10606 		return -1;
10607 
10608 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
10609 		wpabuf_free(buf);
10610 		return -1;
10611 	}
10612 
10613 	if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
10614 	    ParseFailed) {
10615 		wpabuf_free(buf);
10616 		return -1;
10617 	}
10618 
10619 	if (wpa_s->vendor_elem[frame] == NULL) {
10620 		wpa_s->vendor_elem[frame] = buf;
10621 		goto update_ies;
10622 	}
10623 
10624 	if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
10625 		wpabuf_free(buf);
10626 		return -1;
10627 	}
10628 
10629 	wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
10630 	wpabuf_free(buf);
10631 
10632 update_ies:
10633 	wpas_vendor_elem_update(wpa_s);
10634 
10635 	if (frame == VENDOR_ELEM_PROBE_REQ ||
10636 	    frame == VENDOR_ELEM_PROBE_REQ_P2P)
10637 		wpa_supplicant_set_default_scan_ies(wpa_s);
10638 
10639 	return 0;
10640 }
10641 
10642 
10643 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
10644 				     char *buf, size_t buflen)
10645 {
10646 	int frame = atoi(cmd);
10647 
10648 	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10649 		return -1;
10650 	wpa_s = wpas_vendor_elem(wpa_s, frame);
10651 
10652 	if (wpa_s->vendor_elem[frame] == NULL)
10653 		return 0;
10654 
10655 	return wpa_snprintf_hex(buf, buflen,
10656 				wpabuf_head_u8(wpa_s->vendor_elem[frame]),
10657 				wpabuf_len(wpa_s->vendor_elem[frame]));
10658 }
10659 
10660 
10661 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
10662 {
10663 	char *pos = cmd;
10664 	int frame;
10665 	size_t len;
10666 	u8 *buf;
10667 	struct ieee802_11_elems elems;
10668 	int res;
10669 
10670 	frame = atoi(pos);
10671 	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10672 		return -1;
10673 	wpa_s = wpas_vendor_elem(wpa_s, frame);
10674 
10675 	pos = os_strchr(pos, ' ');
10676 	if (pos == NULL)
10677 		return -1;
10678 	pos++;
10679 
10680 	if (*pos == '*') {
10681 		wpabuf_free(wpa_s->vendor_elem[frame]);
10682 		wpa_s->vendor_elem[frame] = NULL;
10683 		wpas_vendor_elem_update(wpa_s);
10684 		return 0;
10685 	}
10686 
10687 	if (wpa_s->vendor_elem[frame] == NULL)
10688 		return -1;
10689 
10690 	len = os_strlen(pos);
10691 	if (len == 0)
10692 		return 0;
10693 	if (len & 1)
10694 		return -1;
10695 	len /= 2;
10696 
10697 	buf = os_malloc(len);
10698 	if (buf == NULL)
10699 		return -1;
10700 
10701 	if (hexstr2bin(pos, buf, len) < 0) {
10702 		os_free(buf);
10703 		return -1;
10704 	}
10705 
10706 	if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
10707 		os_free(buf);
10708 		return -1;
10709 	}
10710 
10711 	res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
10712 	os_free(buf);
10713 	return res;
10714 }
10715 #endif /* EXT_CODE_CROP */
10716 
10717 static int wpa_sta_status(struct wpa_supplicant *wpa_s)
10718 {
10719 	if ((g_sta_status == NULL) || (wpa_s == NULL)) {
10720 		(void)os_event_write(g_wpa_event, WPA_EVENT_STA_STATUS_FAIL);
10721 		return EXT_WIFI_FAIL;
10722 	}
10723 
10724 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
10725 		struct wpa_ssid *ssid = wpa_s->current_ssid;
10726 		os_memcpy(g_sta_status->bssid, wpa_s->bssid, ETH_ALEN);
10727 
10728 		if (los_freq_to_channel(wpa_s->assoc_freq, &g_sta_status->channel) != EXT_WIFI_OK) {
10729 			(void)os_event_write(g_wpa_event, WPA_EVENT_STA_STATUS_FAIL);
10730 			return EXT_WIFI_FAIL;
10731 		}
10732 		if ((ssid != NULL) && (ssid->ssid_len > 0) && (ssid->ssid != NULL)) {
10733 			os_memcpy(g_sta_status->ssid, ssid->ssid, ssid->ssid_len);
10734         } else if ((wpa_s->current_bss != NULL) && (wpa_s->current_bss->ssid_len > 0) &&
10735             (wpa_s->current_bss->ssid != NULL)) {
10736             os_memcpy(g_sta_status->ssid, wpa_s->current_bss->ssid, wpa_s->current_bss->ssid_len);
10737         }
10738 	}
10739 	if (wpa_s->wpa_state < WPA_AUTHENTICATING) {
10740 		g_sta_status->status = EXT_WIFI_DISCONNECTED;
10741 	} else if (wpa_s->wpa_state >= WPA_AUTHENTICATING && wpa_s->wpa_state < WPA_COMPLETED) {
10742 		g_sta_status->status = EXT_WIFI_CONNECTING;
10743 	} else if (wpa_s->wpa_state == WPA_COMPLETED) {
10744 		g_sta_status->status = EXT_WIFI_CONNECTED;
10745 	} else {
10746 		(void)os_event_write(g_wpa_event, WPA_EVENT_STA_STATUS_FAIL);
10747 		return EXT_WIFI_FAIL;
10748 	}
10749 
10750 	(void)os_event_write(g_wpa_event, WPA_EVENT_STA_STATUS_OK);
10751 	return EXT_WIFI_OK;
10752 }
10753 
10754 static int wpa_get_sta_status(struct wpa_supplicant *wpa_s, void *addr)
10755 {
10756     ext_wifi_status_sem *connect_status = (ext_wifi_status_sem *)addr;
10757 
10758     if ((connect_status == NULL) || (wpa_s == NULL)) {
10759         connect_status->status = WIFI_STASTUS_PTR_NULL;
10760         osal_sem_up(&connect_status->sta_status_sem);
10761         return EXT_WIFI_FAIL;
10762 	}
10763 
10764 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
10765 		struct wpa_ssid *ssid = wpa_s->current_ssid;
10766 		os_memcpy(connect_status->conn_status->bssid, wpa_s->bssid, ETH_ALEN);
10767 
10768 		if (los_freq_to_channel(wpa_s->assoc_freq, &connect_status->conn_status->channel) != EXT_WIFI_OK) {
10769             connect_status->status = WIFI_STASTUS_CHAN_FAIL;
10770             osal_sem_up(&connect_status->sta_status_sem);
10771 			return EXT_WIFI_FAIL;
10772 		}
10773 		if ((ssid != NULL) && (ssid->ssid_len > 0) && (ssid->ssid != NULL)) {
10774 			os_memcpy(connect_status->conn_status->ssid, ssid->ssid, ssid->ssid_len);
10775         } else if ((wpa_s->current_bss != NULL) && (wpa_s->current_bss->ssid_len > 0) &&
10776             (wpa_s->current_bss->ssid != NULL)) {
10777             os_memcpy(connect_status->conn_status->ssid, wpa_s->current_bss->ssid, wpa_s->current_bss->ssid_len);
10778         }
10779 	}
10780 	if (wpa_s->wpa_state < WPA_AUTHENTICATING) {
10781 		connect_status->conn_status->status = EXT_WIFI_DISCONNECTED;
10782 	} else if (wpa_s->wpa_state >= WPA_AUTHENTICATING && wpa_s->wpa_state < WPA_COMPLETED) {
10783 		connect_status->conn_status->status = EXT_WIFI_CONNECTING;
10784 	} else if (wpa_s->wpa_state == WPA_COMPLETED) {
10785 		connect_status->conn_status->status = EXT_WIFI_CONNECTED;
10786 	} else {
10787         connect_status->status = WIFI_STASTUS_SET_FAIL;
10788         osal_sem_up(&connect_status->sta_status_sem);
10789 		return EXT_WIFI_FAIL;
10790 	}
10791 
10792     connect_status->status = WIFI_STASTUS_OK;
10793     osal_sem_up(&connect_status->sta_status_sem);
10794 	return EXT_WIFI_OK;
10795 }
10796 
10797 
10798 static int hapd_deauth_peer(struct hostapd_data *hapd, const char *addr_txt)
10799 {
10800 	struct sta_info *sta = NULL;
10801 	u8 addr[ETH_ALEN] = { 0 };
10802 	if (hapd == NULL) {
10803 		wpa_error_log0(MSG_ERROR, "hapd_deauth_peer fail.");
10804 		goto OUT;
10805 	}
10806 	if (hwaddr_aton(addr_txt, addr)) {
10807 		goto OUT;
10808 	}
10809 
10810 	hostapd_drv_sta_remove(hapd, addr);
10811 	(void)os_event_write(g_softap_event, WPA_EVENT_AP_DEAUTH_OK);
10812 	return EXT_WIFI_OK;
10813 OUT:
10814 	(void)os_event_write(g_softap_event, WPA_EVENT_AP_DEAUTH_FAIL);
10815 	return EXT_WIFI_FAIL;
10816 }
10817 
10818 
10819 static int wpa_supplicant_iface_remove(struct wpa_supplicant *wpa_s)
10820 {
10821 	int res = 0;
10822 	if ((wpa_s == NULL) || (wpa_s->global == NULL)) {
10823 		wpa_error_log0(MSG_ERROR, "wpa_s is null.");
10824 		(void)os_event_write(g_wpa_event, WPA_EVENT_REMOVE_IFACE_FLAG);
10825 		return EXT_WIFI_FAIL;
10826 	}
10827 	wpa_s->reassociate = 0;
10828 	wpa_s->disconnected = 1;
10829 	wpa_supplicant_cancel_scan(wpa_s);
10830 	res = wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
10831 	(void)os_event_write(g_wpa_event, WPA_EVENT_REMOVE_IFACE_FLAG);
10832 	return res;
10833 }
10834 
10835 
10836 static int wpa_supplicant_show_sta_check(ext_wifi_iftype iftype)
10837 {
10838 	if ((iftype != EXT_WIFI_IFTYPE_AP) && (iftype != EXT_WIFI_IFTYPE_MESH_POINT) &&
10839 		(iftype != EXT_WIFI_IFTYPE_P2P_GO))
10840 		return -1;
10841 
10842 	if (g_hapd == NULL)
10843 		return -1;
10844 
10845 	if ((iftype == EXT_WIFI_IFTYPE_AP) && (g_ap_sta_info == NULL))
10846 		return -1;
10847 
10848 #ifdef LOS_CONFIG_MESH
10849 	if (g_mesh_get_sta_flag && (g_mesh_sta_info == NULL))
10850 		return -1;
10851 #endif /* LOS_CONFIG_MESH */
10852 
10853 #ifdef LOS_CONFIG_P2P
10854 	if ((iftype == EXT_WIFI_IFTYPE_P2P_GO) && (g_p2p_client_info == NULL))
10855 		return -1;
10856 #endif /* #ifdef LOS_CONFIG_P2P */
10857 	return 0;
10858 }
10859 
10860 
10861 static void wpa_get_ap_info(ext_wifi_iftype iftype, struct sta_info *sta, unsigned int *sta_count)
10862 {
10863 	if ((sta == NULL) || (sta_count == NULL) ||(g_ap_sta_info == NULL))
10864 		return;
10865 	if ((iftype == EXT_WIFI_IFTYPE_AP) && (sta->flags & WLAN_STA_AUTHORIZED)) {
10866 		(void)os_memcpy(g_ap_sta_info->mac, sta->addr, ETH_ALEN);
10867 		g_ap_sta_info++;
10868 		(*sta_count)++;
10869 	}
10870 }
10871 
10872 #ifdef LOS_CONFIG_MESH
10873 static void wpa_fill_mesh_peer_info(struct sta_info *sta)
10874 {
10875 	if ((sta == NULL) || (g_mesh_sta_info == NULL))
10876 		return;
10877 	if (sta->flags & WLAN_STA_AUTHORIZED) {
10878 		g_mesh_sta_info->mesh_role = MESH_STA;
10879 	} else {
10880 		g_mesh_sta_info->mesh_role = MESH_AP;
10881 		g_mesh_sta_info->mesh_is_mbr = sta->mesh_is_mbr;
10882 		g_mesh_sta_info->mesh_bcn_priority = sta->mesh_bcn_priority;
10883 		g_mesh_sta_info->mesh_block = sta->plink_state == PLINK_BLOCKED ? WPA_FLAG_ON : WPA_FLAG_OFF;
10884 	}
10885 	(void)os_memcpy(g_mesh_sta_info->mac, sta->addr, ETH_ALEN);
10886 }
10887 
10888 
10889 static void wpa_get_mesh_info(ext_wifi_iftype iftype, struct sta_info *sta, unsigned int *sta_count)
10890 {
10891 	if ((sta == NULL) || (sta_count == NULL) ||(g_mesh_sta_info == NULL))
10892 		return;
10893 	if (g_mesh_get_sta_flag == WPA_FLAG_ON) {
10894 		if ((sta->plink_state != PLINK_ESTAB) && (sta->plink_state != PLINK_BLOCKED) &&
10895 			!(sta->flags & WLAN_STA_AUTHORIZED)) {
10896 			continue;
10897 		}
10898 		wpa_fill_mesh_peer_info(sta);
10899 		g_mesh_sta_info++;
10900 		(*sta_count)++;
10901 	}
10902 }
10903 #endif /* LOS_CONFIG_MESH */
10904 
10905 
10906 #ifdef LOS_CONFIG_P2P
10907 static void wpa_get_p2p_info(ext_wifi_iftype iftype, struct sta_info *sta, unsigned int *client_count)
10908 {
10909 	struct p2p_message msg;
10910 	const u8 *p2p_dev_addr = NULL;
10911 	if ((sta == NULL) || (client_count == NULL) ||(g_p2p_client_info == NULL))
10912 		return;
10913 
10914 	if ((iftype == EXT_WIFI_IFTYPE_P2P_GO) && (sta->flags & WLAN_STA_AUTHORIZED)) {
10915 		(void)os_memcpy(g_p2p_client_info->mac, sta->addr, ETH_ALEN);
10916 
10917 		if (sta->p2p_ie == NULL)
10918 			return;
10919 		os_memset(&msg, 0, sizeof(msg));
10920 		if (p2p_parse_p2p_ie(sta->p2p_ie, &msg))
10921 			return;
10922 
10923 		(void)os_memcpy(g_p2p_client_info->device_name, msg.device_name, os_strlen(msg.device_name) + 1);
10924 
10925 		p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
10926 		if (p2p_dev_addr == NULL)
10927 			return;
10928 
10929 		(void)os_memcpy(g_p2p_client_info->dev_addr, p2p_dev_addr, ETH_ALEN);
10930 
10931 		g_p2p_client_info++;
10932 		(*client_count)++;
10933 	}
10934 }
10935 #endif /* LOS_CONFIG_P2P */
10936 
10937 
10938 static int wpa_supplicant_show_sta(ext_wifi_iftype iftype)
10939 {
10940 	struct sta_info *sta = NULL;
10941 	unsigned int sta_count = 0;
10942 
10943 	g_sta_num = WPA_MIN(g_sta_num, WIFI_DEFAULT_MAX_NUM_STA);
10944 	if (wpa_supplicant_show_sta_check(iftype) < 0) {
10945 		return -1;
10946 	}
10947 	for (sta = g_hapd->sta_list; sta != NULL; sta = sta->next) {
10948 		if (sta_count >= g_sta_num) {
10949 			break;
10950 		}
10951 		wpa_get_ap_info(iftype, sta, &sta_count);
10952 #ifdef LOS_CONFIG_MESH
10953 		wpa_get_mesh_info(iftype, sta, &sta_count);
10954 #endif /* LOS_CONFIG_MESH */
10955 #ifdef LOS_CONFIG_P2P
10956 		wpa_get_p2p_info(iftype, sta, &sta_count);
10957 #endif /* LOS_CONFIG_P2P */
10958 	}
10959 	g_sta_num = sta_count;
10960 	g_ap_sta_info = NULL;
10961 
10962 #ifdef LOS_CONFIG_MESH
10963 	g_mesh_sta_info = NULL;
10964 #endif /* LOS_CONFIG_MESH */
10965 
10966 #ifdef LOS_CONFIG_P2P
10967 	g_p2p_client_info = NULL;
10968 #endif /* LOS_CONFIG_P2P */
10969 	return 0;
10970 }
10971 
10972 #ifndef EXT_CODE_CROP
10973 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
10974 {
10975 	struct wpa_supplicant *wpa_s = ctx;
10976 	size_t len;
10977 	const u8 *data;
10978 
10979 	/*
10980 	 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
10981 	 * BSSID[6]
10982 	 * BSSID Information[4]
10983 	 * Operating Class[1]
10984 	 * Channel Number[1]
10985 	 * PHY Type[1]
10986 	 * Optional Subelements[variable]
10987 	 */
10988 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
10989 
10990 	if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
10991 		wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
10992 		goto out;
10993 	}
10994 
10995 	data = wpabuf_head_u8(neighbor_rep);
10996 	len = wpabuf_len(neighbor_rep);
10997 
10998 	while (len >= 2 + NR_IE_MIN_LEN) {
10999 		const u8 *nr;
11000 		char lci[256 * 2 + 1];
11001 		char civic[256 * 2 + 1];
11002 		u8 nr_len = data[1];
11003 		const u8 *pos = data, *end;
11004 
11005 		if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
11006 		    nr_len < NR_IE_MIN_LEN) {
11007 			wpa_dbg(wpa_s, MSG_DEBUG,
11008 				"CTRL: Invalid Neighbor Report element: id=%u len=%u",
11009 				data[0], nr_len);
11010 			goto out;
11011 		}
11012 
11013 		if (2U + nr_len > len) {
11014 			wpa_dbg(wpa_s, MSG_DEBUG,
11015 				"CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
11016 				data[0], len, nr_len);
11017 			goto out;
11018 		}
11019 		pos += 2;
11020 		end = pos + nr_len;
11021 
11022 		nr = pos;
11023 		pos += NR_IE_MIN_LEN;
11024 
11025 		lci[0] = '\0';
11026 		civic[0] = '\0';
11027 		while (end - pos > 2) {
11028 			u8 s_id, s_len;
11029 
11030 			s_id = *pos++;
11031 			s_len = *pos++;
11032 			if (s_len > end - pos)
11033 				goto out;
11034 			if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
11035 				/* Measurement Token[1] */
11036 				/* Measurement Report Mode[1] */
11037 				/* Measurement Type[1] */
11038 				/* Measurement Report[variable] */
11039 				switch (pos[2]) {
11040 				case MEASURE_TYPE_LCI:
11041 					if (lci[0])
11042 						break;
11043 					wpa_snprintf_hex(lci, sizeof(lci),
11044 							 pos, s_len);
11045 					break;
11046 				case MEASURE_TYPE_LOCATION_CIVIC:
11047 					if (civic[0])
11048 						break;
11049 					wpa_snprintf_hex(civic, sizeof(civic),
11050 							 pos, s_len);
11051 					break;
11052 				}
11053 			}
11054 
11055 			pos += s_len;
11056 		}
11057 
11058 		wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
11059 			"bssid=" MACSTR
11060 			" info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
11061 			MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
11062 			nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
11063 			nr[ETH_ALEN + 6],
11064 			lci[0] ? " lci=" : "", lci,
11065 			civic[0] ? " civic=" : "", civic);
11066 
11067 		data = end;
11068 		len -= 2 + nr_len;
11069 	}
11070 
11071 out:
11072 	wpabuf_free(neighbor_rep);
11073 }
11074 
11075 
11076 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
11077 					     char *cmd)
11078 {
11079 	struct wpa_ssid_value ssid, *ssid_p = NULL;
11080 	int ret, lci = 0, civic = 0;
11081 	char *ssid_s;
11082 
11083 	ssid_s = os_strstr(cmd, "ssid=");
11084 	if (ssid_s) {
11085 		if (ssid_parse(ssid_s + 5, &ssid)) {
11086 			wpa_msg(wpa_s, MSG_INFO,
11087 				"CTRL: Send Neighbor Report: bad SSID");
11088 			return -1;
11089 		}
11090 
11091 		ssid_p = &ssid;
11092 
11093 		/*
11094 		 * Move cmd after the SSID text that may include "lci" or
11095 		 * "civic".
11096 		 */
11097 		cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
11098 		if (cmd)
11099 			cmd++;
11100 
11101 	}
11102 
11103 	if (cmd && os_strstr(cmd, "lci"))
11104 		lci = 1;
11105 
11106 	if (cmd && os_strstr(cmd, "civic"))
11107 		civic = 1;
11108 
11109 	ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
11110 						 wpas_ctrl_neighbor_rep_cb,
11111 						 wpa_s);
11112 
11113 	return ret;
11114 }
11115 
11116 
11117 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
11118 {
11119 	eapol_sm_erp_flush(wpa_s->eapol);
11120 	return 0;
11121 }
11122 
11123 
11124 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
11125 					 char *cmd)
11126 {
11127 	char *token, *context = NULL;
11128 	unsigned int enable = ~0, type = 0;
11129 	u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
11130 	u8 *addr = NULL, *mask = NULL;
11131 
11132 	while ((token = str_token(cmd, " ", &context))) {
11133 		if (os_strcasecmp(token, "scan") == 0) {
11134 			type |= MAC_ADDR_RAND_SCAN;
11135 		} else if (os_strcasecmp(token, "sched") == 0) {
11136 			type |= MAC_ADDR_RAND_SCHED_SCAN;
11137 		} else if (os_strcasecmp(token, "pno") == 0) {
11138 			type |= MAC_ADDR_RAND_PNO;
11139 		} else if (os_strcasecmp(token, "all") == 0) {
11140 			type = wpa_s->mac_addr_rand_supported;
11141 		} else if (os_strncasecmp(token, "enable=", 7) == 0) {
11142 			enable = atoi(token + 7);
11143 		} else if (os_strncasecmp(token, "addr=", 5) == 0) {
11144 			addr = _addr;
11145 			if (hwaddr_aton(token + 5, addr)) {
11146 				wpa_printf(MSG_INFO,
11147 					   "CTRL: Invalid MAC address: %s",
11148 					   token);
11149 				return -1;
11150 			}
11151 		} else if (os_strncasecmp(token, "mask=", 5) == 0) {
11152 			mask = _mask;
11153 			if (hwaddr_aton(token + 5, mask)) {
11154 				wpa_printf(MSG_INFO,
11155 					   "CTRL: Invalid MAC address mask: %s",
11156 					   token);
11157 				return -1;
11158 			}
11159 		} else {
11160 			wpa_printf(MSG_INFO,
11161 				   "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
11162 				   token);
11163 			return -1;
11164 		}
11165 	}
11166 
11167 	if (!type) {
11168 		wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
11169 		return -1;
11170 	}
11171 
11172 	if (enable > 1) {
11173 		wpa_printf(MSG_INFO,
11174 			   "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
11175 		return -1;
11176 	}
11177 
11178 	if (!enable)
11179 		return wpas_disable_mac_addr_randomization(wpa_s, type);
11180 
11181 	return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
11182 }
11183 
11184 
11185 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
11186 				 char *buf, size_t buflen)
11187 {
11188 	size_t reply_len;
11189 
11190 	reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
11191 #ifdef CONFIG_AP
11192 	reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
11193 					      buflen - reply_len);
11194 #endif /* CONFIG_AP */
11195 	return reply_len;
11196 }
11197 
11198 
11199 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
11200 {
11201 	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
11202 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
11203 #ifdef CONFIG_AP
11204 	wpas_ap_pmksa_cache_flush(wpa_s);
11205 #endif /* CONFIG_AP */
11206 }
11207 #endif /* EXT_CODE_CROP */
11208 
11209 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
11210 
11211 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
11212 				     const char *cmd, char *buf, size_t buflen)
11213 {
11214 	struct rsn_pmksa_cache_entry *entry;
11215 	struct wpa_ssid *ssid;
11216 	char *pos, *pos2, *end;
11217 	int ret;
11218 	struct os_reltime now;
11219 
11220 	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
11221 	if (!ssid)
11222 		return -1;
11223 
11224 	pos = buf;
11225 	end = buf + buflen;
11226 
11227 	os_get_reltime(&now);
11228 
11229 	/*
11230 	 * Entry format:
11231 	 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
11232 	 * <expiration in seconds> <akmp> <opportunistic>
11233 	 * [FILS Cache Identifier]
11234 	 */
11235 
11236 	for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
11237 	     entry = entry->next) {
11238 		if (entry->network_ctx != ssid)
11239 			continue;
11240 
11241 		pos2 = pos;
11242 		ret = os_snprintf(pos2, end - pos2, MACSTR " ",
11243 				  MAC2STR(entry->aa));
11244 		if (os_snprintf_error(end - pos2, ret))
11245 			break;
11246 		pos2 += ret;
11247 
11248 		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
11249 					 PMKID_LEN);
11250 
11251 		ret = os_snprintf(pos2, end - pos2, " ");
11252 		if (os_snprintf_error(end - pos2, ret))
11253 			break;
11254 		pos2 += ret;
11255 
11256 		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
11257 					 entry->pmk_len);
11258 
11259 		ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
11260 				  (int) (entry->reauth_time - now.sec),
11261 				  (int) (entry->expiration - now.sec),
11262 				  entry->akmp,
11263 				  entry->opportunistic);
11264 		if (os_snprintf_error(end - pos2, ret))
11265 			break;
11266 		pos2 += ret;
11267 
11268 		if (entry->fils_cache_id_set) {
11269 			ret = os_snprintf(pos2, end - pos2, " %02x%02x",
11270 					  entry->fils_cache_id[0],
11271 					  entry->fils_cache_id[1]);
11272 			if (os_snprintf_error(end - pos2, ret))
11273 				break;
11274 			pos2 += ret;
11275 		}
11276 
11277 		ret = os_snprintf(pos2, end - pos2, "\n");
11278 		if (os_snprintf_error(end - pos2, ret))
11279 			break;
11280 		pos2 += ret;
11281 
11282 		pos = pos2;
11283 	}
11284 
11285 	return pos - buf;
11286 }
11287 
11288 
11289 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
11290 				     char *cmd)
11291 {
11292 	struct rsn_pmksa_cache_entry *entry;
11293 	struct wpa_ssid *ssid;
11294 	char *pos, *pos2;
11295 	int ret = -1;
11296 	struct os_reltime now;
11297 	int reauth_time = 0, expiration = 0, i;
11298 
11299 	/*
11300 	 * Entry format:
11301 	 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
11302 	 * <expiration in seconds> <akmp> <opportunistic>
11303 	 * [FILS Cache Identifier]
11304 	 */
11305 
11306 	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
11307 	if (!ssid)
11308 		return -1;
11309 
11310 	pos = os_strchr(cmd, ' ');
11311 	if (!pos)
11312 		return -1;
11313 	pos++;
11314 
11315 	entry = os_zalloc(sizeof(*entry));
11316 	if (!entry)
11317 		return -1;
11318 
11319 	if (hwaddr_aton(pos, entry->aa))
11320 		goto fail;
11321 
11322 	pos = os_strchr(pos, ' ');
11323 	if (!pos)
11324 		goto fail;
11325 	pos++;
11326 
11327 	if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
11328 		goto fail;
11329 
11330 	pos = os_strchr(pos, ' ');
11331 	if (!pos)
11332 		goto fail;
11333 	pos++;
11334 
11335 	pos2 = os_strchr(pos, ' ');
11336 	if (!pos2)
11337 		goto fail;
11338 	entry->pmk_len = (pos2 - pos) / 2;
11339 	if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
11340 	    hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
11341 		goto fail;
11342 
11343 	pos = os_strchr(pos, ' ');
11344 	if (!pos)
11345 		goto fail;
11346 	pos++;
11347 
11348 	if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
11349 		   &entry->akmp, &entry->opportunistic) != 4)
11350 		goto fail;
11351 	if (reauth_time > expiration)
11352 		goto fail;
11353 	for (i = 0; i < 4; i++) {
11354 		pos = os_strchr(pos, ' ');
11355 		if (!pos) {
11356 			if (i < 3)
11357 				goto fail;
11358 			break;
11359 		}
11360 		pos++;
11361 	}
11362 	if (pos) {
11363 		if (hexstr2bin(pos, entry->fils_cache_id,
11364 			       FILS_CACHE_ID_LEN) < 0)
11365 			goto fail;
11366 		entry->fils_cache_id_set = 1;
11367 	}
11368 	os_get_reltime(&now);
11369 	entry->expiration = now.sec + expiration;
11370 	entry->reauth_time = now.sec + reauth_time;
11371 
11372 	entry->network_ctx = ssid;
11373 
11374 	entry->external = true;
11375 
11376 	wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
11377 	entry = NULL;
11378 	ret = 0;
11379 fail:
11380 	os_free(entry);
11381 	return ret;
11382 }
11383 
11384 
11385 #ifdef CONFIG_MESH
11386 
11387 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
11388 					  const char *cmd, char *buf,
11389 					  size_t buflen)
11390 {
11391 	u8 spa[ETH_ALEN];
11392 
11393 	if (!wpa_s->ifmsh)
11394 		return -1;
11395 
11396 	if (os_strcasecmp(cmd, "any") == 0)
11397 		return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
11398 
11399 	if (hwaddr_aton(cmd, spa))
11400 		return -1;
11401 
11402 	return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
11403 }
11404 
11405 
11406 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
11407 					  char *cmd)
11408 {
11409 	/*
11410 	 * We do not check mesh interface existence because PMKSA should be
11411 	 * stored before wpa_s->ifmsh creation to suppress commit message
11412 	 * creation.
11413 	 */
11414 	return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
11415 }
11416 
11417 #endif /* CONFIG_MESH */
11418 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
11419 
11420 
11421 #ifdef CONFIG_FILS
11422 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
11423 					    const char *cmd)
11424 {
11425 	struct fils_hlp_req *req;
11426 	const char *pos;
11427 
11428 	/* format: <dst> <packet starting from ethertype> */
11429 
11430 	req = os_zalloc(sizeof(*req));
11431 	if (!req)
11432 		return -1;
11433 
11434 	if (hwaddr_aton(cmd, req->dst))
11435 		goto fail;
11436 
11437 	pos = os_strchr(cmd, ' ');
11438 	if (!pos)
11439 		goto fail;
11440 	pos++;
11441 	req->pkt = wpabuf_parse_bin(pos);
11442 	if (!req->pkt)
11443 		goto fail;
11444 
11445 	dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
11446 	return 0;
11447 fail:
11448 	wpabuf_free(req->pkt);
11449 	os_free(req);
11450 	return -1;
11451 }
11452 #endif /* CONFIG_FILS */
11453 
11454 
11455 static int wpas_ctrl_cmd_debug_level(const char *cmd)
11456 {
11457 	if (os_strcmp(cmd, "PING") == 0 ||
11458 	    os_strncmp(cmd, "BSS ", 4) == 0 ||
11459 	    os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
11460 	    os_strncmp(cmd, "STATUS", 6) == 0 ||
11461 	    os_strncmp(cmd, "STA ", 4) == 0 ||
11462 	    os_strncmp(cmd, "STA-", 4) == 0)
11463 		return MSG_EXCESSIVE;
11464 	return MSG_DEBUG;
11465 }
11466 
11467 #ifdef LOS_WPA_PATCH
11468 static int wpa_supplicant_ctrl_iface_add(struct wpa_supplicant *wpa_s, const char *ifname)
11469 {
11470 	struct wpa_interface iface;
11471 	struct wpa_supplicant *new_wpa_s = NULL;
11472 	struct ext_wifi_dev *wifi_dev = los_get_wifi_dev_by_name(ifname);
11473 	if ((wpa_s == NULL) || (wifi_dev == NULL) ||
11474 		(wpa_s->driver == NULL) || (wpa_s->conf == NULL)) {
11475 		wpa_error_log0(MSG_ERROR, "wpa_s or wifi dev is null.");
11476 		(void)os_event_write(g_wpa_event, WPA_EVENT_ADD_IFACE_ERROR);
11477 		return EXT_WIFI_FAIL;
11478 	}
11479 	os_memset(&iface, 0, sizeof(iface));
11480 	iface.ifname = ifname;
11481 	iface.driver = wpa_s->driver->name;
11482 	iface.driver_param = (const char *)(wpa_s->conf->driver_param);
11483 	iface.ctrl_interface = wpa_s->conf->ctrl_interface;
11484 	new_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, NULL);
11485 	if (new_wpa_s == NULL) {
11486 		wpa_warning_log0(MSG_ERROR, "wpa_supplicant_add_iface fail.");
11487 		(void)os_event_write(g_wpa_event, WPA_EVENT_ADD_IFACE_ERROR);
11488 		return EXT_WIFI_FAIL;
11489 	}
11490 
11491 	unsigned int int_save;
11492 	os_task_lock(&int_save);
11493 
11494 	wifi_dev->priv = new_wpa_s;
11495 	os_task_unlock(int_save);
11496 
11497 #ifdef CONFIG_WAPI
11498 	if (wifi_dev->iftype == EXT_WIFI_IFTYPE_STATION) {
11499 		if (wapi_init_iface(new_wpa_s)) {
11500 			wpa_error_buf(MSG_ERROR, "wpa_supplicant_main: wifi_dev: ifname = %s\n",
11501 				wifi_dev->ifname, strlen(wifi_dev->ifname));
11502 			wpa_supplicant_remove_iface(wpa_s->global, new_wpa_s, 0);
11503 			(void)os_event_write(g_wpa_event, WPA_EVENT_ADD_IFACE_ERROR);
11504 			return EXT_WIFI_FAIL;
11505 		}
11506 	}
11507 #endif /* CONFIG_WAPI */
11508 
11509 	(void)os_event_write(g_wpa_event, WPA_EVENT_ADD_IFACE_OK);
11510 	return EXT_WIFI_OK;
11511 }
11512 #endif /* LOS_WPA_PATCH */
11513 
11514 #ifndef EXT_CODE_CROP
11515 static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
11516 					  const char *cmd)
11517 {
11518 	size_t frame_classifier_len;
11519 	const char *pos, *end;
11520 	struct robust_av_data *robust_av = &wpa_s->robust_av;
11521 	int val;
11522 
11523 	/*
11524 	 * format:
11525 	 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
11526 	 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
11527 	 */
11528 	os_memset(robust_av, 0, sizeof(struct robust_av_data));
11529 	if (os_strncmp(cmd, "add ", 4) == 0) {
11530 		robust_av->request_type = SCS_REQ_ADD;
11531 	} else if (os_strcmp(cmd, "remove") == 0) {
11532 		robust_av->request_type = SCS_REQ_REMOVE;
11533 		robust_av->valid_config = false;
11534 		return wpas_send_mscs_req(wpa_s);
11535 	} else if (os_strncmp(cmd, "change ", 7) == 0) {
11536 		robust_av->request_type = SCS_REQ_CHANGE;
11537 	} else {
11538 		return -1;
11539 	}
11540 
11541 	pos = os_strstr(cmd, "up_bitmap=");
11542 	if (!pos)
11543 		return -1;
11544 
11545 	val = hex2byte(pos + 10);
11546 	if (val < 0)
11547 		return -1;
11548 	robust_av->up_bitmap = val;
11549 
11550 	pos = os_strstr(cmd, "up_limit=");
11551 	if (!pos)
11552 		return -1;
11553 
11554 	robust_av->up_limit = atoi(pos + 9);
11555 
11556 	pos = os_strstr(cmd, "stream_timeout=");
11557 	if (!pos)
11558 		return -1;
11559 
11560 	robust_av->stream_timeout = atoi(pos + 15);
11561 	if (robust_av->stream_timeout == 0)
11562 		return -1;
11563 
11564 	pos = os_strstr(cmd, "frame_classifier=");
11565 	if (!pos)
11566 		return -1;
11567 
11568 	pos += 17;
11569 	end = os_strchr(pos, ' ');
11570 	if (!end)
11571 		end = pos + os_strlen(pos);
11572 
11573 	frame_classifier_len = (end - pos) / 2;
11574 	if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
11575 	    hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
11576 		return -1;
11577 
11578 	robust_av->frame_classifier_len = frame_classifier_len;
11579 	robust_av->valid_config = true;
11580 
11581 	return wpas_send_mscs_req(wpa_s);
11582 }
11583 #endif /* EXT_CODE_CROP */
11584 
11585 #ifdef CONFIG_PASN
11586 static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
11587 {
11588 	char *token, *context = NULL;
11589 	u8 bssid[ETH_ALEN];
11590 	int akmp = -1, cipher = -1, got_bssid = 0;
11591 	u16 group = 0xFFFF;
11592 	u8 *comeback = NULL;
11593 	size_t comeback_len = 0;
11594 	int id = 0, ret = -1;
11595 
11596 	/*
11597 	 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
11598 	 *    [comeback=<hexdump>]
11599 	 */
11600 	while ((token = str_token(cmd, " ", &context))) {
11601 		if (os_strncmp(token, "bssid=", 6) == 0) {
11602 			if (hwaddr_aton(token + 6, bssid))
11603 				goto out;
11604 			got_bssid = 1;
11605 		} else if (os_strcmp(token, "akmp=PASN") == 0) {
11606 			akmp = WPA_KEY_MGMT_PASN;
11607 #ifdef CONFIG_IEEE80211R
11608 		} else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
11609 			akmp = WPA_KEY_MGMT_FT_PSK;
11610 		} else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
11611 			akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
11612 		} else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
11613 			akmp = WPA_KEY_MGMT_FT_IEEE8021X;
11614 #endif /* CONFIG_IEEE80211R */
11615 #ifdef CONFIG_SAE
11616 		} else if (os_strcmp(token, "akmp=SAE") == 0) {
11617 			akmp = WPA_KEY_MGMT_SAE;
11618 #endif /* CONFIG_SAE */
11619 #ifdef CONFIG_FILS
11620 		} else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
11621 			akmp = WPA_KEY_MGMT_FILS_SHA256;
11622 		} else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
11623 			akmp = WPA_KEY_MGMT_FILS_SHA384;
11624 #endif /* CONFIG_FILS */
11625 		} else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
11626 			cipher = WPA_CIPHER_CCMP_256;
11627 		} else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
11628 			cipher = WPA_CIPHER_GCMP_256;
11629 		} else if (os_strcmp(token, "cipher=CCMP") == 0) {
11630 			cipher = WPA_CIPHER_CCMP;
11631 		} else if (os_strcmp(token, "cipher=GCMP") == 0) {
11632 			cipher = WPA_CIPHER_GCMP;
11633 		} else if (os_strncmp(token, "group=", 6) == 0) {
11634 			group = atoi(token + 6);
11635 		} else if (os_strncmp(token, "nid=", 4) == 0) {
11636 			id = atoi(token + 4);
11637 		} else if (os_strncmp(token, "comeback=", 9) == 0) {
11638 			comeback_len = os_strlen(token + 9);
11639 			if (comeback || !comeback_len || comeback_len % 2)
11640 				goto out;
11641 
11642 			comeback_len /= 2;
11643 			comeback = os_malloc(comeback_len);
11644 			if (!comeback ||
11645 			    hexstr2bin(token + 9, comeback, comeback_len))
11646 				goto out;
11647 		} else {
11648 			wpa_printf(MSG_DEBUG,
11649 				   "CTRL: PASN Invalid parameter: '%s'",
11650 				   token);
11651 			goto out;
11652 		}
11653 	}
11654 
11655 	if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
11656 		wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
11657 		goto out;
11658 	}
11659 
11660 	ret = wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id,
11661 				   comeback, comeback_len);
11662 out:
11663 	os_free(comeback);
11664 	return ret;
11665 }
11666 
11667 
11668 static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
11669 					       const char *cmd)
11670 {
11671 	u8 bssid[ETH_ALEN];
11672 
11673 	if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
11674 		wpa_printf(MSG_DEBUG,
11675 			   "CTRL: PASN_DEAUTH without valid BSSID");
11676 		return -1;
11677 	}
11678 
11679 	return wpas_pasn_deauthenticate(wpa_s, bssid);
11680 }
11681 
11682 #endif /* CONFIG_PASN */
11683 
11684 #ifndef EXT_CODE_CROP
11685 static int set_type4_frame_classifier(const char *cmd,
11686 				      struct type4_params *param)
11687 {
11688 	const char *pos, *end;
11689 	u8 classifier_mask = 0;
11690 	int ret;
11691 	char addr[INET6_ADDRSTRLEN];
11692 	size_t alen;
11693 
11694 	if (os_strstr(cmd, "ip_version=ipv4")) {
11695 		param->ip_version = IPV4;
11696 	} else if (os_strstr(cmd, "ip_version=ipv6")) {
11697 		param->ip_version = IPV6;
11698 	} else {
11699 		wpa_printf(MSG_ERROR, "IP version missing/invalid");
11700 		return -1;
11701 	}
11702 
11703 	classifier_mask |= BIT(0);
11704 
11705 	pos = os_strstr(cmd, "src_ip=");
11706 	if (pos) {
11707 		pos += 7;
11708 		end = os_strchr(pos, ' ');
11709 		if (!end)
11710 			end = pos + os_strlen(pos);
11711 
11712 		alen = end - pos;
11713 		if (alen >= INET6_ADDRSTRLEN)
11714 			return -1;
11715 		os_memcpy(addr, pos, alen);
11716 		addr[alen] = '\0';
11717 		if (param->ip_version == IPV4)
11718 			ret = inet_pton(AF_INET, addr,
11719 					&param->ip_params.v4.src_ip);
11720 		else
11721 			ret = inet_pton(AF_INET6, addr,
11722 					&param->ip_params.v6.src_ip);
11723 
11724 		if (ret != 1) {
11725 			wpa_printf(MSG_ERROR,
11726 				   "Error converting src IP address to binary ret=%d",
11727 				   ret);
11728 			return -1;
11729 		}
11730 
11731 		classifier_mask |= BIT(1);
11732 	}
11733 
11734 	pos = os_strstr(cmd, "dst_ip=");
11735 	if (pos) {
11736 		pos += 7;
11737 		end = os_strchr(pos, ' ');
11738 		if (!end)
11739 			end = pos + os_strlen(pos);
11740 
11741 		alen = end - pos;
11742 		if (alen >= INET6_ADDRSTRLEN)
11743 			return -1;
11744 		os_memcpy(addr, pos, alen);
11745 		addr[alen] = '\0';
11746 		if (param->ip_version == IPV4)
11747 			ret = inet_pton(AF_INET, addr,
11748 					&param->ip_params.v4.dst_ip);
11749 		else
11750 			ret = inet_pton(AF_INET6, addr,
11751 					&param->ip_params.v6.dst_ip);
11752 
11753 		if (ret != 1) {
11754 			wpa_printf(MSG_ERROR,
11755 				   "Error converting dst IP address to binary ret=%d",
11756 				   ret);
11757 			return -1;
11758 		}
11759 
11760 		classifier_mask |= BIT(2);
11761 	}
11762 
11763 	pos = os_strstr(cmd, "src_port=");
11764 	if (pos && atoi(pos + 9) > 0) {
11765 		if (param->ip_version == IPV4)
11766 			param->ip_params.v4.src_port = atoi(pos + 9);
11767 		else
11768 			param->ip_params.v6.src_port = atoi(pos + 9);
11769 		classifier_mask |= BIT(3);
11770 	}
11771 
11772 	pos = os_strstr(cmd, "dst_port=");
11773 	if (pos && atoi(pos + 9) > 0) {
11774 		if (param->ip_version == IPV4)
11775 			param->ip_params.v4.dst_port = atoi(pos + 9);
11776 		else
11777 			param->ip_params.v6.dst_port = atoi(pos + 9);
11778 		classifier_mask |= BIT(4);
11779 	}
11780 
11781 	pos = os_strstr(cmd, "dscp=");
11782 	if (pos && atoi(pos + 5) > 0) {
11783 		if (param->ip_version == IPV4)
11784 			param->ip_params.v4.dscp = atoi(pos + 5);
11785 		else
11786 			param->ip_params.v6.dscp = atoi(pos + 5);
11787 		classifier_mask |= BIT(5);
11788 	}
11789 
11790 	if (param->ip_version == IPV4) {
11791 		pos = os_strstr(cmd, "protocol=");
11792 		if (pos) {
11793 			if (os_strstr(pos, "udp")) {
11794 				param->ip_params.v4.protocol = 17;
11795 			} else if (os_strstr(pos, "tcp")) {
11796 				param->ip_params.v4.protocol = 6;
11797 			} else if (os_strstr(pos, "esp")) {
11798 				param->ip_params.v4.protocol = 50;
11799 			} else {
11800 				wpa_printf(MSG_ERROR, "Invalid protocol");
11801 				return -1;
11802 			}
11803 			classifier_mask |= BIT(6);
11804 		}
11805 	} else {
11806 		pos = os_strstr(cmd, "next_header=");
11807 		if (pos) {
11808 			if (os_strstr(pos, "udp")) {
11809 				param->ip_params.v6.next_header = 17;
11810 			} else if (os_strstr(pos, "tcp")) {
11811 				param->ip_params.v6.next_header = 6;
11812 			} else if (os_strstr(pos, "esp")) {
11813 				param->ip_params.v6.next_header = 50;
11814 			} else {
11815 				wpa_printf(MSG_ERROR, "Invalid next header");
11816 				return -1;
11817 			}
11818 
11819 			classifier_mask |= BIT(6);
11820 		}
11821 
11822 		pos = os_strstr(cmd, "flow_label=");
11823 		if (pos) {
11824 			pos += 11;
11825 			end = os_strchr(pos, ' ');
11826 			if (!end)
11827 				end = pos + os_strlen(pos);
11828 
11829 			if (end - pos != 6 ||
11830 			    hexstr2bin(pos, param->ip_params.v6.flow_label,
11831 				       3) ||
11832 			    param->ip_params.v6.flow_label[0] > 0x0F) {
11833 				wpa_printf(MSG_ERROR, "Invalid flow label");
11834 				return -1;
11835 			}
11836 
11837 			classifier_mask |= BIT(7);
11838 		}
11839 	}
11840 
11841 	param->classifier_mask = classifier_mask;
11842 	return 0;
11843 }
11844 
11845 
11846 static int set_type10_frame_classifier(const char *cmd,
11847 				       struct type10_params *param)
11848 {
11849 	const char *pos, *end;
11850 	size_t filter_len;
11851 
11852 	pos = os_strstr(cmd, "prot_instance=");
11853 	if (!pos) {
11854 		wpa_printf(MSG_ERROR, "Protocol instance missing");
11855 		return -1;
11856 	}
11857 	param->prot_instance = atoi(pos + 14);
11858 
11859 	pos = os_strstr(cmd, "prot_number=");
11860 	if (!pos) {
11861 		wpa_printf(MSG_ERROR, "Protocol number missing");
11862 		return -1;
11863 	}
11864 	if (os_strstr(pos, "udp")) {
11865 		param->prot_number = 17;
11866 	} else if (os_strstr(pos, "tcp")) {
11867 		param->prot_number = 6;
11868 	} else if (os_strstr(pos, "esp")) {
11869 		param->prot_number = 50;
11870 	} else {
11871 		wpa_printf(MSG_ERROR, "Invalid protocol number");
11872 		return -1;
11873 	}
11874 
11875 	pos = os_strstr(cmd, "filter_value=");
11876 	if (!pos) {
11877 		wpa_printf(MSG_ERROR,
11878 			   "Classifier parameter filter_value missing");
11879 		return -1;
11880 	}
11881 
11882 	pos += 13;
11883 	end = os_strchr(pos, ' ');
11884 	if (!end)
11885 		end = pos + os_strlen(pos);
11886 
11887 	filter_len = (end - pos) / 2;
11888 	param->filter_value = os_malloc(filter_len);
11889 	if (!param->filter_value)
11890 		return -1;
11891 
11892 	if (hexstr2bin(pos, param->filter_value, filter_len)) {
11893 		wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos);
11894 		goto free;
11895 	}
11896 
11897 	pos = os_strstr(cmd, "filter_mask=");
11898 	if (!pos) {
11899 		wpa_printf(MSG_ERROR,
11900 			   "Classifier parameter filter_mask missing");
11901 		goto free;
11902 	}
11903 
11904 	pos += 12;
11905 	end = os_strchr(pos, ' ');
11906 	if (!end)
11907 		end = pos + os_strlen(pos);
11908 
11909 	if (filter_len != (size_t) (end - pos) / 2) {
11910 		wpa_printf(MSG_ERROR,
11911 			   "Filter mask length mismatch expected=%zu received=%zu",
11912 			   filter_len, (size_t) (end - pos) / 2);
11913 		goto free;
11914 	}
11915 
11916 	param->filter_mask = os_malloc(filter_len);
11917 	if (!param->filter_mask)
11918 		goto free;
11919 
11920 	if (hexstr2bin(pos, param->filter_mask, filter_len)) {
11921 		wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos);
11922 		os_free(param->filter_mask);
11923 		param->filter_mask = NULL;
11924 		goto free;
11925 	}
11926 
11927 	param->filter_len = filter_len;
11928 	return 0;
11929 free:
11930 	os_free(param->filter_value);
11931 	param->filter_value = NULL;
11932 	return -1;
11933 }
11934 
11935 
11936 static int scs_parse_type4(struct tclas_element *elem, const char *pos)
11937 {
11938 	struct type4_params type4_param = { 0 };
11939 
11940 	if (set_type4_frame_classifier(pos, &type4_param) == -1) {
11941 		wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4");
11942 		return -1;
11943 	}
11944 
11945 	os_memcpy(&elem->frame_classifier.type4_param,
11946 		  &type4_param, sizeof(struct type4_params));
11947 	return 0;
11948 }
11949 
11950 
11951 static int scs_parse_type10(struct tclas_element *elem, const char *pos)
11952 {
11953 	struct type10_params type10_param = { 0 };
11954 
11955 	if (set_type10_frame_classifier(pos, &type10_param) == -1) {
11956 		wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10");
11957 		return -1;
11958 	}
11959 
11960 	os_memcpy(&elem->frame_classifier.type10_param,
11961 		  &type10_param, sizeof(struct type10_params));
11962 	return 0;
11963 }
11964 
11965 
11966 static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s,
11967 					 char *cmd)
11968 {
11969 	char *pos1, *pos;
11970 	struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req;
11971 	struct scs_desc_elem desc_elem = { 0 };
11972 	int val;
11973 	unsigned int num_scs_desc = 0;
11974 
11975 	if (wpa_s->ongoing_scs_req) {
11976 		wpa_printf(MSG_ERROR, "%s: SCS Request already in queue",
11977 			   __func__);
11978 		return -1;
11979 	}
11980 
11981 	/**
11982 	 * format:
11983 	 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>]
11984 	 * [classifier_type=<4|10>]
11985 	 * [classifier params based on classifier type]
11986 	 * [tclas_processing=<0|1>] [scs_id=<decimal number>] ...
11987 	 */
11988 	pos1 = os_strstr(cmd, "scs_id=");
11989 	if (!pos1) {
11990 		wpa_printf(MSG_ERROR, "SCSID not present");
11991 		return -1;
11992 	}
11993 
11994 	free_up_scs_desc(scs_data);
11995 
11996 	while (pos1) {
11997 		struct scs_desc_elem *n1;
11998 		struct active_scs_elem *active_scs_desc;
11999 		char *next_scs_desc;
12000 		unsigned int num_tclas_elem = 0;
12001 		bool scsid_active = false;
12002 
12003 		desc_elem.scs_id = atoi(pos1 + 7);
12004 		pos1 += 7;
12005 
12006 		next_scs_desc = os_strstr(pos1, "scs_id=");
12007 		if (next_scs_desc) {
12008 			char temp[20];
12009 
12010 			os_snprintf(temp, sizeof(temp), "scs_id=%d ",
12011 				    desc_elem.scs_id);
12012 			if (os_strstr(next_scs_desc, temp)) {
12013 				wpa_printf(MSG_ERROR,
12014 					   "Multiple SCS descriptors configured with same SCSID(=%d)",
12015 					   desc_elem.scs_id);
12016 				goto free_scs_desc;
12017 			}
12018 			pos1[next_scs_desc - pos1 - 1] = '\0';
12019 		}
12020 
12021 		dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids,
12022 				 struct active_scs_elem, list) {
12023 			if (desc_elem.scs_id == active_scs_desc->scs_id) {
12024 				scsid_active = true;
12025 				break;
12026 			}
12027 		}
12028 
12029 		if (os_strstr(pos1, "add ")) {
12030 			desc_elem.request_type = SCS_REQ_ADD;
12031 			if (scsid_active) {
12032 				wpa_printf(MSG_ERROR, "SCSID %d already active",
12033 					   desc_elem.scs_id);
12034 				return -1;
12035 			}
12036 		} else if (os_strstr(pos1, "remove")) {
12037 			desc_elem.request_type = SCS_REQ_REMOVE;
12038 			if (!scsid_active) {
12039 				wpa_printf(MSG_ERROR, "SCSID %d not active",
12040 					   desc_elem.scs_id);
12041 				return -1;
12042 			}
12043 			goto scs_desc_end;
12044 		} else if (os_strstr(pos1, "change ")) {
12045 			desc_elem.request_type = SCS_REQ_CHANGE;
12046 			if (!scsid_active) {
12047 				wpa_printf(MSG_ERROR, "SCSID %d not active",
12048 					   desc_elem.scs_id);
12049 				return -1;
12050 			}
12051 		} else {
12052 			wpa_printf(MSG_ERROR, "SCS Request type invalid");
12053 			goto free_scs_desc;
12054 		}
12055 
12056 		pos1 = os_strstr(pos1, "scs_up=");
12057 		if (!pos1) {
12058 			wpa_printf(MSG_ERROR,
12059 				   "Intra-Access user priority not present");
12060 			goto free_scs_desc;
12061 		}
12062 
12063 		val = atoi(pos1 + 7);
12064 		if (val < 0 || val > 7) {
12065 			wpa_printf(MSG_ERROR,
12066 				   "Intra-Access user priority invalid %d",
12067 				   val);
12068 			goto free_scs_desc;
12069 		}
12070 
12071 		desc_elem.intra_access_priority = val;
12072 		desc_elem.scs_up_avail = true;
12073 
12074 		pos = os_strstr(pos1, "classifier_type=");
12075 		if (!pos) {
12076 			wpa_printf(MSG_ERROR, "classifier type empty");
12077 			goto free_scs_desc;
12078 		}
12079 
12080 		while (pos) {
12081 			struct tclas_element elem = { 0 }, *n;
12082 			char *next_tclas_elem;
12083 
12084 			val = atoi(pos + 16);
12085 			if (val != 4 && val != 10) {
12086 				wpa_printf(MSG_ERROR,
12087 					   "classifier type invalid %d", val);
12088 				goto free_scs_desc;
12089 			}
12090 
12091 			elem.classifier_type = val;
12092 			pos += 16;
12093 
12094 			next_tclas_elem = os_strstr(pos, "classifier_type=");
12095 			if (next_tclas_elem) {
12096 				pos1 = next_tclas_elem;
12097 				pos[next_tclas_elem - pos - 1] = '\0';
12098 			}
12099 
12100 			switch (val) {
12101 			case 4:
12102 				if (scs_parse_type4(&elem, pos) < 0)
12103 					goto free_scs_desc;
12104 				break;
12105 			case 10:
12106 				if (scs_parse_type10(&elem, pos) < 0)
12107 					goto free_scs_desc;
12108 				break;
12109 			}
12110 
12111 			n = os_realloc(desc_elem.tclas_elems,
12112 				       (num_tclas_elem + 1) * sizeof(elem));
12113 			if (!n)
12114 				goto free_scs_desc;
12115 
12116 			desc_elem.tclas_elems = n;
12117 			os_memcpy((u8 *) desc_elem.tclas_elems +
12118 				  num_tclas_elem * sizeof(elem),
12119 				  &elem, sizeof(elem));
12120 			num_tclas_elem++;
12121 			desc_elem.num_tclas_elem = num_tclas_elem;
12122 			pos = next_tclas_elem;
12123 		}
12124 
12125 		if (desc_elem.num_tclas_elem > 1) {
12126 			pos1 = os_strstr(pos1, "tclas_processing=");
12127 			if (!pos1) {
12128 				wpa_printf(MSG_ERROR, "tclas_processing empty");
12129 				goto free_scs_desc;
12130 			}
12131 
12132 			val = atoi(pos1 + 17);
12133 			if (val != 0 && val != 1) {
12134 				wpa_printf(MSG_ERROR,
12135 					   "tclas_processing invalid");
12136 				goto free_scs_desc;
12137 			}
12138 
12139 			desc_elem.tclas_processing = val;
12140 		}
12141 
12142 scs_desc_end:
12143 		n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) *
12144 				sizeof(struct scs_desc_elem));
12145 		if (!n1)
12146 			goto free_scs_desc;
12147 
12148 		scs_data->scs_desc_elems = n1;
12149 		os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc *
12150 			  sizeof(desc_elem), &desc_elem, sizeof(desc_elem));
12151 		num_scs_desc++;
12152 		scs_data->num_scs_desc = num_scs_desc;
12153 		pos1 = next_scs_desc;
12154 		os_memset(&desc_elem, 0, sizeof(desc_elem));
12155 	}
12156 
12157 	return wpas_send_scs_req(wpa_s);
12158 
12159 free_scs_desc:
12160 	free_up_tclas_elem(&desc_elem);
12161 	free_up_scs_desc(scs_data);
12162 	return -1;
12163 }
12164 #endif
12165 
12166 static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s,
12167 					  const char *cmd)
12168 {
12169 	char *pos;
12170 	struct dscp_policy_status *policy = NULL, *n;
12171 	int num_policies = 0, ret = -1;
12172 	struct dscp_resp_data resp_data;
12173 
12174 	/*
12175 	 * format:
12176 	 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
12177 	 */
12178 
12179 	os_memset(&resp_data, 0, sizeof(resp_data));
12180 
12181 	resp_data.more = os_strstr(cmd, "more") != NULL;
12182 
12183 	if (os_strstr(cmd, "reset")) {
12184 		resp_data.reset = true;
12185 		resp_data.solicited = false;
12186 		goto send_resp;
12187 	}
12188 
12189 	resp_data.solicited = os_strstr(cmd, "solicited") != NULL;
12190 
12191 	pos = os_strstr(cmd, "policy_id=");
12192 	while (pos) {
12193 		n = os_realloc(policy, (num_policies + 1) * sizeof(*policy));
12194 		if (!n)
12195 			goto fail;
12196 
12197 		policy = n;
12198 		pos += 10;
12199 		policy[num_policies].id = atoi(pos);
12200 		if (policy[num_policies].id == 0) {
12201 			wpa_printf(MSG_ERROR, "DSCP: Invalid policy id");
12202 			goto fail;
12203 		}
12204 
12205 		pos = os_strstr(pos, "status=");
12206 		if (!pos) {
12207 			wpa_printf(MSG_ERROR,
12208 				   "DSCP: Status is not found for a policy");
12209 			goto fail;
12210 		}
12211 
12212 		pos += 7;
12213 		policy[num_policies].status = atoi(pos);
12214 		num_policies++;
12215 
12216 		pos = os_strstr(pos, "policy_id");
12217 	}
12218 
12219 	resp_data.policy = policy;
12220 	resp_data.num_policies = num_policies;
12221 send_resp:
12222 	ret = wpas_send_dscp_response(wpa_s, &resp_data);
12223 	if (ret)
12224 		wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response");
12225 fail:
12226 	os_free(policy);
12227 	return ret;
12228 }
12229 
12230 
12231 static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
12232 					   const char *cmd)
12233 {
12234 	char *pos;
12235 
12236 	/*
12237 	 * format:
12238 	 * Wildcard DSCP query
12239 	 * <wildcard>
12240 	 *
12241 	 * DSCP query with a domain name attribute:
12242 	 * [domain_name=<string>]
12243 	 */
12244 
12245 	if (os_strstr(cmd, "wildcard")) {
12246 		wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
12247 		return wpas_send_dscp_query(wpa_s, NULL, 0);
12248 	}
12249 
12250 	pos = os_strstr(cmd, "domain_name=");
12251 	if (!pos || !os_strlen(pos + 12)) {
12252 		wpa_printf(MSG_ERROR, "QM: Domain name not preset");
12253 		return -1;
12254 	}
12255 
12256 	return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
12257 }
12258 
12259 
12260 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
12261 					 char *buf, size_t *resp_len)
12262 {
12263 	char *reply = NULL;
12264 	const int reply_size = 4096;
12265 	int reply_len = -1;
12266 	struct ext_wifi_dev *wifi_dev = NULL;
12267 	if ((buf == NULL) || (resp_len == NULL))
12268 		return NULL;
12269 	if (os_strncmp(buf, "SOFTAP_START ", 13) == 0) {
12270 		hostapd_main(buf + 13);
12271 		goto OUT;
12272 	} else if (os_strncmp(buf, "WPA_START ", 10) == 0) {
12273 		wpa_supplicant_main(buf + 10);
12274 		goto OUT;
12275 	} else if (os_strncmp(buf, "ELOOP_TERMINATE ", 16) == 0) {
12276 		wpa_error_log1(MSG_ERROR, "eloop_terminate : %d", atoi(buf + 16));
12277 		eloop_terminate(atoi(buf + 16));
12278 		goto OUT;
12279 	} else if (os_strcmp(buf, "REMOVE_IFACE") == 0) {
12280 		if (wpa_supplicant_iface_remove(wpa_s) < 0)
12281 			goto OUT;
12282 	} else if (os_strncmp(buf, "ADD_IFACE ", 10) == 0) {
12283 		if (wpa_supplicant_ctrl_iface_add(wpa_s, buf + 10) < 0)
12284 			goto OUT;
12285 	}
12286 	wifi_dev = los_get_wifi_dev_by_priv(wpa_s);
12287 	if (wifi_dev == NULL) {
12288 		wpa_error_log0(MSG_ERROR, "ctrl iface process: get wifi dev failed\n");
12289 		goto OUT;
12290 	}
12291 
12292 	if (os_strncmp(buf, "AP_DEAUTH ", 10) == 0) {
12293 		if (wifi_dev->iftype == EXT_WIFI_IFTYPE_AP)
12294 			(void)hapd_deauth_peer((struct hostapd_data *)(void *)wpa_s, buf + 10);
12295 		goto OUT;
12296 	} else if (os_strcmp(buf, "SHOW_STA") == 0) {
12297 		if (wpa_supplicant_show_sta(wifi_dev->iftype) < 0)
12298 			(void)os_event_write(g_softap_event, WPA_EVENT_AP_SHOW_STA_ERROR);
12299 		else
12300 			(void)os_event_write(g_softap_event, WPA_EVENT_AP_SHOW_STA_OK);
12301 		goto OUT;
12302 #ifdef LOS_CONFIG_P2P
12303 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
12304 		if (wpa_supplicant_ctrl_iface_list_networks(wpa_s) < 0)
12305 			(void)os_event_write(g_p2p_event, WPA_EVENT_P2P_GET_PERSISTENT_GROUP_ERROR);
12306 		else
12307 			(void)os_event_write(g_p2p_event, WPA_EVENT_P2P_GET_PERSISTENT_GROUP_OK);
12308 		goto OUT;
12309 #endif /* LOS_CONFIG_P2P */
12310 	}
12311 
12312 	if ((wpa_s == NULL) || (wifi_dev->iftype == EXT_WIFI_IFTYPE_AP) || (eloop_is_running(ELOOP_TASK_WPA) != EXT_WIFI_OK))
12313 		goto OUT;
12314 
12315 #ifdef CONFIG_MESH
12316 	if (os_strcmp(buf, "JOIN_MESH") == 0) {
12317 		if (wpa_s->ifmsh != NULL)
12318 			los_wpa_join_mesh(wpa_s);
12319 		goto OUT;
12320 	}
12321 #endif
12322 
12323 #ifndef EXT_CODE_CROP
12324 	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
12325 	    os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
12326 	    os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
12327 	    os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12328 		if (wpa_debug_show_keys)
12329 			wpa_dbg(wpa_s, MSG_DEBUG,
12330 				"Control interface command '%s'", buf);
12331 		else
12332 			wpa_dbg(wpa_s, MSG_DEBUG,
12333 				"Control interface command '%s [REMOVED]'",
12334 				os_strncmp(buf, WPA_CTRL_RSP,
12335 					   os_strlen(WPA_CTRL_RSP)) == 0 ?
12336 				WPA_CTRL_RSP :
12337 				(os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
12338 				 "SET_NETWORK" : "key-add"));
12339 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
12340 		   os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
12341 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
12342 				      (const u8 *) buf, os_strlen(buf));
12343 	} else {
12344 		int level = wpas_ctrl_cmd_debug_level(buf);
12345 		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
12346 	}
12347 #endif /* EXT_CODE_CROP */
12348 #ifdef LOS_CONFIG_P2P
12349 	reply = os_malloc(reply_size);
12350 	if (reply == NULL) {
12351 		wpa_error_log0(MSG_ERROR, "ctrl_iface_process fail to malloc buffer.");
12352 		*resp_len = 1;
12353 		return NULL;
12354 	}
12355 
12356 	os_memcpy(reply, "OK\n", 3);
12357 	reply_len = 3;
12358 #endif /* LOS_CONFIG_P2P */
12359 #ifndef EXT_CODE_CROP
12360 	if (os_strcmp(buf, "PING") == 0) {
12361 		os_memcpy(reply, "PONG\n", 5);
12362 		reply_len = 5;
12363 	} else if (os_strcmp(buf, "IFNAME") == 0) {
12364 		reply_len = os_strlen(wpa_s->ifname);
12365 		os_memcpy(reply, wpa_s->ifname, reply_len);
12366 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
12367 		if (wpa_debug_reopen_file() < 0)
12368 			reply_len = -1;
12369 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
12370 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
12371 	} else if (os_strcmp(buf, "MIB") == 0) {
12372 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
12373 		if (reply_len >= 0) {
12374 			reply_len += eapol_sm_get_mib(wpa_s->eapol,
12375 						      reply + reply_len,
12376 						      reply_size - reply_len);
12377 #ifdef CONFIG_MACSEC
12378 			reply_len += ieee802_1x_kay_get_mib(
12379 				wpa_s->kay, reply + reply_len,
12380 				reply_size - reply_len);
12381 #endif /* CONFIG_MACSEC */
12382 		}
12383 	} else
12384 #endif /* EXT_CODE_CROP */
12385 	if (os_strncmp(buf, "STATUS", 6) == 0) {
12386 #ifdef LOS_CONFIG_P2P
12387 		reply_len = wpa_supplicant_ctrl_iface_status(
12388 			wpa_s, buf + 6, reply, reply_size);
12389 #endif /* LOS_CONFIG_P2P */
12390 #ifndef EXT_CODE_CROP
12391 	} else if (os_strcmp(buf, "PMKSA") == 0) {
12392 		reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
12393 	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
12394 		wpas_ctrl_iface_pmksa_flush(wpa_s);
12395 #endif /* EXT_CODE_CROP */
12396 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
12397 	} else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
12398 		reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
12399 						      reply, reply_size);
12400 	} else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
12401 		if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
12402 			reply_len = -1;
12403 #ifdef CONFIG_MESH
12404 	} else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
12405 		reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
12406 							   reply, reply_size);
12407 	} else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12408 		if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
12409 			reply_len = -1;
12410 #endif /* CONFIG_MESH */
12411 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
12412 #ifndef EXT_CODE_CROP
12413 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
12414 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
12415 			reply_len = -1;
12416 	} else if (os_strncmp(buf, "DUMP", 4) == 0) {
12417 		reply_len = wpa_config_dump_values(wpa_s->conf,
12418 						   reply, reply_size);
12419 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
12420 		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
12421 							  reply, reply_size);
12422 	} else if (os_strcmp(buf, "LOGON") == 0) {
12423 		eapol_sm_notify_logoff(wpa_s->eapol, false);
12424 	} else if (os_strcmp(buf, "LOGOFF") == 0) {
12425 		eapol_sm_notify_logoff(wpa_s->eapol, true);
12426 	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
12427 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12428 			reply_len = -1;
12429 		else
12430 			wpas_request_connection(wpa_s);
12431 	} else if (os_strcmp(buf, "REATTACH") == 0) {
12432 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
12433 		    !wpa_s->current_ssid)
12434 			reply_len = -1;
12435 		else {
12436 			wpa_s->reattach = 1;
12437 			wpas_request_connection(wpa_s);
12438 		}
12439 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
12440 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12441 			reply_len = -1;
12442 		else if (wpa_s->disconnected)
12443 			wpas_request_connection(wpa_s);
12444 #ifdef IEEE8021X_EAPOL
12445 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
12446 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
12447 			reply_len = -1;
12448 #endif /* IEEE8021X_EAPOL */
12449 #endif /* EXT_CODE_CROP */
12450 #ifdef CONFIG_IEEE80211R
12451 	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
12452 		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
12453 			reply_len = -1;
12454 #endif /* CONFIG_IEEE80211R */
12455 #ifdef CONFIG_WPS
12456 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
12457 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
12458 #ifndef EXT_CODE_CROP
12459 		if (res == -2) {
12460 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12461 			reply_len = 17;
12462 		} else
12463 #endif /* EXT_CODE_CROP */
12464 		if (res)
12465 			reply_len = -1;
12466 	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
12467 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
12468 #ifndef EXT_CODE_CROP
12469 		if (res == -2) {
12470 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12471 			reply_len = 17;
12472 		} else
12473 #endif /* EXT_CODE_CROP */
12474 		if (res)
12475 			reply_len = -1;
12476 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
12477 		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
12478 							      reply,
12479 							      reply_size);
12480 #ifndef EXT_CODE_CROP
12481 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
12482 		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
12483 			wpa_s, buf + 14, reply, reply_size);
12484 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
12485 		if (wpas_wps_cancel(wpa_s))
12486 			reply_len = -1;
12487 #endif /* EXT_CODE_CROP */
12488 #ifdef CONFIG_WPS_NFC
12489 	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
12490 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
12491 			reply_len = -1;
12492 	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
12493 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
12494 			reply_len = -1;
12495 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
12496 		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
12497 			wpa_s, buf + 21, reply, reply_size);
12498 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
12499 		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
12500 			wpa_s, buf + 14, reply, reply_size);
12501 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
12502 		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
12503 							       buf + 17))
12504 			reply_len = -1;
12505 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
12506 		reply_len = wpas_ctrl_nfc_get_handover_req(
12507 			wpa_s, buf + 21, reply, reply_size);
12508 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
12509 		reply_len = wpas_ctrl_nfc_get_handover_sel(
12510 			wpa_s, buf + 21, reply, reply_size);
12511 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
12512 		if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
12513 			reply_len = -1;
12514 #endif /* CONFIG_WPS_NFC */
12515 #ifndef EXT_CODE_CROP
12516 	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
12517 		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
12518 			reply_len = -1;
12519 #ifdef CONFIG_WPS_AP
12520 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
12521 		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
12522 			wpa_s, buf + 11, reply, reply_size);
12523 #endif /* CONFIG_WPS_AP */
12524 #endif /* EXT_CODE_CROP */
12525 #ifdef CONFIG_WPS_ER
12526 	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
12527 		if (wpas_wps_er_start(wpa_s, NULL))
12528 			reply_len = -1;
12529 	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
12530 		if (wpas_wps_er_start(wpa_s, buf + 13))
12531 			reply_len = -1;
12532 	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
12533 		wpas_wps_er_stop(wpa_s);
12534 	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
12535 		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
12536 			reply_len = -1;
12537 	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
12538 		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
12539 		if (ret == -2) {
12540 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12541 			reply_len = 17;
12542 		} else if (ret == -3) {
12543 			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
12544 			reply_len = 18;
12545 		} else if (ret == -4) {
12546 			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
12547 			reply_len = 20;
12548 		} else if (ret)
12549 			reply_len = -1;
12550 	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
12551 		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
12552 			reply_len = -1;
12553 	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
12554 		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
12555 								buf + 18))
12556 			reply_len = -1;
12557 	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
12558 		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
12559 			reply_len = -1;
12560 #ifdef CONFIG_WPS_NFC
12561 	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
12562 		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
12563 			wpa_s, buf + 24, reply, reply_size);
12564 #endif /* CONFIG_WPS_NFC */
12565 #endif /* CONFIG_WPS_ER */
12566 #endif /* CONFIG_WPS */
12567 #ifdef CONFIG_IBSS_RSN
12568 	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
12569 		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
12570 			reply_len = -1;
12571 #endif /* CONFIG_IBSS_RSN */
12572 #ifndef EXT_CODE_CROP
12573 #ifdef CONFIG_MESH
12574 	} else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
12575 		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12576 			wpa_s, buf + 19, reply, reply_size);
12577 	} else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
12578 		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12579 			wpa_s, "", reply, reply_size);
12580 	} else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
12581 		if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
12582 			reply_len = -1;
12583 	} else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
12584 		if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
12585 								buf + 18))
12586 			reply_len = -1;
12587 	} else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
12588 		if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
12589 			reply_len = -1;
12590 	} else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
12591 		if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
12592 			reply_len = -1;
12593 	} else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
12594 		if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
12595 			reply_len = -1;
12596 #endif /* CONFIG_MESH */
12597 #endif /* EXT_CODE_CROP */
12598 #ifdef CONFIG_P2P
12599 	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
12600 		if (p2p_ctrl_find(wpa_s, buf + 9))
12601 			reply_len = -1;
12602 	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
12603 		if (p2p_ctrl_find(wpa_s, ""))
12604 			reply_len = -1;
12605 	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
12606 		wpas_p2p_stop_find(wpa_s);
12607 #ifndef LOS_P2P_CROP
12608 	} else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
12609 		if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
12610 			reply_len = -1;
12611 	} else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
12612 		if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
12613 			reply_len = -1;
12614 #endif /* LOS_P2P_CROP */
12615 	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
12616 		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
12617 					     reply_size);
12618 #ifndef LOS_P2P_CROP
12619 	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
12620 		if (p2p_ctrl_listen(wpa_s, buf + 11))
12621 			reply_len = -1;
12622 	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
12623 		if (p2p_ctrl_listen(wpa_s, ""))
12624 			reply_len = -1;
12625 #endif /* LOS_P2P_CROP */
12626 	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
12627 		if (wpas_p2p_group_remove(wpa_s, buf + 17))
12628 			reply_len = -1;
12629 #ifndef LOS_P2P_CROP
12630 	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
12631 		if (p2p_ctrl_group_add(wpa_s, ""))
12632 			reply_len = -1;
12633 	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
12634 		if (p2p_ctrl_group_add(wpa_s, buf + 14))
12635 			reply_len = -1;
12636 	} else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
12637 		reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
12638 						  reply_size);
12639 	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
12640 		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
12641 			reply_len = -1;
12642 	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
12643 		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
12644 #endif /* LOS_P2P_CROP */
12645 #ifdef LOS_CONFIG_P2P_SERVICE
12646 	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
12647 		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
12648 						   reply_size);
12649 	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
12650 		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
12651 			reply_len = -1;
12652 	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
12653 		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
12654 			reply_len = -1;
12655 	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
12656 		wpas_p2p_sd_service_update(wpa_s);
12657 	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
12658 		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
12659 			reply_len = -1;
12660 	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
12661 		wpas_p2p_service_flush(wpa_s);
12662 	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
12663 		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
12664 			reply_len = -1;
12665 	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
12666 		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
12667 			reply_len = -1;
12668 	} else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
12669 		if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
12670 			reply_len = -1;
12671 #endif /* LOS_CONFIG_P2P_SERVICE */
12672 	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
12673 		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
12674 			reply_len = -1;
12675 	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
12676 		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
12677 			reply_len = -1;
12678 	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
12679 		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
12680 					      reply_size);
12681 		(void)os_event_write(g_p2p_event, WPA_EVENT_P2P_GET_PEER_OK);
12682 #ifndef LOS_P2P_CROP
12683 	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
12684 		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
12685 			reply_len = -1;
12686 	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
12687 		p2p_ctrl_flush(wpa_s);
12688 	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
12689 		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
12690 			reply_len = -1;
12691 #endif /* LOS_P2P_CROP */
12692 	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
12693 		if (wpas_p2p_cancel(wpa_s))
12694 			reply_len = -1;
12695 #ifndef LOS_P2P_CROP
12696 	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
12697 		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
12698 			reply_len = -1;
12699 	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
12700 		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
12701 			reply_len = -1;
12702 #endif /* LOS_P2P_CROP */
12703 	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
12704 		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
12705 			reply_len = -1;
12706 #ifndef LOS_P2P_CROP
12707 	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
12708 		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
12709 			reply_len = -1;
12710 #endif /* LOS_P2P_CROP */
12711 	} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
12712 		if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
12713 			reply_len = -1;
12714 #ifndef LOS_CONFIG_EXT_DRIVER_NOT_SUPPORT
12715 	} else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
12716 		if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
12717 			reply_len = -1;
12718 	} else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
12719 		if (wpas_p2p_lo_stop(wpa_s))
12720 			reply_len = -1;
12721 #endif /* LOS_CONFIG_EXT_DRIVER_NOT_SUPPORT */
12722 #ifdef LOS_CONFIG_P2P
12723 	} else if (os_strncmp(buf, "P2P_UPDATE_CONFIG ", 18) == 0) {
12724 		if (p2p_ctrl_update_config(wpa_s, buf + 18) < 0)
12725 			reply_len = -1;
12726 #endif /* LOS_CONFIG_P2P */
12727 #endif /* CONFIG_P2P */
12728 #ifdef CONFIG_WIFI_DISPLAY
12729 	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
12730 		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
12731 			reply_len = -1;
12732 	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
12733 		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
12734 						     reply, reply_size);
12735 #endif /* CONFIG_WIFI_DISPLAY */
12736 #ifdef CONFIG_INTERWORKING
12737 	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
12738 		if (interworking_fetch_anqp(wpa_s) < 0)
12739 			reply_len = -1;
12740 	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
12741 		interworking_stop_fetch_anqp(wpa_s);
12742 	} else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
12743 		if (ctrl_interworking_select(wpa_s, NULL) < 0)
12744 			reply_len = -1;
12745 	} else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
12746 		if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
12747 			reply_len = -1;
12748 	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
12749 		if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
12750 			reply_len = -1;
12751 	} else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
12752 		int id;
12753 
12754 		id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
12755 		if (id < 0)
12756 			reply_len = -1;
12757 		else {
12758 			reply_len = os_snprintf(reply, reply_size, "%d\n", id);
12759 			if (os_snprintf_error(reply_size, reply_len))
12760 				reply_len = -1;
12761 		}
12762 	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
12763 		if (get_anqp(wpa_s, buf + 9) < 0)
12764 			reply_len = -1;
12765 	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
12766 		if (gas_request(wpa_s, buf + 12) < 0)
12767 			reply_len = -1;
12768 	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
12769 		reply_len = gas_response_get(wpa_s, buf + 17, reply,
12770 					     reply_size);
12771 #endif /* CONFIG_INTERWORKING */
12772 #ifdef CONFIG_HS20
12773 	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
12774 		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
12775 			reply_len = -1;
12776 	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
12777 		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
12778 			reply_len = -1;
12779 	} else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
12780 		if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
12781 			reply_len = -1;
12782 	} else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
12783 		if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
12784 			reply_len = -1;
12785 	} else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
12786 		reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
12787 	} else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
12788 		if (del_hs20_icon(wpa_s, buf + 14) < 0)
12789 			reply_len = -1;
12790 	} else if (os_strcmp(buf, "FETCH_OSU") == 0) {
12791 		if (hs20_fetch_osu(wpa_s, 0) < 0)
12792 			reply_len = -1;
12793 	} else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
12794 		if (hs20_fetch_osu(wpa_s, 1) < 0)
12795 			reply_len = -1;
12796 	} else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
12797 		hs20_cancel_fetch_osu(wpa_s);
12798 #endif /* CONFIG_HS20 */
12799 #ifndef EXT_CODE_CROP
12800 	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
12801 	{
12802 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
12803 			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
12804 			reply_len = -1;
12805 		else {
12806 			/*
12807 			 * Notify response from timeout to allow the control
12808 			 * interface response to be sent first.
12809 			 */
12810 			eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
12811 					       wpa_s, NULL);
12812 		}
12813 	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
12814 		if (wpa_supplicant_reload_configuration(wpa_s))
12815 			reply_len = -1;
12816 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
12817 		wpa_supplicant_terminate_proc(wpa_s->global);
12818 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
12819 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
12820 			reply_len = -1;
12821 	} else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
12822 		reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
12823 			wpa_s, buf + 12, reply, reply_size);
12824 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
12825 		/* deprecated backwards compatibility alias for BSSID_IGNORE */
12826 		reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
12827 			wpa_s, buf + 9, reply, reply_size);
12828 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
12829 		reply_len = wpa_supplicant_ctrl_iface_log_level(
12830 			wpa_s, buf + 9, reply, reply_size);
12831 	} else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
12832 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
12833 			wpa_s, buf + 14, reply, reply_size);
12834 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
12835 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
12836 			wpa_s, NULL, reply, reply_size);
12837 #endif /* EXT_CODE_CROP */
12838 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
12839 		g_sta_delay_report_flag = WPA_FLAG_OFF;
12840 		wpas_request_disconnection(wpa_s);
12841 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
12842 		reply_len = wpa_supplicant_ctrl_iface_log_level(
12843 			wpa_s, buf + 9, reply, reply_size);
12844 #ifdef LOS_WPA_PATCH
12845     } else if (os_strcmp(buf, "STA_STATUS") == 0) {
12846         (void)wpa_sta_status(wpa_s);
12847     } else if (os_strcmp(buf, "STA_STATUS") > 0) {
12848         void *addr = (void *)atoi((char *)(buf + 11));
12849         (void)wpa_get_sta_status(wpa_s, addr);
12850 #ifdef LOS_CONFIG_MESH
12851 	} else if (os_strncmp(buf, "MESH_DEAUTH ", 12) == 0) {
12852 		(void)wpa_mesh_deauth_peer(wpa_s, buf + 12);
12853 	} else if (os_strncmp(buf, "MESH_SET_ACCEPT ", 16) == 0) {
12854 		(void)wpa_mesh_set_accept(wpa_s, buf + 16);
12855 #endif /* LOS_CONFIG_MESH */
12856 #endif /* LOS_WPA_PATCH */
12857 	} else if (os_strcmp(buf, "SCAN") == 0) {
12858 		wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
12859 	} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
12860 		wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
12861 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
12862 #ifdef EXT_CODE_CROP
12863 		if (reply == NULL) {
12864 			reply = os_malloc(reply_size);
12865 			if (reply == NULL) {
12866 				osal_printk("scan_results malloc fail.\r\n");
12867 				wpa_error_log0(MSG_ERROR, "ctrl_iface_process fail to malloc buffer.");
12868 				*resp_len = 1;
12869 				return NULL;
12870 			}
12871 		}
12872 #endif /* EXT_CODE_CROP */
12873 
12874 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
12875 			wpa_s, reply, reply_size);
12876 #ifdef LOS_WPA_PATCH
12877 		g_scan_result_buf = reply;
12878 		g_result_len = (size_t)reply_len;
12879 		(void)os_event_write(g_wpa_event, WPA_EVENT_GET_SCAN_RESULT_OK);
12880 #endif /* LOS_WPA_PATCH */
12881 #ifndef EXT_CODE_CROP
12882 	} else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
12883 		if (wpas_abort_ongoing_scan(wpa_s) < 0)
12884 			reply_len = -1;
12885 #endif /* EXT_CODE_CROP */
12886 	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
12887 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
12888 			reply_len = -1;
12889 #ifndef EXT_CODE_CROP
12890 	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
12891 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
12892 			reply_len = -1;
12893 	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
12894 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
12895 			reply_len = -1;
12896 #endif /* EXT_CODE_CROP */
12897 	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
12898 		reply_len = wpa_supplicant_ctrl_iface_add_network(
12899 			wpa_s, reply, reply_size);
12900 	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
12901 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
12902 			reply_len = -1;
12903 	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
12904 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
12905 			reply_len = -1;
12906 #ifndef EXT_CODE_CROP
12907 	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
12908 		reply_len = wpa_supplicant_ctrl_iface_get_network(
12909 			wpa_s, buf + 12, reply, reply_size);
12910 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
12911 		if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
12912 							  wpa_s))
12913 			reply_len = -1;
12914 	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
12915 		reply_len = wpa_supplicant_ctrl_iface_list_creds(
12916 			wpa_s, reply, reply_size);
12917 	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
12918 		reply_len = wpa_supplicant_ctrl_iface_add_cred(
12919 			wpa_s, reply, reply_size);
12920 	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
12921 		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
12922 			reply_len = -1;
12923 	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
12924 		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
12925 			reply_len = -1;
12926 	} else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
12927 		reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
12928 							       reply,
12929 							       reply_size);
12930 #ifndef CONFIG_NO_CONFIG_WRITE
12931 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
12932 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
12933 			reply_len = -1;
12934 #endif /* CONFIG_NO_CONFIG_WRITE */
12935 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
12936 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
12937 			wpa_s, buf + 15, reply, reply_size);
12938 	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
12939 		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
12940 			reply_len = -1;
12941 	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
12942 		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
12943 			reply_len = -1;
12944 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
12945 		reply_len = wpa_supplicant_global_iface_list(
12946 			wpa_s->global, reply, reply_size);
12947 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
12948 		reply_len = wpa_supplicant_global_iface_interfaces(
12949 			wpa_s->global, buf + 10, reply, reply_size);
12950 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
12951 		reply_len = wpa_supplicant_ctrl_iface_bss(
12952 			wpa_s, buf + 4, reply, reply_size);
12953 #ifdef CONFIG_AP
12954 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
12955 		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
12956 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
12957 		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
12958 					      reply_size);
12959 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
12960 		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
12961 						   reply_size);
12962 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
12963 		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
12964 			reply_len = -1;
12965 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
12966 		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
12967 			reply_len = -1;
12968 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
12969 		if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
12970 			reply_len = -1;
12971 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
12972 		if (wpas_ap_stop_ap(wpa_s))
12973 			reply_len = -1;
12974 	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
12975 		if (wpas_ap_update_beacon(wpa_s))
12976 			reply_len = -1;
12977 #endif /* CONFIG_AP */
12978 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
12979 		wpas_notify_suspend(wpa_s->global);
12980 	} else if (os_strcmp(buf, "RESUME") == 0) {
12981 		wpas_notify_resume(wpa_s->global);
12982 #endif /* EXT_CODE_CROP */
12983 #ifdef CONFIG_TESTING_OPTIONS
12984 	} else if (os_strcmp(buf, "DROP_SA") == 0) {
12985 		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
12986 #endif /* CONFIG_TESTING_OPTIONS */
12987 #ifndef EXT_CODE_CROP
12988 	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
12989 		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
12990 			reply_len = -1;
12991 	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
12992 		wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
12993 	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
12994 		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
12995 			reply_len = -1;
12996 	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
12997 		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
12998 							       buf + 17))
12999 			reply_len = -1;
13000 #endif /* EXT_CODE_CROP */
13001 	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
13002 		wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
13003 #ifdef LOS_WPA_PATCH
13004         osal_printk("write event WPA_EVENT_SCAN_RESULT_CLEAR_OK.\r\n");
13005         (void)os_event_write(g_wpa_event, WPA_EVENT_SCAN_RESULT_CLEAR_OK);
13006 #endif /* LOS_WPA_PATCH */
13007 #ifdef CONFIG_TDLS
13008 	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
13009 		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
13010 			reply_len = -1;
13011 	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
13012 		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
13013 			reply_len = -1;
13014 	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
13015 		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
13016 			reply_len = -1;
13017 	} else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
13018 		if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
13019 							       buf + 17))
13020 			reply_len = -1;
13021 	} else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
13022 		if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
13023 								      buf + 24))
13024 			reply_len = -1;
13025 	} else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
13026 		reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
13027 			wpa_s, buf + 17, reply, reply_size);
13028 #endif /* CONFIG_TDLS */
13029 #ifdef CONFIG_WMM_AC
13030 	} else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
13031 		reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
13032 	} else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
13033 		if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
13034 			reply_len = -1;
13035 	} else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
13036 		if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
13037 			reply_len = -1;
13038 #endif /* CONFIG_WMM_AC */
13039 #ifndef EXT_CODE_CROP
13040 	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
13041 		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
13042 						       reply_size);
13043 	} else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
13044 		if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
13045 			reply_len = -1;
13046 	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
13047 		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
13048 						       reply_size);
13049 #endif /* EXT_CODE_CROP */
13050 #ifdef CONFIG_AUTOSCAN
13051 	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
13052 		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
13053 			reply_len = -1;
13054 #endif /* CONFIG_AUTOSCAN */
13055 #ifndef EXT_CODE_CROP
13056 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
13057 		reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
13058 							 reply_size);
13059 	} else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
13060 		reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply,
13061 							  reply_size);
13062 #endif /* EXT_CODE_CROP */
13063 #ifdef ANDROID
13064 	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
13065 		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
13066 						      reply_size);
13067 #endif /* ANDROID */
13068 #ifndef EXT_CODE_CROP
13069 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
13070 		reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
13071 						      reply_size);
13072 	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
13073 		pmksa_cache_clear_current(wpa_s->wpa);
13074 		eapol_sm_request_reauth(wpa_s->eapol);
13075 #endif /* EXT_CODE_CROP */
13076 #ifdef CONFIG_WNM
13077 	} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
13078 		if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
13079 			reply_len = -1;
13080 	} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
13081 		if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
13082 				reply_len = -1;
13083 		(void)os_event_write(g_wpa_event, WPA_EVENT_STA_WNM_BSS_QUERY);
13084 	} else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
13085 		if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
13086 			reply_len = -1;
13087 	} else if (os_strncmp(buf, "WNM_Notify ", 11) == 0) {
13088 		if (wpas_mbo_update_non_pref_chan(wpa_s, buf + 11))
13089 			reply_len = -1;
13090 		(void)os_event_write(g_wpa_event, WPA_EVENT_STA_WNM_NOTIFY);
13091 #endif /* CONFIG_WNM */
13092 #ifndef EXT_CODE_CROP
13093 	} else if (os_strcmp(buf, "FLUSH") == 0) {
13094 		wpa_supplicant_ctrl_iface_flush(wpa_s);
13095 	} else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
13096 		reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
13097 						 reply_size);
13098 #endif /* EXT_CODE_CROP */
13099 #ifdef CONFIG_TESTING_OPTIONS
13100 	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
13101 		if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
13102 			reply_len = -1;
13103 	} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
13104 		wpas_ctrl_iface_mgmt_tx_done(wpa_s);
13105 	} else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
13106 		if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
13107 			reply_len = -1;
13108 	} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
13109 		if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
13110 			reply_len = -1;
13111 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
13112 		if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
13113 			reply_len = -1;
13114 	} else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
13115 		if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
13116 			reply_len = -1;
13117 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
13118 		if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
13119 			reply_len = -1;
13120 	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
13121 		if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
13122 			reply_len = -1;
13123 	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
13124 		if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
13125 			reply_len = -1;
13126 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
13127 		if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
13128 			reply_len = -1;
13129 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
13130 		reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
13131 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
13132 		if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0)
13133 			reply_len = -1;
13134 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
13135 		reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
13136 	} else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
13137 		if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
13138 			reply_len = -1;
13139 	} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
13140 		if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
13141 			reply_len = -1;
13142 	} else if (os_strcmp(buf, "RESET_PN") == 0) {
13143 		if (wpas_ctrl_reset_pn(wpa_s) < 0)
13144 			reply_len = -1;
13145 	} else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
13146 		if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
13147 			reply_len = -1;
13148 	} else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
13149 		if (wpas_ctrl_resend_assoc(wpa_s) < 0)
13150 			reply_len = -1;
13151 	} else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
13152 		sme_event_unprot_disconnect(
13153 			wpa_s, wpa_s->bssid, NULL,
13154 			WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13155 	} else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) {
13156 		if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9))
13157 			reply_len = -1;
13158 	} else if (os_strcmp(buf, "TWT_SETUP") == 0) {
13159 		if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
13160 			reply_len = -1;
13161 	} else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
13162 		if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
13163 			reply_len = -1;
13164 	} else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) {
13165 		if (wpas_ctrl_iface_send_twt_teardown(wpa_s, ""))
13166 			reply_len = -1;
13167 #endif /* CONFIG_TESTING_OPTIONS */
13168 #ifndef EXT_CODE_CROP
13169 	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
13170 		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
13171 			reply_len = -1;
13172 	} else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
13173 		reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
13174 						      reply_size);
13175 	} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
13176 		if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
13177 			reply_len = -1;
13178 	} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
13179 		if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
13180 			reply_len = -1;
13181 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
13182 		wpas_ctrl_iface_erp_flush(wpa_s);
13183 	} else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
13184 		if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
13185 			reply_len = -1;
13186 	} else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
13187 		reply_len = wpas_ctrl_iface_get_pref_freq_list(
13188 			wpa_s, buf + 19, reply, reply_size);
13189 #endif /* EXT_CODE_CROP */
13190 #ifdef CONFIG_FILS
13191 	} else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
13192 		if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
13193 			reply_len = -1;
13194 	} else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
13195 		wpas_flush_fils_hlp_req(wpa_s);
13196 #endif /* CONFIG_FILS */
13197 #ifdef CONFIG_DPP
13198 	} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
13199 		int res;
13200 
13201 		res = wpas_dpp_qr_code(wpa_s, buf + 12);
13202 		if (res < 0) {
13203 			reply_len = -1;
13204 		} else {
13205 			reply_len = os_snprintf(reply, reply_size, "%d", res);
13206 			if (os_snprintf_error(reply_size, reply_len))
13207 				reply_len = -1;
13208 		}
13209 	} else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
13210 		int res;
13211 
13212 		res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
13213 		if (res < 0) {
13214 			reply_len = -1;
13215 		} else {
13216 			reply_len = os_snprintf(reply, reply_size, "%d", res);
13217 			if (os_snprintf_error(reply_size, reply_len))
13218 				reply_len = -1;
13219 		}
13220 	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
13221 		int res;
13222 
13223 		res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
13224 		if (res < 0) {
13225 			reply_len = -1;
13226 		} else {
13227 			reply_len = os_snprintf(reply, reply_size, "%d", res);
13228 			if (os_snprintf_error(reply_size, reply_len))
13229 				reply_len = -1;
13230 		}
13231 	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
13232 		int res;
13233 
13234 		res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
13235 		if (res < 0) {
13236 			reply_len = -1;
13237 		} else {
13238 			reply_len = os_snprintf(reply, reply_size, "%d", res);
13239 			if (os_snprintf_error(reply_size, reply_len))
13240 				reply_len = -1;
13241 		}
13242 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
13243 		int res;
13244 
13245 		res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
13246 		if (res < 0) {
13247 			reply_len = -1;
13248 		} else {
13249 			reply_len = os_snprintf(reply, reply_size, "%d", res);
13250 			if (os_snprintf_error(reply_size, reply_len))
13251 				reply_len = -1;
13252 		}
13253 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
13254 		if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
13255 			reply_len = -1;
13256 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
13257 		const char *uri;
13258 
13259 		uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
13260 		if (!uri) {
13261 			reply_len = -1;
13262 		} else {
13263 			reply_len = os_snprintf(reply, reply_size, "%s", uri);
13264 			if (os_snprintf_error(reply_size, reply_len))
13265 				reply_len = -1;
13266 		}
13267 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
13268 		reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
13269 					       reply, reply_size);
13270 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
13271 		if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
13272 				      os_strchr(buf + 18, ' ')) < 0)
13273 			reply_len = -1;
13274 	} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
13275 		if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
13276 			reply_len = -1;
13277 	} else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
13278 		if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
13279 			reply_len = -1;
13280 	} else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
13281 #ifndef EXT_CODE_CROP
13282 		wpas_dpp_stop(wpa_s);
13283 #endif /* EXT_CODE_CROP */
13284 		wpas_dpp_listen_stop(wpa_s);
13285 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
13286 		int res;
13287 
13288 		res = dpp_configurator_add(wpa_s->dpp, buf + 20);
13289 		if (res < 0) {
13290 			reply_len = -1;
13291 		} else {
13292 			reply_len = os_snprintf(reply, reply_size, "%d", res);
13293 			if (os_snprintf_error(reply_size, reply_len))
13294 				reply_len = -1;
13295 		}
13296 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
13297 		if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
13298 			reply_len = -1;
13299 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
13300 		if (wpas_dpp_configurator_sign(wpa_s, buf + 22) < 0)
13301 			reply_len = -1;
13302 #ifndef EXT_CODE_CROP
13303 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
13304 		reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
13305 							atoi(buf + 25),
13306 							reply, reply_size);
13307 #endif /* EXT_CODE_CROP */
13308 	} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
13309 		int res;
13310 
13311 		res = wpas_dpp_pkex_add(wpa_s, buf + 12);
13312 		if (res < 0) {
13313 			reply_len = -1;
13314 		} else {
13315 			reply_len = os_snprintf(reply, reply_size, "%d", res);
13316 			if (os_snprintf_error(reply_size, reply_len))
13317 				reply_len = -1;
13318 		}
13319 	} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
13320 		if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
13321 			reply_len = -1;
13322 #ifdef CONFIG_DPP2
13323 	} else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
13324 		if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
13325 			reply_len = -1;
13326 	} else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
13327 		if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
13328 			reply_len = -1;
13329 	} else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
13330 		dpp_controller_stop(wpa_s->dpp);
13331 	} else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
13332 		if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
13333 			reply_len = -1;
13334 	} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
13335 		wpas_dpp_chirp_stop(wpa_s);
13336 	} else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
13337 		if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0)
13338 			reply_len = -1;
13339 	} else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) {
13340 		if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0)
13341 			reply_len = -1;
13342 #endif /* CONFIG_DPP2 */
13343 #endif /* CONFIG_DPP */
13344 	}
13345 #ifndef EXT_CODE_CROP
13346 	else if (os_strncmp(buf, "MSCS ", 5) == 0) {
13347 		if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
13348 			reply_len = -1;
13349 #ifdef CONFIG_PASN
13350 	} else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
13351 		if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
13352 			reply_len = -1;
13353 	} else if (os_strcmp(buf, "PASN_STOP") == 0) {
13354 		wpas_pasn_auth_stop(wpa_s);
13355 	} else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
13356 		reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
13357 	} else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
13358 		if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
13359 			reply_len = -1;
13360 #endif /* CONFIG_PASN */
13361 	} else if (os_strncmp(buf, "SCS ", 4) == 0) {
13362 		if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
13363 			reply_len = -1;
13364 	} else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
13365 		if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
13366 			reply_len = -1;
13367 	} else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
13368 		if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
13369 			reply_len = -1;
13370 	} else {
13371 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
13372 		reply_len = 16;
13373 	}
13374 
13375 	if (reply_len < 0) {
13376 		os_memcpy(reply, "FAIL\n", 5);
13377 		reply_len = 5;
13378 	}
13379 #endif /* EXT_CODE_CROP */
13380 
13381 OUT:
13382 	*resp_len = reply_len;
13383 	return reply;
13384 }
13385 
13386 #ifndef EXT_CODE_CROP
13387 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
13388 					   char *cmd)
13389 {
13390 	struct wpa_interface iface;
13391 	char *pos, *extra;
13392 	struct wpa_supplicant *wpa_s;
13393 	unsigned int create_iface = 0;
13394 	u8 mac_addr[ETH_ALEN];
13395 	enum wpa_driver_if_type type = WPA_IF_STATION;
13396 
13397 	/*
13398 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
13399 	 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
13400 	 */
13401 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
13402 
13403 	os_memset(&iface, 0, sizeof(iface));
13404 
13405 	do {
13406 		iface.ifname = pos = cmd;
13407 		pos = os_strchr(pos, '\t');
13408 		if (pos)
13409 			*pos++ = '\0';
13410 		if (iface.ifname[0] == '\0')
13411 			return -1;
13412 		if (pos == NULL)
13413 			break;
13414 
13415 		iface.confname = pos;
13416 		pos = os_strchr(pos, '\t');
13417 		if (pos)
13418 			*pos++ = '\0';
13419 		if (iface.confname[0] == '\0')
13420 			iface.confname = NULL;
13421 		if (pos == NULL)
13422 			break;
13423 
13424 		iface.driver = pos;
13425 		pos = os_strchr(pos, '\t');
13426 		if (pos)
13427 			*pos++ = '\0';
13428 		if (iface.driver[0] == '\0')
13429 			iface.driver = NULL;
13430 		if (pos == NULL)
13431 			break;
13432 
13433 		iface.ctrl_interface = pos;
13434 		pos = os_strchr(pos, '\t');
13435 		if (pos)
13436 			*pos++ = '\0';
13437 		if (iface.ctrl_interface[0] == '\0')
13438 			iface.ctrl_interface = NULL;
13439 		if (pos == NULL)
13440 			break;
13441 
13442 		iface.driver_param = pos;
13443 		pos = os_strchr(pos, '\t');
13444 		if (pos)
13445 			*pos++ = '\0';
13446 		if (iface.driver_param[0] == '\0')
13447 			iface.driver_param = NULL;
13448 		if (pos == NULL)
13449 			break;
13450 
13451 		iface.bridge_ifname = pos;
13452 		pos = os_strchr(pos, '\t');
13453 		if (pos)
13454 			*pos++ = '\0';
13455 		if (iface.bridge_ifname[0] == '\0')
13456 			iface.bridge_ifname = NULL;
13457 		if (pos == NULL)
13458 			break;
13459 
13460 		extra = pos;
13461 		pos = os_strchr(pos, '\t');
13462 		if (pos)
13463 			*pos++ = '\0';
13464 		if (!extra[0])
13465 			break;
13466 
13467 		if (os_strcmp(extra, "create") == 0) {
13468 			create_iface = 1;
13469 			if (!pos)
13470 				break;
13471 
13472 			if (os_strcmp(pos, "sta") == 0) {
13473 				type = WPA_IF_STATION;
13474 			} else if (os_strcmp(pos, "ap") == 0) {
13475 				type = WPA_IF_AP_BSS;
13476 			} else {
13477 				wpa_printf(MSG_DEBUG,
13478 					   "INTERFACE_ADD unsupported interface type: '%s'",
13479 					   pos);
13480 				return -1;
13481 			}
13482 		} else {
13483 			wpa_printf(MSG_DEBUG,
13484 				   "INTERFACE_ADD unsupported extra parameter: '%s'",
13485 				   extra);
13486 			return -1;
13487 		}
13488 	} while (0);
13489 
13490 	if (create_iface) {
13491 		wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
13492 			   iface.ifname);
13493 		if (!global->ifaces)
13494 			return -1;
13495 		if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
13496 				   NULL, NULL, NULL, mac_addr, NULL) < 0) {
13497 			wpa_printf(MSG_ERROR,
13498 				   "CTRL_IFACE interface creation failed");
13499 			return -1;
13500 		}
13501 
13502 		wpa_printf(MSG_DEBUG,
13503 			   "CTRL_IFACE interface '%s' created with MAC addr: "
13504 			   MACSTR, iface.ifname, MAC2STR(mac_addr));
13505 	}
13506 
13507 	if (wpa_supplicant_get_iface(global, iface.ifname))
13508 		goto fail;
13509 
13510 	wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
13511 	if (!wpa_s)
13512 		goto fail;
13513 	wpa_s->added_vif = create_iface;
13514 	return 0;
13515 
13516 fail:
13517 	if (create_iface)
13518 		wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
13519 	return -1;
13520 }
13521 
13522 
13523 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
13524 					      char *cmd)
13525 {
13526 	struct wpa_supplicant *wpa_s;
13527 	int ret;
13528 	unsigned int delete_iface;
13529 
13530 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
13531 
13532 	wpa_s = wpa_supplicant_get_iface(global, cmd);
13533 	if (wpa_s == NULL)
13534 		return -1;
13535 	delete_iface = wpa_s->added_vif;
13536 	ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
13537 	if (!ret && delete_iface) {
13538 		wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
13539 			   cmd);
13540 		ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
13541 	}
13542 	return ret;
13543 }
13544 
13545 
13546 static void wpa_free_iface_info(struct wpa_interface_info *iface)
13547 {
13548 	struct wpa_interface_info *prev;
13549 
13550 	while (iface) {
13551 		prev = iface;
13552 		iface = iface->next;
13553 
13554 		os_free(prev->ifname);
13555 		os_free(prev->desc);
13556 		os_free(prev);
13557 	}
13558 }
13559 
13560 
13561 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
13562 					    char *buf, int len)
13563 {
13564 	int i, res;
13565 	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
13566 	char *pos, *end;
13567 
13568 	for (i = 0; wpa_drivers[i]; i++) {
13569 		const struct wpa_driver_ops *drv = wpa_drivers[i];
13570 		if (drv->get_interfaces == NULL)
13571 			continue;
13572 		tmp = drv->get_interfaces(global->drv_priv[i]);
13573 		if (tmp == NULL)
13574 			continue;
13575 
13576 		if (last == NULL)
13577 			iface = last = tmp;
13578 		else
13579 			last->next = tmp;
13580 		while (last->next)
13581 			last = last->next;
13582 	}
13583 
13584 	pos = buf;
13585 	end = buf + len;
13586 	for (tmp = iface; tmp; tmp = tmp->next) {
13587 		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
13588 				  tmp->drv_name, tmp->ifname,
13589 				  tmp->desc ? tmp->desc : "");
13590 		if (os_snprintf_error(end - pos, res)) {
13591 			*pos = '\0';
13592 			break;
13593 		}
13594 		pos += res;
13595 	}
13596 
13597 	wpa_free_iface_info(iface);
13598 
13599 	return pos - buf;
13600 }
13601 
13602 
13603 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
13604 						  const char *input,
13605 						  char *buf, int len)
13606 {
13607 	int res;
13608 	char *pos, *end;
13609 	struct wpa_supplicant *wpa_s;
13610 	int show_ctrl = 0;
13611 
13612 	if (input)
13613 		show_ctrl = !!os_strstr(input, "ctrl");
13614 
13615 	wpa_s = global->ifaces;
13616 	pos = buf;
13617 	end = buf + len;
13618 
13619 	while (wpa_s) {
13620 		if (show_ctrl)
13621 			res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
13622 					  wpa_s->ifname,
13623 					  wpa_s->conf->ctrl_interface ?
13624 					  wpa_s->conf->ctrl_interface : "N/A");
13625 		else
13626 			res = os_snprintf(pos, end - pos, "%s\n",
13627 					  wpa_s->ifname);
13628 
13629 		if (os_snprintf_error(end - pos, res)) {
13630 			*pos = '\0';
13631 			break;
13632 		}
13633 		pos += res;
13634 		wpa_s = wpa_s->next;
13635 	}
13636 	return pos - buf;
13637 }
13638 
13639 
13640 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
13641 					    const char *ifname,
13642 					    char *cmd, size_t *resp_len)
13643 {
13644 	struct wpa_supplicant *wpa_s;
13645 
13646 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
13647 		if (os_strcmp(ifname, wpa_s->ifname) == 0)
13648 			break;
13649 	}
13650 
13651 	if (wpa_s == NULL) {
13652 		char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
13653 		if (resp)
13654 			*resp_len = os_strlen(resp);
13655 		else
13656 			*resp_len = 1;
13657 		return resp;
13658 	}
13659 
13660 	return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
13661 }
13662 
13663 
13664 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
13665 					       char *buf, size_t *resp_len)
13666 {
13667 #ifdef CONFIG_P2P
13668 	static const char * cmd[] = {
13669 		"LIST_NETWORKS",
13670 		"P2P_FIND",
13671 		"P2P_STOP_FIND",
13672 		"P2P_LISTEN",
13673 		"P2P_GROUP_ADD",
13674 		"P2P_GET_PASSPHRASE",
13675 		"P2P_SERVICE_UPDATE",
13676 		"P2P_SERVICE_FLUSH",
13677 		"P2P_FLUSH",
13678 		"P2P_CANCEL",
13679 		"P2P_PRESENCE_REQ",
13680 		"P2P_EXT_LISTEN",
13681 #ifdef CONFIG_AP
13682 		"STA-FIRST",
13683 #endif /* CONFIG_AP */
13684 		NULL
13685 	};
13686 	static const char * prefix[] = {
13687 #ifdef ANDROID
13688 		"DRIVER ",
13689 #endif /* ANDROID */
13690 		"GET_CAPABILITY ",
13691 		"GET_NETWORK ",
13692 		"REMOVE_NETWORK ",
13693 		"P2P_FIND ",
13694 		"P2P_CONNECT ",
13695 		"P2P_LISTEN ",
13696 		"P2P_GROUP_REMOVE ",
13697 		"P2P_GROUP_ADD ",
13698 		"P2P_GROUP_MEMBER ",
13699 		"P2P_PROV_DISC ",
13700 		"P2P_SERV_DISC_REQ ",
13701 		"P2P_SERV_DISC_CANCEL_REQ ",
13702 		"P2P_SERV_DISC_RESP ",
13703 		"P2P_SERV_DISC_EXTERNAL ",
13704 		"P2P_SERVICE_ADD ",
13705 		"P2P_SERVICE_DEL ",
13706 		"P2P_SERVICE_REP ",
13707 		"P2P_REJECT ",
13708 		"P2P_INVITE ",
13709 		"P2P_PEER ",
13710 		"P2P_SET ",
13711 		"P2P_UNAUTHORIZE ",
13712 		"P2P_PRESENCE_REQ ",
13713 		"P2P_EXT_LISTEN ",
13714 		"P2P_REMOVE_CLIENT ",
13715 		"WPS_NFC_TOKEN ",
13716 		"WPS_NFC_TAG_READ ",
13717 		"NFC_GET_HANDOVER_SEL ",
13718 		"NFC_GET_HANDOVER_REQ ",
13719 		"NFC_REPORT_HANDOVER ",
13720 		"P2P_ASP_PROVISION ",
13721 		"P2P_ASP_PROVISION_RESP ",
13722 #ifdef CONFIG_AP
13723 		"STA ",
13724 		"STA-NEXT ",
13725 #endif /* CONFIG_AP */
13726 		NULL
13727 	};
13728 	int found = 0;
13729 	int i;
13730 
13731 	if (global->p2p_init_wpa_s == NULL)
13732 		return NULL;
13733 
13734 	for (i = 0; !found && cmd[i]; i++) {
13735 		if (os_strcmp(buf, cmd[i]) == 0)
13736 			found = 1;
13737 	}
13738 
13739 	for (i = 0; !found && prefix[i]; i++) {
13740 		if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
13741 			found = 1;
13742 	}
13743 
13744 	if (found)
13745 		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
13746 							 buf, resp_len);
13747 #endif /* CONFIG_P2P */
13748 	return NULL;
13749 }
13750 
13751 
13752 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
13753 					       char *buf, size_t *resp_len)
13754 {
13755 #ifdef CONFIG_WIFI_DISPLAY
13756 	if (global->p2p_init_wpa_s == NULL)
13757 		return NULL;
13758 	if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
13759 	    os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
13760 		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
13761 							 buf, resp_len);
13762 #endif /* CONFIG_WIFI_DISPLAY */
13763 	return NULL;
13764 }
13765 
13766 
13767 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
13768 					   char *buf, size_t *resp_len)
13769 {
13770 	char *ret;
13771 
13772 	ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
13773 	if (ret)
13774 		return ret;
13775 
13776 	ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
13777 	if (ret)
13778 		return ret;
13779 
13780 	return NULL;
13781 }
13782 
13783 
13784 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
13785 {
13786 	char *value;
13787 
13788 	value = os_strchr(cmd, ' ');
13789 	if (value == NULL)
13790 		return -1;
13791 	*value++ = '\0';
13792 
13793 	wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
13794 
13795 #ifdef CONFIG_WIFI_DISPLAY
13796 	if (os_strcasecmp(cmd, "wifi_display") == 0) {
13797 		wifi_display_enable(global, !!atoi(value));
13798 		return 0;
13799 	}
13800 #endif /* CONFIG_WIFI_DISPLAY */
13801 
13802 	/* Restore cmd to its original value to allow redirection */
13803 	value[-1] = ' ';
13804 
13805 	return -1;
13806 }
13807 
13808 
13809 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
13810 					      char *cmd)
13811 {
13812 	struct wpa_supplicant *wpa_s[2]; /* src, dst */
13813 	char *p;
13814 	unsigned int i;
13815 
13816 	/* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
13817 	 * <variable name> */
13818 
13819 	for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
13820 		p = os_strchr(cmd, ' ');
13821 		if (p == NULL)
13822 			return -1;
13823 		*p = '\0';
13824 
13825 		wpa_s[i] = global->ifaces;
13826 		for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
13827 			if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
13828 				break;
13829 		}
13830 
13831 		if (!wpa_s[i]) {
13832 			wpa_printf(MSG_DEBUG,
13833 				   "CTRL_IFACE: Could not find iface=%s", cmd);
13834 			return -1;
13835 		}
13836 
13837 		cmd = p + 1;
13838 	}
13839 
13840 	return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
13841 }
13842 
13843 
13844 #ifndef CONFIG_NO_CONFIG_WRITE
13845 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
13846 {
13847 	int ret = 0, saved = 0;
13848 	struct wpa_supplicant *wpa_s;
13849 
13850 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
13851 		if (!wpa_s->conf->update_config) {
13852 			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
13853 			continue;
13854 		}
13855 
13856 		if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
13857 			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
13858 			ret = 1;
13859 		} else {
13860 			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
13861 			saved++;
13862 		}
13863 	}
13864 
13865 	if (!saved && !ret) {
13866 		wpa_dbg(wpa_s, MSG_DEBUG,
13867 			"CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
13868 		ret = 1;
13869 	}
13870 
13871 	return ret;
13872 }
13873 #endif /* CONFIG_NO_CONFIG_WRITE */
13874 
13875 
13876 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
13877 					 char *buf, size_t buflen)
13878 {
13879 	char *pos, *end;
13880 	int ret;
13881 	struct wpa_supplicant *wpa_s;
13882 
13883 	pos = buf;
13884 	end = buf + buflen;
13885 
13886 #ifdef CONFIG_P2P
13887 	if (global->p2p && !global->p2p_disabled) {
13888 		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
13889 				  "\n"
13890 				  "p2p_state=%s\n",
13891 				  MAC2STR(global->p2p_dev_addr),
13892 				  p2p_get_state_txt(global->p2p));
13893 		if (os_snprintf_error(end - pos, ret))
13894 			return pos - buf;
13895 		pos += ret;
13896 	} else if (global->p2p) {
13897 		ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
13898 		if (os_snprintf_error(end - pos, ret))
13899 			return pos - buf;
13900 		pos += ret;
13901 	}
13902 #endif /* CONFIG_P2P */
13903 
13904 #ifdef CONFIG_WIFI_DISPLAY
13905 	ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
13906 			  !!global->wifi_display);
13907 	if (os_snprintf_error(end - pos, ret))
13908 		return pos - buf;
13909 	pos += ret;
13910 #endif /* CONFIG_WIFI_DISPLAY */
13911 
13912 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
13913 		ret = os_snprintf(pos, end - pos, "ifname=%s\n"
13914 				  "address=" MACSTR "\n",
13915 				  wpa_s->ifname, MAC2STR(wpa_s->own_addr));
13916 		if (os_snprintf_error(end - pos, ret))
13917 			return pos - buf;
13918 		pos += ret;
13919 	}
13920 
13921 	return pos - buf;
13922 }
13923 
13924 
13925 #ifdef CONFIG_FST
13926 
13927 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
13928 					     char *cmd, char *buf,
13929 					     size_t reply_size)
13930 {
13931 	char ifname[IFNAMSIZ + 1];
13932 	struct fst_iface_cfg cfg;
13933 	struct wpa_supplicant *wpa_s;
13934 	struct fst_wpa_obj iface_obj;
13935 
13936 	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
13937 		wpa_s = wpa_supplicant_get_iface(global, ifname);
13938 		if (wpa_s) {
13939 			if (wpa_s->fst) {
13940 				wpa_printf(MSG_INFO, "FST: Already attached");
13941 				return -1;
13942 			}
13943 			fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
13944 			wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
13945 						&iface_obj, &cfg);
13946 			if (wpa_s->fst)
13947 				return os_snprintf(buf, reply_size, "OK\n");
13948 		}
13949 	}
13950 
13951 	return -1;
13952 }
13953 
13954 
13955 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
13956 					     char *cmd, char *buf,
13957 					     size_t reply_size)
13958 {
13959 	char ifname[IFNAMSIZ + 1];
13960 	struct wpa_supplicant *wpa_s;
13961 
13962 	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
13963 		wpa_s = wpa_supplicant_get_iface(global, ifname);
13964 		if (wpa_s) {
13965 			if (!fst_iface_detach(ifname)) {
13966 				wpa_s->fst = NULL;
13967 				return os_snprintf(buf, reply_size, "OK\n");
13968 			}
13969 		}
13970 	}
13971 
13972 	return -1;
13973 }
13974 
13975 #endif /* CONFIG_FST */
13976 
13977 
13978 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
13979 						char *buf, size_t *resp_len)
13980 {
13981 	char *reply;
13982 	const int reply_size = 2048;
13983 	int reply_len;
13984 	int level = MSG_DEBUG;
13985 
13986 	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
13987 		char *pos = os_strchr(buf + 7, ' ');
13988 		if (pos) {
13989 			*pos++ = '\0';
13990 			return wpas_global_ctrl_iface_ifname(global,
13991 							     buf + 7, pos,
13992 							     resp_len);
13993 		}
13994 	}
13995 
13996 	reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
13997 	if (reply)
13998 		return reply;
13999 
14000 	if (os_strcmp(buf, "PING") == 0)
14001 		level = MSG_EXCESSIVE;
14002 	wpa_hexdump_ascii(level, "RX global ctrl_iface",
14003 			  (const u8 *) buf, os_strlen(buf));
14004 
14005 	reply = os_malloc(reply_size);
14006 	if (reply == NULL) {
14007 		*resp_len = 1;
14008 		return NULL;
14009 	}
14010 
14011 	os_memcpy(reply, "OK\n", 3);
14012 	reply_len = 3;
14013 
14014 	if (os_strcmp(buf, "PING") == 0) {
14015 		os_memcpy(reply, "PONG\n", 5);
14016 		reply_len = 5;
14017 	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
14018 		if (wpa_supplicant_global_iface_add(global, buf + 14))
14019 			reply_len = -1;
14020 	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
14021 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
14022 			reply_len = -1;
14023 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
14024 		reply_len = wpa_supplicant_global_iface_list(
14025 			global, reply, reply_size);
14026 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
14027 		reply_len = wpa_supplicant_global_iface_interfaces(
14028 			global, buf + 10, reply, reply_size);
14029 #ifdef CONFIG_FST
14030 	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
14031 		reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
14032 							      reply,
14033 							      reply_size);
14034 	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
14035 		reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
14036 							      reply,
14037 							      reply_size);
14038 	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
14039 		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
14040 #endif /* CONFIG_FST */
14041 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
14042 		wpa_supplicant_terminate_proc(global);
14043 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
14044 		wpas_notify_suspend(global);
14045 	} else if (os_strcmp(buf, "RESUME") == 0) {
14046 		wpas_notify_resume(global);
14047 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
14048 		if (wpas_global_ctrl_iface_set(global, buf + 4)) {
14049 #ifdef CONFIG_P2P
14050 			if (global->p2p_init_wpa_s) {
14051 				os_free(reply);
14052 				/* Check if P2P redirection would work for this
14053 				 * command. */
14054 				return wpa_supplicant_ctrl_iface_process(
14055 					global->p2p_init_wpa_s,
14056 					buf, resp_len);
14057 			}
14058 #endif /* CONFIG_P2P */
14059 			reply_len = -1;
14060 		}
14061 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
14062 		if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
14063 			reply_len = -1;
14064 #ifndef CONFIG_NO_CONFIG_WRITE
14065 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
14066 		if (wpas_global_ctrl_iface_save_config(global))
14067 			reply_len = -1;
14068 #endif /* CONFIG_NO_CONFIG_WRITE */
14069 	} else if (os_strcmp(buf, "STATUS") == 0) {
14070 		reply_len = wpas_global_ctrl_iface_status(global, reply,
14071 							  reply_size);
14072 #ifdef CONFIG_MODULE_TESTS
14073 	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
14074 		if (wpas_module_tests() < 0)
14075 			reply_len = -1;
14076 #endif /* CONFIG_MODULE_TESTS */
14077 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
14078 		if (wpa_debug_reopen_file() < 0)
14079 			reply_len = -1;
14080 	} else {
14081 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
14082 		reply_len = 16;
14083 	}
14084 
14085 	if (reply_len < 0) {
14086 		os_memcpy(reply, "FAIL\n", 5);
14087 		reply_len = 5;
14088 	}
14089 
14090 	*resp_len = reply_len;
14091 	return reply;
14092 }
14093 #endif /* EXT_CODE_CROP */