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