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