1  /*
2   * WPA Supplicant / Control interface (shared code for all backends)
3   * Copyright (c) 2004-2024, 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/nan_de.h"
26  #include "common/ptksa_cache.h"
27  #include "crypto/tls.h"
28  #include "ap/hostapd.h"
29  #include "eap_peer/eap.h"
30  #include "eapol_supp/eapol_supp_sm.h"
31  #include "rsn_supp/wpa.h"
32  #include "rsn_supp/preauth.h"
33  #include "rsn_supp/pmksa_cache.h"
34  #include "l2_packet/l2_packet.h"
35  #include "wps/wps.h"
36  #include "fst/fst.h"
37  #include "fst/fst_ctrl_iface.h"
38  #include "config.h"
39  #include "wpa_supplicant_i.h"
40  #include "driver_i.h"
41  #include "wps_supplicant.h"
42  #include "ibss_rsn.h"
43  #include "wpas_glue.h"
44  #include "ap.h"
45  #include "p2p_supplicant.h"
46  #include "p2p/p2p.h"
47  #include "hs20_supplicant.h"
48  #include "wifi_display.h"
49  #include "notify.h"
50  #include "bss.h"
51  #include "scan.h"
52  #include "ctrl_iface.h"
53  #include "interworking.h"
54  #include "bssid_ignore.h"
55  #include "autoscan.h"
56  #include "wnm_sta.h"
57  #include "offchannel.h"
58  #include "drivers/driver.h"
59  #include "mesh.h"
60  #include "dpp_supplicant.h"
61  #include "sme.h"
62  #include "nan_usd.h"
63  
64  #ifdef __NetBSD__
65  #include <net/if_ether.h>
66  #elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS)
67  #include <net/ethernet.h>
68  #endif
69  
70  static int wpa_supplicant_global_iface_list(struct wpa_global *global,
71  					    char *buf, int len);
72  static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
73  						  const char *input,
74  						  char *buf, int len);
75  static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
76  					char *val);
77  
78  
set_bssid_filter(struct wpa_supplicant * wpa_s,char * val)79  static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
80  {
81  	char *pos;
82  	u8 addr[ETH_ALEN], *filter = NULL, *n;
83  	size_t count = 0;
84  
85  	pos = val;
86  	while (pos) {
87  		if (*pos == '\0')
88  			break;
89  		if (hwaddr_aton(pos, addr)) {
90  			os_free(filter);
91  			return -1;
92  		}
93  		n = os_realloc_array(filter, count + 1, ETH_ALEN);
94  		if (n == NULL) {
95  			os_free(filter);
96  			return -1;
97  		}
98  		filter = n;
99  		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
100  		count++;
101  
102  		pos = os_strchr(pos, ' ');
103  		if (pos)
104  			pos++;
105  	}
106  
107  	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
108  	os_free(wpa_s->bssid_filter);
109  	wpa_s->bssid_filter = filter;
110  	wpa_s->bssid_filter_count = count;
111  
112  	return 0;
113  }
114  
115  
set_disallow_aps(struct wpa_supplicant * wpa_s,char * val)116  static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
117  {
118  	char *pos;
119  	u8 addr[ETH_ALEN], *bssid = NULL, *n;
120  	struct wpa_ssid_value *ssid = NULL, *ns;
121  	size_t count = 0, ssid_count = 0;
122  	struct wpa_ssid *c;
123  
124  	/*
125  	 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
126  	 * SSID_SPEC ::= ssid <SSID_HEX>
127  	 * BSSID_SPEC ::= bssid <BSSID_HEX>
128  	 */
129  
130  	pos = val;
131  	while (pos) {
132  		if (*pos == '\0')
133  			break;
134  		if (os_strncmp(pos, "bssid ", 6) == 0) {
135  			int res;
136  			pos += 6;
137  			res = hwaddr_aton2(pos, addr);
138  			if (res < 0) {
139  				os_free(ssid);
140  				os_free(bssid);
141  				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
142  					   "BSSID value '%s'", pos);
143  				return -1;
144  			}
145  			pos += res;
146  			n = os_realloc_array(bssid, count + 1, ETH_ALEN);
147  			if (n == NULL) {
148  				os_free(ssid);
149  				os_free(bssid);
150  				return -1;
151  			}
152  			bssid = n;
153  			os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
154  			count++;
155  		} else if (os_strncmp(pos, "ssid ", 5) == 0) {
156  			char *end;
157  			pos += 5;
158  
159  			end = pos;
160  			while (*end) {
161  				if (*end == '\0' || *end == ' ')
162  					break;
163  				end++;
164  			}
165  
166  			ns = os_realloc_array(ssid, ssid_count + 1,
167  					      sizeof(struct wpa_ssid_value));
168  			if (ns == NULL) {
169  				os_free(ssid);
170  				os_free(bssid);
171  				return -1;
172  			}
173  			ssid = ns;
174  
175  			if ((end - pos) & 0x01 ||
176  			    end - pos > 2 * SSID_MAX_LEN ||
177  			    hexstr2bin(pos, ssid[ssid_count].ssid,
178  				       (end - pos) / 2) < 0) {
179  				os_free(ssid);
180  				os_free(bssid);
181  				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
182  					   "SSID value '%s'", pos);
183  				return -1;
184  			}
185  			ssid[ssid_count].ssid_len = (end - pos) / 2;
186  			wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
187  					  ssid[ssid_count].ssid,
188  					  ssid[ssid_count].ssid_len);
189  			ssid_count++;
190  			pos = end;
191  		} else {
192  			wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
193  				   "'%s'", pos);
194  			os_free(ssid);
195  			os_free(bssid);
196  			return -1;
197  		}
198  
199  		pos = os_strchr(pos, ' ');
200  		if (pos)
201  			pos++;
202  	}
203  
204  	wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
205  	os_free(wpa_s->disallow_aps_bssid);
206  	wpa_s->disallow_aps_bssid = bssid;
207  	wpa_s->disallow_aps_bssid_count = count;
208  
209  	wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
210  	os_free(wpa_s->disallow_aps_ssid);
211  	wpa_s->disallow_aps_ssid = ssid;
212  	wpa_s->disallow_aps_ssid_count = ssid_count;
213  
214  	if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
215  		return 0;
216  
217  	c = wpa_s->current_ssid;
218  	if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
219  		return 0;
220  
221  	if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
222  	    !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
223  		return 0;
224  
225  	wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
226  		   "because current AP was marked disallowed");
227  
228  #ifdef CONFIG_SME
229  	wpa_s->sme.prev_bssid_set = 0;
230  #endif /* CONFIG_SME */
231  	wpa_s->reassociate = 1;
232  	wpa_s->own_disconnect_req = 1;
233  	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
234  	wpa_supplicant_req_scan(wpa_s, 0, 0);
235  
236  	return 0;
237  }
238  
239  
240  #ifndef CONFIG_NO_CONFIG_BLOBS
wpas_ctrl_set_blob(struct wpa_supplicant * wpa_s,char * pos)241  static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
242  {
243  	char *name = pos;
244  	struct wpa_config_blob *blob;
245  	size_t len;
246  
247  	pos = os_strchr(pos, ' ');
248  	if (pos == NULL)
249  		return -1;
250  	*pos++ = '\0';
251  	len = os_strlen(pos);
252  	if (len & 1)
253  		return -1;
254  
255  	wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
256  	blob = os_zalloc(sizeof(*blob));
257  	if (blob == NULL)
258  		return -1;
259  	blob->name = os_strdup(name);
260  	blob->data = os_malloc(len / 2);
261  	if (blob->name == NULL || blob->data == NULL) {
262  		wpa_config_free_blob(blob);
263  		return -1;
264  	}
265  
266  	if (hexstr2bin(pos, blob->data, len / 2) < 0) {
267  		wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
268  		wpa_config_free_blob(blob);
269  		return -1;
270  	}
271  	blob->len = len / 2;
272  
273  	wpa_config_set_blob(wpa_s->conf, blob);
274  
275  	return 0;
276  }
277  #endif /* CONFIG_NO_CONFIG_BLOBS */
278  
279  
wpas_ctrl_pno(struct wpa_supplicant * wpa_s,char * cmd)280  static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
281  {
282  	char *params;
283  	char *pos;
284  	int *freqs = NULL;
285  	int ret;
286  
287  	if (atoi(cmd)) {
288  		params = os_strchr(cmd, ' ');
289  		os_free(wpa_s->manual_sched_scan_freqs);
290  		if (params) {
291  			params++;
292  			pos = os_strstr(params, "freq=");
293  			if (pos)
294  				freqs = freq_range_to_channel_list(wpa_s,
295  								   pos + 5);
296  		}
297  		wpa_s->manual_sched_scan_freqs = freqs;
298  		ret = wpas_start_pno(wpa_s);
299  	} else {
300  		ret = wpas_stop_pno(wpa_s);
301  	}
302  	return ret;
303  }
304  
305  
wpas_ctrl_set_band(struct wpa_supplicant * wpa_s,char * bands)306  static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
307  {
308  	union wpa_event_data event;
309  	u32 setband_mask = WPA_SETBAND_AUTO;
310  
311  	/*
312  	 * For example:
313  	 *  SET setband 2G,6G
314  	 *  SET setband 5G
315  	 *  SET setband AUTO
316  	 */
317  	if (!os_strstr(bands, "AUTO")) {
318  		if (os_strstr(bands, "5G"))
319  			setband_mask |= WPA_SETBAND_5G;
320  		if (os_strstr(bands, "6G"))
321  			setband_mask |= WPA_SETBAND_6G;
322  		if (os_strstr(bands, "2G"))
323  			setband_mask |= WPA_SETBAND_2G;
324  		if (setband_mask == WPA_SETBAND_AUTO)
325  			return -1;
326  	}
327  
328  	wpa_s->setband_mask = setband_mask;
329  	if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
330  		os_memset(&event, 0, sizeof(event));
331  		event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
332  		event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
333  		wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
334  	}
335  
336  	return 0;
337  }
338  
339  
wpas_ctrl_iface_set_lci(struct wpa_supplicant * wpa_s,const char * cmd)340  static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
341  				   const char *cmd)
342  {
343  	struct wpabuf *lci;
344  
345  	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
346  		wpabuf_free(wpa_s->lci);
347  		wpa_s->lci = NULL;
348  		return 0;
349  	}
350  
351  	lci = wpabuf_parse_bin(cmd);
352  	if (!lci)
353  		return -1;
354  
355  	if (os_get_reltime(&wpa_s->lci_time)) {
356  		wpabuf_free(lci);
357  		return -1;
358  	}
359  
360  	wpabuf_free(wpa_s->lci);
361  	wpa_s->lci = lci;
362  
363  	return 0;
364  }
365  
366  
367  static int
wpas_ctrl_set_relative_rssi(struct wpa_supplicant * wpa_s,const char * cmd)368  wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
369  {
370  	int relative_rssi;
371  
372  	if (os_strcmp(cmd, "disable") == 0) {
373  		wpa_s->srp.relative_rssi_set = 0;
374  		return 0;
375  	}
376  
377  	relative_rssi = atoi(cmd);
378  	if (relative_rssi < 0 || relative_rssi > 100)
379  		return -1;
380  	wpa_s->srp.relative_rssi = relative_rssi;
381  	wpa_s->srp.relative_rssi_set = 1;
382  	return 0;
383  }
384  
385  
wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant * wpa_s,const char * cmd)386  static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
387  					      const char *cmd)
388  {
389  	char *pos;
390  	int adjust_rssi;
391  
392  	/* <band>:adjust_value */
393  	pos = os_strchr(cmd, ':');
394  	if (!pos)
395  		return -1;
396  	pos++;
397  	adjust_rssi = atoi(pos);
398  	if (adjust_rssi < -100 || adjust_rssi > 100)
399  		return -1;
400  
401  	if (os_strncmp(cmd, "2G", 2) == 0)
402  		wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
403  	else if (os_strncmp(cmd, "5G", 2) == 0)
404  		wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
405  	else
406  		return -1;
407  
408  	wpa_s->srp.relative_adjust_rssi = adjust_rssi;
409  
410  	return 0;
411  }
412  
413  
wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant * wpa_s,const char * cmd)414  static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
415  				   const char *cmd)
416  {
417  	struct wpabuf *ric_ies;
418  
419  	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
420  		wpabuf_free(wpa_s->ric_ies);
421  		wpa_s->ric_ies = NULL;
422  		return 0;
423  	}
424  
425  	ric_ies = wpabuf_parse_bin(cmd);
426  	if (!ric_ies)
427  		return -1;
428  
429  	wpabuf_free(wpa_s->ric_ies);
430  	wpa_s->ric_ies = ric_ies;
431  
432  	return 0;
433  }
434  
435  
436  #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_iface_set_dso(struct wpa_supplicant * wpa_s,const char * val)437  static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
438  				   const char *val)
439  {
440  	u8 bssid[ETH_ALEN];
441  	const char *pos = val;
442  	struct driver_signal_override *dso = NULL, *tmp, parsed;
443  
444  	if (hwaddr_aton(pos, bssid))
445  		return -1;
446  	pos = os_strchr(pos, ' ');
447  
448  	dl_list_for_each(tmp, &wpa_s->drv_signal_override,
449  			 struct driver_signal_override, list) {
450  		if (ether_addr_equal(bssid, tmp->bssid)) {
451  			dso = tmp;
452  			break;
453  		}
454  	}
455  
456  	if (!pos) {
457  		/* Remove existing entry */
458  		if (dso) {
459  			dl_list_del(&dso->list);
460  			os_free(dso);
461  		}
462  		return 0;
463  	}
464  	pos++;
465  
466  	/* Update an existing entry or add a new one */
467  	os_memset(&parsed, 0, sizeof(parsed));
468  	if (sscanf(pos, "%d %d %d %d %d",
469  		   &parsed.si_current_signal,
470  		   &parsed.si_avg_signal,
471  		   &parsed.si_avg_beacon_signal,
472  		   &parsed.si_current_noise,
473  		   &parsed.scan_level) != 5)
474  		return -1;
475  
476  	if (!dso) {
477  		dso = os_zalloc(sizeof(*dso));
478  		if (!dso)
479  			return -1;
480  		os_memcpy(dso->bssid, bssid, ETH_ALEN);
481  		dl_list_add(&wpa_s->drv_signal_override, &dso->list);
482  	}
483  	dso->si_current_signal = parsed.si_current_signal;
484  	dso->si_avg_signal = parsed.si_avg_signal;
485  	dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
486  	dso->si_current_noise = parsed.si_current_noise;
487  	dso->scan_level = parsed.scan_level;
488  
489  	return 0;
490  }
491  #endif /* CONFIG_TESTING_OPTIONS */
492  
493  
wpa_supplicant_ctrl_iface_set(struct wpa_supplicant * wpa_s,char * cmd)494  static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
495  					 char *cmd)
496  {
497  	char *value;
498  	int ret = 0;
499  
500  	value = os_strchr(cmd, ' ');
501  	if (value == NULL)
502  		return -1;
503  	*value++ = '\0';
504  
505  	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
506  	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
507  		eapol_sm_configure(wpa_s->eapol,
508  				   atoi(value), -1, -1, -1);
509  	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
510  		eapol_sm_configure(wpa_s->eapol,
511  				   -1, atoi(value), -1, -1);
512  	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
513  		eapol_sm_configure(wpa_s->eapol,
514  				   -1, -1, atoi(value), -1);
515  	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
516  		eapol_sm_configure(wpa_s->eapol,
517  				   -1, -1, -1, atoi(value));
518  #ifdef CONFIG_TESTING_OPTIONS
519  	} else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
520  		if (os_strcmp(value, "Auto") == 0)
521  			eapol_sm_notify_portControl(wpa_s->eapol, Auto);
522  		else if (os_strcmp(value, "ForceUnauthorized") == 0)
523  			eapol_sm_notify_portControl(wpa_s->eapol,
524  						    ForceUnauthorized);
525  		else if (os_strcmp(value, "ForceAuthorized") == 0)
526  			eapol_sm_notify_portControl(wpa_s->eapol,
527  						    ForceAuthorized);
528  		else
529  			ret = -1;
530  #endif /* CONFIG_TESTING_OPTIONS */
531  	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
532  		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
533  				     atoi(value))) {
534  			ret = -1;
535  		} else {
536  			value[-1] = '=';
537  			wpa_config_process_global(wpa_s->conf, cmd, -1);
538  		}
539  	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
540  		   0) {
541  		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
542  				     atoi(value))) {
543  			ret = -1;
544  		} else {
545  			value[-1] = '=';
546  			wpa_config_process_global(wpa_s->conf, cmd, -1);
547  		}
548  	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
549  		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
550  				     atoi(value))) {
551  			ret = -1;
552  		} else {
553  			value[-1] = '=';
554  			wpa_config_process_global(wpa_s->conf, cmd, -1);
555  		}
556  	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
557  		wpa_s->wps_fragment_size = atoi(value);
558  #ifdef CONFIG_WPS_TESTING
559  	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
560  		long int val;
561  		val = strtol(value, NULL, 0);
562  		if (val < 0 || val > 0xff) {
563  			ret = -1;
564  			wpa_printf(MSG_DEBUG, "WPS: Invalid "
565  				   "wps_version_number %ld", val);
566  		} else {
567  			wps_version_number = val;
568  			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
569  				   "version %u.%u",
570  				   (wps_version_number & 0xf0) >> 4,
571  				   wps_version_number & 0x0f);
572  		}
573  	} else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
574  		wps_testing_stub_cred = atoi(value);
575  		wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
576  			   wps_testing_stub_cred);
577  	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
578  		wps_corrupt_pkhash = atoi(value);
579  		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
580  			   wps_corrupt_pkhash);
581  	} else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
582  		if (value[0] == '\0') {
583  			wps_force_auth_types_in_use = 0;
584  		} else {
585  			wps_force_auth_types = strtol(value, NULL, 0);
586  			wps_force_auth_types_in_use = 1;
587  		}
588  	} else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
589  		if (value[0] == '\0') {
590  			wps_force_encr_types_in_use = 0;
591  		} else {
592  			wps_force_encr_types = strtol(value, NULL, 0);
593  			wps_force_encr_types_in_use = 1;
594  		}
595  #endif /* CONFIG_WPS_TESTING */
596  	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
597  		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
598  			ret = -1;
599  #ifdef CONFIG_TDLS
600  #ifdef CONFIG_TDLS_TESTING
601  	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
602  		tdls_testing = strtol(value, NULL, 0);
603  		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
604  #endif /* CONFIG_TDLS_TESTING */
605  	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
606  		int disabled = atoi(value);
607  		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
608  		if (disabled) {
609  			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
610  				ret = -1;
611  		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
612  			ret = -1;
613  		wpa_tdls_enable(wpa_s->wpa, !disabled);
614  #endif /* CONFIG_TDLS */
615  	} else if (os_strcasecmp(cmd, "pno") == 0) {
616  		ret = wpas_ctrl_pno(wpa_s, value);
617  	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
618  		int disabled = atoi(value);
619  		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
620  			ret = -1;
621  		else if (disabled)
622  			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
623  	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
624  		if (os_strcmp(value, "disable") == 0)
625  			wpa_s->set_sta_uapsd = 0;
626  		else {
627  			int be, bk, vi, vo;
628  			char *pos;
629  			/* format: BE,BK,VI,VO;max SP Length */
630  			be = atoi(value);
631  			pos = os_strchr(value, ',');
632  			if (pos == NULL)
633  				return -1;
634  			pos++;
635  			bk = atoi(pos);
636  			pos = os_strchr(pos, ',');
637  			if (pos == NULL)
638  				return -1;
639  			pos++;
640  			vi = atoi(pos);
641  			pos = os_strchr(pos, ',');
642  			if (pos == NULL)
643  				return -1;
644  			pos++;
645  			vo = atoi(pos);
646  			/* ignore max SP Length for now */
647  
648  			wpa_s->set_sta_uapsd = 1;
649  			wpa_s->sta_uapsd = 0;
650  			if (be)
651  				wpa_s->sta_uapsd |= BIT(0);
652  			if (bk)
653  				wpa_s->sta_uapsd |= BIT(1);
654  			if (vi)
655  				wpa_s->sta_uapsd |= BIT(2);
656  			if (vo)
657  				wpa_s->sta_uapsd |= BIT(3);
658  		}
659  	} else if (os_strcasecmp(cmd, "ps") == 0) {
660  		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
661  #ifdef CONFIG_WIFI_DISPLAY
662  	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
663  		int enabled = !!atoi(value);
664  		if (enabled && !wpa_s->global->p2p)
665  			ret = -1;
666  		else
667  			wifi_display_enable(wpa_s->global, enabled);
668  #endif /* CONFIG_WIFI_DISPLAY */
669  	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
670  		ret = set_bssid_filter(wpa_s, value);
671  	} else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
672  		ret = set_disallow_aps(wpa_s, value);
673  	} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
674  		wpa_s->no_keep_alive = !!atoi(value);
675  #ifdef CONFIG_DPP
676  	} else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
677  		os_free(wpa_s->dpp_configurator_params);
678  		wpa_s->dpp_configurator_params = os_strdup(value);
679  #ifdef CONFIG_DPP2
680  		dpp_controller_set_params(wpa_s->dpp, value);
681  #endif /* CONFIG_DPP2 */
682  	} else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
683  		wpa_s->dpp_init_max_tries = atoi(value);
684  	} else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
685  		wpa_s->dpp_init_retry_time = atoi(value);
686  	} else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
687  		wpa_s->dpp_resp_wait_time = atoi(value);
688  	} else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
689  		wpa_s->dpp_resp_max_tries = atoi(value);
690  	} else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
691  		wpa_s->dpp_resp_retry_time = atoi(value);
692  #ifdef CONFIG_TESTING_OPTIONS
693  	} else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
694  		if (hwaddr_aton(value, dpp_pkex_own_mac_override))
695  			ret = -1;
696  	} else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
697  		if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
698  			ret = -1;
699  	} else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
700  		size_t hex_len = os_strlen(value);
701  
702  		if (hex_len >
703  		    2 * sizeof(dpp_pkex_ephemeral_key_override))
704  			ret = -1;
705  		else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
706  				    hex_len / 2))
707  			ret = -1;
708  		else
709  			dpp_pkex_ephemeral_key_override_len = hex_len / 2;
710  	} else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
711  		size_t hex_len = os_strlen(value);
712  
713  		if (hex_len > 2 * sizeof(dpp_protocol_key_override))
714  			ret = -1;
715  		else if (hexstr2bin(value, dpp_protocol_key_override,
716  				    hex_len / 2))
717  			ret = -1;
718  		else
719  			dpp_protocol_key_override_len = hex_len / 2;
720  	} else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
721  		size_t hex_len = os_strlen(value);
722  
723  		if (hex_len > 2 * sizeof(dpp_nonce_override))
724  			ret = -1;
725  		else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
726  			ret = -1;
727  		else
728  			dpp_nonce_override_len = hex_len / 2;
729  	} else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
730  		dpp_version_override = atoi(value);
731  #endif /* CONFIG_TESTING_OPTIONS */
732  #endif /* CONFIG_DPP */
733  #ifdef CONFIG_TESTING_OPTIONS
734  	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
735  		wpa_s->ext_mgmt_frame_handling = !!atoi(value);
736  	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
737  		wpa_s->ext_eapol_frame_io = !!atoi(value);
738  #ifdef CONFIG_AP
739  		if (wpa_s->ap_iface) {
740  			wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
741  				wpa_s->ext_eapol_frame_io;
742  		}
743  #endif /* CONFIG_AP */
744  	} else if (os_strcasecmp(cmd, "encrypt_eapol_m2") == 0) {
745  		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2,
746  				 !!atoi(value));
747  	} else if (os_strcasecmp(cmd, "encrypt_eapol_m4") == 0) {
748  		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4,
749  				 !!atoi(value));
750  	} else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
751  		wpa_s->extra_roc_dur = atoi(value);
752  	} else if (os_strcasecmp(cmd, "test_failure") == 0) {
753  		wpa_s->test_failure = atoi(value);
754  	} else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
755  		wpa_s->p2p_go_csa_on_inv = !!atoi(value);
756  	} else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
757  		wpa_s->ignore_auth_resp = !!atoi(value);
758  	} else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
759  		wpa_s->ignore_assoc_disallow = !!atoi(value);
760  		wpa_drv_ignore_assoc_disallow(wpa_s,
761  					      wpa_s->ignore_assoc_disallow);
762  	} else if (os_strcasecmp(cmd, "disable_sa_query") == 0) {
763  		wpa_s->disable_sa_query = !!atoi(value);
764  	} else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
765  		wpa_s->ignore_sae_h2e_only = !!atoi(value);
766  	} else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
767  		char *pos;
768  
769  		os_free(wpa_s->extra_sae_rejected_groups);
770  		wpa_s->extra_sae_rejected_groups = NULL;
771  		pos = value;
772  		while (pos && pos[0]) {
773  			int group;
774  
775  			group = atoi(pos);
776  			wpa_printf(MSG_DEBUG,
777  				   "TESTING: Extra rejection of SAE group %d",
778  				   group);
779  			if (group)
780  				int_array_add_unique(
781  					&wpa_s->extra_sae_rejected_groups,
782  					group);
783  			pos = os_strchr(pos, ' ');
784  			if (!pos)
785  				break;
786  			pos++;
787  		}
788  	} else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) {
789  		wpa_s->ft_rsnxe_used = atoi(value);
790  	} else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) {
791  		wpa_s->oci_freq_override_eapol = atoi(value);
792  	} else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) {
793  		wpa_s->oci_freq_override_saquery_req = atoi(value);
794  	} else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) {
795  		wpa_s->oci_freq_override_saquery_resp = atoi(value);
796  	} else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) {
797  		wpa_s->oci_freq_override_eapol_g2 = atoi(value);
798  		/* Populate value to wpa_sm if already associated. */
799  		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
800  				 wpa_s->oci_freq_override_eapol_g2);
801  	} else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) {
802  		wpa_s->oci_freq_override_ft_assoc = atoi(value);
803  		/* Populate value to wpa_sm if already associated. */
804  		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
805  				 wpa_s->oci_freq_override_ft_assoc);
806  	} else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) {
807  		wpa_s->oci_freq_override_fils_assoc = atoi(value);
808  	} else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) {
809  		wpa_s->oci_freq_override_wnm_sleep = atoi(value);
810  	} else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) {
811  		wpabuf_free(wpa_s->rsne_override_eapol);
812  		if (os_strcmp(value, "NULL") == 0)
813  			wpa_s->rsne_override_eapol = NULL;
814  		else
815  			wpa_s->rsne_override_eapol = wpabuf_parse_bin(value);
816  	} else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
817  		wpabuf_free(wpa_s->rsnxe_override_assoc);
818  		if (os_strcmp(value, "NULL") == 0)
819  			wpa_s->rsnxe_override_assoc = NULL;
820  		else
821  			wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
822  	} else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
823  		wpabuf_free(wpa_s->rsnxe_override_eapol);
824  		if (os_strcmp(value, "NULL") == 0)
825  			wpa_s->rsnxe_override_eapol = NULL;
826  		else
827  			wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
828  	} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
829  		wpa_s->reject_btm_req_reason = atoi(value);
830  	} else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
831  		os_free(wpa_s->get_pref_freq_list_override);
832  		if (!value[0])
833  			wpa_s->get_pref_freq_list_override = NULL;
834  		else
835  			wpa_s->get_pref_freq_list_override = os_strdup(value);
836  	} else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
837  		wpabuf_free(wpa_s->sae_commit_override);
838  		if (value[0] == '\0')
839  			wpa_s->sae_commit_override = NULL;
840  		else
841  			wpa_s->sae_commit_override = wpabuf_parse_bin(value);
842  	} else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
843  		ret = wpas_ctrl_iface_set_dso(wpa_s, value);
844  #ifndef CONFIG_NO_ROBUST_AV
845  	} else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
846  		wpa_s->disable_scs_support = !!atoi(value);
847  	} else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
848  		wpa_s->disable_mscs_support = !!atoi(value);
849  #endif /* CONFIG_NO_ROBUST_AV */
850  	} else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) {
851  		wpa_s->disable_eapol_g2_tx = !!atoi(value);
852  		/* Populate value to wpa_sm if already associated. */
853  		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
854  				 wpa_s->disable_eapol_g2_tx);
855  	} else if (os_strcasecmp(cmd, "test_assoc_comeback_type") == 0) {
856  		wpa_s->test_assoc_comeback_type = atoi(value);
857  #ifdef CONFIG_DPP
858  	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
859  		os_free(wpa_s->dpp_config_obj_override);
860  		if (value[0] == '\0')
861  			wpa_s->dpp_config_obj_override = NULL;
862  		else
863  			wpa_s->dpp_config_obj_override = os_strdup(value);
864  	} else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
865  		os_free(wpa_s->dpp_discovery_override);
866  		if (value[0] == '\0')
867  			wpa_s->dpp_discovery_override = NULL;
868  		else
869  			wpa_s->dpp_discovery_override = os_strdup(value);
870  	} else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
871  		os_free(wpa_s->dpp_groups_override);
872  		if (value[0] == '\0')
873  			wpa_s->dpp_groups_override = NULL;
874  		else
875  			wpa_s->dpp_groups_override = os_strdup(value);
876  	} else if (os_strcasecmp(cmd,
877  				 "dpp_ignore_netaccesskey_mismatch") == 0) {
878  		wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
879  	} else if (os_strcasecmp(cmd, "dpp_discard_public_action") == 0) {
880  		wpa_s->dpp_discard_public_action = atoi(value);
881  	} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
882  		dpp_test = atoi(value);
883  #endif /* CONFIG_DPP */
884  	} else if (os_strcasecmp(cmd, "eapol_2_key_info_set_mask") == 0) {
885  		wpa_s->eapol_2_key_info_set_mask = strtoul(value, NULL, 0x10);
886  #endif /* CONFIG_TESTING_OPTIONS */
887  #ifdef CONFIG_FILS
888  	} else if (os_strcasecmp(cmd, "disable_fils") == 0) {
889  		wpa_s->disable_fils = !!atoi(value);
890  		wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
891  		wpa_supplicant_set_default_scan_ies(wpa_s);
892  #endif /* CONFIG_FILS */
893  #ifndef CONFIG_NO_CONFIG_BLOBS
894  	} else if (os_strcmp(cmd, "blob") == 0) {
895  		ret = wpas_ctrl_set_blob(wpa_s, value);
896  #endif /* CONFIG_NO_CONFIG_BLOBS */
897  	} else if (os_strcasecmp(cmd, "setband") == 0) {
898  		ret = wpas_ctrl_set_band(wpa_s, value);
899  #ifdef CONFIG_MBO
900  	} else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
901  		ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
902  		if (ret == 0) {
903  			value[-1] = '=';
904  			wpa_config_process_global(wpa_s->conf, cmd, -1);
905  		}
906  	} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
907  		int val = atoi(value);
908  
909  		if (val < MBO_CELL_CAPA_AVAILABLE ||
910  		    val > MBO_CELL_CAPA_NOT_SUPPORTED)
911  			return -1;
912  
913  		wpas_mbo_update_cell_capa(wpa_s, val);
914  	} else if (os_strcasecmp(cmd, "oce") == 0) {
915  		int val = atoi(value);
916  
917  		if (val < 0 || val > 3)
918  			return -1;
919  
920  		wpa_s->conf->oce = val;
921  		if (wpa_s->conf->oce) {
922  			if ((wpa_s->conf->oce & OCE_STA) &&
923  			    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
924  				wpa_s->enable_oce = OCE_STA;
925  
926  			if ((wpa_s->conf->oce & OCE_STA_CFON) &&
927  			    (wpa_s->drv_flags &
928  			     WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
929  				/* TODO: Need to add STA-CFON support */
930  				wpa_printf(MSG_ERROR,
931  					   "OCE STA-CFON feature is not yet supported");
932  				return -1;
933  			}
934  		} else {
935  			wpa_s->enable_oce = 0;
936  		}
937  		wpa_supplicant_set_default_scan_ies(wpa_s);
938  #endif /* CONFIG_MBO */
939  	} else if (os_strcasecmp(cmd, "lci") == 0) {
940  		ret = wpas_ctrl_iface_set_lci(wpa_s, value);
941  	} else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
942  		ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
943  	} else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
944  		ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
945  	} else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
946  		ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
947  	} else if (os_strcasecmp(cmd, "ric_ies") == 0) {
948  		ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
949  	} else if (os_strcasecmp(cmd, "roaming") == 0) {
950  		ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
951  #ifdef CONFIG_WNM
952  	} else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
953  		struct wpabuf *elems;
954  
955  		elems = wpabuf_parse_bin(value);
956  		if (!elems)
957  			return -1;
958  		wnm_set_coloc_intf_elems(wpa_s, elems);
959  #endif /* CONFIG_WNM */
960  #ifndef CONFIG_NO_ROBUST_AV
961  	} else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
962  		wpa_s->enable_dscp_policy_capa = !!atoi(value);
963  #endif /* CONFIG_NO_ROBUST_AV */
964  	} else {
965  		value[-1] = '=';
966  		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
967  		if (ret == 0)
968  			wpa_supplicant_update_config(wpa_s);
969  		else if (ret == 1)
970  			ret = 0;
971  	}
972  
973  	return ret;
974  }
975  
976  
wpa_supplicant_ctrl_iface_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)977  static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
978  					 char *cmd, char *buf, size_t buflen)
979  {
980  	int res = -1;
981  
982  	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
983  
984  	if (os_strcmp(cmd, "version") == 0) {
985  		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
986  	} else if (os_strcasecmp(cmd, "max_command_len") == 0) {
987  		res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN);
988  	} else if (os_strcasecmp(cmd, "country") == 0) {
989  		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
990  			res = os_snprintf(buf, buflen, "%c%c",
991  					  wpa_s->conf->country[0],
992  					  wpa_s->conf->country[1]);
993  #ifdef CONFIG_WIFI_DISPLAY
994  	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
995  		int enabled;
996  		if (wpa_s->global->p2p == NULL ||
997  		    wpa_s->global->p2p_disabled)
998  			enabled = 0;
999  		else
1000  			enabled = wpa_s->global->wifi_display;
1001  		res = os_snprintf(buf, buflen, "%d", enabled);
1002  #endif /* CONFIG_WIFI_DISPLAY */
1003  #ifdef CONFIG_TESTING_GET_GTK
1004  	} else if (os_strcmp(cmd, "gtk") == 0) {
1005  		if (wpa_s->last_gtk_len == 0)
1006  			return -1;
1007  		res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
1008  				       wpa_s->last_gtk_len);
1009  		return res;
1010  #endif /* CONFIG_TESTING_GET_GTK */
1011  	} else if (os_strcmp(cmd, "tls_library") == 0) {
1012  		res = tls_get_library_version(buf, buflen);
1013  #ifdef CONFIG_TESTING_OPTIONS
1014  	} else if (os_strcmp(cmd, "anonce") == 0) {
1015  		return wpa_snprintf_hex(buf, buflen,
1016  					wpa_sm_get_anonce(wpa_s->wpa),
1017  					WPA_NONCE_LEN);
1018  	} else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
1019  		res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
1020  #endif /* CONFIG_TESTING_OPTIONS */
1021  	} else {
1022  		res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
1023  	}
1024  
1025  	if (os_snprintf_error(buflen, res))
1026  		return -1;
1027  	return res;
1028  }
1029  
1030  
1031  #ifdef IEEE8021X_EAPOL
wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant * wpa_s,char * addr)1032  static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
1033  					     char *addr)
1034  {
1035  	u8 bssid[ETH_ALEN];
1036  	struct wpa_ssid *ssid = wpa_s->current_ssid;
1037  
1038  	if (hwaddr_aton(addr, bssid)) {
1039  		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
1040  			   "'%s'", addr);
1041  		return -1;
1042  	}
1043  
1044  	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
1045  	rsn_preauth_deinit(wpa_s->wpa);
1046  	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
1047  		return -1;
1048  
1049  	return 0;
1050  }
1051  #endif /* IEEE8021X_EAPOL */
1052  
1053  
1054  #ifdef CONFIG_TDLS
1055  
wpa_supplicant_ctrl_iface_tdls_discover(struct wpa_supplicant * wpa_s,char * addr)1056  static int wpa_supplicant_ctrl_iface_tdls_discover(
1057  	struct wpa_supplicant *wpa_s, char *addr)
1058  {
1059  	u8 peer[ETH_ALEN];
1060  	int ret;
1061  
1062  	if (hwaddr_aton(addr, peer)) {
1063  		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
1064  			   "address '%s'", addr);
1065  		return -1;
1066  	}
1067  
1068  	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
1069  		   MAC2STR(peer));
1070  
1071  	if (wpa_tdls_is_external_setup(wpa_s->wpa))
1072  		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
1073  	else
1074  		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
1075  
1076  	return ret;
1077  }
1078  
1079  
wpa_supplicant_ctrl_iface_tdls_setup(struct wpa_supplicant * wpa_s,char * addr)1080  static int wpa_supplicant_ctrl_iface_tdls_setup(
1081  	struct wpa_supplicant *wpa_s, char *addr)
1082  {
1083  	u8 peer[ETH_ALEN];
1084  	int ret;
1085  
1086  	if (hwaddr_aton(addr, peer)) {
1087  		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
1088  			   "address '%s'", addr);
1089  		return -1;
1090  	}
1091  
1092  	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
1093  		   MAC2STR(peer));
1094  
1095  	if ((wpa_s->conf->tdls_external_control) &&
1096  	    wpa_tdls_is_external_setup(wpa_s->wpa))
1097  		return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1098  
1099  	wpa_tdls_remove(wpa_s->wpa, peer);
1100  
1101  	if (wpa_tdls_is_external_setup(wpa_s->wpa))
1102  		ret = wpa_tdls_start(wpa_s->wpa, peer);
1103  	else
1104  		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1105  
1106  	return ret;
1107  }
1108  
1109  
wpa_supplicant_ctrl_iface_tdls_teardown(struct wpa_supplicant * wpa_s,char * addr)1110  static int wpa_supplicant_ctrl_iface_tdls_teardown(
1111  	struct wpa_supplicant *wpa_s, char *addr)
1112  {
1113  	u8 peer[ETH_ALEN];
1114  	int ret;
1115  
1116  	if (os_strcmp(addr, "*") == 0) {
1117  		/* remove everyone */
1118  		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
1119  		wpa_tdls_teardown_peers(wpa_s->wpa);
1120  		return 0;
1121  	}
1122  
1123  	if (hwaddr_aton(addr, peer)) {
1124  		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
1125  			   "address '%s'", addr);
1126  		return -1;
1127  	}
1128  
1129  	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
1130  		   MAC2STR(peer));
1131  
1132  	if ((wpa_s->conf->tdls_external_control) &&
1133  	    wpa_tdls_is_external_setup(wpa_s->wpa))
1134  		return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1135  
1136  	if (wpa_tdls_is_external_setup(wpa_s->wpa))
1137  		ret = wpa_tdls_teardown_link(
1138  			wpa_s->wpa, peer,
1139  			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
1140  	else
1141  		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1142  
1143  	return ret;
1144  }
1145  
1146  
ctrl_iface_get_capability_tdls(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1147  static int ctrl_iface_get_capability_tdls(
1148  	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1149  {
1150  	int ret;
1151  
1152  	ret = os_snprintf(buf, buflen, "%s\n",
1153  			  wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
1154  			  (wpa_s->drv_flags &
1155  			   WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
1156  			   "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
1157  	if (os_snprintf_error(buflen, ret))
1158  		return -1;
1159  	return ret;
1160  }
1161  
1162  
wpa_supplicant_ctrl_iface_tdls_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1163  static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
1164  	struct wpa_supplicant *wpa_s, char *cmd)
1165  {
1166  	u8 peer[ETH_ALEN];
1167  	struct hostapd_freq_params freq_params;
1168  	u8 oper_class;
1169  	char *pos, *end;
1170  
1171  	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1172  		wpa_printf(MSG_INFO,
1173  			   "tdls_chanswitch: Only supported with external setup");
1174  		return -1;
1175  	}
1176  
1177  	os_memset(&freq_params, 0, sizeof(freq_params));
1178  
1179  	pos = os_strchr(cmd, ' ');
1180  	if (pos == NULL)
1181  		return -1;
1182  	*pos++ = '\0';
1183  
1184  	oper_class = strtol(pos, &end, 10);
1185  	if (pos == end) {
1186  		wpa_printf(MSG_INFO,
1187  			   "tdls_chanswitch: Invalid op class provided");
1188  		return -1;
1189  	}
1190  
1191  	pos = end;
1192  	freq_params.freq = atoi(pos);
1193  	if (freq_params.freq == 0) {
1194  		wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
1195  		return -1;
1196  	}
1197  
1198  #define SET_FREQ_SETTING(str) \
1199  	do { \
1200  		const char *pos2 = os_strstr(pos, " " #str "="); \
1201  		if (pos2) { \
1202  			pos2 += sizeof(" " #str "=") - 1; \
1203  			freq_params.str = atoi(pos2); \
1204  		} \
1205  	} while (0)
1206  
1207  	SET_FREQ_SETTING(center_freq1);
1208  	SET_FREQ_SETTING(center_freq2);
1209  	SET_FREQ_SETTING(bandwidth);
1210  	SET_FREQ_SETTING(sec_channel_offset);
1211  #undef SET_FREQ_SETTING
1212  
1213  	freq_params.ht_enabled = !!os_strstr(pos, " ht");
1214  	freq_params.vht_enabled = !!os_strstr(pos, " vht");
1215  
1216  	if (hwaddr_aton(cmd, peer)) {
1217  		wpa_printf(MSG_DEBUG,
1218  			   "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1219  			   cmd);
1220  		return -1;
1221  	}
1222  
1223  	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1224  		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1225  		   MAC2STR(peer), oper_class, freq_params.freq,
1226  		   freq_params.center_freq1, freq_params.center_freq2,
1227  		   freq_params.bandwidth, freq_params.sec_channel_offset,
1228  		   freq_params.ht_enabled ? " HT" : "",
1229  		   freq_params.vht_enabled ? " VHT" : "");
1230  
1231  	return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1232  					   &freq_params);
1233  }
1234  
1235  
wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1236  static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1237  	struct wpa_supplicant *wpa_s, char *cmd)
1238  {
1239  	u8 peer[ETH_ALEN];
1240  
1241  	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1242  		wpa_printf(MSG_INFO,
1243  			   "tdls_chanswitch: Only supported with external setup");
1244  		return -1;
1245  	}
1246  
1247  	if (hwaddr_aton(cmd, peer)) {
1248  		wpa_printf(MSG_DEBUG,
1249  			   "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1250  			   cmd);
1251  		return -1;
1252  	}
1253  
1254  	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1255  		   MAC2STR(peer));
1256  
1257  	return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1258  }
1259  
1260  
wpa_supplicant_ctrl_iface_tdls_link_status(struct wpa_supplicant * wpa_s,const char * addr,char * buf,size_t buflen)1261  static int wpa_supplicant_ctrl_iface_tdls_link_status(
1262  	struct wpa_supplicant *wpa_s, const char *addr,
1263  	char *buf, size_t buflen)
1264  {
1265  	u8 peer[ETH_ALEN];
1266  	const char *tdls_status;
1267  	int ret;
1268  
1269  	if (hwaddr_aton(addr, peer)) {
1270  		wpa_printf(MSG_DEBUG,
1271  			   "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1272  			   addr);
1273  		return -1;
1274  	}
1275  	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1276  		   MAC2STR(peer));
1277  
1278  	tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1279  	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1280  	ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1281  	if (os_snprintf_error(buflen, ret))
1282  		return -1;
1283  
1284  	return ret;
1285  }
1286  
1287  #endif /* CONFIG_TDLS */
1288  
1289  
1290  #ifndef CONFIG_NO_WMM_AC
1291  
wmm_ac_ctrl_addts(struct wpa_supplicant * wpa_s,char * cmd)1292  static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1293  {
1294  	char *token, *context = NULL;
1295  	struct wmm_ac_ts_setup_params params = {
1296  		.tsid = 0xff,
1297  		.direction = 0xff,
1298  	};
1299  
1300  	while ((token = str_token(cmd, " ", &context))) {
1301  		if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
1302  		    sscanf(token, "up=%i", &params.user_priority) == 1 ||
1303  		    sscanf(token, "nominal_msdu_size=%i",
1304  			   &params.nominal_msdu_size) == 1 ||
1305  		    sscanf(token, "mean_data_rate=%i",
1306  			   &params.mean_data_rate) == 1 ||
1307  		    sscanf(token, "min_phy_rate=%i",
1308  			   &params.minimum_phy_rate) == 1 ||
1309  		    sscanf(token, "sba=%i",
1310  			   &params.surplus_bandwidth_allowance) == 1)
1311  			continue;
1312  
1313  		if (os_strcasecmp(token, "downlink") == 0) {
1314  			params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1315  		} else if (os_strcasecmp(token, "uplink") == 0) {
1316  			params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1317  		} else if (os_strcasecmp(token, "bidi") == 0) {
1318  			params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1319  		} else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1320  			params.fixed_nominal_msdu = 1;
1321  		} else {
1322  			wpa_printf(MSG_DEBUG,
1323  				   "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1324  				   token);
1325  			return -1;
1326  		}
1327  
1328  	}
1329  
1330  	return wpas_wmm_ac_addts(wpa_s, &params);
1331  }
1332  
1333  
wmm_ac_ctrl_delts(struct wpa_supplicant * wpa_s,char * cmd)1334  static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1335  {
1336  	u8 tsid = atoi(cmd);
1337  
1338  	return wpas_wmm_ac_delts(wpa_s, tsid);
1339  }
1340  
1341  #endif /* CONFIG_NO_WMM_AC */
1342  
1343  
1344  #ifdef CONFIG_IEEE80211R
wpa_supplicant_ctrl_iface_ft_ds(struct wpa_supplicant * wpa_s,char * addr)1345  static int wpa_supplicant_ctrl_iface_ft_ds(
1346  	struct wpa_supplicant *wpa_s, char *addr)
1347  {
1348  	u8 target_ap[ETH_ALEN];
1349  	struct wpa_bss *bss;
1350  	const u8 *mdie;
1351  	bool force = os_strstr(addr, " force") != NULL;
1352  
1353  	if (hwaddr_aton(addr, target_ap)) {
1354  		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1355  			   "address '%s'", addr);
1356  		return -1;
1357  	}
1358  
1359  	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1360  
1361  	bss = wpa_bss_get_bssid(wpa_s, target_ap);
1362  	if (bss)
1363  		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1364  	else
1365  		mdie = NULL;
1366  
1367  	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie, force);
1368  }
1369  #endif /* CONFIG_IEEE80211R */
1370  
1371  
1372  #ifdef CONFIG_WPS
wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant * wpa_s,char * cmd)1373  static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1374  					     char *cmd)
1375  {
1376  	u8 bssid[ETH_ALEN], *_bssid = bssid;
1377  #ifdef CONFIG_P2P
1378  	u8 p2p_dev_addr[ETH_ALEN];
1379  #endif /* CONFIG_P2P */
1380  #ifdef CONFIG_AP
1381  	u8 *_p2p_dev_addr = NULL;
1382  #endif /* CONFIG_AP */
1383  	char *pos;
1384  	int multi_ap = 0;
1385  
1386  	if (!cmd || os_strcmp(cmd, "any") == 0 ||
1387  	    os_strncmp(cmd, "any ", 4) == 0) {
1388  		_bssid = NULL;
1389  #ifdef CONFIG_P2P
1390  	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1391  		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1392  			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1393  				   "P2P Device Address '%s'",
1394  				   cmd + 13);
1395  			return -1;
1396  		}
1397  		_p2p_dev_addr = p2p_dev_addr;
1398  #endif /* CONFIG_P2P */
1399  	} else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1400  		_bssid = NULL;
1401  		multi_ap = atoi(cmd + 9);
1402  	} else if (hwaddr_aton(cmd, bssid)) {
1403  		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1404  			   cmd);
1405  		return -1;
1406  	}
1407  
1408  	if (cmd) {
1409  		pos = os_strstr(cmd, " multi_ap=");
1410  		if (pos) {
1411  			pos += 10;
1412  			multi_ap = atoi(pos);
1413  		}
1414  	}
1415  
1416  #ifdef CONFIG_AP
1417  	if (wpa_s->ap_iface)
1418  		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1419  #endif /* CONFIG_AP */
1420  
1421  	return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
1422  }
1423  
1424  
wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1425  static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1426  					     char *cmd, char *buf,
1427  					     size_t buflen)
1428  {
1429  	u8 bssid[ETH_ALEN], *_bssid = bssid;
1430  	char *pin;
1431  	int ret;
1432  
1433  	pin = os_strchr(cmd, ' ');
1434  	if (pin)
1435  		*pin++ = '\0';
1436  
1437  	if (os_strcmp(cmd, "any") == 0)
1438  		_bssid = NULL;
1439  	else if (os_strcmp(cmd, "get") == 0) {
1440  		if (wps_generate_pin((unsigned int *) &ret) < 0)
1441  			return -1;
1442  		goto done;
1443  	} else if (hwaddr_aton(cmd, bssid)) {
1444  		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1445  			   cmd);
1446  		return -1;
1447  	}
1448  
1449  #ifdef CONFIG_AP
1450  	if (wpa_s->ap_iface) {
1451  		int timeout = 0;
1452  		char *pos;
1453  
1454  		if (pin) {
1455  			pos = os_strchr(pin, ' ');
1456  			if (pos) {
1457  				*pos++ = '\0';
1458  				timeout = atoi(pos);
1459  			}
1460  		}
1461  
1462  		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
1463  						 buf, buflen, timeout);
1464  	}
1465  #endif /* CONFIG_AP */
1466  
1467  	if (pin) {
1468  		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1469  					 DEV_PW_DEFAULT);
1470  		if (ret < 0)
1471  			return -1;
1472  		ret = os_snprintf(buf, buflen, "%s", pin);
1473  		if (os_snprintf_error(buflen, ret))
1474  			return -1;
1475  		return ret;
1476  	}
1477  
1478  	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1479  	if (ret < 0)
1480  		return -1;
1481  
1482  done:
1483  	/* Return the generated PIN */
1484  	ret = os_snprintf(buf, buflen, "%08d", ret);
1485  	if (os_snprintf_error(buflen, ret))
1486  		return -1;
1487  	return ret;
1488  }
1489  
1490  
wpa_supplicant_ctrl_iface_wps_check_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1491  static int wpa_supplicant_ctrl_iface_wps_check_pin(
1492  	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1493  {
1494  	char pin[9];
1495  	size_t len;
1496  	char *pos;
1497  	int ret;
1498  
1499  	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1500  			      (u8 *) cmd, os_strlen(cmd));
1501  	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1502  		if (*pos < '0' || *pos > '9')
1503  			continue;
1504  		pin[len++] = *pos;
1505  		if (len == 9) {
1506  			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1507  			return -1;
1508  		}
1509  	}
1510  	if (len != 4 && len != 8) {
1511  		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1512  		return -1;
1513  	}
1514  	pin[len] = '\0';
1515  
1516  	if (len == 8) {
1517  		unsigned int pin_val;
1518  		pin_val = atoi(pin);
1519  		if (!wps_pin_valid(pin_val)) {
1520  			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1521  			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
1522  			if (os_snprintf_error(buflen, ret))
1523  				return -1;
1524  			return ret;
1525  		}
1526  	}
1527  
1528  	ret = os_snprintf(buf, buflen, "%s", pin);
1529  	if (os_snprintf_error(buflen, ret))
1530  		return -1;
1531  
1532  	return ret;
1533  }
1534  
1535  
1536  #ifdef CONFIG_WPS_NFC
1537  
wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant * wpa_s,char * cmd)1538  static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1539  					     char *cmd)
1540  {
1541  	u8 bssid[ETH_ALEN], *_bssid = bssid;
1542  
1543  	if (cmd == NULL || cmd[0] == '\0')
1544  		_bssid = NULL;
1545  	else if (hwaddr_aton(cmd, bssid))
1546  		return -1;
1547  
1548  	return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1549  				  0, 0);
1550  }
1551  
1552  
wpa_supplicant_ctrl_iface_wps_nfc_config_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1553  static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1554  	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1555  {
1556  	int ndef;
1557  	struct wpabuf *buf;
1558  	int res;
1559  	char *pos;
1560  
1561  	pos = os_strchr(cmd, ' ');
1562  	if (pos)
1563  		*pos++ = '\0';
1564  	if (os_strcmp(cmd, "WPS") == 0)
1565  		ndef = 0;
1566  	else if (os_strcmp(cmd, "NDEF") == 0)
1567  		ndef = 1;
1568  	else
1569  		return -1;
1570  
1571  	buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
1572  	if (buf == NULL)
1573  		return -1;
1574  
1575  	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1576  					 wpabuf_len(buf));
1577  	reply[res++] = '\n';
1578  	reply[res] = '\0';
1579  
1580  	wpabuf_free(buf);
1581  
1582  	return res;
1583  }
1584  
1585  
wpa_supplicant_ctrl_iface_wps_nfc_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1586  static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1587  	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1588  {
1589  	int ndef;
1590  	struct wpabuf *buf;
1591  	int res;
1592  
1593  	if (os_strcmp(cmd, "WPS") == 0)
1594  		ndef = 0;
1595  	else if (os_strcmp(cmd, "NDEF") == 0)
1596  		ndef = 1;
1597  	else
1598  		return -1;
1599  
1600  	buf = wpas_wps_nfc_token(wpa_s, ndef);
1601  	if (buf == NULL)
1602  		return -1;
1603  
1604  	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1605  					 wpabuf_len(buf));
1606  	reply[res++] = '\n';
1607  	reply[res] = '\0';
1608  
1609  	wpabuf_free(buf);
1610  
1611  	return res;
1612  }
1613  
1614  
wpa_supplicant_ctrl_iface_wps_nfc_tag_read(struct wpa_supplicant * wpa_s,char * pos)1615  static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1616  	struct wpa_supplicant *wpa_s, char *pos)
1617  {
1618  	size_t len;
1619  	struct wpabuf *buf;
1620  	int ret;
1621  	char *freq;
1622  	int forced_freq = 0;
1623  
1624  	freq = strstr(pos, " freq=");
1625  	if (freq) {
1626  		*freq = '\0';
1627  		freq += 6;
1628  		forced_freq = atoi(freq);
1629  	}
1630  
1631  	len = os_strlen(pos);
1632  	if (len & 0x01)
1633  		return -1;
1634  	len /= 2;
1635  
1636  	buf = wpabuf_alloc(len);
1637  	if (buf == NULL)
1638  		return -1;
1639  	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1640  		wpabuf_free(buf);
1641  		return -1;
1642  	}
1643  
1644  	ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
1645  	wpabuf_free(buf);
1646  
1647  	return ret;
1648  }
1649  
1650  
wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef)1651  static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
1652  					      char *reply, size_t max_len,
1653  					      int ndef)
1654  {
1655  	struct wpabuf *buf;
1656  	int res;
1657  
1658  	buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
1659  	if (buf == NULL)
1660  		return -1;
1661  
1662  	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1663  					 wpabuf_len(buf));
1664  	reply[res++] = '\n';
1665  	reply[res] = '\0';
1666  
1667  	wpabuf_free(buf);
1668  
1669  	return res;
1670  }
1671  
1672  
1673  #ifdef CONFIG_P2P
wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef)1674  static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1675  					      char *reply, size_t max_len,
1676  					      int ndef)
1677  {
1678  	struct wpabuf *buf;
1679  	int res;
1680  
1681  	buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1682  	if (buf == NULL) {
1683  		wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1684  		return -1;
1685  	}
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  #endif /* CONFIG_P2P */
1697  
1698  
wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1699  static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1700  					  char *cmd, char *reply,
1701  					  size_t max_len)
1702  {
1703  	char *pos;
1704  	int ndef;
1705  
1706  	pos = os_strchr(cmd, ' ');
1707  	if (pos == NULL)
1708  		return -1;
1709  	*pos++ = '\0';
1710  
1711  	if (os_strcmp(cmd, "WPS") == 0)
1712  		ndef = 0;
1713  	else if (os_strcmp(cmd, "NDEF") == 0)
1714  		ndef = 1;
1715  	else
1716  		return -1;
1717  
1718  	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1719  		if (!ndef)
1720  			return -1;
1721  		return wpas_ctrl_nfc_get_handover_req_wps(
1722  			wpa_s, reply, max_len, ndef);
1723  	}
1724  
1725  #ifdef CONFIG_P2P
1726  	if (os_strcmp(pos, "P2P-CR") == 0) {
1727  		return wpas_ctrl_nfc_get_handover_req_p2p(
1728  			wpa_s, reply, max_len, ndef);
1729  	}
1730  #endif /* CONFIG_P2P */
1731  
1732  	return -1;
1733  }
1734  
1735  
wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef,int cr,char * uuid)1736  static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1737  					      char *reply, size_t max_len,
1738  					      int ndef, int cr, char *uuid)
1739  {
1740  	struct wpabuf *buf;
1741  	int res;
1742  
1743  	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1744  	if (buf == NULL)
1745  		return -1;
1746  
1747  	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1748  					 wpabuf_len(buf));
1749  	reply[res++] = '\n';
1750  	reply[res] = '\0';
1751  
1752  	wpabuf_free(buf);
1753  
1754  	return res;
1755  }
1756  
1757  
1758  #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)1759  static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1760  					      char *reply, size_t max_len,
1761  					      int ndef, int tag)
1762  {
1763  	struct wpabuf *buf;
1764  	int res;
1765  
1766  	buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1767  	if (buf == NULL)
1768  		return -1;
1769  
1770  	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1771  					 wpabuf_len(buf));
1772  	reply[res++] = '\n';
1773  	reply[res] = '\0';
1774  
1775  	wpabuf_free(buf);
1776  
1777  	return res;
1778  }
1779  #endif /* CONFIG_P2P */
1780  
1781  
wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1782  static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1783  					  char *cmd, char *reply,
1784  					  size_t max_len)
1785  {
1786  	char *pos, *pos2;
1787  	int ndef;
1788  
1789  	pos = os_strchr(cmd, ' ');
1790  	if (pos == NULL)
1791  		return -1;
1792  	*pos++ = '\0';
1793  
1794  	if (os_strcmp(cmd, "WPS") == 0)
1795  		ndef = 0;
1796  	else if (os_strcmp(cmd, "NDEF") == 0)
1797  		ndef = 1;
1798  	else
1799  		return -1;
1800  
1801  	pos2 = os_strchr(pos, ' ');
1802  	if (pos2)
1803  		*pos2++ = '\0';
1804  	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1805  		if (!ndef)
1806  			return -1;
1807  		return wpas_ctrl_nfc_get_handover_sel_wps(
1808  			wpa_s, reply, max_len, ndef,
1809  			os_strcmp(pos, "WPS-CR") == 0, pos2);
1810  	}
1811  
1812  #ifdef CONFIG_P2P
1813  	if (os_strcmp(pos, "P2P-CR") == 0) {
1814  		return wpas_ctrl_nfc_get_handover_sel_p2p(
1815  			wpa_s, reply, max_len, ndef, 0);
1816  	}
1817  
1818  	if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1819  		return wpas_ctrl_nfc_get_handover_sel_p2p(
1820  			wpa_s, reply, max_len, ndef, 1);
1821  	}
1822  #endif /* CONFIG_P2P */
1823  
1824  	return -1;
1825  }
1826  
1827  
wpas_ctrl_nfc_report_handover(struct wpa_supplicant * wpa_s,char * cmd)1828  static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1829  					 char *cmd)
1830  {
1831  	size_t len;
1832  	struct wpabuf *req, *sel;
1833  	int ret;
1834  	char *pos, *role, *type, *pos2;
1835  #ifdef CONFIG_P2P
1836  	char *freq;
1837  	int forced_freq = 0;
1838  
1839  	freq = strstr(cmd, " freq=");
1840  	if (freq) {
1841  		*freq = '\0';
1842  		freq += 6;
1843  		forced_freq = atoi(freq);
1844  	}
1845  #endif /* CONFIG_P2P */
1846  
1847  	role = cmd;
1848  	pos = os_strchr(role, ' ');
1849  	if (pos == NULL) {
1850  		wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1851  		return -1;
1852  	}
1853  	*pos++ = '\0';
1854  
1855  	type = pos;
1856  	pos = os_strchr(type, ' ');
1857  	if (pos == NULL) {
1858  		wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1859  		return -1;
1860  	}
1861  	*pos++ = '\0';
1862  
1863  	pos2 = os_strchr(pos, ' ');
1864  	if (pos2 == NULL) {
1865  		wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1866  		return -1;
1867  	}
1868  	*pos2++ = '\0';
1869  
1870  	len = os_strlen(pos);
1871  	if (len & 0x01) {
1872  		wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1873  		return -1;
1874  	}
1875  	len /= 2;
1876  
1877  	req = wpabuf_alloc(len);
1878  	if (req == NULL) {
1879  		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1880  		return -1;
1881  	}
1882  	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1883  		wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1884  		wpabuf_free(req);
1885  		return -1;
1886  	}
1887  
1888  	len = os_strlen(pos2);
1889  	if (len & 0x01) {
1890  		wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1891  		wpabuf_free(req);
1892  		return -1;
1893  	}
1894  	len /= 2;
1895  
1896  	sel = wpabuf_alloc(len);
1897  	if (sel == NULL) {
1898  		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1899  		wpabuf_free(req);
1900  		return -1;
1901  	}
1902  	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1903  		wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1904  		wpabuf_free(req);
1905  		wpabuf_free(sel);
1906  		return -1;
1907  	}
1908  
1909  	wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1910  		   role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1911  
1912  	if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1913  		ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1914  #ifdef CONFIG_AP
1915  	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1916  	{
1917  		ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1918  		if (ret < 0)
1919  			ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1920  #endif /* CONFIG_AP */
1921  #ifdef CONFIG_P2P
1922  	} else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1923  	{
1924  		ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1925  	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1926  	{
1927  		ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1928  						   forced_freq);
1929  #endif /* CONFIG_P2P */
1930  	} else {
1931  		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1932  			   "reported: role=%s type=%s", role, type);
1933  		ret = -1;
1934  	}
1935  	wpabuf_free(req);
1936  	wpabuf_free(sel);
1937  
1938  	if (ret)
1939  		wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1940  
1941  	return ret;
1942  }
1943  
1944  #endif /* CONFIG_WPS_NFC */
1945  
1946  
wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant * wpa_s,char * cmd)1947  static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1948  					     char *cmd)
1949  {
1950  	u8 bssid[ETH_ALEN];
1951  	char *pin;
1952  	char *new_ssid;
1953  	char *new_auth;
1954  	char *new_encr;
1955  	char *new_key;
1956  	struct wps_new_ap_settings ap;
1957  
1958  	pin = os_strchr(cmd, ' ');
1959  	if (pin == NULL)
1960  		return -1;
1961  	*pin++ = '\0';
1962  
1963  	if (hwaddr_aton(cmd, bssid)) {
1964  		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1965  			   cmd);
1966  		return -1;
1967  	}
1968  
1969  	new_ssid = os_strchr(pin, ' ');
1970  	if (new_ssid == NULL)
1971  		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1972  	*new_ssid++ = '\0';
1973  
1974  	new_auth = os_strchr(new_ssid, ' ');
1975  	if (new_auth == NULL)
1976  		return -1;
1977  	*new_auth++ = '\0';
1978  
1979  	new_encr = os_strchr(new_auth, ' ');
1980  	if (new_encr == NULL)
1981  		return -1;
1982  	*new_encr++ = '\0';
1983  
1984  	new_key = os_strchr(new_encr, ' ');
1985  	if (new_key == NULL)
1986  		return -1;
1987  	*new_key++ = '\0';
1988  
1989  	os_memset(&ap, 0, sizeof(ap));
1990  	ap.ssid_hex = new_ssid;
1991  	ap.auth = new_auth;
1992  	ap.encr = new_encr;
1993  	ap.key_hex = new_key;
1994  	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1995  }
1996  
1997  
1998  #ifdef CONFIG_AP
wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1999  static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
2000  						char *cmd, char *buf,
2001  						size_t buflen)
2002  {
2003  	int timeout = 300;
2004  	char *pos;
2005  	const char *pin_txt;
2006  
2007  	if (!wpa_s->ap_iface)
2008  		return -1;
2009  
2010  	pos = os_strchr(cmd, ' ');
2011  	if (pos)
2012  		*pos++ = '\0';
2013  
2014  	if (os_strcmp(cmd, "disable") == 0) {
2015  		wpas_wps_ap_pin_disable(wpa_s);
2016  		return os_snprintf(buf, buflen, "OK\n");
2017  	}
2018  
2019  	if (os_strcmp(cmd, "random") == 0) {
2020  		if (pos)
2021  			timeout = atoi(pos);
2022  		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
2023  		if (pin_txt == NULL)
2024  			return -1;
2025  		return os_snprintf(buf, buflen, "%s", pin_txt);
2026  	}
2027  
2028  	if (os_strcmp(cmd, "get") == 0) {
2029  		pin_txt = wpas_wps_ap_pin_get(wpa_s);
2030  		if (pin_txt == NULL)
2031  			return -1;
2032  		return os_snprintf(buf, buflen, "%s", pin_txt);
2033  	}
2034  
2035  	if (os_strcmp(cmd, "set") == 0) {
2036  		char *pin;
2037  		if (pos == NULL)
2038  			return -1;
2039  		pin = pos;
2040  		pos = os_strchr(pos, ' ');
2041  		if (pos) {
2042  			*pos++ = '\0';
2043  			timeout = atoi(pos);
2044  		}
2045  		if (os_strlen(pin) > buflen)
2046  			return -1;
2047  		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
2048  			return -1;
2049  		return os_snprintf(buf, buflen, "%s", pin);
2050  	}
2051  
2052  	return -1;
2053  }
2054  #endif /* CONFIG_AP */
2055  
2056  
2057  #ifdef CONFIG_WPS_ER
wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant * wpa_s,char * cmd)2058  static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
2059  						char *cmd)
2060  {
2061  	char *uuid = cmd, *pin, *pos;
2062  	u8 addr_buf[ETH_ALEN], *addr = NULL;
2063  	pin = os_strchr(uuid, ' ');
2064  	if (pin == NULL)
2065  		return -1;
2066  	*pin++ = '\0';
2067  	pos = os_strchr(pin, ' ');
2068  	if (pos) {
2069  		*pos++ = '\0';
2070  		if (hwaddr_aton(pos, addr_buf) == 0)
2071  			addr = addr_buf;
2072  	}
2073  	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
2074  }
2075  
2076  
wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant * wpa_s,char * cmd)2077  static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
2078  						  char *cmd)
2079  {
2080  	char *uuid = cmd, *pin;
2081  	pin = os_strchr(uuid, ' ');
2082  	if (pin == NULL)
2083  		return -1;
2084  	*pin++ = '\0';
2085  	return wpas_wps_er_learn(wpa_s, uuid, pin);
2086  }
2087  
2088  
wpa_supplicant_ctrl_iface_wps_er_set_config(struct wpa_supplicant * wpa_s,char * cmd)2089  static int wpa_supplicant_ctrl_iface_wps_er_set_config(
2090  	struct wpa_supplicant *wpa_s, char *cmd)
2091  {
2092  	char *uuid = cmd, *id;
2093  	id = os_strchr(uuid, ' ');
2094  	if (id == NULL)
2095  		return -1;
2096  	*id++ = '\0';
2097  	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
2098  }
2099  
2100  
wpa_supplicant_ctrl_iface_wps_er_config(struct wpa_supplicant * wpa_s,char * cmd)2101  static int wpa_supplicant_ctrl_iface_wps_er_config(
2102  	struct wpa_supplicant *wpa_s, char *cmd)
2103  {
2104  	char *pin;
2105  	char *new_ssid;
2106  	char *new_auth;
2107  	char *new_encr;
2108  	char *new_key;
2109  	struct wps_new_ap_settings ap;
2110  
2111  	pin = os_strchr(cmd, ' ');
2112  	if (pin == NULL)
2113  		return -1;
2114  	*pin++ = '\0';
2115  
2116  	new_ssid = os_strchr(pin, ' ');
2117  	if (new_ssid == NULL)
2118  		return -1;
2119  	*new_ssid++ = '\0';
2120  
2121  	new_auth = os_strchr(new_ssid, ' ');
2122  	if (new_auth == NULL)
2123  		return -1;
2124  	*new_auth++ = '\0';
2125  
2126  	new_encr = os_strchr(new_auth, ' ');
2127  	if (new_encr == NULL)
2128  		return -1;
2129  	*new_encr++ = '\0';
2130  
2131  	new_key = os_strchr(new_encr, ' ');
2132  	if (new_key == NULL)
2133  		return -1;
2134  	*new_key++ = '\0';
2135  
2136  	os_memset(&ap, 0, sizeof(ap));
2137  	ap.ssid_hex = new_ssid;
2138  	ap.auth = new_auth;
2139  	ap.encr = new_encr;
2140  	ap.key_hex = new_key;
2141  	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
2142  }
2143  
2144  
2145  #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)2146  static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
2147  	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2148  {
2149  	int ndef;
2150  	struct wpabuf *buf;
2151  	int res;
2152  	char *uuid;
2153  
2154  	uuid = os_strchr(cmd, ' ');
2155  	if (uuid == NULL)
2156  		return -1;
2157  	*uuid++ = '\0';
2158  
2159  	if (os_strcmp(cmd, "WPS") == 0)
2160  		ndef = 0;
2161  	else if (os_strcmp(cmd, "NDEF") == 0)
2162  		ndef = 1;
2163  	else
2164  		return -1;
2165  
2166  	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
2167  	if (buf == NULL)
2168  		return -1;
2169  
2170  	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
2171  					 wpabuf_len(buf));
2172  	reply[res++] = '\n';
2173  	reply[res] = '\0';
2174  
2175  	wpabuf_free(buf);
2176  
2177  	return res;
2178  }
2179  #endif /* CONFIG_WPS_NFC */
2180  #endif /* CONFIG_WPS_ER */
2181  
2182  #endif /* CONFIG_WPS */
2183  
2184  
2185  #ifdef CONFIG_IBSS_RSN
wpa_supplicant_ctrl_iface_ibss_rsn(struct wpa_supplicant * wpa_s,char * addr)2186  static int wpa_supplicant_ctrl_iface_ibss_rsn(
2187  	struct wpa_supplicant *wpa_s, char *addr)
2188  {
2189  	u8 peer[ETH_ALEN];
2190  
2191  	if (hwaddr_aton(addr, peer)) {
2192  		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
2193  			   "address '%s'", addr);
2194  		return -1;
2195  	}
2196  
2197  	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
2198  		   MAC2STR(peer));
2199  
2200  	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
2201  }
2202  #endif /* CONFIG_IBSS_RSN */
2203  
2204  
wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant * wpa_s,char * rsp)2205  static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
2206  					      char *rsp)
2207  {
2208  #ifdef IEEE8021X_EAPOL
2209  	char *pos, *id_pos;
2210  	int id;
2211  	struct wpa_ssid *ssid;
2212  
2213  	pos = os_strchr(rsp, '-');
2214  	if (pos == NULL)
2215  		return -1;
2216  	*pos++ = '\0';
2217  	id_pos = pos;
2218  	pos = os_strchr(pos, ':');
2219  	if (pos == NULL)
2220  		return -1;
2221  	*pos++ = '\0';
2222  	id = atoi(id_pos);
2223  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2224  	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2225  			      (u8 *) pos, os_strlen(pos));
2226  
2227  	ssid = wpa_config_get_network(wpa_s->conf, id);
2228  	if (ssid == NULL) {
2229  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2230  			   "to update", id);
2231  		return -1;
2232  	}
2233  
2234  	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2235  							 pos);
2236  #else /* IEEE8021X_EAPOL */
2237  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2238  	return -1;
2239  #endif /* IEEE8021X_EAPOL */
2240  }
2241  
2242  
wpa_supplicant_ctrl_iface_status(struct wpa_supplicant * wpa_s,const char * params,char * buf,size_t buflen)2243  static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2244  					    const char *params,
2245  					    char *buf, size_t buflen)
2246  {
2247  	char *pos, *end, tmp[30];
2248  	int res, verbose, wps, ret;
2249  #ifdef CONFIG_HS20
2250  	const u8 *hs20;
2251  #endif /* CONFIG_HS20 */
2252  	const u8 *sess_id;
2253  	size_t sess_id_len;
2254  
2255  	if (os_strcmp(params, "-DRIVER") == 0)
2256  		return wpa_drv_status(wpa_s, buf, buflen);
2257  	verbose = os_strcmp(params, "-VERBOSE") == 0;
2258  	wps = os_strcmp(params, "-WPS") == 0;
2259  	pos = buf;
2260  	end = buf + buflen;
2261  	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2262  		struct wpa_ssid *ssid = wpa_s->current_ssid;
2263  		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2264  				  MAC2STR(wpa_s->bssid));
2265  		if (os_snprintf_error(end - pos, ret))
2266  			return pos - buf;
2267  		pos += ret;
2268  		ret = os_snprintf(pos, end - pos, "freq=%u\n",
2269  				  wpa_s->assoc_freq);
2270  		if (os_snprintf_error(end - pos, ret))
2271  			return pos - buf;
2272  		pos += ret;
2273  		if (ssid) {
2274  			u8 *_ssid = ssid->ssid;
2275  			size_t ssid_len = ssid->ssid_len;
2276  			u8 ssid_buf[SSID_MAX_LEN];
2277  			if (ssid_len == 0) {
2278  				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2279  				if (_res < 0)
2280  					ssid_len = 0;
2281  				else
2282  					ssid_len = _res;
2283  				_ssid = ssid_buf;
2284  			}
2285  			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2286  					  wpa_ssid_txt(_ssid, ssid_len),
2287  					  ssid->id);
2288  			if (os_snprintf_error(end - pos, ret))
2289  				return pos - buf;
2290  			pos += ret;
2291  
2292  			if (wps && ssid->passphrase &&
2293  			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2294  			    (ssid->mode == WPAS_MODE_AP ||
2295  			     ssid->mode == WPAS_MODE_P2P_GO)) {
2296  				ret = os_snprintf(pos, end - pos,
2297  						  "passphrase=%s\n",
2298  						  ssid->passphrase);
2299  				if (os_snprintf_error(end - pos, ret))
2300  					return pos - buf;
2301  				pos += ret;
2302  			}
2303  			if (ssid->id_str) {
2304  				ret = os_snprintf(pos, end - pos,
2305  						  "id_str=%s\n",
2306  						  ssid->id_str);
2307  				if (os_snprintf_error(end - pos, ret))
2308  					return pos - buf;
2309  				pos += ret;
2310  			}
2311  
2312  			switch (ssid->mode) {
2313  			case WPAS_MODE_INFRA:
2314  				ret = os_snprintf(pos, end - pos,
2315  						  "mode=station\n");
2316  				break;
2317  			case WPAS_MODE_IBSS:
2318  				ret = os_snprintf(pos, end - pos,
2319  						  "mode=IBSS\n");
2320  				break;
2321  			case WPAS_MODE_AP:
2322  				ret = os_snprintf(pos, end - pos,
2323  						  "mode=AP\n");
2324  				break;
2325  			case WPAS_MODE_P2P_GO:
2326  				ret = os_snprintf(pos, end - pos,
2327  						  "mode=P2P GO\n");
2328  				break;
2329  			case WPAS_MODE_P2P_GROUP_FORMATION:
2330  				ret = os_snprintf(pos, end - pos,
2331  						  "mode=P2P GO - group "
2332  						  "formation\n");
2333  				break;
2334  			case WPAS_MODE_MESH:
2335  				ret = os_snprintf(pos, end - pos,
2336  						  "mode=mesh\n");
2337  				break;
2338  			default:
2339  				ret = 0;
2340  				break;
2341  			}
2342  			if (os_snprintf_error(end - pos, ret))
2343  				return pos - buf;
2344  			pos += ret;
2345  		}
2346  
2347  		if (wpa_s->connection_set &&
2348  		    (wpa_s->connection_ht || wpa_s->connection_vht ||
2349  		     wpa_s->connection_he || wpa_s->connection_eht)) {
2350  			ret = os_snprintf(pos, end - pos,
2351  					  "wifi_generation=%u\n",
2352  					  wpa_s->connection_eht ? 7 :
2353  					  (wpa_s->connection_he ? 6 :
2354  					   (wpa_s->connection_vht ? 5 : 4)));
2355  			if (os_snprintf_error(end - pos, ret))
2356  				return pos - buf;
2357  			pos += ret;
2358  		}
2359  
2360  #ifdef CONFIG_AP
2361  		if (wpa_s->ap_iface) {
2362  			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2363  							    end - pos,
2364  							    verbose);
2365  		} else
2366  #endif /* CONFIG_AP */
2367  		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2368  	}
2369  #ifdef CONFIG_SME
2370  #ifdef CONFIG_SAE
2371  	if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
2372  #ifdef CONFIG_AP
2373  	    !wpa_s->ap_iface &&
2374  #endif /* CONFIG_AP */
2375  	    wpa_s->sme.sae.state == SAE_ACCEPTED) {
2376  		ret = os_snprintf(pos, end - pos, "sae_group=%d\n"
2377  				  "sae_h2e=%d\n"
2378  				  "sae_pk=%d\n",
2379  				  wpa_s->sme.sae.group,
2380  				  wpa_s->sme.sae.h2e,
2381  				  wpa_s->sme.sae.pk);
2382  		if (os_snprintf_error(end - pos, ret))
2383  			return pos - buf;
2384  		pos += ret;
2385  	}
2386  #endif /* CONFIG_SAE */
2387  #endif /* CONFIG_SME */
2388  	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2389  			  wpa_supplicant_state_txt(wpa_s->wpa_state));
2390  	if (os_snprintf_error(end - pos, ret))
2391  		return pos - buf;
2392  	pos += ret;
2393  
2394  	if (wpa_s->l2 &&
2395  	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2396  		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
2397  		if (os_snprintf_error(end - pos, ret))
2398  			return pos - buf;
2399  		pos += ret;
2400  	}
2401  
2402  #ifdef CONFIG_P2P
2403  	if (wpa_s->global->p2p) {
2404  		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2405  				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
2406  		if (os_snprintf_error(end - pos, ret))
2407  			return pos - buf;
2408  		pos += ret;
2409  	}
2410  #endif /* CONFIG_P2P */
2411  
2412  	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2413  			  MAC2STR(wpa_s->own_addr));
2414  	if (os_snprintf_error(end - pos, ret))
2415  		return pos - buf;
2416  	pos += ret;
2417  
2418  	if (wpa_s->valid_links) {
2419  		ret = os_snprintf(pos, end - pos, "ap_mld_addr=" MACSTR "\n",
2420  				  MAC2STR(wpa_s->ap_mld_addr));
2421  		if (os_snprintf_error(end - pos, ret))
2422  			return pos - buf;
2423  		pos += ret;
2424  	}
2425  
2426  #ifdef CONFIG_HS20
2427  	if (wpa_s->current_bss &&
2428  	    (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2429  					  HS20_IE_VENDOR_TYPE)) &&
2430  	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
2431  	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2432  		int release = 1;
2433  		if (hs20[1] >= 5) {
2434  			u8 rel_num = (hs20[6] & 0xf0) >> 4;
2435  			release = rel_num + 1;
2436  		}
2437  		ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
2438  		if (os_snprintf_error(end - pos, ret))
2439  			return pos - buf;
2440  		pos += ret;
2441  	}
2442  
2443  	if (wpa_s->current_ssid) {
2444  		struct wpa_cred *cred;
2445  		char *type;
2446  
2447  		for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
2448  			size_t i;
2449  
2450  			if (wpa_s->current_ssid->parent_cred != cred)
2451  				continue;
2452  
2453  			if (cred->provisioning_sp) {
2454  				ret = os_snprintf(pos, end - pos,
2455  						  "provisioning_sp=%s\n",
2456  						  cred->provisioning_sp);
2457  				if (os_snprintf_error(end - pos, ret))
2458  					return pos - buf;
2459  				pos += ret;
2460  			}
2461  
2462  			if (!cred->domain)
2463  				goto no_domain;
2464  
2465  			i = 0;
2466  			if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2467  				struct wpabuf *names =
2468  					wpa_s->current_bss->anqp->domain_name;
2469  				for (i = 0; names && i < cred->num_domain; i++)
2470  				{
2471  					if (domain_name_list_contains(
2472  						    names, cred->domain[i], 1))
2473  						break;
2474  				}
2475  				if (i == cred->num_domain)
2476  					i = 0; /* show first entry by default */
2477  			}
2478  			ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2479  					  cred->domain[i]);
2480  			if (os_snprintf_error(end - pos, ret))
2481  				return pos - buf;
2482  			pos += ret;
2483  
2484  		no_domain:
2485  			if (wpa_s->current_bss == NULL ||
2486  			    wpa_s->current_bss->anqp == NULL)
2487  				res = -1;
2488  			else
2489  				res = interworking_home_sp_cred(
2490  					wpa_s, cred,
2491  					wpa_s->current_bss->anqp->domain_name);
2492  			if (res > 0)
2493  				type = "home";
2494  			else if (res == 0)
2495  				type = "roaming";
2496  			else
2497  				type = "unknown";
2498  
2499  			ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
2500  			if (os_snprintf_error(end - pos, ret))
2501  				return pos - buf;
2502  			pos += ret;
2503  
2504  			break;
2505  		}
2506  	}
2507  #endif /* CONFIG_HS20 */
2508  
2509  	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2510  	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2511  		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2512  					  verbose);
2513  		if (res >= 0)
2514  			pos += res;
2515  	}
2516  
2517  #ifdef CONFIG_MACSEC
2518  	res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2519  	if (res > 0)
2520  		pos += res;
2521  #endif /* CONFIG_MACSEC */
2522  
2523  	sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2524  	if (sess_id) {
2525  		char *start = pos;
2526  
2527  		ret = os_snprintf(pos, end - pos, "eap_session_id=");
2528  		if (os_snprintf_error(end - pos, ret))
2529  			return start - buf;
2530  		pos += ret;
2531  		ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2532  		if (ret <= 0)
2533  			return start - buf;
2534  		pos += ret;
2535  		ret = os_snprintf(pos, end - pos, "\n");
2536  		if (os_snprintf_error(end - pos, ret))
2537  			return start - buf;
2538  		pos += ret;
2539  	}
2540  
2541  	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2542  	if (res >= 0)
2543  		pos += res;
2544  
2545  #ifdef CONFIG_WPS
2546  	{
2547  		char uuid_str[100];
2548  		uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2549  		ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
2550  		if (os_snprintf_error(end - pos, ret))
2551  			return pos - buf;
2552  		pos += ret;
2553  	}
2554  #endif /* CONFIG_WPS */
2555  
2556  	if (wpa_s->ieee80211ac) {
2557  		ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2558  		if (os_snprintf_error(end - pos, ret))
2559  			return pos - buf;
2560  		pos += ret;
2561  	}
2562  
2563  #ifdef CONFIG_SME
2564  	if (wpa_s->sme.bss_max_idle_period) {
2565  		ret = os_snprintf(pos, end - pos, "bss_max_idle_period=%d\n",
2566  				  wpa_s->sme.bss_max_idle_period);
2567  		if (os_snprintf_error(end - pos, ret))
2568  			return pos - buf;
2569  		pos += ret;
2570  	}
2571  #endif /* CONFIG_SME */
2572  
2573  	if (wpa_s->ssid_verified) {
2574  		ret = os_snprintf(pos, end - pos, "ssid_verified=1\n");
2575  		if (os_snprintf_error(end - pos, ret))
2576  			return pos - buf;
2577  		pos += ret;
2578  	}
2579  
2580  	if (wpa_s->bigtk_set) {
2581  		ret = os_snprintf(pos, end - pos, "bigtk_set=1\n");
2582  		if (os_snprintf_error(end - pos, ret))
2583  			return pos - buf;
2584  		pos += ret;
2585  	}
2586  
2587  #ifdef ANDROID
2588  	/*
2589  	 * Allow using the STATUS command with default behavior, say for debug,
2590  	 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2591  	 * events with STATUS-NO_EVENTS.
2592  	 */
2593  	if (os_strcmp(params, "-NO_EVENTS")) {
2594  		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2595  			     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2596  			     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2597  			     wpa_s->wpa_state,
2598  			     MAC2STR(wpa_s->bssid),
2599  			     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2600  			     wpa_ssid_txt(wpa_s->current_ssid->ssid,
2601  					  wpa_s->current_ssid->ssid_len) : "");
2602  		if (wpa_s->wpa_state == WPA_COMPLETED) {
2603  			struct wpa_ssid *ssid = wpa_s->current_ssid;
2604  			char mld_addr[50];
2605  
2606  			mld_addr[0] = '\0';
2607  			if (wpa_s->valid_links)
2608  				os_snprintf(mld_addr, sizeof(mld_addr),
2609  					    " ap_mld_addr=" MACSTR,
2610  					    MAC2STR(wpa_s->ap_mld_addr));
2611  
2612  			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2613  				     "- connection to " MACSTR
2614  				     " completed %s [id=%d id_str=%s]%s",
2615  				     MAC2STR(wpa_s->bssid), "(auth)",
2616  				     ssid ? ssid->id : -1,
2617  				     ssid && ssid->id_str ? ssid->id_str : "",
2618  				     mld_addr);
2619  		}
2620  	}
2621  #endif /* ANDROID */
2622  
2623  	return pos - buf;
2624  }
2625  
2626  
wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant * wpa_s,char * cmd)2627  static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2628  					   char *cmd)
2629  {
2630  	char *pos;
2631  	int id;
2632  	struct wpa_ssid *ssid;
2633  	u8 bssid[ETH_ALEN];
2634  
2635  	/* cmd: "<network id> <BSSID>" */
2636  	pos = os_strchr(cmd, ' ');
2637  	if (pos == NULL)
2638  		return -1;
2639  	*pos++ = '\0';
2640  	id = atoi(cmd);
2641  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2642  	if (hwaddr_aton(pos, bssid)) {
2643  		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2644  		return -1;
2645  	}
2646  
2647  	ssid = wpa_config_get_network(wpa_s->conf, id);
2648  	if (ssid == NULL) {
2649  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2650  			   "to update", id);
2651  		return -1;
2652  	}
2653  
2654  	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2655  	ssid->bssid_set = !is_zero_ether_addr(bssid);
2656  
2657  	return 0;
2658  }
2659  
2660  
wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2661  static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
2662  						  char *cmd, char *buf,
2663  						  size_t buflen)
2664  {
2665  	u8 bssid[ETH_ALEN];
2666  	struct wpa_bssid_ignore *e;
2667  	char *pos, *end;
2668  	int ret;
2669  
2670  	/* cmd: "BSSID_IGNORE [<BSSID>]" */
2671  	if (*cmd == '\0') {
2672  		pos = buf;
2673  		end = buf + buflen;
2674  		e = wpa_s->bssid_ignore;
2675  		while (e) {
2676  			ret = os_snprintf(pos, end - pos, MACSTR "\n",
2677  					  MAC2STR(e->bssid));
2678  			if (os_snprintf_error(end - pos, ret))
2679  				return pos - buf;
2680  			pos += ret;
2681  			e = e->next;
2682  		}
2683  		return pos - buf;
2684  	}
2685  
2686  	cmd++;
2687  	if (os_strncmp(cmd, "clear", 5) == 0) {
2688  		wpa_bssid_ignore_clear(wpa_s);
2689  		os_memcpy(buf, "OK\n", 3);
2690  		return 3;
2691  	}
2692  
2693  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
2694  	if (hwaddr_aton(cmd, bssid)) {
2695  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
2696  		return -1;
2697  	}
2698  
2699  	/*
2700  	 * Add the BSSID twice, so its count will be 2, causing it to be
2701  	 * skipped when processing scan results.
2702  	 */
2703  	ret = wpa_bssid_ignore_add(wpa_s, bssid);
2704  	if (ret < 0)
2705  		return -1;
2706  	ret = wpa_bssid_ignore_add(wpa_s, bssid);
2707  	if (ret < 0)
2708  		return -1;
2709  	os_memcpy(buf, "OK\n", 3);
2710  	return 3;
2711  }
2712  
2713  
wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2714  static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2715  					       char *cmd, char *buf,
2716  					       size_t buflen)
2717  {
2718  	char *pos, *end, *stamp;
2719  	int ret;
2720  
2721  	/* cmd: "LOG_LEVEL [<level>]" */
2722  	if (*cmd == '\0') {
2723  		pos = buf;
2724  		end = buf + buflen;
2725  		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2726  				  "Timestamp: %d\n",
2727  				  debug_level_str(wpa_debug_level),
2728  				  wpa_debug_timestamp);
2729  		if (os_snprintf_error(end - pos, ret))
2730  			ret = 0;
2731  
2732  		return ret;
2733  	}
2734  
2735  	while (*cmd == ' ')
2736  		cmd++;
2737  
2738  	stamp = os_strchr(cmd, ' ');
2739  	if (stamp) {
2740  		*stamp++ = '\0';
2741  		while (*stamp == ' ') {
2742  			stamp++;
2743  		}
2744  	}
2745  
2746  	if (os_strlen(cmd)) {
2747  		int level = str_to_debug_level(cmd);
2748  		if (level < 0)
2749  			return -1;
2750  		wpa_debug_level = level;
2751  	}
2752  
2753  	if (stamp && os_strlen(stamp))
2754  		wpa_debug_timestamp = atoi(stamp);
2755  
2756  	os_memcpy(buf, "OK\n", 3);
2757  	return 3;
2758  }
2759  
2760  
wpa_supplicant_ctrl_iface_list_networks(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2761  static int wpa_supplicant_ctrl_iface_list_networks(
2762  	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2763  {
2764  	char *pos, *end, *prev;
2765  	struct wpa_ssid *ssid;
2766  	int ret;
2767  
2768  	pos = buf;
2769  	end = buf + buflen;
2770  	ret = os_snprintf(pos, end - pos,
2771  			  "network id / ssid / bssid / flags\n");
2772  	if (os_snprintf_error(end - pos, ret))
2773  		return pos - buf;
2774  	pos += ret;
2775  
2776  	ssid = wpa_s->conf->ssid;
2777  
2778  	/* skip over ssids until we find next one */
2779  	if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2780  		int last_id = atoi(cmd + 8);
2781  		if (last_id != -1) {
2782  			while (ssid != NULL && ssid->id <= last_id) {
2783  				ssid = ssid->next;
2784  			}
2785  		}
2786  	}
2787  
2788  	while (ssid) {
2789  		prev = pos;
2790  		ret = os_snprintf(pos, end - pos, "%d\t%s",
2791  				  ssid->id,
2792  				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2793  		if (os_snprintf_error(end - pos, ret))
2794  			return prev - buf;
2795  		pos += ret;
2796  		if (ssid->bssid_set) {
2797  			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2798  					  MAC2STR(ssid->bssid));
2799  		} else {
2800  			ret = os_snprintf(pos, end - pos, "\tany");
2801  		}
2802  		if (os_snprintf_error(end - pos, ret))
2803  			return prev - buf;
2804  		pos += ret;
2805  		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2806  				  ssid == wpa_s->current_ssid ?
2807  				  "[CURRENT]" : "",
2808  				  ssid->disabled ? "[DISABLED]" : "",
2809  				  ssid->disabled_until.sec ?
2810  				  "[TEMP-DISABLED]" : "",
2811  				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2812  				  "");
2813  		if (os_snprintf_error(end - pos, ret))
2814  			return prev - buf;
2815  		pos += ret;
2816  		ret = os_snprintf(pos, end - pos, "\n");
2817  		if (os_snprintf_error(end - pos, ret))
2818  			return prev - buf;
2819  		pos += ret;
2820  
2821  		ssid = ssid->next;
2822  	}
2823  
2824  	return pos - buf;
2825  }
2826  
2827  
wpa_supplicant_cipher_txt(char * pos,char * end,int cipher)2828  static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2829  {
2830  	int ret;
2831  	ret = os_snprintf(pos, end - pos, "-");
2832  	if (os_snprintf_error(end - pos, ret))
2833  		return pos;
2834  	pos += ret;
2835  	ret = wpa_write_ciphers(pos, end, cipher, "+");
2836  	if (ret < 0)
2837  		return pos;
2838  	pos += ret;
2839  	return pos;
2840  }
2841  
2842  
wpa_supplicant_ie_txt(char * pos,char * end,const char * proto,const u8 * ie,size_t ie_len)2843  static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2844  				    const u8 *ie, size_t ie_len)
2845  {
2846  	struct wpa_ie_data data;
2847  	char *start;
2848  	int ret;
2849  
2850  	ret = os_snprintf(pos, end - pos, "[%s-", proto);
2851  	if (os_snprintf_error(end - pos, ret))
2852  		return pos;
2853  	pos += ret;
2854  
2855  	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2856  		ret = os_snprintf(pos, end - pos, "?]");
2857  		if (os_snprintf_error(end - pos, ret))
2858  			return pos;
2859  		pos += ret;
2860  		return pos;
2861  	}
2862  
2863  	start = pos;
2864  	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2865  		ret = os_snprintf(pos, end - pos, "%sEAP",
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_PSK) {
2872  		ret = os_snprintf(pos, end - pos, "%sPSK",
2873  				  pos == start ? "" : "+");
2874  		if (os_snprintf_error(end - pos, ret))
2875  			return pos;
2876  		pos += ret;
2877  	}
2878  	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2879  		ret = os_snprintf(pos, end - pos, "%sNone",
2880  				  pos == start ? "" : "+");
2881  		if (os_snprintf_error(end - pos, ret))
2882  			return pos;
2883  		pos += ret;
2884  	}
2885  	if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2886  		ret = os_snprintf(pos, end - pos, "%sSAE",
2887  				  pos == start ? "" : "+");
2888  		if (os_snprintf_error(end - pos, ret))
2889  			return pos;
2890  		pos += ret;
2891  	}
2892  	if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
2893  		ret = os_snprintf(pos, end - pos, "%sSAE-EXT-KEY",
2894  				  pos == start ? "" : "+");
2895  		if (os_snprintf_error(end - pos, ret))
2896  			return pos;
2897  		pos += ret;
2898  	}
2899  #ifdef CONFIG_IEEE80211R
2900  	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2901  		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2902  				  pos == start ? "" : "+");
2903  		if (os_snprintf_error(end - pos, ret))
2904  			return pos;
2905  		pos += ret;
2906  	}
2907  	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2908  		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2909  				  pos == start ? "" : "+");
2910  		if (os_snprintf_error(end - pos, ret))
2911  			return pos;
2912  		pos += ret;
2913  	}
2914  	if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2915  		ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2916  				  pos == start ? "" : "+");
2917  		if (os_snprintf_error(end - pos, ret))
2918  			return pos;
2919  		pos += ret;
2920  	}
2921  	if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
2922  		ret = os_snprintf(pos, end - pos, "%sFT/SAE-EXT-KEY",
2923  				  pos == start ? "" : "+");
2924  		if (os_snprintf_error(end - pos, ret))
2925  			return pos;
2926  		pos += ret;
2927  	}
2928  #endif /* CONFIG_IEEE80211R */
2929  	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2930  		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2931  				  pos == start ? "" : "+");
2932  		if (os_snprintf_error(end - pos, ret))
2933  			return pos;
2934  		pos += ret;
2935  	}
2936  	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2937  		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2938  				  pos == start ? "" : "+");
2939  		if (os_snprintf_error(end - pos, ret))
2940  			return pos;
2941  		pos += ret;
2942  	}
2943  
2944  #ifdef CONFIG_SUITEB
2945  	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2946  		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2947  				  pos == start ? "" : "+");
2948  		if (os_snprintf_error(end - pos, ret))
2949  			return pos;
2950  		pos += ret;
2951  	}
2952  #endif /* CONFIG_SUITEB */
2953  
2954  #ifdef CONFIG_SUITEB192
2955  	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2956  		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2957  				  pos == start ? "" : "+");
2958  		if (os_snprintf_error(end - pos, ret))
2959  			return pos;
2960  		pos += ret;
2961  	}
2962  #endif /* CONFIG_SUITEB192 */
2963  
2964  #ifdef CONFIG_FILS
2965  	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
2966  		ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
2967  				  pos == start ? "" : "+");
2968  		if (os_snprintf_error(end - pos, ret))
2969  			return pos;
2970  		pos += ret;
2971  	}
2972  	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
2973  		ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
2974  				  pos == start ? "" : "+");
2975  		if (os_snprintf_error(end - pos, ret))
2976  			return pos;
2977  		pos += ret;
2978  	}
2979  #ifdef CONFIG_IEEE80211R
2980  	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
2981  		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
2982  				  pos == start ? "" : "+");
2983  		if (os_snprintf_error(end - pos, ret))
2984  			return pos;
2985  		pos += ret;
2986  	}
2987  	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
2988  		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
2989  				  pos == start ? "" : "+");
2990  		if (os_snprintf_error(end - pos, ret))
2991  			return pos;
2992  		pos += ret;
2993  	}
2994  #endif /* CONFIG_IEEE80211R */
2995  #endif /* CONFIG_FILS */
2996  
2997  #ifdef CONFIG_OWE
2998  	if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
2999  		ret = os_snprintf(pos, end - pos, "%sOWE",
3000  				  pos == start ? "" : "+");
3001  		if (os_snprintf_error(end - pos, ret))
3002  			return pos;
3003  		pos += ret;
3004  	}
3005  #endif /* CONFIG_OWE */
3006  
3007  #ifdef CONFIG_DPP
3008  	if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
3009  		ret = os_snprintf(pos, end - pos, "%sDPP",
3010  				  pos == start ? "" : "+");
3011  		if (os_snprintf_error(end - pos, ret))
3012  			return pos;
3013  		pos += ret;
3014  	}
3015  #endif /* CONFIG_DPP */
3016  
3017  #ifdef CONFIG_SHA384
3018  	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
3019  		ret = os_snprintf(pos, end - pos, "%sEAP-SHA384",
3020  				  pos == start ? "" : "+");
3021  		if (os_snprintf_error(end - pos, ret))
3022  			return pos;
3023  		pos += ret;
3024  	}
3025  #endif /* CONFIG_SHA384 */
3026  
3027  	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
3028  
3029  	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
3030  		ret = os_snprintf(pos, end - pos, "-preauth");
3031  		if (os_snprintf_error(end - pos, ret))
3032  			return pos;
3033  		pos += ret;
3034  	}
3035  
3036  	ret = os_snprintf(pos, end - pos, "]");
3037  	if (os_snprintf_error(end - pos, ret))
3038  		return pos;
3039  	pos += ret;
3040  
3041  	return pos;
3042  }
3043  
3044  
3045  #ifdef CONFIG_WPS
wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant * wpa_s,char * pos,char * end,struct wpabuf * wps_ie)3046  static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
3047  					    char *pos, char *end,
3048  					    struct wpabuf *wps_ie)
3049  {
3050  	int ret;
3051  	const char *txt;
3052  
3053  	if (wps_ie == NULL)
3054  		return pos;
3055  	if (wps_is_selected_pbc_registrar(wps_ie))
3056  		txt = "[WPS-PBC]";
3057  	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
3058  		txt = "[WPS-AUTH]";
3059  	else if (wps_is_selected_pin_registrar(wps_ie))
3060  		txt = "[WPS-PIN]";
3061  	else
3062  		txt = "[WPS]";
3063  
3064  	ret = os_snprintf(pos, end - pos, "%s", txt);
3065  	if (!os_snprintf_error(end - pos, ret))
3066  		pos += ret;
3067  	wpabuf_free(wps_ie);
3068  	return pos;
3069  }
3070  #endif /* CONFIG_WPS */
3071  
3072  
wpa_supplicant_wps_ie_txt(struct wpa_supplicant * wpa_s,char * pos,char * end,const struct wpa_bss * bss)3073  static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
3074  					char *pos, char *end,
3075  					const struct wpa_bss *bss)
3076  {
3077  #ifdef CONFIG_WPS
3078  	struct wpabuf *wps_ie;
3079  	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
3080  	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
3081  #else /* CONFIG_WPS */
3082  	return pos;
3083  #endif /* CONFIG_WPS */
3084  }
3085  
3086  
3087  /* 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)3088  static int wpa_supplicant_ctrl_iface_scan_result(
3089  	struct wpa_supplicant *wpa_s,
3090  	const struct wpa_bss *bss, char *buf, size_t buflen)
3091  {
3092  	char *pos, *end;
3093  	int ret;
3094  	const u8 *ie, *ie2, *p2p, *mesh, *owe, *rsnxe;
3095  
3096  	mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
3097  	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
3098  	if (!p2p)
3099  		p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
3100  	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
3101  	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
3102  	    0)
3103  		return 0; /* Do not show P2P listen discovery results here */
3104  
3105  	pos = buf;
3106  	end = buf + buflen;
3107  
3108  	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
3109  			  MAC2STR(bss->bssid), bss->freq, bss->level);
3110  	if (os_snprintf_error(end - pos, ret))
3111  		return -1;
3112  	pos += ret;
3113  	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3114  	if (ie)
3115  		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
3116  	ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
3117  	if (ie2) {
3118  		pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
3119  					    ie2, 2 + ie2[1]);
3120  	}
3121  	rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
3122  	if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
3123  		ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
3124  		if (os_snprintf_error(end - pos, ret))
3125  			return -1;
3126  		pos += ret;
3127  	}
3128  	if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
3129  		ret = os_snprintf(pos, end - pos, "[SAE-PK]");
3130  		if (os_snprintf_error(end - pos, ret))
3131  			return -1;
3132  		pos += ret;
3133  	}
3134  	owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3135  	if (owe) {
3136  		ret = os_snprintf(pos, end - pos,
3137  				  ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
3138  		if (os_snprintf_error(end - pos, ret))
3139  			return -1;
3140  		pos += ret;
3141  	}
3142  	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3143  	if (!ie && !ie2 && (bss->caps & IEEE80211_CAP_PRIVACY)) {
3144  		ret = os_snprintf(pos, end - pos, "[WEP]");
3145  		if (os_snprintf_error(end - pos, ret))
3146  			return -1;
3147  		pos += ret;
3148  	}
3149  	if (mesh) {
3150  		ret = os_snprintf(pos, end - pos, "[MESH]");
3151  		if (os_snprintf_error(end - pos, ret))
3152  			return -1;
3153  		pos += ret;
3154  	}
3155  	if (bss_is_dmg(bss)) {
3156  		const char *s;
3157  
3158  		if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
3159  			ret = os_snprintf(pos, end - pos, "[EDMG]");
3160  			if (os_snprintf_error(end - pos, ret))
3161  				return -1;
3162  			pos += ret;
3163  		}
3164  
3165  		ret = os_snprintf(pos, end - pos, "[DMG]");
3166  		if (os_snprintf_error(end - pos, ret))
3167  			return -1;
3168  		pos += ret;
3169  		switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
3170  		case IEEE80211_CAP_DMG_IBSS:
3171  			s = "[IBSS]";
3172  			break;
3173  		case IEEE80211_CAP_DMG_AP:
3174  			s = "[ESS]";
3175  			break;
3176  		case IEEE80211_CAP_DMG_PBSS:
3177  			s = "[PBSS]";
3178  			break;
3179  		default:
3180  			s = "";
3181  			break;
3182  		}
3183  		ret = os_snprintf(pos, end - pos, "%s", s);
3184  		if (os_snprintf_error(end - pos, ret))
3185  			return -1;
3186  		pos += ret;
3187  	} else {
3188  		if (bss->caps & IEEE80211_CAP_IBSS) {
3189  			ret = os_snprintf(pos, end - pos, "[IBSS]");
3190  			if (os_snprintf_error(end - pos, ret))
3191  				return -1;
3192  			pos += ret;
3193  		}
3194  		if (bss->caps & IEEE80211_CAP_ESS) {
3195  			ret = os_snprintf(pos, end - pos, "[ESS]");
3196  			if (os_snprintf_error(end - pos, ret))
3197  				return -1;
3198  			pos += ret;
3199  		}
3200  	}
3201  	if (p2p) {
3202  		ret = os_snprintf(pos, end - pos, "[P2P]");
3203  		if (os_snprintf_error(end - pos, ret))
3204  			return -1;
3205  		pos += ret;
3206  	}
3207  #ifdef CONFIG_HS20
3208  	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
3209  		ret = os_snprintf(pos, end - pos, "[HS20]");
3210  		if (os_snprintf_error(end - pos, ret))
3211  			return -1;
3212  		pos += ret;
3213  	}
3214  #endif /* CONFIG_HS20 */
3215  #ifdef CONFIG_FILS
3216  	if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
3217  		ret = os_snprintf(pos, end - pos, "[FILS]");
3218  		if (os_snprintf_error(end - pos, ret))
3219  			return -1;
3220  		pos += ret;
3221  	}
3222  #endif /* CONFIG_FILS */
3223  #ifdef CONFIG_FST
3224  	if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
3225  		ret = os_snprintf(pos, end - pos, "[FST]");
3226  		if (os_snprintf_error(end - pos, ret))
3227  			return -1;
3228  		pos += ret;
3229  	}
3230  #endif /* CONFIG_FST */
3231  	if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
3232  		ret = os_snprintf(pos, end - pos, "[UTF-8]");
3233  		if (os_snprintf_error(end - pos, ret))
3234  			return -1;
3235  		pos += ret;
3236  	}
3237  
3238  	ret = os_snprintf(pos, end - pos, "\t%s",
3239  			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
3240  	if (os_snprintf_error(end - pos, ret))
3241  		return -1;
3242  	pos += ret;
3243  
3244  	ret = os_snprintf(pos, end - pos, "\n");
3245  	if (os_snprintf_error(end - pos, ret))
3246  		return -1;
3247  	pos += ret;
3248  
3249  	return pos - buf;
3250  }
3251  
3252  
wpa_supplicant_ctrl_iface_scan_results(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3253  static int wpa_supplicant_ctrl_iface_scan_results(
3254  	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3255  {
3256  	char *pos, *end;
3257  	struct wpa_bss *bss;
3258  	int ret;
3259  
3260  	pos = buf;
3261  	end = buf + buflen;
3262  	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
3263  			  "flags / ssid\n");
3264  	if (os_snprintf_error(end - pos, ret))
3265  		return pos - buf;
3266  	pos += ret;
3267  
3268  	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3269  		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
3270  							    end - pos);
3271  		if (ret < 0 || ret >= end - pos)
3272  			return pos - buf;
3273  		pos += ret;
3274  	}
3275  
3276  	return pos - buf;
3277  }
3278  
3279  
3280  #ifdef CONFIG_MESH
3281  
wpa_supplicant_ctrl_iface_mesh_interface_add(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)3282  static int wpa_supplicant_ctrl_iface_mesh_interface_add(
3283  	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
3284  {
3285  	char *pos, ifname[IFNAMSIZ + 1];
3286  
3287  	ifname[0] = '\0';
3288  
3289  	pos = os_strstr(cmd, "ifname=");
3290  	if (pos) {
3291  		pos += 7;
3292  		os_strlcpy(ifname, pos, sizeof(ifname));
3293  	}
3294  
3295  	if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3296  		return -1;
3297  
3298  	os_strlcpy(reply, ifname, max_len);
3299  	return os_strlen(ifname);
3300  }
3301  
3302  
wpa_supplicant_ctrl_iface_mesh_group_add(struct wpa_supplicant * wpa_s,char * cmd)3303  static int wpa_supplicant_ctrl_iface_mesh_group_add(
3304  	struct wpa_supplicant *wpa_s, char *cmd)
3305  {
3306  	int id;
3307  	struct wpa_ssid *ssid;
3308  
3309  	id = atoi(cmd);
3310  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3311  
3312  	ssid = wpa_config_get_network(wpa_s->conf, id);
3313  	if (ssid == NULL) {
3314  		wpa_printf(MSG_DEBUG,
3315  			   "CTRL_IFACE: Could not find network id=%d", id);
3316  		return -1;
3317  	}
3318  	if (ssid->mode != WPAS_MODE_MESH) {
3319  		wpa_printf(MSG_DEBUG,
3320  			   "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3321  		return -1;
3322  	}
3323  	if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
3324  	    ssid->key_mgmt != WPA_KEY_MGMT_SAE &&
3325  	    ssid->key_mgmt != WPA_KEY_MGMT_SAE_EXT_KEY) {
3326  		wpa_printf(MSG_ERROR,
3327  			   "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3328  		return -1;
3329  	}
3330  
3331  	/*
3332  	 * TODO: If necessary write our own group_add function,
3333  	 * for now we can reuse select_network
3334  	 */
3335  	wpa_supplicant_select_network(wpa_s, ssid);
3336  
3337  	return 0;
3338  }
3339  
3340  
wpa_supplicant_ctrl_iface_mesh_group_remove(struct wpa_supplicant * wpa_s,char * cmd)3341  static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3342  	struct wpa_supplicant *wpa_s, char *cmd)
3343  {
3344  	struct wpa_supplicant *orig;
3345  	struct wpa_global *global;
3346  	int found = 0;
3347  
3348  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3349  
3350  	global = wpa_s->global;
3351  	orig = wpa_s;
3352  
3353  	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3354  		if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3355  			found = 1;
3356  			break;
3357  		}
3358  	}
3359  	if (!found) {
3360  		wpa_printf(MSG_ERROR,
3361  			   "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3362  			   cmd);
3363  		return -1;
3364  	}
3365  	if (wpa_s->mesh_if_created && wpa_s == orig) {
3366  		wpa_printf(MSG_ERROR,
3367  			   "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3368  		return -1;
3369  	}
3370  
3371  	wpa_s->reassociate = 0;
3372  	wpa_s->disconnected = 1;
3373  	wpa_supplicant_cancel_sched_scan(wpa_s);
3374  	wpa_supplicant_cancel_scan(wpa_s);
3375  
3376  	/*
3377  	 * TODO: If necessary write our own group_remove function,
3378  	 * for now we can reuse deauthenticate
3379  	 */
3380  	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3381  
3382  	if (wpa_s->mesh_if_created)
3383  		wpa_supplicant_remove_iface(global, wpa_s, 0);
3384  
3385  	return 0;
3386  }
3387  
3388  
wpa_supplicant_ctrl_iface_mesh_peer_remove(struct wpa_supplicant * wpa_s,char * cmd)3389  static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3390  	struct wpa_supplicant *wpa_s, char *cmd)
3391  {
3392  	u8 addr[ETH_ALEN];
3393  
3394  	if (hwaddr_aton(cmd, addr) < 0)
3395  		return -1;
3396  
3397  	return wpas_mesh_peer_remove(wpa_s, addr);
3398  }
3399  
3400  
wpa_supplicant_ctrl_iface_mesh_peer_add(struct wpa_supplicant * wpa_s,char * cmd)3401  static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3402  	struct wpa_supplicant *wpa_s, char *cmd)
3403  {
3404  	u8 addr[ETH_ALEN];
3405  	int duration;
3406  	char *pos;
3407  
3408  	pos = os_strstr(cmd, " duration=");
3409  	if (pos) {
3410  		*pos = '\0';
3411  		duration = atoi(pos + 10);
3412  	} else {
3413  		duration = -1;
3414  	}
3415  
3416  	if (hwaddr_aton(cmd, addr))
3417  		return -1;
3418  
3419  	return wpas_mesh_peer_add(wpa_s, addr, duration);
3420  }
3421  
3422  
wpa_supplicant_ctrl_iface_mesh_link_probe(struct wpa_supplicant * wpa_s,char * cmd)3423  static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3424  	struct wpa_supplicant *wpa_s, char *cmd)
3425  {
3426  	struct ether_header *eth;
3427  	u8 addr[ETH_ALEN];
3428  	u8 *buf;
3429  	char *pos;
3430  	size_t payload_len = 0, len;
3431  	int ret = -1;
3432  
3433  	if (hwaddr_aton(cmd, addr))
3434  		return -1;
3435  
3436  	pos = os_strstr(cmd, " payload=");
3437  	if (pos) {
3438  		pos = pos + 9;
3439  		payload_len = os_strlen(pos);
3440  		if (payload_len & 1)
3441  			return -1;
3442  
3443  		payload_len /= 2;
3444  	}
3445  
3446  	len = ETH_HLEN + payload_len;
3447  	buf = os_malloc(len);
3448  	if (!buf)
3449  		return -1;
3450  
3451  	eth = (struct ether_header *) buf;
3452  	os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3453  	os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3454  	eth->ether_type = htons(ETH_P_802_3);
3455  
3456  	if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3457  		goto fail;
3458  
3459  	ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3460  fail:
3461  	os_free(buf);
3462  	return -ret;
3463  }
3464  
3465  #endif /* CONFIG_MESH */
3466  
3467  
wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant * wpa_s,char * cmd)3468  static int wpa_supplicant_ctrl_iface_select_network(
3469  	struct wpa_supplicant *wpa_s, char *cmd)
3470  {
3471  	int id;
3472  	struct wpa_ssid *ssid;
3473  	char *pos;
3474  
3475  	/* cmd: "<network id>" or "any" */
3476  	if (os_strncmp(cmd, "any", 3) == 0) {
3477  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3478  		ssid = NULL;
3479  	} else {
3480  		id = atoi(cmd);
3481  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3482  
3483  		ssid = wpa_config_get_network(wpa_s->conf, id);
3484  		if (ssid == NULL) {
3485  			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3486  				   "network id=%d", id);
3487  			return -1;
3488  		}
3489  		if (ssid->disabled == 2) {
3490  			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3491  				   "SELECT_NETWORK with persistent P2P group");
3492  			return -1;
3493  		}
3494  	}
3495  
3496  	pos = os_strstr(cmd, " freq=");
3497  	if (pos) {
3498  		int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3499  		if (freqs) {
3500  			os_free(wpa_s->select_network_scan_freqs);
3501  			wpa_s->select_network_scan_freqs = freqs;
3502  		}
3503  	}
3504  
3505  	wpa_s->scan_min_time.sec = 0;
3506  	wpa_s->scan_min_time.usec = 0;
3507  	wpa_supplicant_select_network(wpa_s, ssid);
3508  
3509  	return 0;
3510  }
3511  
3512  
wpa_supplicant_ctrl_iface_enable_network(struct wpa_supplicant * wpa_s,char * cmd)3513  static int wpa_supplicant_ctrl_iface_enable_network(
3514  	struct wpa_supplicant *wpa_s, char *cmd)
3515  {
3516  	int id;
3517  	struct wpa_ssid *ssid;
3518  
3519  	/* cmd: "<network id>" or "all" */
3520  	if (os_strcmp(cmd, "all") == 0) {
3521  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3522  		ssid = NULL;
3523  	} else {
3524  		id = atoi(cmd);
3525  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3526  
3527  		ssid = wpa_config_get_network(wpa_s->conf, id);
3528  		if (ssid == NULL) {
3529  			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3530  				   "network id=%d", id);
3531  			return -1;
3532  		}
3533  		if (ssid->disabled == 2) {
3534  			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3535  				   "ENABLE_NETWORK with persistent P2P group");
3536  			return -1;
3537  		}
3538  
3539  		if (os_strstr(cmd, " no-connect")) {
3540  			ssid->disabled = 0;
3541  			return 0;
3542  		}
3543  	}
3544  	wpa_s->scan_min_time.sec = 0;
3545  	wpa_s->scan_min_time.usec = 0;
3546  	wpa_supplicant_enable_network(wpa_s, ssid);
3547  
3548  	return 0;
3549  }
3550  
3551  
wpa_supplicant_ctrl_iface_disable_network(struct wpa_supplicant * wpa_s,char * cmd)3552  static int wpa_supplicant_ctrl_iface_disable_network(
3553  	struct wpa_supplicant *wpa_s, char *cmd)
3554  {
3555  	int id;
3556  	struct wpa_ssid *ssid;
3557  
3558  	/* cmd: "<network id>" or "all" */
3559  	if (os_strcmp(cmd, "all") == 0) {
3560  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3561  		ssid = NULL;
3562  	} else {
3563  		id = atoi(cmd);
3564  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3565  
3566  		ssid = wpa_config_get_network(wpa_s->conf, id);
3567  		if (ssid == NULL) {
3568  			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3569  				   "network id=%d", id);
3570  			return -1;
3571  		}
3572  		if (ssid->disabled == 2) {
3573  			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3574  				   "DISABLE_NETWORK with persistent P2P "
3575  				   "group");
3576  			return -1;
3577  		}
3578  	}
3579  	wpa_supplicant_disable_network(wpa_s, ssid);
3580  
3581  	return 0;
3582  }
3583  
3584  
wpa_supplicant_ctrl_iface_add_network(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3585  static int wpa_supplicant_ctrl_iface_add_network(
3586  	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3587  {
3588  	struct wpa_ssid *ssid;
3589  	int ret;
3590  
3591  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3592  
3593  	ssid = wpa_supplicant_add_network(wpa_s);
3594  	if (ssid == NULL)
3595  		return -1;
3596  
3597  	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
3598  	if (os_snprintf_error(buflen, ret))
3599  		return -1;
3600  	return ret;
3601  }
3602  
3603  
wpa_supplicant_ctrl_iface_remove_network(struct wpa_supplicant * wpa_s,char * cmd)3604  static int wpa_supplicant_ctrl_iface_remove_network(
3605  	struct wpa_supplicant *wpa_s, char *cmd)
3606  {
3607  	int id;
3608  	int result;
3609  
3610  	/* cmd: "<network id>" or "all" */
3611  	if (os_strcmp(cmd, "all") == 0) {
3612  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
3613  		return wpa_supplicant_remove_all_networks(wpa_s);
3614  	}
3615  
3616  	id = atoi(cmd);
3617  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3618  
3619  	result = wpa_supplicant_remove_network(wpa_s, id);
3620  	if (result == -1) {
3621  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3622  			   "id=%d", id);
3623  		return -1;
3624  	}
3625  	if (result == -2) {
3626  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3627  			   "network id=%d", id);
3628  		return -1;
3629  	}
3630  	return 0;
3631  }
3632  
3633  
wpa_supplicant_ctrl_iface_update_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,char * name,char * value)3634  static int wpa_supplicant_ctrl_iface_update_network(
3635  	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3636  	char *name, char *value)
3637  {
3638  	int ret;
3639  
3640  	ret = wpa_config_set(ssid, name, value, 0);
3641  	if (ret < 0) {
3642  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3643  			   "variable '%s'", name);
3644  		return -1;
3645  	}
3646  	if (ret == 1)
3647  		return 0; /* No change to the previously configured value */
3648  
3649  #ifdef CONFIG_BGSCAN
3650  	if (os_strcmp(name, "bgscan") == 0) {
3651  		/*
3652  		 * Reset the bgscan parameters for the current network and
3653  		 * return. There's no need to flush caches for bgscan parameter
3654  		 * changes.
3655  		 */
3656  		if (wpa_s->current_ssid == ssid &&
3657  		    wpa_s->wpa_state == WPA_COMPLETED)
3658  			wpa_supplicant_reset_bgscan(wpa_s);
3659  		return 0;
3660  	}
3661  #endif /* CONFIG_BGSCAN */
3662  
3663  	if (os_strcmp(name, "bssid") != 0 &&
3664  	    os_strncmp(name, "bssid_", 6) != 0 &&
3665  	    os_strcmp(name, "scan_freq") != 0 &&
3666  	    os_strcmp(name, "priority") != 0) {
3667  		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3668  
3669  		if (wpa_s->current_ssid == ssid ||
3670  		    wpa_s->current_ssid == NULL) {
3671  			/*
3672  			 * Invalidate the EAP session cache if anything in the
3673  			 * current or previously used configuration changes.
3674  			 */
3675  			eapol_sm_invalidate_cached_session(wpa_s->eapol);
3676  		}
3677  	}
3678  
3679  	if ((os_strcmp(name, "psk") == 0 &&
3680  	     value[0] == '"' && ssid->ssid_len) ||
3681  	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3682  		wpa_config_update_psk(ssid);
3683  	else if (os_strcmp(name, "priority") == 0)
3684  		wpa_config_update_prio_list(wpa_s->conf);
3685  
3686  	return 0;
3687  }
3688  
3689  
wpa_supplicant_ctrl_iface_set_network(struct wpa_supplicant * wpa_s,char * cmd)3690  static int wpa_supplicant_ctrl_iface_set_network(
3691  	struct wpa_supplicant *wpa_s, char *cmd)
3692  {
3693  	int id, ret, prev_bssid_set, prev_disabled;
3694  	struct wpa_ssid *ssid;
3695  	char *name, *value;
3696  	u8 prev_bssid[ETH_ALEN];
3697  
3698  	/* cmd: "<network id> <variable name> <value>" */
3699  	name = os_strchr(cmd, ' ');
3700  	if (name == NULL)
3701  		return -1;
3702  	*name++ = '\0';
3703  
3704  	value = os_strchr(name, ' ');
3705  	if (value == NULL)
3706  		return -1;
3707  	*value++ = '\0';
3708  
3709  	id = atoi(cmd);
3710  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3711  		   id, name);
3712  	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3713  			      (u8 *) value, os_strlen(value));
3714  
3715  	ssid = wpa_config_get_network(wpa_s->conf, id);
3716  	if (ssid == NULL) {
3717  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3718  			   "id=%d", id);
3719  		return -1;
3720  	}
3721  
3722  	prev_bssid_set = ssid->bssid_set;
3723  	prev_disabled = ssid->disabled;
3724  	os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3725  	ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3726  						       value);
3727  	if (ret == 0 &&
3728  	    (ssid->bssid_set != prev_bssid_set ||
3729  	     !ether_addr_equal(ssid->bssid, prev_bssid)))
3730  		wpas_notify_network_bssid_set_changed(wpa_s, ssid);
3731  
3732  	if (prev_disabled != ssid->disabled &&
3733  	    (prev_disabled == 2 || ssid->disabled == 2))
3734  		wpas_notify_network_type_changed(wpa_s, ssid);
3735  
3736  	return ret;
3737  }
3738  
3739  
wpa_supplicant_ctrl_iface_get_network(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3740  static int wpa_supplicant_ctrl_iface_get_network(
3741  	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3742  {
3743  	int id;
3744  	size_t res;
3745  	struct wpa_ssid *ssid;
3746  	char *name, *value;
3747  
3748  	/* cmd: "<network id> <variable name>" */
3749  	name = os_strchr(cmd, ' ');
3750  	if (name == NULL || buflen == 0)
3751  		return -1;
3752  	*name++ = '\0';
3753  
3754  	id = atoi(cmd);
3755  	wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
3756  		   id, name);
3757  
3758  	ssid = wpa_config_get_network(wpa_s->conf, id);
3759  	if (ssid == NULL) {
3760  		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
3761  			   "id=%d", id);
3762  		return -1;
3763  	}
3764  
3765  	value = wpa_config_get_no_key(ssid, name);
3766  	if (value == NULL) {
3767  		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
3768  			   "variable '%s'", name);
3769  		return -1;
3770  	}
3771  
3772  	res = os_strlcpy(buf, value, buflen);
3773  	if (res >= buflen) {
3774  		os_free(value);
3775  		return -1;
3776  	}
3777  
3778  	os_free(value);
3779  
3780  	return res;
3781  }
3782  
3783  
wpa_supplicant_ctrl_iface_dup_network(struct wpa_supplicant * wpa_s,char * cmd,struct wpa_supplicant * dst_wpa_s)3784  static int wpa_supplicant_ctrl_iface_dup_network(
3785  	struct wpa_supplicant *wpa_s, char *cmd,
3786  	struct wpa_supplicant *dst_wpa_s)
3787  {
3788  	struct wpa_ssid *ssid_s, *ssid_d;
3789  	char *name, *id, *value;
3790  	int id_s, id_d, ret;
3791  
3792  	/* cmd: "<src network id> <dst network id> <variable name>" */
3793  	id = os_strchr(cmd, ' ');
3794  	if (id == NULL)
3795  		return -1;
3796  	*id++ = '\0';
3797  
3798  	name = os_strchr(id, ' ');
3799  	if (name == NULL)
3800  		return -1;
3801  	*name++ = '\0';
3802  
3803  	id_s = atoi(cmd);
3804  	id_d = atoi(id);
3805  
3806  	wpa_printf(MSG_DEBUG,
3807  		   "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3808  		   wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
3809  
3810  	ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3811  	if (ssid_s == NULL) {
3812  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3813  			   "network id=%d", id_s);
3814  		return -1;
3815  	}
3816  
3817  	ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
3818  	if (ssid_d == NULL) {
3819  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3820  			   "network id=%d", id_d);
3821  		return -1;
3822  	}
3823  
3824  	value = wpa_config_get(ssid_s, name);
3825  	if (value == NULL) {
3826  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3827  			   "variable '%s'", name);
3828  		return -1;
3829  	}
3830  
3831  	ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
3832  						       value);
3833  
3834  	os_free(value);
3835  
3836  	return ret;
3837  }
3838  
3839  
wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3840  static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3841  						char *buf, size_t buflen)
3842  {
3843  	char *pos, *end;
3844  	struct wpa_cred *cred;
3845  	int ret;
3846  
3847  	pos = buf;
3848  	end = buf + buflen;
3849  	ret = os_snprintf(pos, end - pos,
3850  			  "cred id / realm / username / domain / imsi\n");
3851  	if (os_snprintf_error(end - pos, ret))
3852  		return pos - buf;
3853  	pos += ret;
3854  
3855  	cred = wpa_s->conf->cred;
3856  	while (cred) {
3857  		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3858  				  cred->id, cred->realm ? cred->realm : "",
3859  				  cred->username ? cred->username : "",
3860  				  cred->domain ? cred->domain[0] : "",
3861  				  cred->imsi ? cred->imsi : "");
3862  		if (os_snprintf_error(end - pos, ret))
3863  			return pos - buf;
3864  		pos += ret;
3865  
3866  		cred = cred->next;
3867  	}
3868  
3869  	return pos - buf;
3870  }
3871  
3872  
wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3873  static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3874  					      char *buf, size_t buflen)
3875  {
3876  	struct wpa_cred *cred;
3877  	int ret;
3878  
3879  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3880  
3881  	cred = wpa_config_add_cred(wpa_s->conf);
3882  	if (cred == NULL)
3883  		return -1;
3884  
3885  	wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3886  
3887  	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
3888  	if (os_snprintf_error(buflen, ret))
3889  		return -1;
3890  	return ret;
3891  }
3892  
3893  
wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant * wpa_s,char * cmd)3894  static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3895  						 char *cmd)
3896  {
3897  	int id;
3898  	struct wpa_cred *cred, *prev;
3899  
3900  	/* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3901  	 * "provisioning_sp=<FQDN> */
3902  	if (os_strcmp(cmd, "all") == 0) {
3903  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
3904  		return wpas_remove_all_creds(wpa_s);
3905  	}
3906  
3907  	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3908  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3909  			   cmd + 8);
3910  		cred = wpa_s->conf->cred;
3911  		while (cred) {
3912  			prev = cred;
3913  			cred = cred->next;
3914  			if (prev->domain) {
3915  				size_t i;
3916  				for (i = 0; i < prev->num_domain; i++) {
3917  					if (os_strcmp(prev->domain[i], cmd + 8)
3918  					    != 0)
3919  						continue;
3920  					wpas_remove_cred(wpa_s, prev);
3921  					break;
3922  				}
3923  			}
3924  		}
3925  		return 0;
3926  	}
3927  
3928  	if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3929  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3930  			   cmd + 16);
3931  		cred = wpa_s->conf->cred;
3932  		while (cred) {
3933  			prev = cred;
3934  			cred = cred->next;
3935  			if (prev->provisioning_sp &&
3936  			    os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
3937  				wpas_remove_cred(wpa_s, prev);
3938  		}
3939  		return 0;
3940  	}
3941  
3942  	id = atoi(cmd);
3943  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3944  
3945  	cred = wpa_config_get_cred(wpa_s->conf, id);
3946  	return wpas_remove_cred(wpa_s, cred);
3947  }
3948  
3949  
wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant * wpa_s,char * cmd)3950  static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3951  					      char *cmd)
3952  {
3953  	int id;
3954  	struct wpa_cred *cred;
3955  	char *name, *value;
3956  
3957  	/* cmd: "<cred id> <variable name> <value>" */
3958  	name = os_strchr(cmd, ' ');
3959  	if (name == NULL)
3960  		return -1;
3961  	*name++ = '\0';
3962  
3963  	value = os_strchr(name, ' ');
3964  	if (value == NULL)
3965  		return -1;
3966  	*value++ = '\0';
3967  
3968  	id = atoi(cmd);
3969  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3970  		   id, name);
3971  	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3972  			      (u8 *) value, os_strlen(value));
3973  
3974  	cred = wpa_config_get_cred(wpa_s->conf, id);
3975  	if (cred == NULL) {
3976  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3977  			   id);
3978  		return -1;
3979  	}
3980  
3981  	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3982  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3983  			   "variable '%s'", name);
3984  		return -1;
3985  	}
3986  
3987  	wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3988  
3989  	return 0;
3990  }
3991  
3992  
wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3993  static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
3994  					      char *cmd, char *buf,
3995  					      size_t buflen)
3996  {
3997  	int id;
3998  	size_t res;
3999  	struct wpa_cred *cred;
4000  	char *name, *value;
4001  
4002  	/* cmd: "<cred id> <variable name>" */
4003  	name = os_strchr(cmd, ' ');
4004  	if (name == NULL)
4005  		return -1;
4006  	*name++ = '\0';
4007  
4008  	id = atoi(cmd);
4009  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
4010  		   id, name);
4011  
4012  	cred = wpa_config_get_cred(wpa_s->conf, id);
4013  	if (cred == NULL) {
4014  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
4015  			   id);
4016  		return -1;
4017  	}
4018  
4019  	value = wpa_config_get_cred_no_key(cred, name);
4020  	if (value == NULL) {
4021  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
4022  			   name);
4023  		return -1;
4024  	}
4025  
4026  	res = os_strlcpy(buf, value, buflen);
4027  	if (res >= buflen) {
4028  		os_free(value);
4029  		return -1;
4030  	}
4031  
4032  	os_free(value);
4033  
4034  	return res;
4035  }
4036  
4037  
4038  #ifndef CONFIG_NO_CONFIG_WRITE
wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant * wpa_s)4039  static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
4040  {
4041  	int ret;
4042  
4043  	if (!wpa_s->conf->update_config) {
4044  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
4045  			   "to update configuration (update_config=0)");
4046  		return -1;
4047  	}
4048  
4049  	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
4050  	if (ret) {
4051  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
4052  			   "update configuration");
4053  	} else {
4054  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
4055  			   " updated");
4056  	}
4057  
4058  	return ret;
4059  }
4060  #endif /* CONFIG_NO_CONFIG_WRITE */
4061  
4062  
4063  struct cipher_info {
4064  	unsigned int capa;
4065  	const char *name;
4066  	int group_only;
4067  };
4068  
4069  static const struct cipher_info ciphers[] = {
4070  	{ WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
4071  	{ WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
4072  	{ WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
4073  	{ WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
4074  #ifndef CONFIG_NO_TKIP
4075  	{ WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
4076  #endif /* CONFIG_NO_TKIP */
4077  	{ WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
4078  #ifdef CONFIG_WEP
4079  	{ WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
4080  	{ WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
4081  #endif /* CONFIG_WEP */
4082  };
4083  
4084  static const struct cipher_info ciphers_group_mgmt[] = {
4085  	{ WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
4086  	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
4087  	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
4088  	{ WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
4089  };
4090  
4091  
ctrl_iface_get_capability_pairwise(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4092  static int ctrl_iface_get_capability_pairwise(int res, bool strict,
4093  					      struct wpa_driver_capa *capa,
4094  					      char *buf, size_t buflen)
4095  {
4096  	int ret;
4097  	char *pos, *end;
4098  	size_t len;
4099  	unsigned int i;
4100  
4101  	pos = buf;
4102  	end = pos + buflen;
4103  
4104  	if (res < 0) {
4105  		if (strict)
4106  			return 0;
4107  #ifdef CONFIG_NO_TKIP
4108  		len = os_strlcpy(buf, "CCMP NONE", buflen);
4109  #else /* CONFIG_NO_TKIP */
4110  		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
4111  #endif /* CONFIG_NO_TKIP */
4112  		if (len >= buflen)
4113  			return -1;
4114  		return len;
4115  	}
4116  
4117  	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4118  		if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
4119  			ret = os_snprintf(pos, end - pos, "%s%s",
4120  					  pos == buf ? "" : " ",
4121  					  ciphers[i].name);
4122  			if (os_snprintf_error(end - pos, ret))
4123  				return pos - buf;
4124  			pos += ret;
4125  		}
4126  	}
4127  
4128  	return pos - buf;
4129  }
4130  
4131  
ctrl_iface_get_capability_group(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4132  static int ctrl_iface_get_capability_group(int res, bool strict,
4133  					   struct wpa_driver_capa *capa,
4134  					   char *buf, size_t buflen)
4135  {
4136  	int ret;
4137  	char *pos, *end;
4138  	size_t len;
4139  	unsigned int i;
4140  
4141  	pos = buf;
4142  	end = pos + buflen;
4143  
4144  	if (res < 0) {
4145  		if (strict)
4146  			return 0;
4147  #ifdef CONFIG_WEP
4148  #ifdef CONFIG_NO_TKIP
4149  		len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen);
4150  #else /* CONFIG_NO_TKIP */
4151  		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
4152  #endif /* CONFIG_NO_TKIP */
4153  #else /* CONFIG_WEP */
4154  #ifdef CONFIG_NO_TKIP
4155  		len = os_strlcpy(buf, "CCMP", buflen);
4156  #else /* CONFIG_NO_TKIP */
4157  		len = os_strlcpy(buf, "CCMP TKIP", buflen);
4158  #endif /* CONFIG_NO_TKIP */
4159  #endif /* CONFIG_WEP */
4160  		if (len >= buflen)
4161  			return -1;
4162  		return len;
4163  	}
4164  
4165  	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4166  		if (capa->enc & ciphers[i].capa) {
4167  			ret = os_snprintf(pos, end - pos, "%s%s",
4168  					  pos == buf ? "" : " ",
4169  					  ciphers[i].name);
4170  			if (os_snprintf_error(end - pos, ret))
4171  				return pos - buf;
4172  			pos += ret;
4173  		}
4174  	}
4175  
4176  	return pos - buf;
4177  }
4178  
4179  
ctrl_iface_get_capability_group_mgmt(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4180  static int ctrl_iface_get_capability_group_mgmt(int res, bool strict,
4181  						struct wpa_driver_capa *capa,
4182  						char *buf, size_t buflen)
4183  {
4184  	int ret;
4185  	char *pos, *end;
4186  	unsigned int i;
4187  
4188  	pos = buf;
4189  	end = pos + buflen;
4190  
4191  	if (res < 0)
4192  		return 0;
4193  
4194  	for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
4195  		if (capa->enc & ciphers_group_mgmt[i].capa) {
4196  			ret = os_snprintf(pos, end - pos, "%s%s",
4197  					  pos == buf ? "" : " ",
4198  					  ciphers_group_mgmt[i].name);
4199  			if (os_snprintf_error(end - pos, ret))
4200  				return pos - buf;
4201  			pos += ret;
4202  		}
4203  	}
4204  
4205  	return pos - buf;
4206  }
4207  
4208  
iftype_str_to_index(const char * iftype_str)4209  static int iftype_str_to_index(const char *iftype_str)
4210  {
4211  	if (!iftype_str)
4212  		return WPA_IF_MAX;
4213  
4214  	if (os_strcmp(iftype_str, "STATION") == 0)
4215  		return WPA_IF_STATION;
4216  
4217  	if (os_strcmp(iftype_str, "AP_VLAN") == 0)
4218  		return WPA_IF_AP_VLAN;
4219  
4220  	if (os_strcmp(iftype_str, "AP") == 0)
4221  		return WPA_IF_AP_BSS;
4222  
4223  	if (os_strcmp(iftype_str, "P2P_GO") == 0)
4224  		return WPA_IF_P2P_GO;
4225  
4226  	if (os_strcmp(iftype_str, "P2P_CLIENT") == 0)
4227  		return WPA_IF_P2P_CLIENT;
4228  
4229  	if (os_strcmp(iftype_str, "P2P_DEVICE") == 0)
4230  		return WPA_IF_P2P_DEVICE;
4231  
4232  	if (os_strcmp(iftype_str, "MESH") == 0)
4233  		return WPA_IF_MESH;
4234  
4235  	if (os_strcmp(iftype_str, "IBSS") == 0)
4236  		return WPA_IF_IBSS;
4237  
4238  	if (os_strcmp(iftype_str, "NAN") == 0)
4239  		return WPA_IF_NAN;
4240  
4241  	return WPA_IF_MAX;
4242  }
4243  
4244  
ctrl_iface_get_capability_key_mgmt(int res,bool strict,struct wpa_driver_capa * capa,const char * iftype_str,char * buf,size_t buflen)4245  static int ctrl_iface_get_capability_key_mgmt(int res, bool strict,
4246  					      struct wpa_driver_capa *capa,
4247  					      const char *iftype_str,
4248  					      char *buf, size_t buflen)
4249  {
4250  	int ret;
4251  	unsigned int key_mgmt;
4252  	char *pos, *end;
4253  	size_t len;
4254  
4255  	pos = buf;
4256  	end = pos + buflen;
4257  
4258  	if (res < 0) {
4259  		if (strict)
4260  			return 0;
4261  		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
4262  				 "NONE", buflen);
4263  		if (len >= buflen)
4264  			return -1;
4265  		return len;
4266  	}
4267  
4268  	if (iftype_str) {
4269  		enum wpa_driver_if_type iftype;
4270  
4271  		iftype = iftype_str_to_index(iftype_str);
4272  		if (iftype == WPA_IF_MAX)
4273  			return -1;
4274  		key_mgmt = capa->key_mgmt_iftype[iftype];
4275  	} else {
4276  		key_mgmt = capa->key_mgmt;
4277  	}
4278  
4279  	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
4280  	if (os_snprintf_error(end - pos, ret))
4281  		return pos - buf;
4282  	pos += ret;
4283  
4284  	if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4285  			WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
4286  		ret = os_snprintf(pos, end - pos, " WPA-EAP");
4287  		if (os_snprintf_error(end - pos, ret))
4288  			return pos - buf;
4289  		pos += ret;
4290  	}
4291  
4292  	if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
4293  			WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4294  		ret = os_snprintf(pos, end - pos, " WPA-PSK");
4295  		if (os_snprintf_error(end - pos, ret))
4296  			return pos - buf;
4297  		pos += ret;
4298  	}
4299  
4300  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
4301  		ret = os_snprintf(pos, end - pos, " WPA-NONE");
4302  		if (os_snprintf_error(end - pos, ret))
4303  			return pos - buf;
4304  		pos += ret;
4305  	}
4306  
4307  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) {
4308  		ret = os_snprintf(pos, end - pos, " WAPI-PSK");
4309  		if (os_snprintf_error(end - pos, ret))
4310  			return pos - buf;
4311  		pos += ret;
4312  	}
4313  
4314  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) {
4315  		ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE");
4316  		if (os_snprintf_error(end - pos, ret))
4317  			return pos - buf;
4318  		pos += ret;
4319  	}
4320  
4321  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) {
4322  		ret = os_snprintf(pos, end - pos, " CCKM");
4323  		if (os_snprintf_error(end - pos, ret))
4324  			return pos - buf;
4325  		pos += ret;
4326  	}
4327  
4328  #ifdef CONFIG_SUITEB
4329  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
4330  		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4331  		if (os_snprintf_error(end - pos, ret))
4332  			return pos - buf;
4333  		pos += ret;
4334  	}
4335  #endif /* CONFIG_SUITEB */
4336  #ifdef CONFIG_SUITEB192
4337  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
4338  		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4339  		if (os_snprintf_error(end - pos, ret))
4340  			return pos - buf;
4341  		pos += ret;
4342  	}
4343  #endif /* CONFIG_SUITEB192 */
4344  #ifdef CONFIG_OWE
4345  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
4346  		ret = os_snprintf(pos, end - pos, " OWE");
4347  		if (os_snprintf_error(end - pos, ret))
4348  			return pos - buf;
4349  		pos += ret;
4350  	}
4351  #endif /* CONFIG_OWE */
4352  #ifdef CONFIG_DPP
4353  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
4354  		ret = os_snprintf(pos, end - pos, " DPP");
4355  		if (os_snprintf_error(end - pos, ret))
4356  			return pos - buf;
4357  		pos += ret;
4358  	}
4359  #endif /* CONFIG_DPP */
4360  #ifdef CONFIG_FILS
4361  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
4362  		ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4363  		if (os_snprintf_error(end - pos, ret))
4364  			return pos - buf;
4365  		pos += ret;
4366  	}
4367  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
4368  		ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4369  		if (os_snprintf_error(end - pos, ret))
4370  			return pos - buf;
4371  		pos += ret;
4372  	}
4373  #ifdef CONFIG_IEEE80211R
4374  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
4375  		ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4376  		if (os_snprintf_error(end - pos, ret))
4377  			return pos - buf;
4378  		pos += ret;
4379  	}
4380  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
4381  		ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4382  		if (os_snprintf_error(end - pos, ret))
4383  			return pos - buf;
4384  		pos += ret;
4385  	}
4386  #endif /* CONFIG_IEEE80211R */
4387  #endif /* CONFIG_FILS */
4388  #ifdef CONFIG_IEEE80211R
4389  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
4390  		ret = os_snprintf(pos, end - pos, " FT-PSK");
4391  		if (os_snprintf_error(end - pos, ret))
4392  			return pos - buf;
4393  		pos += ret;
4394  	}
4395  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) {
4396  		ret = os_snprintf(pos, end - pos, " FT-EAP");
4397  		if (os_snprintf_error(end - pos, ret))
4398  			return pos - buf;
4399  		pos += ret;
4400  	}
4401  #ifdef CONFIG_SAE
4402  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) {
4403  		ret = os_snprintf(pos, end - pos, " FT-SAE");
4404  		if (os_snprintf_error(end - pos, ret))
4405  			return pos - buf;
4406  		pos += ret;
4407  	}
4408  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY) {
4409  		ret = os_snprintf(pos, end - pos, " FT-SAE-EXT-KEY");
4410  		if (os_snprintf_error(end - pos, ret))
4411  			return pos - buf;
4412  		pos += ret;
4413  	}
4414  #endif /* CONFIG_SAE */
4415  #ifdef CONFIG_SHA384
4416  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) {
4417  		ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384");
4418  		if (os_snprintf_error(end - pos, ret))
4419  			return pos - buf;
4420  		pos += ret;
4421  	}
4422  #endif /* CONFIG_SHA384 */
4423  #endif /* CONFIG_IEEE80211R */
4424  #ifdef CONFIG_SAE
4425  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
4426  		ret = os_snprintf(pos, end - pos, " SAE");
4427  		if (os_snprintf_error(end - pos, ret))
4428  			return pos - buf;
4429  		pos += ret;
4430  	}
4431  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY) {
4432  		ret = os_snprintf(pos, end - pos, " SAE-EXT-KEY");
4433  		if (os_snprintf_error(end - pos, ret))
4434  			return pos - buf;
4435  		pos += ret;
4436  	}
4437  #endif /* CONFIG_SAE */
4438  #ifdef CONFIG_SHA256
4439  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) {
4440  		ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256");
4441  		if (os_snprintf_error(end - pos, ret))
4442  			return pos - buf;
4443  		pos += ret;
4444  	}
4445  
4446  	if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) {
4447  		ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256");
4448  		if (os_snprintf_error(end - pos, ret))
4449  			return pos - buf;
4450  		pos += ret;
4451  	}
4452  #endif /* CONFIG_SHA256 */
4453  
4454  	return pos - buf;
4455  }
4456  
4457  
ctrl_iface_get_capability_proto(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4458  static int ctrl_iface_get_capability_proto(int res, bool strict,
4459  					   struct wpa_driver_capa *capa,
4460  					   char *buf, size_t buflen)
4461  {
4462  	int ret;
4463  	char *pos, *end;
4464  	size_t len;
4465  
4466  	pos = buf;
4467  	end = pos + buflen;
4468  
4469  	if (res < 0) {
4470  		if (strict)
4471  			return 0;
4472  		len = os_strlcpy(buf, "RSN WPA", buflen);
4473  		if (len >= buflen)
4474  			return -1;
4475  		return len;
4476  	}
4477  
4478  	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4479  			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4480  		ret = os_snprintf(pos, end - pos, "%sRSN",
4481  				  pos == buf ? "" : " ");
4482  		if (os_snprintf_error(end - pos, ret))
4483  			return pos - buf;
4484  		pos += ret;
4485  	}
4486  
4487  	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4488  			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
4489  		ret = os_snprintf(pos, end - pos, "%sWPA",
4490  				  pos == buf ? "" : " ");
4491  		if (os_snprintf_error(end - pos, ret))
4492  			return pos - buf;
4493  		pos += ret;
4494  	}
4495  
4496  	return pos - buf;
4497  }
4498  
4499  
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)4500  static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
4501  					      int res, bool strict,
4502  					      struct wpa_driver_capa *capa,
4503  					      char *buf, size_t buflen)
4504  {
4505  	int ret;
4506  	char *pos, *end;
4507  	size_t len;
4508  
4509  	pos = buf;
4510  	end = pos + buflen;
4511  
4512  	if (res < 0) {
4513  		if (strict)
4514  			return 0;
4515  		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4516  		if (len >= buflen)
4517  			return -1;
4518  		return len;
4519  	}
4520  
4521  	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
4522  		ret = os_snprintf(pos, end - pos, "%sOPEN",
4523  				  pos == buf ? "" : " ");
4524  		if (os_snprintf_error(end - pos, ret))
4525  			return pos - buf;
4526  		pos += ret;
4527  	}
4528  
4529  	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4530  		ret = os_snprintf(pos, end - pos, "%sSHARED",
4531  				  pos == buf ? "" : " ");
4532  		if (os_snprintf_error(end - pos, ret))
4533  			return pos - buf;
4534  		pos += ret;
4535  	}
4536  
4537  	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
4538  		ret = os_snprintf(pos, end - pos, "%sLEAP",
4539  				  pos == buf ? "" : " ");
4540  		if (os_snprintf_error(end - pos, ret))
4541  			return pos - buf;
4542  		pos += ret;
4543  	}
4544  
4545  #ifdef CONFIG_SAE
4546  	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4547  		ret = os_snprintf(pos, end - pos, "%sSAE",
4548  				  pos == buf ? "" : " ");
4549  		if (os_snprintf_error(end - pos, ret))
4550  			return pos - buf;
4551  		pos += ret;
4552  	}
4553  #endif /* CONFIG_SAE */
4554  
4555  #ifdef CONFIG_FILS
4556  	if (wpa_is_fils_supported(wpa_s)) {
4557  		ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4558  				  pos == buf ? "" : " ");
4559  		if (os_snprintf_error(end - pos, ret))
4560  			return pos - buf;
4561  		pos += ret;
4562  	}
4563  
4564  #ifdef CONFIG_FILS_SK_PFS
4565  	if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4566  		ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4567  				  pos == buf ? "" : " ");
4568  		if (os_snprintf_error(end - pos, ret))
4569  			return pos - buf;
4570  		pos += ret;
4571  	}
4572  #endif /* CONFIG_FILS_SK_PFS */
4573  #endif /* CONFIG_FILS */
4574  
4575  #ifdef CONFIG_PASN
4576  	ret = os_snprintf(pos, end - pos, "%sPASN",
4577  			  pos == buf ? "" : " ");
4578  	if (os_snprintf_error(end - pos, ret))
4579  		return pos - buf;
4580  	pos += ret;
4581  
4582  #endif /* CONFIG_PASN */
4583  
4584  	return pos - buf;
4585  }
4586  
4587  
ctrl_iface_get_capability_modes(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4588  static int ctrl_iface_get_capability_modes(int res, bool strict,
4589  					   struct wpa_driver_capa *capa,
4590  					   char *buf, size_t buflen)
4591  {
4592  	int ret;
4593  	char *pos, *end;
4594  	size_t len;
4595  
4596  	pos = buf;
4597  	end = pos + buflen;
4598  
4599  	if (res < 0) {
4600  		if (strict)
4601  			return 0;
4602  		len = os_strlcpy(buf, "IBSS AP", buflen);
4603  		if (len >= buflen)
4604  			return -1;
4605  		return len;
4606  	}
4607  
4608  	if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
4609  		ret = os_snprintf(pos, end - pos, "%sIBSS",
4610  				  pos == buf ? "" : " ");
4611  		if (os_snprintf_error(end - pos, ret))
4612  			return pos - buf;
4613  		pos += ret;
4614  	}
4615  
4616  	if (capa->flags & WPA_DRIVER_FLAGS_AP) {
4617  		ret = os_snprintf(pos, end - pos, "%sAP",
4618  				  pos == buf ? "" : " ");
4619  		if (os_snprintf_error(end - pos, ret))
4620  			return pos - buf;
4621  		pos += ret;
4622  	}
4623  
4624  #ifdef CONFIG_MESH
4625  	if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4626  		ret = os_snprintf(pos, end - pos, "%sMESH",
4627  				  pos == buf ? "" : " ");
4628  		if (os_snprintf_error(end - pos, ret))
4629  			return pos - buf;
4630  		pos += ret;
4631  	}
4632  #endif /* CONFIG_MESH */
4633  
4634  	return pos - buf;
4635  }
4636  
4637  
ctrl_iface_get_capability_channels(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4638  static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4639  					      char *buf, size_t buflen)
4640  {
4641  	struct hostapd_channel_data *chnl;
4642  	int ret, i, j;
4643  	char *pos, *end, *hmode;
4644  
4645  	pos = buf;
4646  	end = pos + buflen;
4647  
4648  	for (j = 0; j < wpa_s->hw.num_modes; j++) {
4649  		switch (wpa_s->hw.modes[j].mode) {
4650  		case HOSTAPD_MODE_IEEE80211B:
4651  			hmode = "B";
4652  			break;
4653  		case HOSTAPD_MODE_IEEE80211G:
4654  			hmode = "G";
4655  			break;
4656  		case HOSTAPD_MODE_IEEE80211A:
4657  			hmode = "A";
4658  			break;
4659  		case HOSTAPD_MODE_IEEE80211AD:
4660  			hmode = "AD";
4661  			break;
4662  		default:
4663  			continue;
4664  		}
4665  		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
4666  		if (os_snprintf_error(end - pos, ret))
4667  			return pos - buf;
4668  		pos += ret;
4669  		chnl = wpa_s->hw.modes[j].channels;
4670  		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4671  			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4672  				continue;
4673  			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
4674  			if (os_snprintf_error(end - pos, ret))
4675  				return pos - buf;
4676  			pos += ret;
4677  		}
4678  		ret = os_snprintf(pos, end - pos, "\n");
4679  		if (os_snprintf_error(end - pos, ret))
4680  			return pos - buf;
4681  		pos += ret;
4682  	}
4683  
4684  	return pos - buf;
4685  }
4686  
4687  
ctrl_iface_get_capability_freq(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4688  static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4689  					  char *buf, size_t buflen)
4690  {
4691  	struct hostapd_channel_data *chnl;
4692  	int ret, i, j;
4693  	char *pos, *end, *hmode;
4694  
4695  	pos = buf;
4696  	end = pos + buflen;
4697  
4698  	for (j = 0; j < wpa_s->hw.num_modes; j++) {
4699  		switch (wpa_s->hw.modes[j].mode) {
4700  		case HOSTAPD_MODE_IEEE80211B:
4701  			hmode = "B";
4702  			break;
4703  		case HOSTAPD_MODE_IEEE80211G:
4704  			hmode = "G";
4705  			break;
4706  		case HOSTAPD_MODE_IEEE80211A:
4707  			hmode = "A";
4708  			break;
4709  		case HOSTAPD_MODE_IEEE80211AD:
4710  			hmode = "AD";
4711  			break;
4712  		default:
4713  			continue;
4714  		}
4715  		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4716  				  hmode);
4717  		if (os_snprintf_error(end - pos, ret))
4718  			return pos - buf;
4719  		pos += ret;
4720  		chnl = wpa_s->hw.modes[j].channels;
4721  		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4722  			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4723  				continue;
4724  			ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
4725  					  chnl[i].chan, chnl[i].freq,
4726  					  chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4727  					  " (NO_IR)" : "",
4728  					  chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4729  					  " (DFS)" : "");
4730  
4731  			if (os_snprintf_error(end - pos, ret))
4732  				return pos - buf;
4733  			pos += ret;
4734  		}
4735  		ret = os_snprintf(pos, end - pos, "\n");
4736  		if (os_snprintf_error(end - pos, ret))
4737  			return pos - buf;
4738  		pos += ret;
4739  	}
4740  
4741  	return pos - buf;
4742  }
4743  
4744  
wpa_supplicant_ctrl_iface_get_capability(struct wpa_supplicant * wpa_s,const char * _field,char * buf,size_t buflen)4745  static int wpa_supplicant_ctrl_iface_get_capability(
4746  	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4747  	size_t buflen)
4748  {
4749  	struct wpa_driver_capa capa;
4750  	int res;
4751  	char *next_param, *curr_param, *iftype = NULL;
4752  	bool strict = false;
4753  	char field[50];
4754  	size_t len;
4755  
4756  	/* Determine whether or not strict checking was requested */
4757  	len = os_strlcpy(field, _field, sizeof(field));
4758  	if (len >= sizeof(field))
4759  		return -1;
4760  
4761  	next_param = os_strchr(field, ' ');
4762  	while (next_param) {
4763  		*next_param++ = '\0';
4764  		curr_param = next_param;
4765  		next_param = os_strchr(next_param, ' ');
4766  
4767  		if (next_param)
4768  			*next_param = '\0';
4769  
4770  		if (os_strcmp(curr_param, "strict") == 0)
4771  			strict = true;
4772  		else if (os_strncmp(curr_param, "iftype=", 7) == 0)
4773  			iftype = curr_param + 7;
4774  		else
4775  			return -1;
4776  	}
4777  
4778  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s",
4779  		   field, iftype ? " iftype=" : "", iftype ? iftype : "",
4780  		   strict ? " strict" : "");
4781  
4782  	if (os_strcmp(field, "eap") == 0) {
4783  		return eap_get_names(buf, buflen);
4784  	}
4785  
4786  	res = wpa_drv_get_capa(wpa_s, &capa);
4787  
4788  	if (os_strcmp(field, "pairwise") == 0)
4789  		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4790  							  buf, buflen);
4791  
4792  	if (os_strcmp(field, "group") == 0)
4793  		return ctrl_iface_get_capability_group(res, strict, &capa,
4794  						       buf, buflen);
4795  
4796  	if (os_strcmp(field, "group_mgmt") == 0)
4797  		return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4798  							    buf, buflen);
4799  
4800  	if (os_strcmp(field, "key_mgmt") == 0)
4801  		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
4802  							  iftype, buf, buflen);
4803  
4804  	if (os_strcmp(field, "proto") == 0)
4805  		return ctrl_iface_get_capability_proto(res, strict, &capa,
4806  						       buf, buflen);
4807  
4808  	if (os_strcmp(field, "auth_alg") == 0)
4809  		return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4810  							  &capa, buf, buflen);
4811  
4812  	if (os_strcmp(field, "modes") == 0)
4813  		return ctrl_iface_get_capability_modes(res, strict, &capa,
4814  						       buf, buflen);
4815  
4816  	if (os_strcmp(field, "channels") == 0)
4817  		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4818  
4819  	if (os_strcmp(field, "freq") == 0)
4820  		return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4821  
4822  #ifdef CONFIG_TDLS
4823  	if (os_strcmp(field, "tdls") == 0)
4824  		return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4825  #endif /* CONFIG_TDLS */
4826  
4827  #ifdef CONFIG_ERP
4828  	if (os_strcmp(field, "erp") == 0) {
4829  		res = os_snprintf(buf, buflen, "ERP");
4830  		if (os_snprintf_error(buflen, res))
4831  			return -1;
4832  		return res;
4833  	}
4834  #endif /* CONFIG_EPR */
4835  
4836  #ifdef CONFIG_FIPS
4837  	if (os_strcmp(field, "fips") == 0) {
4838  		res = os_snprintf(buf, buflen, "FIPS");
4839  		if (os_snprintf_error(buflen, res))
4840  			return -1;
4841  		return res;
4842  	}
4843  #endif /* CONFIG_FIPS */
4844  
4845  #ifdef CONFIG_ACS
4846  	if (os_strcmp(field, "acs") == 0) {
4847  		res = os_snprintf(buf, buflen, "ACS");
4848  		if (os_snprintf_error(buflen, res))
4849  			return -1;
4850  		return res;
4851  	}
4852  #endif /* CONFIG_ACS */
4853  
4854  #ifdef CONFIG_FILS
4855  	if (os_strcmp(field, "fils") == 0) {
4856  #ifdef CONFIG_FILS_SK_PFS
4857  		if (wpa_is_fils_supported(wpa_s) &&
4858  		    wpa_is_fils_sk_pfs_supported(wpa_s)) {
4859  			res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4860  			if (os_snprintf_error(buflen, res))
4861  				return -1;
4862  			return res;
4863  		}
4864  #endif /* CONFIG_FILS_SK_PFS */
4865  
4866  		if (wpa_is_fils_supported(wpa_s)) {
4867  			res = os_snprintf(buf, buflen, "FILS");
4868  			if (os_snprintf_error(buflen, res))
4869  				return -1;
4870  			return res;
4871  		}
4872  	}
4873  #endif /* CONFIG_FILS */
4874  
4875  	if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4876  		res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4877  		if (os_snprintf_error(buflen, res))
4878  			return -1;
4879  		return res;
4880  	}
4881  
4882  #ifdef CONFIG_DPP
4883  	if (os_strcmp(field, "dpp") == 0) {
4884  #ifdef CONFIG_DPP3
4885  		res = os_snprintf(buf, buflen, "DPP=3");
4886  #elif defined(CONFIG_DPP2)
4887  		res = os_snprintf(buf, buflen, "DPP=2");
4888  #else /* CONFIG_DPP2 */
4889  		res = os_snprintf(buf, buflen, "DPP=1");
4890  #endif /* CONFIG_DPP2 */
4891  		if (os_snprintf_error(buflen, res))
4892  			return -1;
4893  		return res;
4894  	}
4895  #endif /* CONFIG_DPP */
4896  
4897  #ifdef CONFIG_NAN_USD
4898  	if (os_strcmp(field, "nan") == 0) {
4899  		res = os_snprintf(buf, buflen, "USD");
4900  		if (os_snprintf_error(buflen, res))
4901  			return -1;
4902  		return res;
4903  	}
4904  #endif /* CONFIG_NAN_USD */
4905  
4906  #ifdef CONFIG_SAE
4907  	if (os_strcmp(field, "sae") == 0 &&
4908  	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
4909  #ifdef CONFIG_SAE_PK
4910  		res = os_snprintf(buf, buflen, "H2E PK");
4911  #else /* CONFIG_SAE_PK */
4912  		res = os_snprintf(buf, buflen, "H2E");
4913  #endif /* CONFIG_SAE_PK */
4914  		if (os_snprintf_error(buflen, res))
4915  			return -1;
4916  		return res;
4917  	}
4918  #endif /* CONFIG_SAE */
4919  
4920  #ifdef CONFIG_OCV
4921  	if (os_strcmp(field, "ocv") == 0) {
4922  		if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
4923  		    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
4924  			res = os_snprintf(buf, buflen, "supported");
4925  		else
4926  			res = os_snprintf(buf, buflen, "not supported");
4927  		if (os_snprintf_error(buflen, res))
4928  			return -1;
4929  		return res;
4930  	}
4931  #endif /* CONFIG_OCV */
4932  
4933  	if (os_strcmp(field, "beacon_prot") == 0) {
4934  		if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
4935  		    (wpa_s->drv_flags2 &
4936  		     WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
4937  			res = os_snprintf(buf, buflen, "supported");
4938  		else
4939  			res = os_snprintf(buf, buflen, "not supported");
4940  		if (os_snprintf_error(buflen, res))
4941  			return -1;
4942  		return res;
4943  	}
4944  
4945  #ifdef CONFIG_P2P
4946  	if (os_strcmp(field, "p2p2") == 0) {
4947  		if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_P2P_FEATURE_V2)
4948  			res = os_snprintf(buf, buflen, "supported");
4949  		else
4950  			res = os_snprintf(buf, buflen, "not supported");
4951  		if (os_snprintf_error(buflen, res))
4952  			return -1;
4953  		return res;
4954  	}
4955  
4956  	if (os_strcmp(field, "pcc_mode") == 0) {
4957  		if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_P2P_FEATURE_PCC_MODE)
4958  			res = os_snprintf(buf, buflen, "supported");
4959  		else
4960  			res = os_snprintf(buf, buflen, "not supported");
4961  		if (os_snprintf_error(buflen, res))
4962  			return -1;
4963  		return res;
4964  	}
4965  #endif /* CONFIG_P2P */
4966  
4967  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
4968  		   field);
4969  
4970  	return -1;
4971  }
4972  
4973  
4974  #ifdef CONFIG_INTERWORKING
anqp_add_hex(char * pos,char * end,const char * title,struct wpabuf * data)4975  static char * anqp_add_hex(char *pos, char *end, const char *title,
4976  			   struct wpabuf *data)
4977  {
4978  	char *start = pos;
4979  	size_t i;
4980  	int ret;
4981  	const u8 *d;
4982  
4983  	if (data == NULL)
4984  		return start;
4985  
4986  	ret = os_snprintf(pos, end - pos, "%s=", title);
4987  	if (os_snprintf_error(end - pos, ret))
4988  		return start;
4989  	pos += ret;
4990  
4991  	d = wpabuf_head_u8(data);
4992  	for (i = 0; i < wpabuf_len(data); i++) {
4993  		ret = os_snprintf(pos, end - pos, "%02x", *d++);
4994  		if (os_snprintf_error(end - pos, ret))
4995  			return start;
4996  		pos += ret;
4997  	}
4998  
4999  	ret = os_snprintf(pos, end - pos, "\n");
5000  	if (os_snprintf_error(end - pos, ret))
5001  		return start;
5002  	pos += ret;
5003  
5004  	return pos;
5005  }
5006  #endif /* CONFIG_INTERWORKING */
5007  
5008  
5009  #ifdef CONFIG_FILS
print_fils_indication(struct wpa_bss * bss,char * pos,char * end)5010  static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
5011  {
5012  	char *start = pos;
5013  	const u8 *ie, *ie_end;
5014  	u16 info, realms;
5015  	int ret;
5016  
5017  	ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
5018  	if (!ie)
5019  		return 0;
5020  	ie_end = ie + 2 + ie[1];
5021  	ie += 2;
5022  	if (ie_end - ie < 2)
5023  		return 0;
5024  
5025  	info = WPA_GET_LE16(ie);
5026  	ie += 2;
5027  	ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
5028  	if (os_snprintf_error(end - pos, ret))
5029  		return 0;
5030  	pos += ret;
5031  
5032  	if (info & BIT(7)) {
5033  		/* Cache Identifier Included */
5034  		if (ie_end - ie < 2)
5035  			return 0;
5036  		ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
5037  				  ie[0], ie[1]);
5038  		if (os_snprintf_error(end - pos, ret))
5039  			return 0;
5040  		pos += ret;
5041  		ie += 2;
5042  	}
5043  
5044  	if (info & BIT(8)) {
5045  		/* HESSID Included */
5046  		if (ie_end - ie < ETH_ALEN)
5047  			return 0;
5048  		ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
5049  				  MAC2STR(ie));
5050  		if (os_snprintf_error(end - pos, ret))
5051  			return 0;
5052  		pos += ret;
5053  		ie += ETH_ALEN;
5054  	}
5055  
5056  	realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
5057  	if (realms) {
5058  		if (ie_end - ie < realms * 2)
5059  			return 0;
5060  		ret = os_snprintf(pos, end - pos, "fils_realms=");
5061  		if (os_snprintf_error(end - pos, ret))
5062  			return 0;
5063  		pos += ret;
5064  
5065  		ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
5066  		if (ret <= 0)
5067  			return 0;
5068  		pos += ret;
5069  		ie += realms * 2;
5070  		ret = os_snprintf(pos, end - pos, "\n");
5071  		if (os_snprintf_error(end - pos, ret))
5072  			return 0;
5073  		pos += ret;
5074  	}
5075  
5076  	return pos - start;
5077  }
5078  #endif /* CONFIG_FILS */
5079  
5080  
print_rnr(struct wpa_bss * bss,char * pos,char * end)5081  static int print_rnr(struct wpa_bss *bss, char *pos, char *end)
5082  {
5083  	char *start = pos;
5084  	const u8 *ie, *ie_end;
5085  	unsigned int n = 0;
5086  	int ret;
5087  
5088  	ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
5089  	if (!ie)
5090  		return 0;
5091  
5092  	ie_end = ie + 2 + ie[1];
5093  	ie += 2;
5094  
5095  	while (ie < ie_end) {
5096  		const struct ieee80211_neighbor_ap_info *info =
5097  			(const struct ieee80211_neighbor_ap_info *) ie;
5098  		const u8 *tbtt_start;
5099  		size_t left = ie_end - ie;
5100  
5101  		if (left < sizeof(struct ieee80211_neighbor_ap_info))
5102  			return 0;
5103  
5104  		left -= sizeof(struct ieee80211_neighbor_ap_info);
5105  		if (left < info->tbtt_info_len)
5106  			return 0;
5107  
5108  		ret = os_snprintf(pos, end - pos,
5109  				  "ap_info[%u]: tbtt_info: hdr=0x%x, len=%u, op_c=%u, channel=%u, ",
5110  				  n, *ie, info->tbtt_info_len,
5111  				  info->op_class, info->channel);
5112  		if (os_snprintf_error(end - pos, ret))
5113  			return 0;
5114  		pos += ret;
5115  
5116  		ie += sizeof(struct ieee80211_neighbor_ap_info);
5117  		tbtt_start = ie;
5118  		if (info->tbtt_info_len >= 1) {
5119  			ret = os_snprintf(pos, end - pos,
5120  					  "tbtt_offset=%u, ", *ie);
5121  			if (os_snprintf_error(end - pos, ret))
5122  				return 0;
5123  
5124  			ie++;
5125  			pos += ret;
5126  		}
5127  
5128  		if (info->tbtt_info_len >= 7) {
5129  			ret = os_snprintf(pos, end - pos,
5130  					  "bssid=" MACSTR ", ",
5131  					  MAC2STR(ie));
5132  			if (os_snprintf_error(end - pos, ret))
5133  				return 0;
5134  
5135  			ie += ETH_ALEN;
5136  			pos += ret;
5137  		}
5138  
5139  		if (info->tbtt_info_len >= 11) {
5140  			ret = os_snprintf(pos, end - pos,
5141  					  "short SSID=0x%x, ",
5142  					  WPA_GET_LE32(ie));
5143  			if (os_snprintf_error(end - pos, ret))
5144  				return 0;
5145  
5146  			ie += 4;
5147  			pos += ret;
5148  		}
5149  
5150  		if (info->tbtt_info_len >= 12) {
5151  			ret = os_snprintf(pos, end - pos,
5152  					  "bss_params=0x%x, ", *ie);
5153  			if (os_snprintf_error(end - pos, ret))
5154  				return 0;
5155  
5156  			ie++;
5157  			pos += ret;
5158  		}
5159  
5160  		if (info->tbtt_info_len >= 13) {
5161  			ret = os_snprintf(pos, end - pos,
5162  					  "PSD=0x%x, ", *ie);
5163  			if (os_snprintf_error(end - pos, ret))
5164  				return 0;
5165  
5166  			ie++;
5167  			pos += ret;
5168  		}
5169  
5170  		if (info->tbtt_info_len >= 16) {
5171  			ret = os_snprintf(pos, end - pos,
5172  					  "mld ID=%u, link ID=%u",
5173  					  *ie, *(ie + 1) & 0xF);
5174  			if (os_snprintf_error(end - pos, ret))
5175  				return 0;
5176  
5177  			ie += 3;
5178  			pos += ret;
5179  		}
5180  
5181  		ie = tbtt_start + info->tbtt_info_len;
5182  
5183  		ret = os_snprintf(pos, end - pos, "\n");
5184  		if (os_snprintf_error(end - pos, ret))
5185  			return 0;
5186  		pos += ret;
5187  
5188  		n++;
5189  	}
5190  
5191  	return pos - start;
5192  }
5193  
5194  
print_ml(struct wpa_bss * bss,char * pos,char * end)5195  static int print_ml(struct wpa_bss *bss, char *pos, char *end)
5196  {
5197  	const struct ieee80211_eht_ml *ml;
5198  	char *start = pos;
5199  	const u8 *ie, *ie_end;
5200  	u16 ml_control;
5201  	u8 common_info_length;
5202  	int ret;
5203  
5204  	ie = get_ml_ie(wpa_bss_ie_ptr(bss), bss->ie_len,
5205  		       MULTI_LINK_CONTROL_TYPE_BASIC);
5206  	if (!ie)
5207  		return 0;
5208  
5209  	ie_end = ie + 2 + ie[1];
5210  	ie += 3;
5211  	ml = (const struct ieee80211_eht_ml *) ie;
5212  
5213  	/* control + common info length + MLD MAC Address */
5214  	if (ie_end - ie < 2 + 1 + ETH_ALEN)
5215  		return 0;
5216  
5217  	ml_control = le_to_host16(ml->ml_control);
5218  
5219  	common_info_length = *(ie + 2);
5220  	ret = os_snprintf(pos, end - pos,
5221  			  "multi-link: control=0x%x, common info len=%u",
5222  			  ml_control, common_info_length);
5223  	if (os_snprintf_error(end - pos, ret))
5224  		return 0;
5225  	pos += ret;
5226  
5227  	ie += 2;
5228  	if (ie_end - ie < common_info_length)
5229  		return 0;
5230  
5231  	ie++;
5232  	common_info_length--;
5233  
5234  	if (common_info_length < ETH_ALEN)
5235  		return 0;
5236  
5237  	ret = os_snprintf(pos, end - pos, ", MLD addr=" MACSTR, MAC2STR(ie));
5238  	if (os_snprintf_error(end - pos, ret))
5239  		return 0;
5240  	pos += ret;
5241  
5242  	ie += ETH_ALEN;
5243  	common_info_length -= ETH_ALEN;
5244  
5245  	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
5246  		if (common_info_length < 1)
5247  			return 0;
5248  
5249  		ret = os_snprintf(pos, end - pos, ", link ID=%u", *ie & 0x0f);
5250  		if (os_snprintf_error(end - pos, ret))
5251  			return 0;
5252  		pos += ret;
5253  		ie++;
5254  		common_info_length--;
5255  	}
5256  
5257  	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
5258  		if (common_info_length < 1)
5259  			return 0;
5260  
5261  		ret = os_snprintf(pos, end - pos,
5262  				  ", BSS change parameters=0x%x", *ie);
5263  		if (os_snprintf_error(end - pos, ret))
5264  			return 0;
5265  		pos += ret;
5266  		ie++;
5267  		common_info_length--;
5268  	}
5269  
5270  	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
5271  		if (common_info_length < 2)
5272  			return 0;
5273  
5274  		ret = os_snprintf(pos, end - pos, ", MSD Info=0x%x",
5275  				  WPA_GET_LE16(ie));
5276  		if (os_snprintf_error(end - pos, ret))
5277  			return 0;
5278  		pos += ret;
5279  		ie += 2;
5280  		common_info_length -= 2;
5281  	}
5282  
5283  	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
5284  		if (common_info_length < 2)
5285  			return 0;
5286  
5287  		ret = os_snprintf(pos, end - pos, ", EML capabilities=0x%x",
5288  				  WPA_GET_LE16(ie));
5289  		if (os_snprintf_error(end - pos, ret))
5290  			return 0;
5291  		pos += ret;
5292  		ie += 2;
5293  		common_info_length -= 2;
5294  	}
5295  
5296  	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
5297  		if (common_info_length < 2)
5298  			return 0;
5299  
5300  		ret = os_snprintf(pos, end - pos, ", MLD capabilities=0x%x",
5301  				  WPA_GET_LE16(ie));
5302  		if (os_snprintf_error(end - pos, ret))
5303  			return 0;
5304  		pos += ret;
5305  		ie += 2;
5306  		common_info_length -= 2;
5307  	}
5308  
5309  	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
5310  		if (common_info_length < 1)
5311  			return 0;
5312  
5313  		ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie);
5314  		if (os_snprintf_error(end - pos, ret))
5315  			return 0;
5316  		pos += ret;
5317  		ie += 1;
5318  		common_info_length--;
5319  	}
5320  
5321  	ret = os_snprintf(pos, end - pos, "\n");
5322  	if (os_snprintf_error(end - pos, ret))
5323  		return 0;
5324  	pos += ret;
5325  
5326  	return pos - start;
5327  }
5328  
5329  
print_bss_info(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,unsigned long mask,char * buf,size_t buflen)5330  static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
5331  			  unsigned long mask, char *buf, size_t buflen)
5332  {
5333  	size_t i;
5334  	int ret;
5335  	char *pos, *end;
5336  	const u8 *ie, *ie2, *mesh, *owe, *rsnxe;
5337  
5338  	pos = buf;
5339  	end = buf + buflen;
5340  
5341  	if (mask & WPA_BSS_MASK_ID) {
5342  		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
5343  		if (os_snprintf_error(end - pos, ret))
5344  			return 0;
5345  		pos += ret;
5346  	}
5347  
5348  	if (mask & WPA_BSS_MASK_BSSID) {
5349  		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
5350  				  MAC2STR(bss->bssid));
5351  		if (os_snprintf_error(end - pos, ret))
5352  			return 0;
5353  		pos += ret;
5354  	}
5355  
5356  	if (mask & WPA_BSS_MASK_FREQ) {
5357  		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
5358  		if (os_snprintf_error(end - pos, ret))
5359  			return 0;
5360  		pos += ret;
5361  	}
5362  
5363  	if (mask & WPA_BSS_MASK_BEACON_INT) {
5364  		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
5365  				  bss->beacon_int);
5366  		if (os_snprintf_error(end - pos, ret))
5367  			return 0;
5368  		pos += ret;
5369  	}
5370  
5371  	if (mask & WPA_BSS_MASK_CAPABILITIES) {
5372  		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
5373  				  bss->caps);
5374  		if (os_snprintf_error(end - pos, ret))
5375  			return 0;
5376  		pos += ret;
5377  	}
5378  
5379  	if (mask & WPA_BSS_MASK_QUAL) {
5380  		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
5381  		if (os_snprintf_error(end - pos, ret))
5382  			return 0;
5383  		pos += ret;
5384  	}
5385  
5386  	if (mask & WPA_BSS_MASK_NOISE) {
5387  		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
5388  		if (os_snprintf_error(end - pos, ret))
5389  			return 0;
5390  		pos += ret;
5391  	}
5392  
5393  	if (mask & WPA_BSS_MASK_LEVEL) {
5394  		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
5395  		if (os_snprintf_error(end - pos, ret))
5396  			return 0;
5397  		pos += ret;
5398  	}
5399  
5400  	if (mask & WPA_BSS_MASK_TSF) {
5401  		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
5402  				  (unsigned long long) bss->tsf);
5403  		if (os_snprintf_error(end - pos, ret))
5404  			return 0;
5405  		pos += ret;
5406  	}
5407  
5408  	if (mask & WPA_BSS_MASK_AGE) {
5409  		struct os_reltime now;
5410  
5411  		os_get_reltime(&now);
5412  		ret = os_snprintf(pos, end - pos, "age=%d\n",
5413  				  (int) (now.sec - bss->last_update.sec));
5414  		if (os_snprintf_error(end - pos, ret))
5415  			return 0;
5416  		pos += ret;
5417  	}
5418  
5419  	if (mask & WPA_BSS_MASK_IE) {
5420  		ret = os_snprintf(pos, end - pos, "ie=");
5421  		if (os_snprintf_error(end - pos, ret))
5422  			return 0;
5423  		pos += ret;
5424  
5425  		ie = wpa_bss_ie_ptr(bss);
5426  		for (i = 0; i < bss->ie_len; i++) {
5427  			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5428  			if (os_snprintf_error(end - pos, ret))
5429  				return 0;
5430  			pos += ret;
5431  		}
5432  
5433  		ret = os_snprintf(pos, end - pos, "\n");
5434  		if (os_snprintf_error(end - pos, ret))
5435  			return 0;
5436  		pos += ret;
5437  	}
5438  
5439  	if (mask & WPA_BSS_MASK_FLAGS) {
5440  		ret = os_snprintf(pos, end - pos, "flags=");
5441  		if (os_snprintf_error(end - pos, ret))
5442  			return 0;
5443  		pos += ret;
5444  
5445  		mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
5446  
5447  		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
5448  		if (ie)
5449  			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
5450  						    2 + ie[1]);
5451  		ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
5452  		if (ie2)
5453  			pos = wpa_supplicant_ie_txt(pos, end,
5454  						    mesh ? "RSN" : "WPA2", ie2,
5455  						    2 + ie2[1]);
5456  		rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
5457  		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
5458  			ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
5459  			if (os_snprintf_error(end - pos, ret))
5460  				return 0;
5461  			pos += ret;
5462  		}
5463  		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
5464  			ret = os_snprintf(pos, end - pos, "[SAE-PK]");
5465  			if (os_snprintf_error(end - pos, ret))
5466  				return 0;
5467  			pos += ret;
5468  		}
5469  		owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5470  		if (owe) {
5471  			ret = os_snprintf(
5472  				pos, end - pos,
5473  				ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
5474  			if (os_snprintf_error(end - pos, ret))
5475  				return 0;
5476  			pos += ret;
5477  		}
5478  		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
5479  		if (!ie && !ie2 &&
5480  		    (bss->caps & IEEE80211_CAP_PRIVACY)) {
5481  			ret = os_snprintf(pos, end - pos, "[WEP]");
5482  			if (os_snprintf_error(end - pos, ret))
5483  				return 0;
5484  			pos += ret;
5485  		}
5486  
5487  		if (mesh) {
5488  			ret = os_snprintf(pos, end - pos, "[MESH]");
5489  			if (os_snprintf_error(end - pos, ret))
5490  				return 0;
5491  			pos += ret;
5492  		}
5493  
5494  		if (bss_is_dmg(bss)) {
5495  			const char *s;
5496  			ret = os_snprintf(pos, end - pos, "[DMG]");
5497  			if (os_snprintf_error(end - pos, ret))
5498  				return 0;
5499  			pos += ret;
5500  			switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
5501  			case IEEE80211_CAP_DMG_IBSS:
5502  				s = "[IBSS]";
5503  				break;
5504  			case IEEE80211_CAP_DMG_AP:
5505  				s = "[ESS]";
5506  				break;
5507  			case IEEE80211_CAP_DMG_PBSS:
5508  				s = "[PBSS]";
5509  				break;
5510  			default:
5511  				s = "";
5512  				break;
5513  			}
5514  			ret = os_snprintf(pos, end - pos, "%s", s);
5515  			if (os_snprintf_error(end - pos, ret))
5516  				return 0;
5517  			pos += ret;
5518  		} else {
5519  			if (bss->caps & IEEE80211_CAP_IBSS) {
5520  				ret = os_snprintf(pos, end - pos, "[IBSS]");
5521  				if (os_snprintf_error(end - pos, ret))
5522  					return 0;
5523  				pos += ret;
5524  			}
5525  			if (bss->caps & IEEE80211_CAP_ESS) {
5526  				ret = os_snprintf(pos, end - pos, "[ESS]");
5527  				if (os_snprintf_error(end - pos, ret))
5528  					return 0;
5529  				pos += ret;
5530  			}
5531  		}
5532  		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
5533  		    wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
5534  			ret = os_snprintf(pos, end - pos, "[P2P]");
5535  			if (os_snprintf_error(end - pos, ret))
5536  				return 0;
5537  			pos += ret;
5538  		}
5539  #ifdef CONFIG_HS20
5540  		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
5541  			ret = os_snprintf(pos, end - pos, "[HS20]");
5542  			if (os_snprintf_error(end - pos, ret))
5543  				return 0;
5544  			pos += ret;
5545  		}
5546  #endif /* CONFIG_HS20 */
5547  #ifdef CONFIG_FILS
5548  		if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
5549  			ret = os_snprintf(pos, end - pos, "[FILS]");
5550  			if (os_snprintf_error(end - pos, ret))
5551  				return 0;
5552  			pos += ret;
5553  		}
5554  #endif /* CONFIG_FILS */
5555  #ifdef CONFIG_FST
5556  		if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
5557  			ret = os_snprintf(pos, end - pos, "[FST]");
5558  			if (os_snprintf_error(end - pos, ret))
5559  				return 0;
5560  			pos += ret;
5561  		}
5562  #endif /* CONFIG_FST */
5563  		if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
5564  			ret = os_snprintf(pos, end - pos, "[UTF-8]");
5565  			if (os_snprintf_error(end - pos, ret))
5566  				return 0;
5567  			pos += ret;
5568  		}
5569  
5570  		ret = os_snprintf(pos, end - pos, "\n");
5571  		if (os_snprintf_error(end - pos, ret))
5572  			return 0;
5573  		pos += ret;
5574  	}
5575  
5576  	if (mask & WPA_BSS_MASK_SSID) {
5577  		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
5578  				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
5579  		if (os_snprintf_error(end - pos, ret))
5580  			return 0;
5581  		pos += ret;
5582  	}
5583  
5584  #ifdef CONFIG_WPS
5585  	if (mask & WPA_BSS_MASK_WPS_SCAN) {
5586  		ie = wpa_bss_ie_ptr(bss);
5587  		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
5588  		if (ret >= end - pos)
5589  			return 0;
5590  		if (ret > 0)
5591  			pos += ret;
5592  	}
5593  #endif /* CONFIG_WPS */
5594  
5595  #ifdef CONFIG_P2P
5596  	if (mask & WPA_BSS_MASK_P2P_SCAN) {
5597  		ie = wpa_bss_ie_ptr(bss);
5598  		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
5599  		if (ret >= end - pos)
5600  			return 0;
5601  		if (ret > 0)
5602  			pos += ret;
5603  	}
5604  #endif /* CONFIG_P2P */
5605  
5606  #ifdef CONFIG_WIFI_DISPLAY
5607  	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
5608  		struct wpabuf *wfd;
5609  
5610  		ie = wpa_bss_ie_ptr(bss);
5611  		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
5612  						  WFD_IE_VENDOR_TYPE);
5613  		if (wfd) {
5614  			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
5615  			if (os_snprintf_error(end - pos, ret)) {
5616  				wpabuf_free(wfd);
5617  				return 0;
5618  			}
5619  			pos += ret;
5620  
5621  			pos += wpa_snprintf_hex(pos, end - pos,
5622  						wpabuf_head(wfd),
5623  						wpabuf_len(wfd));
5624  			wpabuf_free(wfd);
5625  
5626  			ret = os_snprintf(pos, end - pos, "\n");
5627  			if (os_snprintf_error(end - pos, ret))
5628  				return 0;
5629  			pos += ret;
5630  		}
5631  	}
5632  #endif /* CONFIG_WIFI_DISPLAY */
5633  
5634  #ifdef CONFIG_INTERWORKING
5635  	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
5636  		struct wpa_bss_anqp *anqp = bss->anqp;
5637  		struct wpa_bss_anqp_elem *elem;
5638  
5639  		pos = anqp_add_hex(pos, end, "anqp_capability_list",
5640  				   anqp->capability_list);
5641  		pos = anqp_add_hex(pos, end, "anqp_venue_name",
5642  				   anqp->venue_name);
5643  		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
5644  				   anqp->network_auth_type);
5645  		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
5646  				   anqp->roaming_consortium);
5647  		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
5648  				   anqp->ip_addr_type_availability);
5649  		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
5650  				   anqp->nai_realm);
5651  		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
5652  		pos = anqp_add_hex(pos, end, "anqp_domain_name",
5653  				   anqp->domain_name);
5654  		pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
5655  				   anqp->fils_realm_info);
5656  #ifdef CONFIG_HS20
5657  		pos = anqp_add_hex(pos, end, "hs20_capability_list",
5658  				   anqp->hs20_capability_list);
5659  		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
5660  				   anqp->hs20_operator_friendly_name);
5661  		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
5662  				   anqp->hs20_wan_metrics);
5663  		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
5664  				   anqp->hs20_connection_capability);
5665  		pos = anqp_add_hex(pos, end, "hs20_operating_class",
5666  				   anqp->hs20_operating_class);
5667  #endif /* CONFIG_HS20 */
5668  
5669  		dl_list_for_each(elem, &anqp->anqp_elems,
5670  				 struct wpa_bss_anqp_elem, list) {
5671  			char title[20];
5672  
5673  			os_snprintf(title, sizeof(title), "anqp[%u]",
5674  				    elem->infoid);
5675  			pos = anqp_add_hex(pos, end, title, elem->payload);
5676  			if (elem->protected_response) {
5677  				ret = os_snprintf(pos, end - pos,
5678  						  "protected-anqp-info[%u]=1\n",
5679  						  elem->infoid);
5680  				if (os_snprintf_error(end - pos, ret))
5681  					return 0;
5682  				pos += ret;
5683  			}
5684  		}
5685  	}
5686  #endif /* CONFIG_INTERWORKING */
5687  
5688  #ifdef CONFIG_MESH
5689  	if (mask & WPA_BSS_MASK_MESH_SCAN) {
5690  		ie = wpa_bss_ie_ptr(bss);
5691  		ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
5692  		if (ret >= end - pos)
5693  			return 0;
5694  		if (ret > 0)
5695  			pos += ret;
5696  	}
5697  #endif /* CONFIG_MESH */
5698  
5699  	if (mask & WPA_BSS_MASK_SNR) {
5700  		ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
5701  		if (os_snprintf_error(end - pos, ret))
5702  			return 0;
5703  		pos += ret;
5704  	}
5705  
5706  	if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
5707  		ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
5708  				  bss->est_throughput);
5709  		if (os_snprintf_error(end - pos, ret))
5710  			return 0;
5711  		pos += ret;
5712  	}
5713  
5714  #ifdef CONFIG_FST
5715  	if (mask & WPA_BSS_MASK_FST) {
5716  		ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
5717  		if (ret < 0 || ret >= end - pos)
5718  			return 0;
5719  		pos += ret;
5720  	}
5721  #endif /* CONFIG_FST */
5722  
5723  	if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5724  		ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5725  				  bss->last_update_idx);
5726  		if (os_snprintf_error(end - pos, ret))
5727  			return 0;
5728  		pos += ret;
5729  	}
5730  
5731  	if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5732  		ret = os_snprintf(pos, end - pos, "beacon_ie=");
5733  		if (os_snprintf_error(end - pos, ret))
5734  			return 0;
5735  		pos += ret;
5736  
5737  		ie = wpa_bss_ie_ptr(bss);
5738  		ie += bss->ie_len;
5739  		for (i = 0; i < bss->beacon_ie_len; i++) {
5740  			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5741  			if (os_snprintf_error(end - pos, ret))
5742  				return 0;
5743  			pos += ret;
5744  		}
5745  
5746  		ret = os_snprintf(pos, end - pos, "\n");
5747  		if (os_snprintf_error(end - pos, ret))
5748  			return 0;
5749  		pos += ret;
5750  	}
5751  
5752  #ifdef CONFIG_FILS
5753  	if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5754  		ret = print_fils_indication(bss, pos, end);
5755  		pos += ret;
5756  	}
5757  #endif /* CONFIG_FILS */
5758  
5759  	if (!is_zero_ether_addr(bss->mld_addr) &&
5760  	    (mask & WPA_BSS_MASK_AP_MLD_ADDR)) {
5761  		ret = os_snprintf(pos, end - pos,
5762  				  "ap_mld_addr=" MACSTR "\n",
5763  				  MAC2STR(bss->mld_addr));
5764  		if (os_snprintf_error(end - pos, ret))
5765  			return 0;
5766  		pos += ret;
5767  	}
5768  
5769  	if (mask & WPA_BSS_MASK_RNR)
5770  		pos += print_rnr(bss, pos, end);
5771  
5772  	if (mask & WPA_BSS_MASK_ML)
5773  		pos += print_ml(bss, pos, end);
5774  
5775  	if (mask & WPA_BSS_MASK_DELIM) {
5776  		ret = os_snprintf(pos, end - pos, "====\n");
5777  		if (os_snprintf_error(end - pos, ret))
5778  			return 0;
5779  		pos += ret;
5780  	}
5781  
5782  	return pos - buf;
5783  }
5784  
5785  
wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)5786  static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5787  					 const char *cmd, char *buf,
5788  					 size_t buflen)
5789  {
5790  	u8 bssid[ETH_ALEN];
5791  	size_t i;
5792  	struct wpa_bss *bss;
5793  	struct wpa_bss *bsslast = NULL;
5794  	struct dl_list *next;
5795  	int ret = 0;
5796  	int len;
5797  	char *ctmp, *end = buf + buflen;
5798  	unsigned long mask = WPA_BSS_MASK_ALL;
5799  
5800  	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5801  		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5802  			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
5803  					    list_id);
5804  			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5805  					       list_id);
5806  		} else { /* N1-N2 */
5807  			unsigned int id1, id2;
5808  
5809  			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5810  				wpa_printf(MSG_INFO, "Wrong BSS range "
5811  					   "format");
5812  				return 0;
5813  			}
5814  
5815  			if (*(cmd + 6) == '-')
5816  				id1 = 0;
5817  			else
5818  				id1 = atoi(cmd + 6);
5819  			ctmp++;
5820  			if (*ctmp >= '0' && *ctmp <= '9')
5821  				id2 = atoi(ctmp);
5822  			else
5823  				id2 = (unsigned int) -1;
5824  			bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5825  			if (id2 == (unsigned int) -1)
5826  				bsslast = dl_list_last(&wpa_s->bss_id,
5827  						       struct wpa_bss,
5828  						       list_id);
5829  			else {
5830  				bsslast = wpa_bss_get_id(wpa_s, id2);
5831  				if (bsslast == NULL && bss && id2 > id1) {
5832  					struct wpa_bss *tmp = bss;
5833  					for (;;) {
5834  						next = tmp->list_id.next;
5835  						if (next == &wpa_s->bss_id)
5836  							break;
5837  						tmp = dl_list_entry(
5838  							next, struct wpa_bss,
5839  							list_id);
5840  						if (tmp->id > id2)
5841  							break;
5842  						bsslast = tmp;
5843  					}
5844  				}
5845  			}
5846  		}
5847  	} else if (os_strncmp(cmd, "FIRST", 5) == 0)
5848  		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
5849  	else if (os_strncmp(cmd, "LAST", 4) == 0)
5850  		bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
5851  	else if (os_strncmp(cmd, "ID-", 3) == 0) {
5852  		i = atoi(cmd + 3);
5853  		bss = wpa_bss_get_id(wpa_s, i);
5854  	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5855  		i = atoi(cmd + 5);
5856  		bss = wpa_bss_get_id(wpa_s, i);
5857  		if (bss) {
5858  			next = bss->list_id.next;
5859  			if (next == &wpa_s->bss_id)
5860  				bss = NULL;
5861  			else
5862  				bss = dl_list_entry(next, struct wpa_bss,
5863  						    list_id);
5864  		}
5865  	} else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5866  		bss = wpa_s->current_bss;
5867  #ifdef CONFIG_P2P
5868  	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5869  		if (hwaddr_aton(cmd + 13, bssid) == 0)
5870  			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5871  		else
5872  			bss = NULL;
5873  #endif /* CONFIG_P2P */
5874  	} else if (hwaddr_aton(cmd, bssid) == 0)
5875  		bss = wpa_bss_get_bssid(wpa_s, bssid);
5876  	else {
5877  		struct wpa_bss *tmp;
5878  		i = atoi(cmd);
5879  		bss = NULL;
5880  		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5881  		{
5882  			if (i == 0) {
5883  				bss = tmp;
5884  				break;
5885  			}
5886  			i--;
5887  		}
5888  	}
5889  
5890  	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5891  		mask = strtoul(ctmp + 5, NULL, 0x10);
5892  		if (mask == 0)
5893  			mask = WPA_BSS_MASK_ALL;
5894  	}
5895  
5896  	if (bss == NULL)
5897  		return 0;
5898  
5899  	if (bsslast == NULL)
5900  		bsslast = bss;
5901  	do {
5902  		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5903  		ret += len;
5904  		buf += len;
5905  		buflen -= len;
5906  		if (bss == bsslast) {
5907  			if ((mask & WPA_BSS_MASK_DELIM) && len &&
5908  			    (bss == dl_list_last(&wpa_s->bss_id,
5909  						 struct wpa_bss, list_id))) {
5910  				int res;
5911  
5912  				res = os_snprintf(buf - 5, end - buf + 5,
5913  						  "####\n");
5914  				if (os_snprintf_error(end - buf + 5, res)) {
5915  					wpa_printf(MSG_DEBUG,
5916  						   "Could not add end delim");
5917  				}
5918  			}
5919  			break;
5920  		}
5921  		next = bss->list_id.next;
5922  		if (next == &wpa_s->bss_id)
5923  			break;
5924  		bss = dl_list_entry(next, struct wpa_bss, list_id);
5925  	} while (bss && len);
5926  
5927  	return ret;
5928  }
5929  
5930  
wpa_supplicant_ctrl_iface_ap_scan(struct wpa_supplicant * wpa_s,char * cmd)5931  static int wpa_supplicant_ctrl_iface_ap_scan(
5932  	struct wpa_supplicant *wpa_s, char *cmd)
5933  {
5934  	int ap_scan = atoi(cmd);
5935  	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5936  }
5937  
5938  
wpa_supplicant_ctrl_iface_scan_interval(struct wpa_supplicant * wpa_s,char * cmd)5939  static int wpa_supplicant_ctrl_iface_scan_interval(
5940  	struct wpa_supplicant *wpa_s, char *cmd)
5941  {
5942  	int scan_int = atoi(cmd);
5943  	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
5944  }
5945  
5946  
wpa_supplicant_ctrl_iface_bss_expire_age(struct wpa_supplicant * wpa_s,char * cmd)5947  static int wpa_supplicant_ctrl_iface_bss_expire_age(
5948  	struct wpa_supplicant *wpa_s, char *cmd)
5949  {
5950  	int expire_age = atoi(cmd);
5951  	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5952  }
5953  
5954  
wpa_supplicant_ctrl_iface_bss_expire_count(struct wpa_supplicant * wpa_s,char * cmd)5955  static int wpa_supplicant_ctrl_iface_bss_expire_count(
5956  	struct wpa_supplicant *wpa_s, char *cmd)
5957  {
5958  	int expire_count = atoi(cmd);
5959  	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5960  }
5961  
5962  
wpa_supplicant_ctrl_iface_bss_flush(struct wpa_supplicant * wpa_s,char * cmd)5963  static void wpa_supplicant_ctrl_iface_bss_flush(
5964  	struct wpa_supplicant *wpa_s, char *cmd)
5965  {
5966  	int flush_age = atoi(cmd);
5967  
5968  	if (flush_age == 0)
5969  		wpa_bss_flush(wpa_s);
5970  	else
5971  		wpa_bss_flush_by_age(wpa_s, flush_age);
5972  }
5973  
5974  
5975  #ifdef CONFIG_TESTING_OPTIONS
wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant * wpa_s)5976  static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5977  {
5978  	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5979  	/* MLME-DELETEKEYS.request */
5980  	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
5981  			0, KEY_FLAG_GROUP);
5982  	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
5983  			0, KEY_FLAG_GROUP);
5984  	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
5985  			0, KEY_FLAG_GROUP);
5986  	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
5987  			0, KEY_FLAG_GROUP);
5988  	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
5989  			0, KEY_FLAG_GROUP);
5990  	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
5991  			0, KEY_FLAG_GROUP);
5992  
5993  	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0,
5994  			NULL, 0, KEY_FLAG_PAIRWISE);
5995  	if (wpa_sm_ext_key_id(wpa_s->wpa))
5996  		wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
5997  				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
5998  	/* MLME-SETPROTECTION.request(None) */
5999  	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
6000  				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
6001  				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
6002  	wpa_sm_drop_sa(wpa_s->wpa);
6003  }
6004  #endif /* CONFIG_TESTING_OPTIONS */
6005  
6006  
wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant * wpa_s,char * addr)6007  static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
6008  					  char *addr)
6009  {
6010  #ifdef CONFIG_NO_SCAN_PROCESSING
6011  	return -1;
6012  #else /* CONFIG_NO_SCAN_PROCESSING */
6013  	u8 bssid[ETH_ALEN];
6014  	struct wpa_bss *bss;
6015  	struct wpa_ssid *ssid = wpa_s->current_ssid;
6016  	struct wpa_radio_work *already_connecting;
6017  
6018  	if (hwaddr_aton(addr, bssid)) {
6019  		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
6020  			   "address '%s'", addr);
6021  		return -1;
6022  	}
6023  
6024  	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
6025  
6026  	if (!ssid) {
6027  		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
6028  			   "configuration known for the target AP");
6029  		return -1;
6030  	}
6031  
6032  	bss = wpa_bss_get_connection(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
6033  	if (!bss) {
6034  		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
6035  			   "from BSS table");
6036  		return -1;
6037  	}
6038  
6039  	/*
6040  	 * TODO: Find best network configuration block from configuration to
6041  	 * allow roaming to other networks
6042  	 */
6043  
6044  	already_connecting = radio_work_pending(wpa_s, "sme-connect");
6045  	wpa_s->reassociate = 1;
6046  	wpa_supplicant_connect(wpa_s, bss, ssid);
6047  
6048  	/*
6049  	 * Indicate that an explicitly requested roam is in progress so scan
6050  	 * results that come in before the 'sme-connect' radio work gets
6051  	 * executed do not override the original connection attempt.
6052  	 */
6053  	if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
6054  		wpa_s->roam_in_progress = true;
6055  
6056  	return 0;
6057  #endif /* CONFIG_NO_SCAN_PROCESSING */
6058  }
6059  
6060  
6061  #ifdef CONFIG_P2P
p2p_ctrl_find(struct wpa_supplicant * wpa_s,char * cmd)6062  static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
6063  {
6064  	unsigned int timeout = atoi(cmd);
6065  	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
6066  	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
6067  	u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
6068  	char *pos;
6069  	unsigned int search_delay;
6070  	const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
6071  	u8 seek_count = 0;
6072  	int freq = 0;
6073  	bool include_6ghz = false;
6074  
6075  	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6076  		wpa_dbg(wpa_s, MSG_INFO,
6077  			"Reject P2P_FIND since interface is disabled");
6078  		return -1;
6079  	}
6080  
6081  	if (os_strstr(cmd, " include_6ghz"))
6082  		include_6ghz = true;
6083  	if (os_strstr(cmd, "type=social"))
6084  		type = P2P_FIND_ONLY_SOCIAL;
6085  	else if (os_strstr(cmd, "type=progressive"))
6086  		type = P2P_FIND_PROGRESSIVE;
6087  
6088  	pos = os_strstr(cmd, "dev_id=");
6089  	if (pos) {
6090  		pos += 7;
6091  		if (hwaddr_aton(pos, dev_id))
6092  			return -1;
6093  		_dev_id = dev_id;
6094  	}
6095  
6096  	pos = os_strstr(cmd, "dev_type=");
6097  	if (pos) {
6098  		pos += 9;
6099  		if (wps_dev_type_str2bin(pos, dev_type) < 0)
6100  			return -1;
6101  		_dev_type = dev_type;
6102  	}
6103  
6104  	pos = os_strstr(cmd, "delay=");
6105  	if (pos) {
6106  		pos += 6;
6107  		search_delay = atoi(pos);
6108  	} else
6109  		search_delay = wpas_p2p_search_delay(wpa_s);
6110  
6111  	pos = os_strstr(cmd, "freq=");
6112  	if (pos) {
6113  		pos += 5;
6114  		freq = atoi(pos);
6115  		if (freq <= 0)
6116  			return -1;
6117  	}
6118  
6119  	/* Must be searched for last, because it adds nul termination */
6120  	pos = os_strstr(cmd, " seek=");
6121  	if (pos)
6122  		pos += 6;
6123  	while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
6124  		char *term;
6125  
6126  		_seek[seek_count++] = pos;
6127  		seek = _seek;
6128  		term = os_strchr(pos, ' ');
6129  		if (!term)
6130  			break;
6131  		*term = '\0';
6132  		pos = os_strstr(term + 1, "seek=");
6133  		if (pos)
6134  			pos += 5;
6135  	}
6136  	if (seek_count > P2P_MAX_QUERY_HASH) {
6137  		seek[0] = NULL;
6138  		seek_count = 1;
6139  	}
6140  
6141  	return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
6142  			     _dev_id, search_delay, seek_count, seek, freq,
6143  			     include_6ghz);
6144  }
6145  
6146  
p2ps_ctrl_parse_cpt_priority(const char * pos,u8 * cpt)6147  static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
6148  {
6149  	const char *last = NULL;
6150  	const char *token;
6151  	long int token_len;
6152  	unsigned int i;
6153  
6154  	/* Expected predefined CPT names delimited by ':' */
6155  	for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
6156  		if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
6157  			wpa_printf(MSG_ERROR,
6158  				   "P2PS: CPT name list is too long, expected up to %d names",
6159  				   P2PS_FEATURE_CAPAB_CPT_MAX);
6160  			cpt[0] = 0;
6161  			return -1;
6162  		}
6163  
6164  		token_len = last - token;
6165  
6166  		if (token_len  == 3 &&
6167  		    os_memcmp(token, "UDP", token_len) == 0) {
6168  			cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6169  		} else if (token_len == 3 &&
6170  			   os_memcmp(token, "MAC", token_len) == 0) {
6171  			cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
6172  		} else {
6173  			wpa_printf(MSG_ERROR,
6174  				   "P2PS: Unsupported CPT name '%s'", token);
6175  			cpt[0] = 0;
6176  			return -1;
6177  		}
6178  
6179  		if (isblank((unsigned char) *last)) {
6180  			i++;
6181  			break;
6182  		}
6183  	}
6184  	cpt[i] = 0;
6185  	return 0;
6186  }
6187  
6188  
p2p_parse_asp_provision_cmd(const char * cmd)6189  static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
6190  {
6191  	struct p2ps_provision *p2ps_prov;
6192  	char *pos;
6193  	size_t info_len = 0;
6194  	char *info = NULL;
6195  	u8 role = P2PS_SETUP_NONE;
6196  	long long unsigned val;
6197  	int i;
6198  
6199  	pos = os_strstr(cmd, "info=");
6200  	if (pos) {
6201  		pos += 5;
6202  		info_len = os_strlen(pos);
6203  
6204  		if (info_len) {
6205  			info = os_malloc(info_len + 1);
6206  			if (info) {
6207  				info_len = utf8_unescape(pos, info_len,
6208  							 info, info_len + 1);
6209  			} else
6210  				info_len = 0;
6211  		}
6212  	}
6213  
6214  	p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
6215  	if (p2ps_prov == NULL) {
6216  		os_free(info);
6217  		return NULL;
6218  	}
6219  
6220  	if (info) {
6221  		os_memcpy(p2ps_prov->info, info, info_len);
6222  		p2ps_prov->info[info_len] = '\0';
6223  		os_free(info);
6224  	}
6225  
6226  	pos = os_strstr(cmd, "status=");
6227  	if (pos)
6228  		p2ps_prov->status = atoi(pos + 7);
6229  	else
6230  		p2ps_prov->status = -1;
6231  
6232  	pos = os_strstr(cmd, "adv_id=");
6233  	if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
6234  		goto invalid_args;
6235  	p2ps_prov->adv_id = val;
6236  
6237  	pos = os_strstr(cmd, "method=");
6238  	if (pos)
6239  		p2ps_prov->method = strtol(pos + 7, NULL, 16);
6240  	else
6241  		p2ps_prov->method = 0;
6242  
6243  	pos = os_strstr(cmd, "session=");
6244  	if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
6245  		goto invalid_args;
6246  	p2ps_prov->session_id = val;
6247  
6248  	pos = os_strstr(cmd, "adv_mac=");
6249  	if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
6250  		goto invalid_args;
6251  
6252  	pos = os_strstr(cmd, "session_mac=");
6253  	if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
6254  		goto invalid_args;
6255  
6256  	pos = os_strstr(cmd, "cpt=");
6257  	if (pos) {
6258  		if (p2ps_ctrl_parse_cpt_priority(pos + 4,
6259  						 p2ps_prov->cpt_priority))
6260  			goto invalid_args;
6261  	} else {
6262  		p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6263  	}
6264  
6265  	for (i = 0; p2ps_prov->cpt_priority[i]; i++)
6266  		p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
6267  
6268  	/* force conncap with tstCap (no validity checks) */
6269  	pos = os_strstr(cmd, "tstCap=");
6270  	if (pos) {
6271  		role = strtol(pos + 7, NULL, 16);
6272  	} else {
6273  		pos = os_strstr(cmd, "role=");
6274  		if (pos) {
6275  			role = strtol(pos + 5, NULL, 16);
6276  			if (role != P2PS_SETUP_CLIENT &&
6277  			    role != P2PS_SETUP_GROUP_OWNER)
6278  				role = P2PS_SETUP_NONE;
6279  		}
6280  	}
6281  	p2ps_prov->role = role;
6282  
6283  	return p2ps_prov;
6284  
6285  invalid_args:
6286  	os_free(p2ps_prov);
6287  	return NULL;
6288  }
6289  
6290  
p2p_ctrl_asp_provision_resp(struct wpa_supplicant * wpa_s,char * cmd)6291  static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
6292  {
6293  	u8 addr[ETH_ALEN];
6294  	struct p2ps_provision *p2ps_prov;
6295  	char *pos;
6296  
6297  	/* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
6298  
6299  	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6300  
6301  	if (hwaddr_aton(cmd, addr))
6302  		return -1;
6303  
6304  	pos = cmd + 17;
6305  	if (*pos != ' ')
6306  		return -1;
6307  
6308  	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6309  	if (!p2ps_prov)
6310  		return -1;
6311  
6312  	if (p2ps_prov->status < 0) {
6313  		os_free(p2ps_prov);
6314  		return -1;
6315  	}
6316  
6317  	return wpas_p2p_prov_disc(wpa_s, addr, NULL, 0, WPAS_P2P_PD_FOR_ASP,
6318  				  p2ps_prov);
6319  }
6320  
6321  
p2p_ctrl_asp_provision(struct wpa_supplicant * wpa_s,char * cmd)6322  static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
6323  {
6324  	u8 addr[ETH_ALEN];
6325  	struct p2ps_provision *p2ps_prov;
6326  	char *pos;
6327  
6328  	/* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
6329  	 *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
6330  	 */
6331  
6332  	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6333  	if (hwaddr_aton(cmd, addr))
6334  		return -1;
6335  
6336  	pos = cmd + 17;
6337  	if (*pos != ' ')
6338  		return -1;
6339  
6340  	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6341  	if (!p2ps_prov)
6342  		return -1;
6343  
6344  	p2ps_prov->pd_seeker = 1;
6345  
6346  	return wpas_p2p_prov_disc(wpa_s, addr, NULL, 0, WPAS_P2P_PD_FOR_ASP,
6347  				  p2ps_prov);
6348  }
6349  
6350  
bootstrap_pwd_required(u16 bootstrap)6351  static bool bootstrap_pwd_required(u16 bootstrap)
6352  {
6353  	switch (bootstrap) {
6354  	case P2P_PBMA_OPPORTUNISTIC:
6355  		return false;
6356  	case P2P_PBMA_PIN_CODE_DISPLAY:
6357  	case P2P_PBMA_PASSPHRASE_DISPLAY:
6358  	case P2P_PBMA_QR_DISPLAY:
6359  	case P2P_PBMA_NFC_TAG:
6360  	case P2P_PBMA_PIN_CODE_KEYPAD:
6361  	case P2P_PBMA_PASSPHRASE_KEYPAD:
6362  	case P2P_PBMA_QR_SCAN:
6363  	case P2P_PBMA_NFC_READER:
6364  		return true;
6365  	case P2P_PBMA_SERVICE_MANAGED:
6366  	case P2P_PBMA_HANDSHAKE_SKIP:
6367  		return false;
6368  	}
6369  
6370  	return false;
6371  }
6372  
6373  
p2p_ctrl_connect(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6374  static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
6375  			    char *buf, size_t buflen)
6376  {
6377  	u8 addr[ETH_ALEN];
6378  	char *pos, *pos2;
6379  	char *pin = NULL;
6380  	enum p2p_wps_method wps_method;
6381  	int new_pin;
6382  	int ret;
6383  	int persistent_group, persistent_id = -1;
6384  	int join;
6385  	int auth;
6386  	int automatic;
6387  	int go_intent = -1;
6388  	int freq = 0;
6389  	int pd;
6390  	int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
6391  	int edmg;
6392  	u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
6393  	size_t group_ssid_len = 0;
6394  	int he;
6395  	bool allow_6ghz;
6396  	bool p2p2, skip_prov;
6397  	u16 bootstrap = 0;
6398  	const char *password = NULL;
6399  	char *token, *context = NULL;
6400  
6401  	if (!wpa_s->global->p2p_init_wpa_s)
6402  		return -1;
6403  	if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
6404  		wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
6405  			wpa_s->global->p2p_init_wpa_s->ifname);
6406  		wpa_s = wpa_s->global->p2p_init_wpa_s;
6407  	}
6408  
6409  	/* <addr> <"pbc" | "pin" | "pair" | PIN> [label|display|keypad|p2ps]
6410  	 * [persistent|persistent=<network id>]
6411  	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
6412  	 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>]
6413  	 * [p2p2] [skip_prov] [bstrapmethod=<value>] [password=<string>]
6414  	 */
6415  
6416  	if (hwaddr_aton(cmd, addr))
6417  		return -1;
6418  
6419  	pos = cmd + 17;
6420  	if (*pos != ' ')
6421  		return -1;
6422  	pos++;
6423  
6424  	persistent_group = os_strstr(pos, " persistent") != NULL;
6425  	pos2 = os_strstr(pos, " persistent=");
6426  	if (pos2) {
6427  		struct wpa_ssid *ssid;
6428  		persistent_id = atoi(pos2 + 12);
6429  		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6430  		if (ssid == NULL || ssid->disabled != 2 ||
6431  		    ssid->mode != WPAS_MODE_P2P_GO) {
6432  			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
6433  				   "SSID id=%d for persistent P2P group (GO)",
6434  				   persistent_id);
6435  			return -1;
6436  		}
6437  	}
6438  	join = os_strstr(pos, " join") != NULL;
6439  	allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
6440  	auth = os_strstr(pos, " auth") != NULL;
6441  	automatic = os_strstr(pos, " auto") != NULL;
6442  	pd = os_strstr(pos, " provdisc") != NULL;
6443  	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6444  	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6445  		vht;
6446  	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
6447  	edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
6448  	p2p2 = os_strstr(pos, " p2p2") != NULL;
6449  	skip_prov = os_strstr(pos, " skip_prov") != NULL;
6450  
6451  	pos2 = os_strstr(pos, " go_intent=");
6452  	if (pos2) {
6453  		pos2 += 11;
6454  		go_intent = atoi(pos2);
6455  		if (go_intent < 0 || go_intent > 15)
6456  			return -1;
6457  	}
6458  
6459  	pos2 = os_strstr(pos, " freq=");
6460  	if (pos2) {
6461  		pos2 += 6;
6462  		freq = atoi(pos2);
6463  		if (freq <= 0)
6464  			return -1;
6465  	}
6466  
6467  	pos2 = os_strstr(pos, " freq2=");
6468  	if (pos2)
6469  		freq2 = atoi(pos2 + 7);
6470  
6471  	pos2 = os_strstr(pos, " max_oper_chwidth=");
6472  	if (pos2)
6473  		chwidth = atoi(pos2 + 18);
6474  
6475  	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
6476  	if (max_oper_chwidth < 0)
6477  		return -1;
6478  
6479  	if (allow_6ghz && chwidth == 40)
6480  		max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
6481  
6482  	pos2 = os_strstr(pos, " ssid=");
6483  	if (pos2) {
6484  		char *end;
6485  
6486  		pos2 += 6;
6487  		end = os_strchr(pos2, ' ');
6488  		if (!end)
6489  			group_ssid_len = os_strlen(pos2) / 2;
6490  		else
6491  			group_ssid_len = (end - pos2) / 2;
6492  		if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
6493  		    hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
6494  			return -1;
6495  		group_ssid = _group_ssid;
6496  	}
6497  
6498  	if (os_strncmp(pos, "pin", 3) == 0) {
6499  		/* Request random PIN (to be displayed) and enable the PIN */
6500  		wps_method = WPS_PIN_DISPLAY;
6501  	} else if (os_strncmp(pos, "pbc", 3) == 0) {
6502  		wps_method = WPS_PBC;
6503  	} else if (os_strstr(pos, "p2ps") != NULL) {
6504  		wps_method = WPS_P2PS;
6505  	} else if (os_strncmp(pos, "pair", 4) == 0 && p2p2) {
6506  		wps_method = WPS_NOT_READY;
6507  	} else {
6508  		pin = pos;
6509  		pos = os_strchr(pin, ' ');
6510  		wps_method = WPS_PIN_KEYPAD;
6511  		if (pos) {
6512  			*pos++ = '\0';
6513  			if (os_strncmp(pos, "display", 7) == 0)
6514  				wps_method = WPS_PIN_DISPLAY;
6515  		}
6516  		if (!wps_pin_str_valid(pin)) {
6517  			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
6518  			return 17;
6519  		}
6520  	}
6521  
6522  	pos2 = os_strstr(pos, "bstrapmethod=");
6523  	if (pos2) {
6524  		pos2 += 13;
6525  		bootstrap = atoi(pos2);
6526  	}
6527  
6528  	while ((token = str_token(pos, " ", &context))) {
6529  		if (os_strncmp(token, "password=", 9) == 0) {
6530  			password = token + 9;
6531  			continue;
6532  		}
6533  	}
6534  
6535  	if (bootstrap_pwd_required(bootstrap) && !password) {
6536  		wpa_printf(MSG_DEBUG,
6537  			   "CTRL_IFACE: This P2P2 bootstrap method requires password");
6538  		return -1;
6539  	}
6540  
6541  	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
6542  				   persistent_group, automatic, join,
6543  				   auth, go_intent, freq, freq2, persistent_id,
6544  				   pd, ht40, vht, max_oper_chwidth, he, edmg,
6545  				   group_ssid, group_ssid_len, allow_6ghz, p2p2,
6546  				   bootstrap, password, skip_prov);
6547  	if (new_pin == -2) {
6548  		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
6549  		return 25;
6550  	}
6551  	if (new_pin == -3) {
6552  		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
6553  		return 25;
6554  	}
6555  	if (new_pin < 0)
6556  		return -1;
6557  	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
6558  		ret = os_snprintf(buf, buflen, "%08d", new_pin);
6559  		if (os_snprintf_error(buflen, ret))
6560  			return -1;
6561  		return ret;
6562  	}
6563  
6564  	os_memcpy(buf, "OK\n", 3);
6565  	return 3;
6566  }
6567  
6568  
p2p_ctrl_listen(struct wpa_supplicant * wpa_s,char * cmd)6569  static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
6570  {
6571  	unsigned int timeout = atoi(cmd);
6572  	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6573  		wpa_dbg(wpa_s, MSG_INFO,
6574  			"Reject P2P_LISTEN since interface is disabled");
6575  		return -1;
6576  	}
6577  	return wpas_p2p_listen(wpa_s, timeout);
6578  }
6579  
6580  
p2p_ctrl_prov_disc(struct wpa_supplicant * wpa_s,char * cmd)6581  static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
6582  {
6583  	u8 addr[ETH_ALEN];
6584  	char *pos, *pos2;
6585  	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
6586  	u16 bootstrap = 0;
6587  
6588  	/* <addr> <config method> [join|auto] [bstrapmethod=<value>] */
6589  
6590  	if (hwaddr_aton(cmd, addr))
6591  		return -1;
6592  
6593  	pos = cmd + 17;
6594  	if (*pos != ' ')
6595  		return -1;
6596  	pos++;
6597  
6598  	if (os_strstr(pos, " join") != NULL)
6599  		use = WPAS_P2P_PD_FOR_JOIN;
6600  	else if (os_strstr(pos, " auto") != NULL)
6601  		use = WPAS_P2P_PD_AUTO;
6602  
6603  	pos2 = os_strstr(pos, "bstrapmethod=");
6604  	if (pos2) {
6605  		pos2 += 13;
6606  		bootstrap = atoi(pos2);
6607  	}
6608  
6609  	return wpas_p2p_prov_disc(wpa_s, addr, pos, bootstrap, use, NULL);
6610  }
6611  
6612  
p2p_get_passphrase(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)6613  static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
6614  			      size_t buflen)
6615  {
6616  	struct wpa_ssid *ssid = wpa_s->current_ssid;
6617  
6618  	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6619  	    ssid->passphrase == NULL)
6620  		return -1;
6621  
6622  	os_strlcpy(buf, ssid->passphrase, buflen);
6623  	return os_strlen(buf);
6624  }
6625  
6626  
p2p_ctrl_validate_dira(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6627  static int p2p_ctrl_validate_dira(struct wpa_supplicant *wpa_s, char *cmd,
6628  				  char *buf, size_t buflen)
6629  {
6630  	char *pos, *pos2;
6631  	u8 addr[ETH_ALEN];
6632  	u8 nonce[DEVICE_IDENTITY_NONCE_LEN];
6633  	u8 tag[DEVICE_IDENTITY_TAG_LEN];
6634  	int id;
6635  	int res;
6636  
6637  	if (hwaddr_aton(cmd, addr))
6638  		return -1;
6639  
6640  	pos = cmd + 17;
6641  	if (*pos != ' ')
6642  		return -1;
6643  
6644  	pos2 = os_strstr(pos, "nonce=");
6645  	if (pos2) {
6646  		pos2 += 6;
6647  		if (hexstr2bin(pos2, nonce, sizeof(nonce)) < 0)
6648  			return -1;
6649  	} else {
6650  		return -1;
6651  	}
6652  
6653  	pos2 = os_strstr(pos, "tag=");
6654  	if (pos2) {
6655  		pos2 += 4;
6656  		if (hexstr2bin(pos2, tag, sizeof(tag)) < 0)
6657  			return -1;
6658  	} else {
6659  		return -1;
6660  	}
6661  
6662  	id = wpas_p2p_validate_dira(wpa_s, addr, 0, nonce, tag);
6663  	if (id <= 0)
6664  		return -1;
6665  
6666  	res = os_snprintf(buf, buflen, "%u", id);
6667  	if (os_snprintf_error(buflen, res))
6668  		return -1;
6669  	return res;
6670  }
6671  
6672  
p2p_ctrl_serv_disc_req(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6673  static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
6674  				  char *buf, size_t buflen)
6675  {
6676  	u64 ref;
6677  	int res;
6678  	u8 dst_buf[ETH_ALEN], *dst;
6679  	struct wpabuf *tlvs;
6680  	char *pos;
6681  	size_t len;
6682  
6683  	if (hwaddr_aton(cmd, dst_buf))
6684  		return -1;
6685  	dst = dst_buf;
6686  	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
6687  	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
6688  		dst = NULL;
6689  	pos = cmd + 17;
6690  	if (*pos != ' ')
6691  		return -1;
6692  	pos++;
6693  
6694  	if (os_strncmp(pos, "upnp ", 5) == 0) {
6695  		u8 version;
6696  		pos += 5;
6697  		if (hexstr2bin(pos, &version, 1) < 0)
6698  			return -1;
6699  		pos += 2;
6700  		if (*pos != ' ')
6701  			return -1;
6702  		pos++;
6703  		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
6704  #ifdef CONFIG_WIFI_DISPLAY
6705  	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
6706  		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
6707  #endif /* CONFIG_WIFI_DISPLAY */
6708  	} else if (os_strncmp(pos, "asp ", 4) == 0) {
6709  		char *svc_str;
6710  		char *svc_info = NULL;
6711  		u32 id;
6712  
6713  		pos += 4;
6714  		if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
6715  			return -1;
6716  
6717  		pos = os_strchr(pos, ' ');
6718  		if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
6719  			return -1;
6720  
6721  		svc_str = pos + 1;
6722  
6723  		pos = os_strchr(svc_str, ' ');
6724  
6725  		if (pos)
6726  			*pos++ = '\0';
6727  
6728  		/* All remaining data is the svc_info string */
6729  		if (pos && pos[0] && pos[0] != ' ') {
6730  			len = os_strlen(pos);
6731  
6732  			/* Unescape in place */
6733  			len = utf8_unescape(pos, len, pos, len);
6734  			if (len > 0xff)
6735  				return -1;
6736  
6737  			svc_info = pos;
6738  		}
6739  
6740  		ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
6741  					      svc_str, svc_info);
6742  	} else {
6743  		len = os_strlen(pos);
6744  		if (len & 1)
6745  			return -1;
6746  		len /= 2;
6747  		tlvs = wpabuf_alloc(len);
6748  		if (tlvs == NULL)
6749  			return -1;
6750  		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
6751  			wpabuf_free(tlvs);
6752  			return -1;
6753  		}
6754  
6755  		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
6756  		wpabuf_free(tlvs);
6757  	}
6758  	if (ref == 0)
6759  		return -1;
6760  	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
6761  	if (os_snprintf_error(buflen, res))
6762  		return -1;
6763  	return res;
6764  }
6765  
6766  
p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant * wpa_s,char * cmd)6767  static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
6768  					 char *cmd)
6769  {
6770  	long long unsigned val;
6771  	u64 req;
6772  	if (sscanf(cmd, "%llx", &val) != 1)
6773  		return -1;
6774  	req = val;
6775  	return wpas_p2p_sd_cancel_request(wpa_s, req);
6776  }
6777  
6778  
p2p_ctrl_serv_disc_resp(struct wpa_supplicant * wpa_s,char * cmd)6779  static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
6780  {
6781  	int freq;
6782  	u8 dst[ETH_ALEN];
6783  	u8 dialog_token;
6784  	struct wpabuf *resp_tlvs;
6785  	char *pos, *pos2;
6786  	size_t len;
6787  
6788  	pos = os_strchr(cmd, ' ');
6789  	if (pos == NULL)
6790  		return -1;
6791  	*pos++ = '\0';
6792  	freq = atoi(cmd);
6793  	if (freq == 0)
6794  		return -1;
6795  
6796  	if (hwaddr_aton(pos, dst))
6797  		return -1;
6798  	pos += 17;
6799  	if (*pos != ' ')
6800  		return -1;
6801  	pos++;
6802  
6803  	pos2 = os_strchr(pos, ' ');
6804  	if (pos2 == NULL)
6805  		return -1;
6806  	*pos2++ = '\0';
6807  	dialog_token = atoi(pos);
6808  
6809  	len = os_strlen(pos2);
6810  	if (len & 1)
6811  		return -1;
6812  	len /= 2;
6813  	resp_tlvs = wpabuf_alloc(len);
6814  	if (resp_tlvs == NULL)
6815  		return -1;
6816  	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
6817  		wpabuf_free(resp_tlvs);
6818  		return -1;
6819  	}
6820  
6821  	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
6822  	wpabuf_free(resp_tlvs);
6823  	return 0;
6824  }
6825  
6826  
p2p_ctrl_serv_disc_external(struct wpa_supplicant * wpa_s,char * cmd)6827  static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
6828  				       char *cmd)
6829  {
6830  	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
6831  		return -1;
6832  	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
6833  	return 0;
6834  }
6835  
6836  
p2p_ctrl_service_add_bonjour(struct wpa_supplicant * wpa_s,char * cmd)6837  static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
6838  					char *cmd)
6839  {
6840  	char *pos;
6841  	size_t len;
6842  	struct wpabuf *query, *resp;
6843  	int ret;
6844  
6845  	pos = os_strchr(cmd, ' ');
6846  	if (pos == NULL)
6847  		return -1;
6848  	*pos++ = '\0';
6849  
6850  	len = os_strlen(cmd);
6851  	if (len & 1)
6852  		return -1;
6853  	len /= 2;
6854  	query = wpabuf_alloc(len);
6855  	if (query == NULL)
6856  		return -1;
6857  	ret = hexstr2bin(cmd, wpabuf_put(query, len), len);
6858  	if (ret < 0)
6859  		goto err_query;
6860  	ret = -1;
6861  	len = os_strlen(pos);
6862  	if (len & 1)
6863  		goto err_query;
6864  	len /= 2;
6865  	resp = wpabuf_alloc(len);
6866  	if (!resp)
6867  		goto err_query;
6868  	ret = hexstr2bin(pos, wpabuf_put(resp, len), len);
6869  	if (ret < 0)
6870  		goto err_resp;
6871  
6872  	ret = wpas_p2p_service_add_bonjour(wpa_s, query, resp);
6873  
6874  err_resp:
6875  	wpabuf_free(resp);
6876  err_query:
6877  	wpabuf_free(query);
6878  	return ret;
6879  }
6880  
6881  
p2p_ctrl_service_add_upnp(struct wpa_supplicant * wpa_s,char * cmd)6882  static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6883  {
6884  	char *pos;
6885  	u8 version;
6886  
6887  	pos = os_strchr(cmd, ' ');
6888  	if (pos == NULL)
6889  		return -1;
6890  	*pos++ = '\0';
6891  
6892  	if (hexstr2bin(cmd, &version, 1) < 0)
6893  		return -1;
6894  
6895  	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6896  }
6897  
6898  
p2p_ctrl_service_add_asp(struct wpa_supplicant * wpa_s,u8 replace,char * cmd)6899  static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6900  				    u8 replace, char *cmd)
6901  {
6902  	char *pos;
6903  	char *adv_str;
6904  	u32 auto_accept, adv_id, svc_state, config_methods;
6905  	char *svc_info = NULL;
6906  	char *cpt_prio_str;
6907  	u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
6908  
6909  	pos = os_strchr(cmd, ' ');
6910  	if (pos == NULL)
6911  		return -1;
6912  	*pos++ = '\0';
6913  
6914  	/* Auto-Accept value is mandatory, and must be one of the
6915  	 * single values (0, 1, 2, 4) */
6916  	auto_accept = atoi(cmd);
6917  	switch (auto_accept) {
6918  	case P2PS_SETUP_NONE: /* No auto-accept */
6919  	case P2PS_SETUP_NEW:
6920  	case P2PS_SETUP_CLIENT:
6921  	case P2PS_SETUP_GROUP_OWNER:
6922  		break;
6923  	default:
6924  		return -1;
6925  	}
6926  
6927  	/* Advertisement ID is mandatory */
6928  	cmd = pos;
6929  	pos = os_strchr(cmd, ' ');
6930  	if (pos == NULL)
6931  		return -1;
6932  	*pos++ = '\0';
6933  
6934  	/* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6935  	if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6936  		return -1;
6937  
6938  	/* Only allow replacements if exist, and adds if not */
6939  	if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6940  		if (!replace)
6941  			return -1;
6942  	} else {
6943  		if (replace)
6944  			return -1;
6945  	}
6946  
6947  	/* svc_state between 0 - 0xff is mandatory */
6948  	if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6949  		return -1;
6950  
6951  	pos = os_strchr(pos, ' ');
6952  	if (pos == NULL)
6953  		return -1;
6954  
6955  	/* config_methods is mandatory */
6956  	pos++;
6957  	if (sscanf(pos, "%x", &config_methods) != 1)
6958  		return -1;
6959  
6960  	if (!(config_methods &
6961  	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6962  		return -1;
6963  
6964  	pos = os_strchr(pos, ' ');
6965  	if (pos == NULL)
6966  		return -1;
6967  
6968  	pos++;
6969  	adv_str = pos;
6970  
6971  	/* Advertisement string is mandatory */
6972  	if (!pos[0] || pos[0] == ' ')
6973  		return -1;
6974  
6975  	/* Terminate svc string */
6976  	pos = os_strchr(pos, ' ');
6977  	if (pos != NULL)
6978  		*pos++ = '\0';
6979  
6980  	cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6981  	if (cpt_prio_str) {
6982  		pos = os_strchr(pos, ' ');
6983  		if (pos != NULL)
6984  			*pos++ = '\0';
6985  
6986  		if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6987  			return -1;
6988  	} else {
6989  		cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6990  		cpt_prio[1] = 0;
6991  	}
6992  
6993  	/* Service and Response Information are optional */
6994  	if (pos && pos[0]) {
6995  		size_t len;
6996  
6997  		/* Note the bare ' included, which cannot exist legally
6998  		 * in unescaped string. */
6999  		svc_info = os_strstr(pos, "svc_info='");
7000  
7001  		if (svc_info) {
7002  			svc_info += 9;
7003  			len = os_strlen(svc_info);
7004  			utf8_unescape(svc_info, len, svc_info, len);
7005  		}
7006  	}
7007  
7008  	return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
7009  					(u8) svc_state, (u16) config_methods,
7010  					svc_info, cpt_prio);
7011  }
7012  
7013  
p2p_ctrl_service_add(struct wpa_supplicant * wpa_s,char * cmd)7014  static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
7015  {
7016  	char *pos;
7017  
7018  	pos = os_strchr(cmd, ' ');
7019  	if (pos == NULL)
7020  		return -1;
7021  	*pos++ = '\0';
7022  
7023  	if (os_strcmp(cmd, "bonjour") == 0)
7024  		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
7025  	if (os_strcmp(cmd, "upnp") == 0)
7026  		return p2p_ctrl_service_add_upnp(wpa_s, pos);
7027  	if (os_strcmp(cmd, "asp") == 0)
7028  		return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
7029  	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7030  	return -1;
7031  }
7032  
7033  
p2p_ctrl_service_del_bonjour(struct wpa_supplicant * wpa_s,char * cmd)7034  static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
7035  					char *cmd)
7036  {
7037  	size_t len;
7038  	struct wpabuf *query;
7039  	int ret;
7040  
7041  	len = os_strlen(cmd);
7042  	if (len & 1)
7043  		return -1;
7044  	len /= 2;
7045  	query = wpabuf_alloc(len);
7046  	if (query == NULL)
7047  		return -1;
7048  	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
7049  		wpabuf_free(query);
7050  		return -1;
7051  	}
7052  
7053  	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
7054  	wpabuf_free(query);
7055  	return ret;
7056  }
7057  
7058  
p2p_ctrl_service_del_upnp(struct wpa_supplicant * wpa_s,char * cmd)7059  static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
7060  {
7061  	char *pos;
7062  	u8 version;
7063  
7064  	pos = os_strchr(cmd, ' ');
7065  	if (pos == NULL)
7066  		return -1;
7067  	*pos++ = '\0';
7068  
7069  	if (hexstr2bin(cmd, &version, 1) < 0)
7070  		return -1;
7071  
7072  	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
7073  }
7074  
7075  
p2p_ctrl_service_del_asp(struct wpa_supplicant * wpa_s,char * cmd)7076  static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
7077  {
7078  	u32 adv_id;
7079  
7080  	if (os_strcmp(cmd, "all") == 0) {
7081  		wpas_p2p_service_flush_asp(wpa_s);
7082  		return 0;
7083  	}
7084  
7085  	if (sscanf(cmd, "%x", &adv_id) != 1)
7086  		return -1;
7087  
7088  	return wpas_p2p_service_del_asp(wpa_s, adv_id);
7089  }
7090  
7091  
p2p_ctrl_service_del(struct wpa_supplicant * wpa_s,char * cmd)7092  static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
7093  {
7094  	char *pos;
7095  
7096  	pos = os_strchr(cmd, ' ');
7097  	if (pos == NULL)
7098  		return -1;
7099  	*pos++ = '\0';
7100  
7101  	if (os_strcmp(cmd, "bonjour") == 0)
7102  		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
7103  	if (os_strcmp(cmd, "upnp") == 0)
7104  		return p2p_ctrl_service_del_upnp(wpa_s, pos);
7105  	if (os_strcmp(cmd, "asp") == 0)
7106  		return p2p_ctrl_service_del_asp(wpa_s, pos);
7107  	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7108  	return -1;
7109  }
7110  
7111  
p2p_ctrl_service_replace(struct wpa_supplicant * wpa_s,char * cmd)7112  static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
7113  {
7114  	char *pos;
7115  
7116  	pos = os_strchr(cmd, ' ');
7117  	if (pos == NULL)
7118  		return -1;
7119  	*pos++ = '\0';
7120  
7121  	if (os_strcmp(cmd, "asp") == 0)
7122  		return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
7123  
7124  	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7125  	return -1;
7126  }
7127  
7128  
p2p_ctrl_reject(struct wpa_supplicant * wpa_s,char * cmd)7129  static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
7130  {
7131  	u8 addr[ETH_ALEN];
7132  
7133  	/* <addr> */
7134  
7135  	if (hwaddr_aton(cmd, addr))
7136  		return -1;
7137  
7138  	return wpas_p2p_reject(wpa_s, addr);
7139  }
7140  
7141  
p2p_ctrl_invite_persistent(struct wpa_supplicant * wpa_s,char * cmd)7142  static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
7143  {
7144  	char *pos;
7145  	int id;
7146  	struct wpa_ssid *ssid = NULL;
7147  	u8 *_peer = NULL, peer[ETH_ALEN];
7148  	int freq = 0, pref_freq = 0;
7149  	int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
7150  	int edmg;
7151  	bool allow_6ghz;
7152  	bool p2p2;
7153  
7154  	p2p2 = os_strstr(cmd, " p2p2") != NULL;
7155  
7156  	pos = os_strstr(cmd, " peer=");
7157  	if (pos) {
7158  		pos += 6;
7159  		if (hwaddr_aton(pos, peer))
7160  			return -1;
7161  		_peer = peer;
7162  	}
7163  
7164  	if (os_strncmp(cmd, "persistent=", 11) == 0) {
7165  		id = atoi(cmd + 11);
7166  		ssid = wpa_config_get_network(wpa_s->conf, id);
7167  		if (!ssid || ssid->disabled != 2) {
7168  			wpa_printf(MSG_DEBUG,
7169  				   "CTRL_IFACE: Could not find SSID id=%d for persistent P2P group",
7170  				   id);
7171  			return -1;
7172  		}
7173  	} else if (p2p2 && !_peer) {
7174  		wpa_printf(MSG_DEBUG,
7175  			   "CTRL_IFACE: Could not find peer for persistent P2P group");
7176  		return -1;
7177  	}
7178  
7179  	pos = os_strstr(cmd, " freq=");
7180  	if (pos) {
7181  		pos += 6;
7182  		freq = atoi(pos);
7183  		if (freq <= 0)
7184  			return -1;
7185  	}
7186  
7187  	pos = os_strstr(cmd, " pref=");
7188  	if (pos) {
7189  		pos += 6;
7190  		pref_freq = atoi(pos);
7191  		if (pref_freq <= 0)
7192  			return -1;
7193  	}
7194  
7195  	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
7196  	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
7197  		vht;
7198  	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
7199  	edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
7200  
7201  	pos = os_strstr(cmd, "freq2=");
7202  	if (pos)
7203  		freq2 = atoi(pos + 6);
7204  
7205  	pos = os_strstr(cmd, " max_oper_chwidth=");
7206  	if (pos)
7207  		chwidth = atoi(pos + 18);
7208  
7209  	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
7210  	if (max_oper_chwidth < 0)
7211  		return -1;
7212  
7213  	allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
7214  
7215  	if (allow_6ghz && chwidth == 40)
7216  		max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
7217  
7218  	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
7219  			       max_oper_chwidth, pref_freq, he, edmg,
7220  			       allow_6ghz, p2p2);
7221  }
7222  
7223  
p2p_ctrl_invite_group(struct wpa_supplicant * wpa_s,char * cmd)7224  static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
7225  {
7226  	char *pos;
7227  	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
7228  	bool allow_6ghz;
7229  
7230  	pos = os_strstr(cmd, " peer=");
7231  	if (!pos)
7232  		return -1;
7233  
7234  	*pos = '\0';
7235  	pos += 6;
7236  	if (hwaddr_aton(pos, peer)) {
7237  		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
7238  		return -1;
7239  	}
7240  
7241  	allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
7242  
7243  	pos = os_strstr(pos, " go_dev_addr=");
7244  	if (pos) {
7245  		pos += 13;
7246  		if (hwaddr_aton(pos, go_dev_addr)) {
7247  			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
7248  				   pos);
7249  			return -1;
7250  		}
7251  		go_dev = go_dev_addr;
7252  	}
7253  
7254  	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
7255  }
7256  
7257  
p2p_ctrl_invite(struct wpa_supplicant * wpa_s,char * cmd)7258  static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
7259  {
7260  	if (os_strncmp(cmd, "persistent", 10) == 0)
7261  		return p2p_ctrl_invite_persistent(wpa_s, cmd);
7262  	if (os_strncmp(cmd, "group=", 6) == 0)
7263  		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
7264  
7265  	return -1;
7266  }
7267  
7268  
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,bool allow_6ghz,const u8 * go_bssid)7269  static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
7270  					 int id, int freq, int vht_center_freq2,
7271  					 int ht40, int vht, int vht_chwidth,
7272  					 int he, int edmg, bool allow_6ghz,
7273  					 const u8 *go_bssid)
7274  {
7275  	struct wpa_ssid *ssid;
7276  
7277  	ssid = wpa_config_get_network(wpa_s->conf, id);
7278  	if (ssid == NULL || ssid->disabled != 2) {
7279  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7280  			   "for persistent P2P group",
7281  			   id);
7282  		return -1;
7283  	}
7284  
7285  	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, freq,
7286  					     vht_center_freq2, ht40, vht,
7287  					     vht_chwidth, he, edmg,
7288  					     NULL, 0, 0, allow_6ghz, 0,
7289  					     go_bssid, NULL, NULL, NULL, 0);
7290  }
7291  
7292  
p2p_ctrl_group_add(struct wpa_supplicant * wpa_s,char * cmd)7293  static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
7294  {
7295  	int freq = 0, persistent = 0, group_id = -1;
7296  	bool p2p2 = false;
7297  	int p2pmode = WPA_P2P_MODE_WFD_R1;
7298  	bool allow_6ghz = false;
7299  	int vht = wpa_s->conf->p2p_go_vht;
7300  	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
7301  	int he = wpa_s->conf->p2p_go_he;
7302  	int edmg = wpa_s->conf->p2p_go_edmg;
7303  	int max_oper_chwidth, chwidth = 0, freq2 = 0;
7304  	char *token, *context = NULL;
7305  	u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
7306  #ifdef CONFIG_ACS
7307  	int acs = 0;
7308  #endif /* CONFIG_ACS */
7309  
7310  	while ((token = str_token(cmd, " ", &context))) {
7311  		if (sscanf(token, "freq2=%d", &freq2) == 1 ||
7312  		    sscanf(token, "persistent=%d", &group_id) == 1 ||
7313  		    sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1 ||
7314  		    sscanf(token, "p2pmode=%d", &p2pmode) == 1) {
7315  			continue;
7316  #ifdef CONFIG_ACS
7317  		} else if (os_strcmp(token, "freq=acs") == 0) {
7318  			acs = 1;
7319  #endif /* CONFIG_ACS */
7320  		} else if (sscanf(token, "freq=%d", &freq) == 1) {
7321  			continue;
7322  		} else if (os_strcmp(token, "ht40") == 0) {
7323  			ht40 = 1;
7324  		} else if (os_strcmp(token, "vht") == 0) {
7325  			vht = 1;
7326  			ht40 = 1;
7327  		} else if (os_strcmp(token, "he") == 0) {
7328  			he = 1;
7329  		} else if (os_strcmp(token, "edmg") == 0) {
7330  			edmg = 1;
7331  		} else if (os_strcmp(token, "persistent") == 0) {
7332  			persistent = 1;
7333  		} else if (os_strcmp(token, "allow_6ghz") == 0) {
7334  			allow_6ghz = true;
7335  		} else if (os_strcmp(token, "p2p2") == 0) {
7336  			p2p2 = true;
7337  		} else if (os_strncmp(token, "go_bssid=", 9) == 0) {
7338  			if (hwaddr_aton(token + 9, go_bssid_buf))
7339  				return -1;
7340  			go_bssid = go_bssid_buf;
7341  		} else {
7342  			wpa_printf(MSG_DEBUG,
7343  				   "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
7344  				   token);
7345  			return -1;
7346  		}
7347  	}
7348  
7349  #ifdef CONFIG_ACS
7350  	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
7351  	    (acs || freq == 2 || freq == 5)) {
7352  		if (freq == 2 && wpa_s->best_24_freq <= 0) {
7353  			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
7354  			wpa_s->p2p_go_do_acs = 1;
7355  			freq = 0;
7356  		} else if (freq == 5 && wpa_s->best_5_freq <= 0) {
7357  			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
7358  			wpa_s->p2p_go_do_acs = 1;
7359  			freq = 0;
7360  		} else {
7361  			wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
7362  			wpa_s->p2p_go_do_acs = 1;
7363  		}
7364  	} else {
7365  		wpa_s->p2p_go_do_acs = 0;
7366  	}
7367  #endif /* CONFIG_ACS */
7368  
7369  	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
7370  	if (max_oper_chwidth < 0)
7371  		return -1;
7372  
7373  	if (allow_6ghz && chwidth == 40)
7374  		max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
7375  
7376  	/* Allow DFS to be used for Autonomous GO */
7377  	wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
7378  				     WPA_DRIVER_FLAGS_DFS_OFFLOAD);
7379  
7380  	if (group_id >= 0)
7381  		return p2p_ctrl_group_add_persistent(wpa_s, group_id,
7382  						     freq, freq2, ht40, vht,
7383  						     max_oper_chwidth, he,
7384  						     edmg, allow_6ghz,
7385  						     go_bssid);
7386  
7387  	if (p2pmode < WPA_P2P_MODE_WFD_R1 || p2pmode > WPA_P2P_MODE_WFD_PCC)
7388  		return -1;
7389  
7390  	return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
7391  				  max_oper_chwidth, he, edmg, allow_6ghz, p2p2,
7392  				  (enum wpa_p2p_mode) p2pmode);
7393  }
7394  
7395  
p2p_ctrl_group_member(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)7396  static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
7397  				 char *buf, size_t buflen)
7398  {
7399  	u8 dev_addr[ETH_ALEN];
7400  	struct wpa_ssid *ssid;
7401  	int res;
7402  	const u8 *iaddr;
7403  
7404  	ssid = wpa_s->current_ssid;
7405  	if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
7406  	    hwaddr_aton(cmd, dev_addr))
7407  		return -1;
7408  
7409  	iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
7410  	if (!iaddr)
7411  		return -1;
7412  	res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
7413  	if (os_snprintf_error(buflen, res))
7414  		return -1;
7415  	return res;
7416  }
7417  
7418  
wpas_find_p2p_dev_addr_bss(struct wpa_global * global,const u8 * p2p_dev_addr)7419  static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
7420  				      const u8 *p2p_dev_addr)
7421  {
7422  	struct wpa_supplicant *wpa_s;
7423  
7424  	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7425  		if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
7426  			return 1;
7427  	}
7428  
7429  	return 0;
7430  }
7431  
7432  
p2p_ctrl_peer(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)7433  static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
7434  			 char *buf, size_t buflen)
7435  {
7436  	u8 addr[ETH_ALEN], *addr_ptr, group_capab;
7437  	int next, res;
7438  	const struct p2p_peer_info *info;
7439  	char *pos, *end;
7440  	char devtype[WPS_DEV_TYPE_BUFSIZE];
7441  	struct wpa_ssid *ssid;
7442  	size_t i;
7443  
7444  	if (!wpa_s->global->p2p)
7445  		return -1;
7446  
7447  	if (os_strcmp(cmd, "FIRST") == 0) {
7448  		addr_ptr = NULL;
7449  		next = 0;
7450  	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
7451  		if (hwaddr_aton(cmd + 5, addr) < 0)
7452  			return -1;
7453  		addr_ptr = addr;
7454  		next = 1;
7455  	} else {
7456  		if (hwaddr_aton(cmd, addr) < 0)
7457  			return -1;
7458  		addr_ptr = addr;
7459  		next = 0;
7460  	}
7461  
7462  	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
7463  	if (info == NULL)
7464  		return -1;
7465  	group_capab = info->group_capab;
7466  
7467  	if (group_capab &&
7468  	    !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
7469  		wpa_printf(MSG_DEBUG,
7470  			   "P2P: Could not find any BSS with p2p_dev_addr "
7471  			   MACSTR ", hence override group_capab from 0x%x to 0",
7472  			   MAC2STR(info->p2p_device_addr), group_capab);
7473  		group_capab = 0;
7474  	}
7475  
7476  	pos = buf;
7477  	end = buf + buflen;
7478  
7479  	res = os_snprintf(pos, end - pos, MACSTR "\n"
7480  			  "pri_dev_type=%s\n"
7481  			  "device_name=%s\n"
7482  			  "manufacturer=%s\n"
7483  			  "model_name=%s\n"
7484  			  "model_number=%s\n"
7485  			  "serial_number=%s\n"
7486  			  "config_methods=0x%x\n"
7487  			  "dev_capab=0x%x\n"
7488  			  "group_capab=0x%x\n"
7489  			  "level=%d\n",
7490  			  MAC2STR(info->p2p_device_addr),
7491  			  wps_dev_type_bin2str(info->pri_dev_type,
7492  					       devtype, sizeof(devtype)),
7493  			  info->device_name,
7494  			  info->manufacturer,
7495  			  info->model_name,
7496  			  info->model_number,
7497  			  info->serial_number,
7498  			  info->config_methods,
7499  			  info->dev_capab,
7500  			  group_capab,
7501  			  info->level);
7502  	if (os_snprintf_error(end - pos, res))
7503  		return pos - buf;
7504  	pos += res;
7505  
7506  	for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
7507  	{
7508  		const u8 *t;
7509  		t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
7510  		res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
7511  				  wps_dev_type_bin2str(t, devtype,
7512  						       sizeof(devtype)));
7513  		if (os_snprintf_error(end - pos, res))
7514  			return pos - buf;
7515  		pos += res;
7516  	}
7517  
7518  	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
7519  	if (ssid) {
7520  		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
7521  		if (os_snprintf_error(end - pos, res))
7522  			return pos - buf;
7523  		pos += res;
7524  	}
7525  
7526  	res = p2p_get_peer_info_txt(info, pos, end - pos);
7527  	if (res < 0)
7528  		return pos - buf;
7529  	pos += res;
7530  
7531  	if (info->vendor_elems) {
7532  		res = os_snprintf(pos, end - pos, "vendor_elems=");
7533  		if (os_snprintf_error(end - pos, res))
7534  			return pos - buf;
7535  		pos += res;
7536  
7537  		pos += wpa_snprintf_hex(pos, end - pos,
7538  					wpabuf_head(info->vendor_elems),
7539  					wpabuf_len(info->vendor_elems));
7540  
7541  		res = os_snprintf(pos, end - pos, "\n");
7542  		if (os_snprintf_error(end - pos, res))
7543  			return pos - buf;
7544  		pos += res;
7545  	}
7546  
7547  	return pos - buf;
7548  }
7549  
7550  
p2p_ctrl_disallow_freq(struct wpa_supplicant * wpa_s,const char * param)7551  static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
7552  				  const char *param)
7553  {
7554  	unsigned int i;
7555  
7556  	if (wpa_s->global->p2p == NULL)
7557  		return -1;
7558  
7559  	if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
7560  		return -1;
7561  
7562  	for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
7563  		struct wpa_freq_range *freq;
7564  		freq = &wpa_s->global->p2p_disallow_freq.range[i];
7565  		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
7566  			   freq->min, freq->max);
7567  	}
7568  
7569  	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
7570  	return 0;
7571  }
7572  
7573  
p2p_ctrl_set(struct wpa_supplicant * wpa_s,char * cmd)7574  static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
7575  {
7576  	char *param;
7577  
7578  	if (wpa_s->global->p2p == NULL)
7579  		return -1;
7580  
7581  	param = os_strchr(cmd, ' ');
7582  	if (param == NULL)
7583  		return -1;
7584  	*param++ = '\0';
7585  
7586  	if (os_strcmp(cmd, "discoverability") == 0) {
7587  		p2p_set_client_discoverability(wpa_s->global->p2p,
7588  					       atoi(param));
7589  		return 0;
7590  	}
7591  
7592  	if (os_strcmp(cmd, "managed") == 0) {
7593  		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
7594  		return 0;
7595  	}
7596  
7597  	if (os_strcmp(cmd, "listen_channel") == 0) {
7598  		char *pos;
7599  		u8 channel, op_class;
7600  
7601  		channel = atoi(param);
7602  		pos = os_strchr(param, ' ');
7603  		op_class = pos ? atoi(pos) : 81;
7604  
7605  		return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
7606  					      channel, 1);
7607  	}
7608  
7609  	if (os_strcmp(cmd, "ssid_postfix") == 0) {
7610  		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
7611  					    os_strlen(param));
7612  	}
7613  
7614  	if (os_strcmp(cmd, "noa") == 0) {
7615  		char *pos;
7616  		int count, start, duration;
7617  		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
7618  		count = atoi(param);
7619  		pos = os_strchr(param, ',');
7620  		if (pos == NULL)
7621  			return -1;
7622  		pos++;
7623  		start = atoi(pos);
7624  		pos = os_strchr(pos, ',');
7625  		if (pos == NULL)
7626  			return -1;
7627  		pos++;
7628  		duration = atoi(pos);
7629  		if (count < 0 || count > 255 || start < 0 || duration < 0)
7630  			return -1;
7631  		if (count == 0 && duration > 0)
7632  			return -1;
7633  		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
7634  			   "start=%d duration=%d", count, start, duration);
7635  		return wpas_p2p_set_noa(wpa_s, count, start, duration);
7636  	}
7637  
7638  	if (os_strcmp(cmd, "ps") == 0)
7639  		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
7640  
7641  	if (os_strcmp(cmd, "oppps") == 0)
7642  		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
7643  
7644  	if (os_strcmp(cmd, "ctwindow") == 0)
7645  		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
7646  
7647  	if (os_strcmp(cmd, "disabled") == 0) {
7648  		wpa_s->global->p2p_disabled = atoi(param);
7649  		wpa_printf(MSG_DEBUG, "P2P functionality %s",
7650  			   wpa_s->global->p2p_disabled ?
7651  			   "disabled" : "enabled");
7652  		if (wpa_s->global->p2p_disabled) {
7653  			wpas_p2p_stop_find(wpa_s);
7654  			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7655  			p2p_flush(wpa_s->global->p2p);
7656  		}
7657  		return 0;
7658  	}
7659  
7660  	if (os_strcmp(cmd, "conc_pref") == 0) {
7661  		if (os_strcmp(param, "sta") == 0)
7662  			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
7663  		else if (os_strcmp(param, "p2p") == 0)
7664  			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
7665  		else {
7666  			wpa_printf(MSG_INFO, "Invalid conc_pref value");
7667  			return -1;
7668  		}
7669  		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
7670  			   "%s", param);
7671  		return 0;
7672  	}
7673  
7674  	if (os_strcmp(cmd, "force_long_sd") == 0) {
7675  		wpa_s->force_long_sd = atoi(param);
7676  		return 0;
7677  	}
7678  
7679  	if (os_strcmp(cmd, "peer_filter") == 0) {
7680  		u8 addr[ETH_ALEN];
7681  		if (hwaddr_aton(param, addr))
7682  			return -1;
7683  		p2p_set_peer_filter(wpa_s->global->p2p, addr);
7684  		return 0;
7685  	}
7686  
7687  	if (os_strcmp(cmd, "cross_connect") == 0)
7688  		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
7689  
7690  	if (os_strcmp(cmd, "go_apsd") == 0) {
7691  		if (os_strcmp(param, "disable") == 0)
7692  			wpa_s->set_ap_uapsd = 0;
7693  		else {
7694  			wpa_s->set_ap_uapsd = 1;
7695  			wpa_s->ap_uapsd = atoi(param);
7696  		}
7697  		return 0;
7698  	}
7699  
7700  	if (os_strcmp(cmd, "client_apsd") == 0) {
7701  		if (os_strcmp(param, "disable") == 0)
7702  			wpa_s->set_sta_uapsd = 0;
7703  		else {
7704  			int be, bk, vi, vo;
7705  			char *pos;
7706  			/* format: BE,BK,VI,VO;max SP Length */
7707  			be = atoi(param);
7708  			pos = os_strchr(param, ',');
7709  			if (pos == NULL)
7710  				return -1;
7711  			pos++;
7712  			bk = atoi(pos);
7713  			pos = os_strchr(pos, ',');
7714  			if (pos == NULL)
7715  				return -1;
7716  			pos++;
7717  			vi = atoi(pos);
7718  			pos = os_strchr(pos, ',');
7719  			if (pos == NULL)
7720  				return -1;
7721  			pos++;
7722  			vo = atoi(pos);
7723  			/* ignore max SP Length for now */
7724  
7725  			wpa_s->set_sta_uapsd = 1;
7726  			wpa_s->sta_uapsd = 0;
7727  			if (be)
7728  				wpa_s->sta_uapsd |= BIT(0);
7729  			if (bk)
7730  				wpa_s->sta_uapsd |= BIT(1);
7731  			if (vi)
7732  				wpa_s->sta_uapsd |= BIT(2);
7733  			if (vo)
7734  				wpa_s->sta_uapsd |= BIT(3);
7735  		}
7736  		return 0;
7737  	}
7738  
7739  	if (os_strcmp(cmd, "disallow_freq") == 0)
7740  		return p2p_ctrl_disallow_freq(wpa_s, param);
7741  
7742  	if (os_strcmp(cmd, "disc_int") == 0) {
7743  		int min_disc_int, max_disc_int, max_disc_tu;
7744  		char *pos;
7745  
7746  		pos = param;
7747  
7748  		min_disc_int = atoi(pos);
7749  		pos = os_strchr(pos, ' ');
7750  		if (pos == NULL)
7751  			return -1;
7752  		*pos++ = '\0';
7753  
7754  		max_disc_int = atoi(pos);
7755  		pos = os_strchr(pos, ' ');
7756  		if (pos == NULL)
7757  			return -1;
7758  		*pos++ = '\0';
7759  
7760  		max_disc_tu = atoi(pos);
7761  
7762  		return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
7763  					max_disc_int, max_disc_tu);
7764  	}
7765  
7766  	if (os_strcmp(cmd, "per_sta_psk") == 0) {
7767  		wpa_s->global->p2p_per_sta_psk = !!atoi(param);
7768  		return 0;
7769  	}
7770  
7771  #ifdef CONFIG_WPS_NFC
7772  	if (os_strcmp(cmd, "nfc_tag") == 0)
7773  		return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
7774  #endif /* CONFIG_WPS_NFC */
7775  
7776  	if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
7777  		wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
7778  		return 0;
7779  	}
7780  
7781  	if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
7782  		int op_class, chan;
7783  
7784  		op_class = atoi(param);
7785  		param = os_strchr(param, ':');
7786  		if (!param)
7787  			return -1;
7788  		param++;
7789  		chan = atoi(param);
7790  		p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
7791  					      chan);
7792  		return 0;
7793  	}
7794  
7795  #ifdef CONFIG_TESTING_OPTIONS
7796  	if (os_strcmp(cmd, "pairing_setup") == 0) {
7797  		p2p_set_pairing_setup(wpa_s->global->p2p, atoi(param));
7798  		return 0;
7799  	}
7800  
7801  	if (os_strcmp(cmd, "pairing_cache") == 0) {
7802  		p2p_set_pairing_cache(wpa_s->global->p2p, atoi(param));
7803  		return 0;
7804  	}
7805  
7806  	if (os_strcmp(cmd, "supported_bootstrapmethods") == 0) {
7807  		p2p_set_bootstrapmethods(wpa_s->global->p2p, atoi(param));
7808  		return 0;
7809  	}
7810  
7811  	if (os_strcmp(cmd, "pasn_type") == 0) {
7812  		p2p_set_pasn_type(wpa_s->global->p2p, atoi(param));
7813  		return 0;
7814  	}
7815  
7816  	if (os_strcmp(cmd, "comeback_after") == 0) {
7817  		p2p_set_comeback_after(wpa_s->global->p2p, atoi(param));
7818  		return 0;
7819  	}
7820  
7821  	if (os_strcmp(cmd, "reginfo") == 0) {
7822  		p2p_set_reg_info(wpa_s->global->p2p, atoi(param));
7823  		return 0;
7824  	}
7825  
7826  	if (os_strcmp(cmd, "twt_power_mgmt") == 0) {
7827  		p2p_set_twt_power_mgmt(wpa_s->global->p2p, atoi(param));
7828  		return 0;
7829  	}
7830  
7831  	if (os_strcmp(cmd, "chan_switch_req_enable") == 0) {
7832  		p2p_set_chan_switch_req_enable(wpa_s->global->p2p, atoi(param));
7833  		return 0;
7834  	}
7835  
7836  	if (os_strcmp(cmd, "inv_oper_freq") == 0) {
7837  		p2p_set_invitation_op_freq(wpa_s->global->p2p, atoi(param));
7838  		return 0;
7839  	}
7840  #endif /* CONFIG_TESTING_OPTIONS */
7841  
7842  	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
7843  		   cmd);
7844  
7845  	return -1;
7846  }
7847  
7848  
p2p_ctrl_flush(struct wpa_supplicant * wpa_s)7849  static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
7850  {
7851  	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7852  	wpa_s->force_long_sd = 0;
7853  
7854  #ifdef CONFIG_TESTING_OPTIONS
7855  	os_free(wpa_s->get_pref_freq_list_override);
7856  	wpa_s->get_pref_freq_list_override = NULL;
7857  	p2p_set_invitation_op_freq(wpa_s->global->p2p, -1);
7858  #endif /* CONFIG_TESTING_OPTIONS */
7859  
7860  	wpas_p2p_stop_find(wpa_s);
7861  	wpa_s->parent->p2ps_method_config_any = 0;
7862  	if (wpa_s->global->p2p)
7863  		p2p_flush(wpa_s->global->p2p);
7864  
7865  	wpa_s->p2p2 = false;
7866  }
7867  
7868  
p2p_ctrl_presence_req(struct wpa_supplicant * wpa_s,char * cmd)7869  static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
7870  {
7871  	char *pos, *pos2;
7872  	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
7873  
7874  	if (cmd[0]) {
7875  		pos = os_strchr(cmd, ' ');
7876  		if (pos == NULL)
7877  			return -1;
7878  		*pos++ = '\0';
7879  		dur1 = atoi(cmd);
7880  
7881  		pos2 = os_strchr(pos, ' ');
7882  		if (pos2)
7883  			*pos2++ = '\0';
7884  		int1 = atoi(pos);
7885  	} else
7886  		pos2 = NULL;
7887  
7888  	if (pos2) {
7889  		pos = os_strchr(pos2, ' ');
7890  		if (pos == NULL)
7891  			return -1;
7892  		*pos++ = '\0';
7893  		dur2 = atoi(pos2);
7894  		int2 = atoi(pos);
7895  	}
7896  
7897  	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
7898  }
7899  
7900  
p2p_ctrl_ext_listen(struct wpa_supplicant * wpa_s,char * cmd)7901  static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
7902  {
7903  	char *pos;
7904  	unsigned int period = 0, interval = 0;
7905  
7906  	if (cmd[0]) {
7907  		pos = os_strchr(cmd, ' ');
7908  		if (pos == NULL)
7909  			return -1;
7910  		*pos++ = '\0';
7911  		period = atoi(cmd);
7912  		interval = atoi(pos);
7913  	}
7914  
7915  	return wpas_p2p_ext_listen(wpa_s, period, interval);
7916  }
7917  
7918  
p2p_ctrl_remove_client(struct wpa_supplicant * wpa_s,const char * cmd)7919  static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
7920  {
7921  	const char *pos;
7922  	u8 peer[ETH_ALEN];
7923  	int iface_addr = 0;
7924  
7925  	pos = cmd;
7926  	if (os_strncmp(pos, "iface=", 6) == 0) {
7927  		iface_addr = 1;
7928  		pos += 6;
7929  	}
7930  	if (hwaddr_aton(pos, peer))
7931  		return -1;
7932  
7933  	wpas_p2p_remove_client(wpa_s, peer, iface_addr);
7934  	return 0;
7935  }
7936  
7937  
p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant * wpa_s,char * cmd)7938  static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
7939  {
7940  	int freq = 0, period = 0, interval = 0, count = 0;
7941  
7942  	if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
7943  	{
7944  		wpa_printf(MSG_DEBUG,
7945  			   "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
7946  		return -1;
7947  	}
7948  
7949  	return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7950  }
7951  
7952  
7953  #ifdef CONFIG_TESTING_OPTIONS
p2p_ctrl_pmk_get(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)7954  static int p2p_ctrl_pmk_get(struct wpa_supplicant *wpa_s, char *buf,
7955  			    size_t buflen)
7956  {
7957  	const u8 *pmk;
7958  	size_t pmk_len;
7959  
7960  	/* Return the PMK from the first identity entry. This assumes test
7961  	 * cases to remove all indentities at the beginning so that only one
7962  	 * entry is available. */
7963  	if (!wpa_s->conf->identity || !wpa_s->conf->identity->pmk)
7964  		return -1;
7965  
7966  	pmk_len = wpabuf_len(wpa_s->conf->identity->pmk);
7967  	pmk = wpabuf_head(wpa_s->conf->identity->pmk);
7968  
7969  	return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
7970  }
7971  #endif /* CONFIG_TESTING_OPTIONS */
7972  #endif /* CONFIG_P2P */
7973  
7974  
freq_range_to_channel_list(struct wpa_supplicant * wpa_s,char * val)7975  static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7976  {
7977  	struct wpa_freq_range_list ranges;
7978  	int *freqs = NULL;
7979  	struct hostapd_hw_modes *mode;
7980  	u16 i;
7981  
7982  	if (wpa_s->hw.modes == NULL)
7983  		return NULL;
7984  
7985  	os_memset(&ranges, 0, sizeof(ranges));
7986  	if (freq_range_list_parse(&ranges, val) < 0)
7987  		return NULL;
7988  
7989  	for (i = 0; i < wpa_s->hw.num_modes; i++) {
7990  		int j;
7991  
7992  		mode = &wpa_s->hw.modes[i];
7993  		for (j = 0; j < mode->num_channels; j++) {
7994  			unsigned int freq;
7995  
7996  			if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7997  				continue;
7998  
7999  			freq = mode->channels[j].freq;
8000  			if (!freq_range_list_includes(&ranges, freq))
8001  				continue;
8002  
8003  			int_array_add_unique(&freqs, freq);
8004  		}
8005  	}
8006  
8007  	os_free(ranges.range);
8008  	return freqs;
8009  }
8010  
8011  
8012  #ifdef CONFIG_INTERWORKING
8013  
ctrl_interworking_select(struct wpa_supplicant * wpa_s,char * param)8014  static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
8015  {
8016  	int auto_sel = 0;
8017  	int *freqs = NULL;
8018  
8019  	if (param) {
8020  		char *pos;
8021  
8022  		auto_sel = os_strstr(param, "auto") != NULL;
8023  
8024  		pos = os_strstr(param, "freq=");
8025  		if (pos) {
8026  			freqs = freq_range_to_channel_list(wpa_s, pos + 5);
8027  			if (freqs == NULL)
8028  				return -1;
8029  		}
8030  
8031  	}
8032  
8033  	return interworking_select(wpa_s, auto_sel, freqs);
8034  }
8035  
8036  
ctrl_interworking_connect(struct wpa_supplicant * wpa_s,char * dst,int only_add)8037  static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
8038  				     int only_add)
8039  {
8040  	u8 bssid[ETH_ALEN];
8041  	struct wpa_bss *bss;
8042  
8043  	if (hwaddr_aton(dst, bssid)) {
8044  		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
8045  		return -1;
8046  	}
8047  
8048  	bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
8049  	if (bss == NULL) {
8050  		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
8051  			   MAC2STR(bssid));
8052  		return -1;
8053  	}
8054  
8055  	if (bss->ssid_len == 0) {
8056  		int found = 0;
8057  
8058  		wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
8059  			   " does not have SSID information", MAC2STR(bssid));
8060  
8061  		dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
8062  					 list) {
8063  			if (ether_addr_equal(bss->bssid, bssid) &&
8064  			    bss->ssid_len > 0) {
8065  				found = 1;
8066  				break;
8067  			}
8068  		}
8069  
8070  		if (!found)
8071  			return -1;
8072  		wpa_printf(MSG_DEBUG,
8073  			   "Found another matching BSS entry with SSID");
8074  	}
8075  
8076  	return interworking_connect(wpa_s, bss, only_add);
8077  }
8078  
8079  
get_anqp(struct wpa_supplicant * wpa_s,char * dst)8080  static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
8081  {
8082  	u8 dst_addr[ETH_ALEN];
8083  	int used, freq = 0;
8084  	char *pos;
8085  #define MAX_ANQP_INFO_ID 100
8086  	u16 id[MAX_ANQP_INFO_ID];
8087  	size_t num_id = 0;
8088  	u32 subtypes = 0;
8089  	u32 mbo_subtypes = 0;
8090  
8091  	used = hwaddr_aton2(dst, dst_addr);
8092  	if (used < 0)
8093  		return -1;
8094  	pos = dst + used;
8095  	if (*pos == ' ')
8096  		pos++;
8097  
8098  	if (os_strncmp(pos, "freq=", 5) == 0) {
8099  		freq = atoi(pos + 5);
8100  		pos = os_strchr(pos, ' ');
8101  		if (!pos)
8102  			return -1;
8103  		pos++;
8104  	}
8105  
8106  	while (num_id < MAX_ANQP_INFO_ID) {
8107  		if (os_strncmp(pos, "hs20:", 5) == 0) {
8108  #ifdef CONFIG_HS20
8109  			int num = atoi(pos + 5);
8110  			if (num <= 0 || num > 31)
8111  				return -1;
8112  			subtypes |= BIT(num);
8113  #else /* CONFIG_HS20 */
8114  			return -1;
8115  #endif /* CONFIG_HS20 */
8116  		} else if (os_strncmp(pos, "mbo:", 4) == 0) {
8117  #ifdef CONFIG_MBO
8118  			int num = atoi(pos + 4);
8119  
8120  			if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
8121  				return -1;
8122  			mbo_subtypes |= BIT(num);
8123  #else /* CONFIG_MBO */
8124  			return -1;
8125  #endif /* CONFIG_MBO */
8126  		} else {
8127  			id[num_id] = atoi(pos);
8128  			if (id[num_id])
8129  				num_id++;
8130  		}
8131  		pos = os_strchr(pos + 1, ',');
8132  		if (pos == NULL)
8133  			break;
8134  		pos++;
8135  	}
8136  
8137  	if (num_id == 0 && !subtypes && !mbo_subtypes)
8138  		return -1;
8139  
8140  	return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
8141  			     mbo_subtypes);
8142  }
8143  
8144  
gas_request(struct wpa_supplicant * wpa_s,char * cmd)8145  static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
8146  {
8147  	u8 dst_addr[ETH_ALEN];
8148  	struct wpabuf *advproto, *query = NULL;
8149  	int used, ret = -1;
8150  	char *pos, *end;
8151  	size_t len;
8152  
8153  	used = hwaddr_aton2(cmd, dst_addr);
8154  	if (used < 0)
8155  		return -1;
8156  
8157  	pos = cmd + used;
8158  	while (*pos == ' ')
8159  		pos++;
8160  
8161  	/* Advertisement Protocol ID */
8162  	end = os_strchr(pos, ' ');
8163  	if (end)
8164  		len = end - pos;
8165  	else
8166  		len = os_strlen(pos);
8167  	if (len & 0x01)
8168  		return -1;
8169  	len /= 2;
8170  	if (len == 0)
8171  		return -1;
8172  	advproto = wpabuf_alloc(len);
8173  	if (advproto == NULL)
8174  		return -1;
8175  	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
8176  		goto fail;
8177  
8178  	if (end) {
8179  		/* Optional Query Request */
8180  		pos = end + 1;
8181  		while (*pos == ' ')
8182  			pos++;
8183  
8184  		len = os_strlen(pos);
8185  		if (len) {
8186  			if (len & 0x01)
8187  				goto fail;
8188  			len /= 2;
8189  			if (len == 0)
8190  				goto fail;
8191  			query = wpabuf_alloc(len);
8192  			if (query == NULL)
8193  				goto fail;
8194  			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
8195  				goto fail;
8196  		}
8197  	}
8198  
8199  	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
8200  
8201  fail:
8202  	wpabuf_free(advproto);
8203  	wpabuf_free(query);
8204  
8205  	return ret;
8206  }
8207  
8208  
gas_response_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8209  static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
8210  			    size_t buflen)
8211  {
8212  	u8 addr[ETH_ALEN];
8213  	int dialog_token;
8214  	int used;
8215  	char *pos;
8216  	size_t resp_len, start, requested_len;
8217  	struct wpabuf *resp;
8218  	int ret;
8219  
8220  	used = hwaddr_aton2(cmd, addr);
8221  	if (used < 0)
8222  		return -1;
8223  
8224  	pos = cmd + used;
8225  	while (*pos == ' ')
8226  		pos++;
8227  	dialog_token = atoi(pos);
8228  
8229  	if (wpa_s->last_gas_resp &&
8230  	    ether_addr_equal(addr, wpa_s->last_gas_addr) &&
8231  	    dialog_token == wpa_s->last_gas_dialog_token)
8232  		resp = wpa_s->last_gas_resp;
8233  	else if (wpa_s->prev_gas_resp &&
8234  		 ether_addr_equal(addr, wpa_s->prev_gas_addr) &&
8235  		 dialog_token == wpa_s->prev_gas_dialog_token)
8236  		resp = wpa_s->prev_gas_resp;
8237  	else
8238  		return -1;
8239  
8240  	resp_len = wpabuf_len(resp);
8241  	start = 0;
8242  	requested_len = resp_len;
8243  
8244  	pos = os_strchr(pos, ' ');
8245  	if (pos) {
8246  		start = atoi(pos);
8247  		if (start > resp_len)
8248  			return os_snprintf(buf, buflen, "FAIL-Invalid range");
8249  		pos = os_strchr(pos, ',');
8250  		if (pos == NULL)
8251  			return -1;
8252  		pos++;
8253  		requested_len = atoi(pos);
8254  		if (start + requested_len > resp_len)
8255  			return os_snprintf(buf, buflen, "FAIL-Invalid range");
8256  	}
8257  
8258  	if (requested_len * 2 + 1 > buflen)
8259  		return os_snprintf(buf, buflen, "FAIL-Too long response");
8260  
8261  	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
8262  			       requested_len);
8263  
8264  	if (start + requested_len == resp_len) {
8265  		/*
8266  		 * Free memory by dropping the response after it has been
8267  		 * fetched.
8268  		 */
8269  		if (resp == wpa_s->prev_gas_resp) {
8270  			wpabuf_free(wpa_s->prev_gas_resp);
8271  			wpa_s->prev_gas_resp = NULL;
8272  		} else {
8273  			wpabuf_free(wpa_s->last_gas_resp);
8274  			wpa_s->last_gas_resp = NULL;
8275  		}
8276  	}
8277  
8278  	return ret;
8279  }
8280  #endif /* CONFIG_INTERWORKING */
8281  
8282  
8283  #ifdef CONFIG_HS20
8284  
get_hs20_anqp(struct wpa_supplicant * wpa_s,char * dst)8285  static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
8286  {
8287  	u8 dst_addr[ETH_ALEN];
8288  	int used;
8289  	char *pos;
8290  	u32 subtypes = 0;
8291  
8292  	used = hwaddr_aton2(dst, dst_addr);
8293  	if (used < 0)
8294  		return -1;
8295  	pos = dst + used;
8296  	if (*pos == ' ')
8297  		pos++;
8298  	for (;;) {
8299  		int num = atoi(pos);
8300  		if (num <= 0 || num > 31)
8301  			return -1;
8302  		subtypes |= BIT(num);
8303  		pos = os_strchr(pos + 1, ',');
8304  		if (pos == NULL)
8305  			break;
8306  		pos++;
8307  	}
8308  
8309  	if (subtypes == 0)
8310  		return -1;
8311  
8312  	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
8313  }
8314  
8315  
hs20_nai_home_realm_list(struct wpa_supplicant * wpa_s,const u8 * addr,const char * realm)8316  static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8317  				    const u8 *addr, const char *realm)
8318  {
8319  	u8 *buf;
8320  	size_t rlen, len;
8321  	int ret;
8322  
8323  	rlen = os_strlen(realm);
8324  	len = 3 + rlen;
8325  	buf = os_malloc(len);
8326  	if (buf == NULL)
8327  		return -1;
8328  	buf[0] = 1; /* NAI Home Realm Count */
8329  	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
8330  	buf[2] = rlen;
8331  	os_memcpy(buf + 3, realm, rlen);
8332  
8333  	ret = hs20_anqp_send_req(wpa_s, addr,
8334  				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
8335  				 buf, len);
8336  
8337  	os_free(buf);
8338  
8339  	return ret;
8340  }
8341  
8342  
hs20_get_nai_home_realm_list(struct wpa_supplicant * wpa_s,char * dst)8343  static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8344  					char *dst)
8345  {
8346  	struct wpa_cred *cred = wpa_s->conf->cred;
8347  	u8 dst_addr[ETH_ALEN];
8348  	int used;
8349  	u8 *buf;
8350  	size_t len;
8351  	int ret;
8352  
8353  	used = hwaddr_aton2(dst, dst_addr);
8354  	if (used < 0)
8355  		return -1;
8356  
8357  	while (dst[used] == ' ')
8358  		used++;
8359  	if (os_strncmp(dst + used, "realm=", 6) == 0)
8360  		return hs20_nai_home_realm_list(wpa_s, dst_addr,
8361  						dst + used + 6);
8362  
8363  	len = os_strlen(dst + used);
8364  
8365  	if (len == 0 && cred && cred->realm)
8366  		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
8367  
8368  	if (len & 1)
8369  		return -1;
8370  	len /= 2;
8371  	buf = os_malloc(len);
8372  	if (buf == NULL)
8373  		return -1;
8374  	if (hexstr2bin(dst + used, buf, len) < 0) {
8375  		os_free(buf);
8376  		return -1;
8377  	}
8378  
8379  	ret = hs20_anqp_send_req(wpa_s, dst_addr,
8380  				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
8381  				 buf, len);
8382  	os_free(buf);
8383  
8384  	return ret;
8385  }
8386  
8387  #endif /* CONFIG_HS20 */
8388  
8389  
8390  #ifdef CONFIG_AUTOSCAN
8391  
wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant * wpa_s,char * cmd)8392  static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
8393  					      char *cmd)
8394  {
8395  	enum wpa_states state = wpa_s->wpa_state;
8396  	char *new_params = NULL;
8397  
8398  	if (os_strlen(cmd) > 0) {
8399  		new_params = os_strdup(cmd);
8400  		if (new_params == NULL)
8401  			return -1;
8402  	}
8403  
8404  	os_free(wpa_s->conf->autoscan);
8405  	wpa_s->conf->autoscan = new_params;
8406  
8407  	if (wpa_s->conf->autoscan == NULL)
8408  		autoscan_deinit(wpa_s);
8409  	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
8410  		autoscan_init(wpa_s, 1);
8411  	else if (state == WPA_SCANNING)
8412  		wpa_supplicant_reinit_autoscan(wpa_s);
8413  	else
8414  		wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
8415  			   wpa_supplicant_state_txt(state));
8416  
8417  	return 0;
8418  }
8419  
8420  #endif /* CONFIG_AUTOSCAN */
8421  
8422  
8423  #ifdef CONFIG_WNM
8424  
wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant * wpa_s,char * cmd)8425  static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
8426  {
8427  	int enter;
8428  	int intval = 0;
8429  	char *pos;
8430  	int ret;
8431  	struct wpabuf *tfs_req = NULL;
8432  
8433  	if (os_strncmp(cmd, "enter", 5) == 0)
8434  		enter = 1;
8435  	else if (os_strncmp(cmd, "exit", 4) == 0)
8436  		enter = 0;
8437  	else
8438  		return -1;
8439  
8440  	pos = os_strstr(cmd, " interval=");
8441  	if (pos)
8442  		intval = atoi(pos + 10);
8443  
8444  	pos = os_strstr(cmd, " tfs_req=");
8445  	if (pos) {
8446  		char *end;
8447  		size_t len;
8448  		pos += 9;
8449  		end = os_strchr(pos, ' ');
8450  		if (end)
8451  			len = end - pos;
8452  		else
8453  			len = os_strlen(pos);
8454  		if (len & 1)
8455  			return -1;
8456  		len /= 2;
8457  		tfs_req = wpabuf_alloc(len);
8458  		if (tfs_req == NULL)
8459  			return -1;
8460  		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
8461  			wpabuf_free(tfs_req);
8462  			return -1;
8463  		}
8464  	}
8465  
8466  	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
8467  					   WNM_SLEEP_MODE_EXIT, intval,
8468  					   tfs_req);
8469  	wpabuf_free(tfs_req);
8470  
8471  	return ret;
8472  }
8473  
8474  
wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant * wpa_s,char * cmd)8475  static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
8476  {
8477  	int query_reason, list = 0;
8478  	char *btm_candidates = NULL;
8479  
8480  	query_reason = atoi(cmd);
8481  
8482  	cmd = os_strchr(cmd, ' ');
8483  	if (cmd) {
8484  		if (os_strncmp(cmd, " list", 5) == 0)
8485  			list = 1;
8486  		else
8487  			btm_candidates = cmd;
8488  	}
8489  
8490  	wpa_printf(MSG_DEBUG,
8491  		   "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
8492  		   query_reason, list ? " candidate list" : "");
8493  
8494  	return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
8495  						  btm_candidates,
8496  						  list);
8497  }
8498  
8499  
wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant * wpa_s,char * cmd)8500  static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
8501  					     char *cmd)
8502  {
8503  	struct wpabuf *elems;
8504  	int ret;
8505  
8506  	elems = wpabuf_parse_bin(cmd);
8507  	if (!elems)
8508  		return -1;
8509  
8510  	ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
8511  	wpabuf_free(elems);
8512  	return ret;
8513  }
8514  
8515  #endif /* CONFIG_WNM */
8516  
8517  
wpa_supplicant_signal_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8518  static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
8519  				      size_t buflen)
8520  {
8521  	struct wpa_signal_info si;
8522  	int ret;
8523  	char *pos, *end;
8524  
8525  	ret = wpa_drv_signal_poll(wpa_s, &si);
8526  	if (ret)
8527  		return -1;
8528  
8529  	pos = buf;
8530  	end = buf + buflen;
8531  
8532  	ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%lu\n"
8533  			  "NOISE=%d\nFREQUENCY=%u\n",
8534  			  si.data.signal, si.data.current_tx_rate / 1000,
8535  			  si.current_noise, si.frequency);
8536  	if (os_snprintf_error(end - pos, ret))
8537  		return -1;
8538  	pos += ret;
8539  
8540  	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
8541  		ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
8542  				  channel_width_to_string(si.chanwidth));
8543  		if (os_snprintf_error(end - pos, ret))
8544  			return -1;
8545  		pos += ret;
8546  	}
8547  
8548  	if (si.center_frq1 > 0) {
8549  		ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
8550  				  si.center_frq1);
8551  		if (os_snprintf_error(end - pos, ret))
8552  			return -1;
8553  		pos += ret;
8554  	}
8555  
8556  	if (si.center_frq2 > 0) {
8557  		ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
8558  				  si.center_frq2);
8559  		if (os_snprintf_error(end - pos, ret))
8560  			return -1;
8561  		pos += ret;
8562  	}
8563  
8564  	if (si.data.avg_signal) {
8565  		ret = os_snprintf(pos, end - pos,
8566  				  "AVG_RSSI=%d\n", si.data.avg_signal);
8567  		if (os_snprintf_error(end - pos, ret))
8568  			return -1;
8569  		pos += ret;
8570  	}
8571  
8572  	if (si.data.avg_beacon_signal) {
8573  		ret = os_snprintf(pos, end - pos,
8574  				  "AVG_BEACON_RSSI=%d\n",
8575  				  si.data.avg_beacon_signal);
8576  		if (os_snprintf_error(end - pos, ret))
8577  			return -1;
8578  		pos += ret;
8579  	}
8580  
8581  	return pos - buf;
8582  }
8583  
8584  
wpas_ctrl_iface_signal_monitor(struct wpa_supplicant * wpa_s,const char * cmd)8585  static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
8586  					  const char *cmd)
8587  {
8588  	const char *pos;
8589  	int threshold = 0;
8590  	int hysteresis = 0;
8591  
8592  	if (wpa_s->bgscan && wpa_s->bgscan_priv) {
8593  		wpa_printf(MSG_DEBUG,
8594  			   "Reject SIGNAL_MONITOR command - bgscan is active");
8595  		return -1;
8596  	}
8597  	pos = os_strstr(cmd, "THRESHOLD=");
8598  	if (pos)
8599  		threshold = atoi(pos + 10);
8600  	pos = os_strstr(cmd, "HYSTERESIS=");
8601  	if (pos)
8602  		hysteresis = atoi(pos + 11);
8603  	return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
8604  }
8605  
8606  
8607  #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,struct weighted_pcl * freq_list)8608  int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
8609  						enum wpa_driver_if_type if_type,
8610  						unsigned int *num,
8611  						struct weighted_pcl *freq_list)
8612  {
8613  	char *pos = wpa_s->get_pref_freq_list_override;
8614  	char *end;
8615  	unsigned int count = 0;
8616  
8617  	/* Override string format:
8618  	 *  <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
8619  
8620  	while (pos) {
8621  		if (atoi(pos) == (int) if_type)
8622  			break;
8623  		pos = os_strchr(pos, ' ');
8624  		if (pos)
8625  			pos++;
8626  	}
8627  	if (!pos)
8628  		return -1;
8629  	pos = os_strchr(pos, ':');
8630  	if (!pos)
8631  		return -1;
8632  	pos++;
8633  	end = os_strchr(pos, ' ');
8634  	while (pos && (!end || pos < end) && count < *num) {
8635  		freq_list[count].freq = atoi(pos);
8636  		freq_list[count++].flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI;
8637  		pos = os_strchr(pos, ',');
8638  		if (pos)
8639  			pos++;
8640  	}
8641  
8642  	*num = count;
8643  	return 0;
8644  }
8645  #endif /* CONFIG_TESTING_OPTIONS */
8646  
8647  
wpas_ctrl_iface_get_pref_freq_list(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8648  static int wpas_ctrl_iface_get_pref_freq_list(
8649  	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
8650  {
8651  	unsigned int num = 100, i;
8652  	int ret;
8653  	enum wpa_driver_if_type iface_type;
8654  	char *pos, *end;
8655  	struct weighted_pcl freq_list[100];
8656  
8657  	pos = buf;
8658  	end = buf + buflen;
8659  
8660  	/* buf: "<interface_type>" */
8661  	if (os_strcmp(cmd, "STATION") == 0)
8662  		iface_type = WPA_IF_STATION;
8663  	else if (os_strcmp(cmd, "AP") == 0)
8664  		iface_type = WPA_IF_AP_BSS;
8665  	else if (os_strcmp(cmd, "P2P_GO") == 0)
8666  		iface_type = WPA_IF_P2P_GO;
8667  	else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
8668  		iface_type = WPA_IF_P2P_CLIENT;
8669  	else if (os_strcmp(cmd, "IBSS") == 0)
8670  		iface_type = WPA_IF_IBSS;
8671  	else if (os_strcmp(cmd, "TDLS") == 0)
8672  		iface_type = WPA_IF_TDLS;
8673  	else
8674  		return -1;
8675  
8676  	wpa_printf(MSG_DEBUG,
8677  		   "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
8678  		   iface_type, cmd);
8679  
8680  	ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
8681  	if (ret)
8682  		return -1;
8683  
8684  	for (i = 0; i < num; i++) {
8685  		ret = os_snprintf(pos, end - pos, "%s%u",
8686  				  i > 0 ? "," : "", freq_list[i].freq);
8687  		if (os_snprintf_error(end - pos, ret))
8688  			return -1;
8689  		pos += ret;
8690  	}
8691  
8692  	return pos - buf;
8693  }
8694  
8695  
wpas_ctrl_iface_driver_flags(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8696  static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
8697  					char *buf, size_t buflen)
8698  {
8699  	int ret, i;
8700  	char *pos, *end;
8701  
8702  	ret = os_snprintf(buf, buflen, "%016llX:\n",
8703  			  (long long unsigned) wpa_s->drv_flags);
8704  	if (os_snprintf_error(buflen, ret))
8705  		return -1;
8706  
8707  	pos = buf + ret;
8708  	end = buf + buflen;
8709  
8710  	for (i = 0; i < 64; i++) {
8711  		if (wpa_s->drv_flags & (1LLU << i)) {
8712  			ret = os_snprintf(pos, end - pos, "%s\n",
8713  					  driver_flag_to_string(1LLU << i));
8714  			if (os_snprintf_error(end - pos, ret))
8715  				return -1;
8716  			pos += ret;
8717  		}
8718  	}
8719  
8720  	return pos - buf;
8721  }
8722  
8723  
wpas_ctrl_iface_driver_flags2(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8724  static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s,
8725  					 char *buf, size_t buflen)
8726  {
8727  	int ret, i;
8728  	char *pos, *end;
8729  
8730  	ret = os_snprintf(buf, buflen, "%016llX:\n",
8731  			  (long long unsigned) wpa_s->drv_flags2);
8732  	if (os_snprintf_error(buflen, ret))
8733  		return -1;
8734  
8735  	pos = buf + ret;
8736  	end = buf + buflen;
8737  
8738  	for (i = 0; i < 64; i++) {
8739  		if (wpa_s->drv_flags2 & (1LLU << i)) {
8740  			ret = os_snprintf(pos, end - pos, "%s\n",
8741  					  driver_flag2_to_string(1LLU << i));
8742  			if (os_snprintf_error(end - pos, ret))
8743  				return -1;
8744  			pos += ret;
8745  		}
8746  	}
8747  
8748  	return pos - buf;
8749  }
8750  
8751  
wpa_supplicant_pktcnt_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8752  static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
8753  				      size_t buflen)
8754  {
8755  	struct hostap_sta_driver_data sta;
8756  	int ret;
8757  
8758  	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
8759  	if (ret)
8760  		return -1;
8761  
8762  	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
8763  			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
8764  	if (os_snprintf_error(buflen, ret))
8765  		return -1;
8766  	return ret;
8767  }
8768  
8769  
8770  #ifdef ANDROID
wpa_supplicant_driver_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8771  static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8772  				     char *buf, size_t buflen)
8773  {
8774  	int ret;
8775  
8776  	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
8777  	if (ret == 0) {
8778  #ifdef CONFIG_P2P
8779  		if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
8780  			struct p2p_data *p2p = wpa_s->global->p2p;
8781  			if (p2p) {
8782  				char country[3];
8783  				country[0] = cmd[8];
8784  				country[1] = cmd[9];
8785  				country[2] = 0x04;
8786  				p2p_set_country(p2p, country);
8787  			}
8788  		}
8789  #endif /* CONFIG_P2P */
8790  		ret = os_snprintf(buf, buflen, "%s\n", "OK");
8791  		if (os_snprintf_error(buflen, ret))
8792  			ret = -1;
8793  	}
8794  	return ret;
8795  }
8796  #endif /* ANDROID */
8797  
8798  
wpa_supplicant_vendor_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8799  static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8800  				     char *buf, size_t buflen)
8801  {
8802  	int ret;
8803  	char *pos, *temp = NULL;
8804  	u8 *data = NULL;
8805  	unsigned int vendor_id, subcmd;
8806  	enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
8807  	struct wpabuf *reply;
8808  	size_t data_len = 0;
8809  
8810  	/**
8811  	 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
8812  	 * [nested=<0|1>]
8813  	 */
8814  	vendor_id = strtoul(cmd, &pos, 16);
8815  	if (!isblank((unsigned char) *pos))
8816  		return -EINVAL;
8817  
8818  	subcmd = strtoul(pos, &pos, 10);
8819  
8820  	if (*pos != '\0') {
8821  		if (!isblank((unsigned char) *pos++))
8822  			return -EINVAL;
8823  
8824  		temp = os_strchr(pos, ' ');
8825  		data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
8826  	}
8827  
8828  	if (data_len) {
8829  		data_len /= 2;
8830  		data = os_malloc(data_len);
8831  		if (!data)
8832  			return -1;
8833  
8834  		if (hexstr2bin(pos, data, data_len)) {
8835  			wpa_printf(MSG_DEBUG,
8836  				   "Vendor command: wrong parameter format");
8837  			os_free(data);
8838  			return -EINVAL;
8839  		}
8840  	}
8841  
8842  	pos = os_strstr(cmd, "nested=");
8843  	if (pos)
8844  		nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
8845  			NESTED_ATTR_NOT_USED;
8846  
8847  	reply = wpabuf_alloc((buflen - 1) / 2);
8848  	if (!reply) {
8849  		os_free(data);
8850  		return -1;
8851  	}
8852  
8853  	ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
8854  				 nested_attr_flag, reply);
8855  
8856  	if (ret == 0)
8857  		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
8858  				       wpabuf_len(reply));
8859  
8860  	wpabuf_free(reply);
8861  	os_free(data);
8862  
8863  	return ret;
8864  }
8865  
8866  
wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant * wpa_s)8867  static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
8868  {
8869  #ifdef CONFIG_P2P
8870  	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
8871  		wpa_s->global->p2p_init_wpa_s : wpa_s;
8872  #endif /* CONFIG_P2P */
8873  
8874  	wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
8875  
8876  	if (wpas_abort_ongoing_scan(wpa_s) == 0)
8877  		wpa_s->ignore_post_flush_scan_res = 1;
8878  
8879  	if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
8880  		/*
8881  		 * Avoid possible auto connect re-connection on getting
8882  		 * disconnected due to state flush.
8883  		 */
8884  		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
8885  	}
8886  
8887  #ifdef CONFIG_P2P
8888  	wpas_p2p_group_remove(p2p_wpa_s, "*");
8889  	wpas_p2p_cancel(p2p_wpa_s);
8890  	p2p_ctrl_flush(p2p_wpa_s);
8891  	wpas_p2p_service_flush(p2p_wpa_s);
8892  	p2p_wpa_s->global->p2p_disabled = 0;
8893  	p2p_wpa_s->global->p2p_per_sta_psk = 0;
8894  	p2p_wpa_s->conf->num_sec_device_types = 0;
8895  	p2p_wpa_s->p2p_disable_ip_addr_req = 0;
8896  	os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
8897  	p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
8898  	p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
8899  	p2p_wpa_s->global->pending_p2ps_group = 0;
8900  	p2p_wpa_s->global->pending_p2ps_group_freq = 0;
8901  #endif /* CONFIG_P2P */
8902  
8903  #ifdef CONFIG_WPS_TESTING
8904  	wps_version_number = 0x20;
8905  	wps_testing_stub_cred = 0;
8906  	wps_corrupt_pkhash = 0;
8907  	wps_force_auth_types_in_use = 0;
8908  	wps_force_encr_types_in_use = 0;
8909  #endif /* CONFIG_WPS_TESTING */
8910  #ifdef CONFIG_WPS
8911  	wpa_s->wps_fragment_size = 0;
8912  	wpas_wps_cancel(wpa_s);
8913  	wps_registrar_flush(wpa_s->wps->registrar);
8914  #endif /* CONFIG_WPS */
8915  	wpa_s->after_wps = 0;
8916  	wpa_s->known_wps_freq = 0;
8917  
8918  #ifdef CONFIG_DPP
8919  	wpas_dpp_deinit(wpa_s);
8920  	wpa_s->dpp_init_max_tries = 0;
8921  	wpa_s->dpp_init_retry_time = 0;
8922  	wpa_s->dpp_resp_wait_time = 0;
8923  	wpa_s->dpp_resp_max_tries = 0;
8924  	wpa_s->dpp_resp_retry_time = 0;
8925  #ifdef CONFIG_DPP2
8926  	wpas_dpp_chirp_stop(wpa_s);
8927  	wpa_s->dpp_pfs_fallback = 0;
8928  #endif /* CONFIG_DPP2 */
8929  #ifdef CONFIG_DPP3
8930  	{
8931  		int i;
8932  
8933  		for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
8934  			struct dpp_pb_info *info;
8935  
8936  			info = &wpa_s->dpp_pb[i];
8937  			info->rx_time.sec = 0;
8938  			info->rx_time.usec = 0;
8939  		}
8940  	}
8941  #endif /* CONFIG_DPP3 */
8942  #ifdef CONFIG_TESTING_OPTIONS
8943  	os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
8944  	os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
8945  	dpp_pkex_ephemeral_key_override_len = 0;
8946  	dpp_protocol_key_override_len = 0;
8947  	dpp_nonce_override_len = 0;
8948  #ifdef CONFIG_DPP3
8949  	dpp_version_override = 3;
8950  #elif defined(CONFIG_DPP2)
8951  	dpp_version_override = 2;
8952  #else /* CONFIG_DPP2 */
8953  	dpp_version_override = 1;
8954  #endif /* CONFIG_DPP2 */
8955  #endif /* CONFIG_TESTING_OPTIONS */
8956  #endif /* CONFIG_DPP */
8957  
8958  #ifdef CONFIG_TDLS
8959  #ifdef CONFIG_TDLS_TESTING
8960  	tdls_testing = 0;
8961  #endif /* CONFIG_TDLS_TESTING */
8962  	wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
8963  	wpa_tdls_enable(wpa_s->wpa, 1);
8964  #endif /* CONFIG_TDLS */
8965  
8966  	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
8967  	wpa_supplicant_stop_countermeasures(wpa_s, NULL);
8968  	wpa_s->last_michael_mic_error.sec = 0;
8969  
8970  	wpa_s->no_keep_alive = 0;
8971  	wpa_s->own_disconnect_req = 0;
8972  	wpa_s->own_reconnect_req = 0;
8973  	wpa_s->deny_ptk0_rekey = 0;
8974  
8975  	os_free(wpa_s->disallow_aps_bssid);
8976  	wpa_s->disallow_aps_bssid = NULL;
8977  	wpa_s->disallow_aps_bssid_count = 0;
8978  	os_free(wpa_s->disallow_aps_ssid);
8979  	wpa_s->disallow_aps_ssid = NULL;
8980  	wpa_s->disallow_aps_ssid_count = 0;
8981  
8982  	wpa_s->set_sta_uapsd = 0;
8983  	wpa_s->sta_uapsd = 0;
8984  
8985  	wpa_s->consecutive_conn_failures = 0;
8986  
8987  	wpa_drv_radio_disable(wpa_s, 0);
8988  	wpa_bssid_ignore_clear(wpa_s);
8989  	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
8990  	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
8991  	wpa_config_flush_blobs(wpa_s->conf);
8992  	wpa_s->conf->auto_interworking = 0;
8993  	wpa_s->conf->okc = 0;
8994  
8995  	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
8996  	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
8997  	rsn_preauth_deinit(wpa_s->wpa);
8998  
8999  	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
9000  	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
9001  	wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
9002  	eapol_sm_notify_logoff(wpa_s->eapol, false);
9003  
9004  	radio_remove_works(wpa_s, NULL, 1);
9005  	wpa_s->ext_work_in_progress = 0;
9006  
9007  	wpa_s->next_ssid = NULL;
9008  
9009  	wnm_btm_reset(wpa_s);
9010  
9011  	wpa_s->ext_mgmt_frame_handling = 0;
9012  	wpa_s->ext_eapol_frame_io = 0;
9013  #ifdef CONFIG_TESTING_OPTIONS
9014  	wpa_s->extra_roc_dur = 0;
9015  	wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
9016  	wpa_s->p2p_go_csa_on_inv = 0;
9017  	wpa_s->ignore_auth_resp = 0;
9018  	wpa_s->ignore_assoc_disallow = 0;
9019  	wpa_s->disable_sa_query = 0;
9020  	wpa_s->testing_resend_assoc = 0;
9021  	wpa_s->ignore_sae_h2e_only = 0;
9022  	wpa_s->ft_rsnxe_used = 0;
9023  	wpa_s->reject_btm_req_reason = 0;
9024  	wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
9025  	wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
9026  	wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
9027  	wpa_sm_set_test_rsnxe_data(wpa_s->wpa, NULL, NULL);
9028  	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
9029  	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
9030  	os_free(wpa_s->get_pref_freq_list_override);
9031  	wpa_s->get_pref_freq_list_override = NULL;
9032  	wpabuf_free(wpa_s->sae_commit_override);
9033  	wpa_s->sae_commit_override = NULL;
9034  	os_free(wpa_s->extra_sae_rejected_groups);
9035  	wpa_s->extra_sae_rejected_groups = NULL;
9036  	wpabuf_free(wpa_s->rsne_override_eapol);
9037  	wpa_s->rsne_override_eapol = NULL;
9038  	wpabuf_free(wpa_s->rsnxe_override_assoc);
9039  	wpa_s->rsnxe_override_assoc = NULL;
9040  	wpabuf_free(wpa_s->rsnxe_override_eapol);
9041  	wpa_s->rsnxe_override_eapol = NULL;
9042  	wpas_clear_driver_signal_override(wpa_s);
9043  #ifndef CONFIG_NO_ROBUST_AV
9044  	wpa_s->disable_scs_support = 0;
9045  	wpa_s->disable_mscs_support = 0;
9046  	wpa_s->enable_dscp_policy_capa = 0;
9047  #endif /* CONFIG_NO_ROBUST_AV */
9048  	wpa_s->oci_freq_override_eapol = 0;
9049  	wpa_s->oci_freq_override_saquery_req = 0;
9050  	wpa_s->oci_freq_override_saquery_resp = 0;
9051  	wpa_s->oci_freq_override_eapol_g2 = 0;
9052  	wpa_s->oci_freq_override_ft_assoc = 0;
9053  	wpa_s->oci_freq_override_fils_assoc = 0;
9054  	wpa_s->oci_freq_override_wnm_sleep = 0;
9055  	wpa_s->disable_eapol_g2_tx = 0;
9056  	wpa_s->eapol_2_key_info_set_mask = 0;
9057  	wpa_s->test_assoc_comeback_type = -1;
9058  #ifdef CONFIG_DPP
9059  	os_free(wpa_s->dpp_config_obj_override);
9060  	wpa_s->dpp_config_obj_override = NULL;
9061  	os_free(wpa_s->dpp_discovery_override);
9062  	wpa_s->dpp_discovery_override = NULL;
9063  	os_free(wpa_s->dpp_groups_override);
9064  	wpa_s->dpp_groups_override = NULL;
9065  	wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
9066  	wpa_s->dpp_discard_public_action = 0;
9067  	dpp_test = DPP_TEST_DISABLED;
9068  #endif /* CONFIG_DPP */
9069  #endif /* CONFIG_TESTING_OPTIONS */
9070  
9071  	wpa_s->disconnected = 0;
9072  	os_free(wpa_s->next_scan_freqs);
9073  	wpa_s->next_scan_freqs = NULL;
9074  	os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
9075  	wpa_s->next_scan_bssid_wildcard_ssid = 0;
9076  	os_free(wpa_s->select_network_scan_freqs);
9077  	wpa_s->select_network_scan_freqs = NULL;
9078  #ifndef CONFIG_NO_ROBUST_AV
9079  	os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
9080  #endif /* CONFIG_NO_ROBUST_AV */
9081  
9082  	wpa_bss_flush(wpa_s);
9083  	if (!dl_list_empty(&wpa_s->bss)) {
9084  		wpa_printf(MSG_DEBUG,
9085  			   "BSS table not empty after flush: %u entries, current_bss=%p bssid="
9086  			   MACSTR " pending_bssid=" MACSTR,
9087  			   dl_list_len(&wpa_s->bss), wpa_s->current_bss,
9088  			   MAC2STR(wpa_s->bssid),
9089  			   MAC2STR(wpa_s->pending_bssid));
9090  	}
9091  
9092  	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
9093  	wpa_s->wnmsleep_used = 0;
9094  
9095  #ifdef CONFIG_SME
9096  	wpa_s->sme.last_unprot_disconnect.sec = 0;
9097  	wpa_s->sme.auth_alg = 0;
9098  #endif /* CONFIG_SME */
9099  
9100  	wpabuf_free(wpa_s->ric_ies);
9101  	wpa_s->ric_ies = NULL;
9102  
9103  	wpa_supplicant_update_channel_list(wpa_s, NULL);
9104  
9105  	free_bss_tmp_disallowed(wpa_s);
9106  
9107  #ifndef CONFIG_NO_ROBUST_AV
9108  	os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
9109  #endif /* CONFIG_NO_ROBUST_AV */
9110  
9111  #ifdef CONFIG_PASN
9112  	wpas_pasn_auth_stop(wpa_s);
9113  #endif /* CONFIG_PASN */
9114  
9115  	if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
9116  		wpas_restore_permanent_mac_addr(wpa_s);
9117  
9118  	wpa_s->conf->ignore_old_scan_res = 0;
9119  
9120  #ifdef CONFIG_NAN_USD
9121  	wpas_nan_usd_flush(wpa_s);
9122  #endif /* CONFIG_NAN_USD */
9123  }
9124  
9125  
wpas_ctrl_radio_work_show(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)9126  static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
9127  				     char *buf, size_t buflen)
9128  {
9129  	struct wpa_radio_work *work;
9130  	char *pos, *end;
9131  	struct os_reltime now, diff;
9132  
9133  	pos = buf;
9134  	end = buf + buflen;
9135  
9136  	os_get_reltime(&now);
9137  
9138  	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9139  	{
9140  		int ret;
9141  
9142  		os_reltime_sub(&now, &work->time, &diff);
9143  		ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
9144  				  work->type, work->wpa_s->ifname, work->freq,
9145  				  work->started, diff.sec, diff.usec);
9146  		if (os_snprintf_error(end - pos, ret))
9147  			break;
9148  		pos += ret;
9149  	}
9150  
9151  	return pos - buf;
9152  }
9153  
9154  
wpas_ctrl_radio_work_timeout(void * eloop_ctx,void * timeout_ctx)9155  static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
9156  {
9157  	struct wpa_radio_work *work = eloop_ctx;
9158  	struct wpa_external_work *ework = work->ctx;
9159  
9160  	wpa_dbg(work->wpa_s, MSG_DEBUG,
9161  		"Timing out external radio work %u (%s)",
9162  		ework->id, work->type);
9163  	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
9164  	work->wpa_s->ext_work_in_progress = 0;
9165  	radio_work_done(work);
9166  	os_free(ework);
9167  }
9168  
9169  
wpas_ctrl_radio_work_cb(struct wpa_radio_work * work,int deinit)9170  static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
9171  {
9172  	struct wpa_external_work *ework = work->ctx;
9173  
9174  	if (deinit) {
9175  		if (work->started)
9176  			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9177  					     work, NULL);
9178  
9179  		/*
9180  		 * work->type points to a buffer in ework, so need to replace
9181  		 * that here with a fixed string to avoid use of freed memory
9182  		 * in debug prints.
9183  		 */
9184  		work->type = "freed-ext-work";
9185  		work->ctx = NULL;
9186  		os_free(ework);
9187  		return;
9188  	}
9189  
9190  	wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
9191  		ework->id, ework->type);
9192  	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
9193  	work->wpa_s->ext_work_in_progress = 1;
9194  	if (!ework->timeout)
9195  		ework->timeout = 10;
9196  	eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
9197  			       work, NULL);
9198  }
9199  
9200  
wpas_ctrl_radio_work_add(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)9201  static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
9202  				    char *buf, size_t buflen)
9203  {
9204  	struct wpa_external_work *ework;
9205  	char *pos, *pos2;
9206  	size_t type_len;
9207  	int ret;
9208  	unsigned int freq = 0;
9209  
9210  	/* format: <name> [freq=<MHz>] [timeout=<seconds>] */
9211  
9212  	ework = os_zalloc(sizeof(*ework));
9213  	if (ework == NULL)
9214  		return -1;
9215  
9216  	pos = os_strchr(cmd, ' ');
9217  	if (pos) {
9218  		type_len = pos - cmd;
9219  		pos++;
9220  
9221  		pos2 = os_strstr(pos, "freq=");
9222  		if (pos2)
9223  			freq = atoi(pos2 + 5);
9224  
9225  		pos2 = os_strstr(pos, "timeout=");
9226  		if (pos2)
9227  			ework->timeout = atoi(pos2 + 8);
9228  	} else {
9229  		type_len = os_strlen(cmd);
9230  	}
9231  	if (4 + type_len >= sizeof(ework->type))
9232  		type_len = sizeof(ework->type) - 4 - 1;
9233  	os_strlcpy(ework->type, "ext:", sizeof(ework->type));
9234  	os_memcpy(ework->type + 4, cmd, type_len);
9235  	ework->type[4 + type_len] = '\0';
9236  
9237  	wpa_s->ext_work_id++;
9238  	if (wpa_s->ext_work_id == 0)
9239  		wpa_s->ext_work_id++;
9240  	ework->id = wpa_s->ext_work_id;
9241  
9242  	if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
9243  			   ework) < 0) {
9244  		os_free(ework);
9245  		return -1;
9246  	}
9247  
9248  	ret = os_snprintf(buf, buflen, "%u", ework->id);
9249  	if (os_snprintf_error(buflen, ret))
9250  		return -1;
9251  	return ret;
9252  }
9253  
9254  
wpas_ctrl_radio_work_done(struct wpa_supplicant * wpa_s,char * cmd)9255  static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
9256  {
9257  	struct wpa_radio_work *work;
9258  	unsigned int id = atoi(cmd);
9259  
9260  	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9261  	{
9262  		struct wpa_external_work *ework;
9263  
9264  		if (os_strncmp(work->type, "ext:", 4) != 0)
9265  			continue;
9266  		ework = work->ctx;
9267  		if (id && ework->id != id)
9268  			continue;
9269  		wpa_dbg(wpa_s, MSG_DEBUG,
9270  			"Completed external radio work %u (%s)",
9271  			ework->id, ework->type);
9272  		eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
9273  		wpa_s->ext_work_in_progress = 0;
9274  		radio_work_done(work);
9275  		os_free(ework);
9276  		return 3; /* "OK\n" */
9277  	}
9278  
9279  	return -1;
9280  }
9281  
9282  
wpas_ctrl_radio_work(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)9283  static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
9284  				char *buf, size_t buflen)
9285  {
9286  	if (os_strcmp(cmd, "show") == 0)
9287  		return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
9288  	if (os_strncmp(cmd, "add ", 4) == 0)
9289  		return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
9290  	if (os_strncmp(cmd, "done ", 5) == 0)
9291  		return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
9292  	return -1;
9293  }
9294  
9295  
wpas_ctrl_radio_work_flush(struct wpa_supplicant * wpa_s)9296  void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
9297  {
9298  	struct wpa_radio_work *work, *tmp;
9299  
9300  	if (!wpa_s || !wpa_s->radio)
9301  		return;
9302  
9303  	dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
9304  			      struct wpa_radio_work, list) {
9305  		struct wpa_external_work *ework;
9306  
9307  		if (os_strncmp(work->type, "ext:", 4) != 0)
9308  			continue;
9309  		ework = work->ctx;
9310  		wpa_dbg(wpa_s, MSG_DEBUG,
9311  			"Flushing%s external radio work %u (%s)",
9312  			work->started ? " started" : "", ework->id,
9313  			ework->type);
9314  		if (work->started)
9315  			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9316  					     work, NULL);
9317  		radio_work_done(work);
9318  		os_free(ework);
9319  	}
9320  }
9321  
9322  
wpas_ctrl_eapol_response(void * eloop_ctx,void * timeout_ctx)9323  static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
9324  {
9325  	struct wpa_supplicant *wpa_s = eloop_ctx;
9326  	eapol_sm_notify_ctrl_response(wpa_s->eapol);
9327  }
9328  
9329  
scan_id_list_parse(struct wpa_supplicant * wpa_s,const char * value,unsigned int * scan_id_count,int scan_id[])9330  static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
9331  			      unsigned int *scan_id_count, int scan_id[])
9332  {
9333  	const char *pos = value;
9334  
9335  	while (pos) {
9336  		if (*pos == ' ' || *pos == '\0')
9337  			break;
9338  		if (*scan_id_count == MAX_SCAN_ID)
9339  			return -1;
9340  		scan_id[(*scan_id_count)++] = atoi(pos);
9341  		pos = os_strchr(pos, ',');
9342  		if (pos)
9343  			pos++;
9344  	}
9345  
9346  	return 0;
9347  }
9348  
9349  
wpas_ctrl_scan(struct wpa_supplicant * wpa_s,char * params,char * reply,int reply_size,int * reply_len)9350  static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
9351  			   char *reply, int reply_size, int *reply_len)
9352  {
9353  	char *pos;
9354  	unsigned int manual_scan_passive = 0;
9355  	unsigned int manual_scan_use_id = 0;
9356  	unsigned int manual_scan_only_new = 0;
9357  	unsigned int scan_only = 0;
9358  	unsigned int scan_id_count = 0;
9359  	unsigned int manual_non_coloc_6ghz = 0;
9360  	int scan_id[MAX_SCAN_ID];
9361  	void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
9362  				 struct wpa_scan_results *scan_res);
9363  	int *manual_scan_freqs = NULL;
9364  	struct wpa_ssid_value *ssid = NULL, *ns;
9365  	unsigned int ssid_count = 0;
9366  
9367  	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
9368  		*reply_len = -1;
9369  		return;
9370  	}
9371  
9372  	if (radio_work_pending(wpa_s, "scan")) {
9373  		wpa_printf(MSG_DEBUG,
9374  			   "Pending scan scheduled - reject new request");
9375  		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9376  		return;
9377  	}
9378  
9379  #ifdef CONFIG_INTERWORKING
9380  	if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
9381  		wpa_printf(MSG_DEBUG,
9382  			   "Interworking select in progress - reject new scan");
9383  		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9384  		return;
9385  	}
9386  #endif /* CONFIG_INTERWORKING */
9387  
9388  	if (params) {
9389  		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
9390  			scan_only = 1;
9391  
9392  		pos = os_strstr(params, "freq=");
9393  		if (pos) {
9394  			manual_scan_freqs = freq_range_to_channel_list(wpa_s,
9395  								       pos + 5);
9396  			if (manual_scan_freqs == NULL) {
9397  				*reply_len = -1;
9398  				goto done;
9399  			}
9400  		}
9401  
9402  		pos = os_strstr(params, "passive=");
9403  		if (pos)
9404  			manual_scan_passive = !!atoi(pos + 8);
9405  
9406  		pos = os_strstr(params, "use_id=");
9407  		if (pos)
9408  			manual_scan_use_id = atoi(pos + 7);
9409  
9410  		pos = os_strstr(params, "only_new=1");
9411  		if (pos)
9412  			manual_scan_only_new = 1;
9413  
9414  		pos = os_strstr(params, "scan_id=");
9415  		if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
9416  					      scan_id) < 0) {
9417  			*reply_len = -1;
9418  			goto done;
9419  		}
9420  
9421  		pos = os_strstr(params, "bssid=");
9422  		if (pos) {
9423  			u8 bssid[ETH_ALEN];
9424  
9425  			pos += 6;
9426  			if (hwaddr_aton(pos, bssid)) {
9427  				wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
9428  				*reply_len = -1;
9429  				goto done;
9430  			}
9431  			os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
9432  
9433  			wpa_s->next_scan_bssid_wildcard_ssid =
9434  				os_strstr(params, "wildcard_ssid=1") != NULL;
9435  		}
9436  
9437  		pos = os_strstr(params, "non_coloc_6ghz=");
9438  		if (pos)
9439  			manual_non_coloc_6ghz = !!atoi(pos + 15);
9440  
9441  		pos = params;
9442  		while (pos && *pos != '\0') {
9443  			if (os_strncmp(pos, "ssid ", 5) == 0) {
9444  				char *end;
9445  
9446  				pos += 5;
9447  				end = pos;
9448  				while (*end) {
9449  					if (*end == '\0' || *end == ' ')
9450  						break;
9451  					end++;
9452  				}
9453  
9454  				ns = os_realloc_array(
9455  					ssid, ssid_count + 1,
9456  					sizeof(struct wpa_ssid_value));
9457  				if (ns == NULL) {
9458  					*reply_len = -1;
9459  					goto done;
9460  				}
9461  				ssid = ns;
9462  
9463  				if ((end - pos) & 0x01 ||
9464  				    end - pos > 2 * SSID_MAX_LEN ||
9465  				    hexstr2bin(pos, ssid[ssid_count].ssid,
9466  					       (end - pos) / 2) < 0) {
9467  					wpa_printf(MSG_DEBUG,
9468  						   "Invalid SSID value '%s'",
9469  						   pos);
9470  					*reply_len = -1;
9471  					goto done;
9472  				}
9473  				ssid[ssid_count].ssid_len = (end - pos) / 2;
9474  				wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
9475  						  ssid[ssid_count].ssid,
9476  						  ssid[ssid_count].ssid_len);
9477  				ssid_count++;
9478  				pos = end;
9479  			}
9480  
9481  			pos = os_strchr(pos, ' ');
9482  			if (pos)
9483  				pos++;
9484  		}
9485  	}
9486  
9487  	wpa_s->num_ssids_from_scan_req = ssid_count;
9488  	os_free(wpa_s->ssids_from_scan_req);
9489  	if (ssid_count) {
9490  		wpa_s->ssids_from_scan_req = ssid;
9491  		ssid = NULL;
9492  	} else {
9493  		wpa_s->ssids_from_scan_req = NULL;
9494  	}
9495  
9496  	if (scan_only)
9497  		scan_res_handler = scan_only_handler;
9498  	else if (wpa_s->scan_res_handler == scan_only_handler)
9499  		scan_res_handler = NULL;
9500  	else
9501  		scan_res_handler = wpa_s->scan_res_handler;
9502  
9503  	if (!wpa_s->sched_scanning && !wpa_s->scanning &&
9504  	    ((wpa_s->wpa_state <= WPA_SCANNING) ||
9505  	     (wpa_s->wpa_state == WPA_COMPLETED))) {
9506  		wpa_s->manual_scan_passive = manual_scan_passive;
9507  		wpa_s->manual_scan_use_id = manual_scan_use_id;
9508  		wpa_s->manual_scan_only_new = manual_scan_only_new;
9509  		wpa_s->scan_id_count = scan_id_count;
9510  		wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
9511  		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9512  		wpa_s->scan_res_handler = scan_res_handler;
9513  		os_free(wpa_s->manual_scan_freqs);
9514  		wpa_s->manual_scan_freqs = manual_scan_freqs;
9515  		manual_scan_freqs = NULL;
9516  
9517  		wpa_s->normal_scans = 0;
9518  		wpa_s->scan_req = MANUAL_SCAN_REQ;
9519  		wpa_s->after_wps = 0;
9520  		wpa_s->known_wps_freq = 0;
9521  		wpa_supplicant_req_scan(wpa_s, 0, 0);
9522  		if (wpa_s->manual_scan_use_id) {
9523  			wpa_s->manual_scan_id++;
9524  			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9525  				wpa_s->manual_scan_id);
9526  			*reply_len = os_snprintf(reply, reply_size, "%u\n",
9527  						 wpa_s->manual_scan_id);
9528  		}
9529  	} else if (wpa_s->sched_scanning) {
9530  		wpa_s->manual_scan_passive = manual_scan_passive;
9531  		wpa_s->manual_scan_use_id = manual_scan_use_id;
9532  		wpa_s->manual_scan_only_new = manual_scan_only_new;
9533  		wpa_s->scan_id_count = scan_id_count;
9534  		wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
9535  		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9536  		wpa_s->scan_res_handler = scan_res_handler;
9537  		os_free(wpa_s->manual_scan_freqs);
9538  		wpa_s->manual_scan_freqs = manual_scan_freqs;
9539  		manual_scan_freqs = NULL;
9540  
9541  		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
9542  		wpa_supplicant_cancel_sched_scan(wpa_s);
9543  		wpa_s->scan_req = MANUAL_SCAN_REQ;
9544  		wpa_supplicant_req_scan(wpa_s, 0, 0);
9545  		if (wpa_s->manual_scan_use_id) {
9546  			wpa_s->manual_scan_id++;
9547  			*reply_len = os_snprintf(reply, reply_size, "%u\n",
9548  						 wpa_s->manual_scan_id);
9549  			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9550  				wpa_s->manual_scan_id);
9551  		}
9552  	} else {
9553  		wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
9554  		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9555  	}
9556  
9557  done:
9558  	os_free(manual_scan_freqs);
9559  	os_free(ssid);
9560  }
9561  
9562  
9563  #ifdef CONFIG_TESTING_OPTIONS
9564  
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)9565  static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
9566  				       unsigned int freq, const u8 *dst,
9567  				       const u8 *src, const u8 *bssid,
9568  				       const u8 *data, size_t data_len,
9569  				       enum offchannel_send_action_result
9570  				       result)
9571  {
9572  	wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
9573  		" src=" MACSTR " bssid=" MACSTR " result=%s",
9574  		freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
9575  		result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
9576  		"SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
9577  			     "NO_ACK" : "FAILED"));
9578  }
9579  
9580  
wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant * wpa_s,char * cmd)9581  static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
9582  {
9583  	char *pos, *param;
9584  	size_t len;
9585  	u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
9586  	int res, used;
9587  	int freq = 0, no_cck = 0, wait_time = 0;
9588  
9589  	/* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
9590  	 *    <action=Action frame payload> */
9591  
9592  	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
9593  
9594  	pos = cmd;
9595  	used = hwaddr_aton2(pos, da);
9596  	if (used < 0)
9597  		return -1;
9598  	pos += used;
9599  	while (*pos == ' ')
9600  		pos++;
9601  	used = hwaddr_aton2(pos, bssid);
9602  	if (used < 0)
9603  		return -1;
9604  	pos += used;
9605  
9606  	param = os_strstr(pos, " freq=");
9607  	if (param) {
9608  		param += 6;
9609  		freq = atoi(param);
9610  	}
9611  
9612  	param = os_strstr(pos, " no_cck=");
9613  	if (param) {
9614  		param += 8;
9615  		no_cck = atoi(param);
9616  	}
9617  
9618  	param = os_strstr(pos, " wait_time=");
9619  	if (param) {
9620  		param += 11;
9621  		wait_time = atoi(param);
9622  	}
9623  
9624  	param = os_strstr(pos, " action=");
9625  	if (param == NULL)
9626  		return -1;
9627  	param += 8;
9628  
9629  	len = os_strlen(param);
9630  	if (len & 1)
9631  		return -1;
9632  	len /= 2;
9633  
9634  	buf = os_malloc(len);
9635  	if (buf == NULL)
9636  		return -1;
9637  
9638  	if (hexstr2bin(param, buf, len) < 0) {
9639  		os_free(buf);
9640  		return -1;
9641  	}
9642  
9643  	res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
9644  				     buf, len, wait_time,
9645  				     wpas_ctrl_iface_mgmt_tx_cb, no_cck);
9646  	os_free(buf);
9647  	return res;
9648  }
9649  
9650  
wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant * wpa_s)9651  static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
9652  {
9653  	wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
9654  	offchannel_send_action_done(wpa_s);
9655  }
9656  
9657  
wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant * wpa_s,char * cmd)9658  static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
9659  					   char *cmd)
9660  {
9661  	char *pos, *param;
9662  	size_t len;
9663  	u8 *buf;
9664  	int freq = 0, datarate = 0, ssi_signal = 0;
9665  	union wpa_event_data event;
9666  
9667  	if (!wpa_s->ext_mgmt_frame_handling)
9668  		return -1;
9669  
9670  	/* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
9671  
9672  	wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
9673  
9674  	pos = cmd;
9675  	param = os_strstr(pos, "freq=");
9676  	if (param) {
9677  		param += 5;
9678  		freq = atoi(param);
9679  	}
9680  
9681  	param = os_strstr(pos, " datarate=");
9682  	if (param) {
9683  		param += 10;
9684  		datarate = atoi(param);
9685  	}
9686  
9687  	param = os_strstr(pos, " ssi_signal=");
9688  	if (param) {
9689  		param += 12;
9690  		ssi_signal = atoi(param);
9691  	}
9692  
9693  	param = os_strstr(pos, " frame=");
9694  	if (param == NULL)
9695  		return -1;
9696  	param += 7;
9697  
9698  	len = os_strlen(param);
9699  	if (len & 1)
9700  		return -1;
9701  	len /= 2;
9702  
9703  	buf = os_malloc(len);
9704  	if (buf == NULL)
9705  		return -1;
9706  
9707  	if (hexstr2bin(param, buf, len) < 0) {
9708  		os_free(buf);
9709  		return -1;
9710  	}
9711  
9712  	os_memset(&event, 0, sizeof(event));
9713  	event.rx_mgmt.freq = freq;
9714  	event.rx_mgmt.frame = buf;
9715  	event.rx_mgmt.frame_len = len;
9716  	event.rx_mgmt.ssi_signal = ssi_signal;
9717  	event.rx_mgmt.datarate = datarate;
9718  	wpa_s->ext_mgmt_frame_handling = 0;
9719  	wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
9720  	wpa_s->ext_mgmt_frame_handling = 1;
9721  
9722  	os_free(buf);
9723  
9724  	return 0;
9725  }
9726  
9727  
wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant * wpa_s,char * param)9728  static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
9729  					   char *param)
9730  {
9731  	struct wpa_scan_res *res;
9732  	struct os_reltime now;
9733  	char *pos, *end;
9734  	int ret = -1;
9735  
9736  	if (!param)
9737  		return -1;
9738  
9739  	if (os_strcmp(param, "START") == 0) {
9740  		wpa_bss_update_start(wpa_s);
9741  		return 0;
9742  	}
9743  
9744  	if (os_strcmp(param, "END") == 0) {
9745  		wpa_bss_update_end(wpa_s, NULL, 1);
9746  		return 0;
9747  	}
9748  
9749  	if (os_strncmp(param, "BSS ", 4) != 0)
9750  		return -1;
9751  	param += 3;
9752  
9753  	res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
9754  	if (!res)
9755  		return -1;
9756  
9757  	pos = os_strstr(param, " flags=");
9758  	if (pos)
9759  		res->flags = strtol(pos + 7, NULL, 16);
9760  
9761  	pos = os_strstr(param, " bssid=");
9762  	if (pos && hwaddr_aton(pos + 7, res->bssid))
9763  		goto fail;
9764  
9765  	pos = os_strstr(param, " freq=");
9766  	if (pos)
9767  		res->freq = atoi(pos + 6);
9768  
9769  	pos = os_strstr(param, " beacon_int=");
9770  	if (pos)
9771  		res->beacon_int = atoi(pos + 12);
9772  
9773  	pos = os_strstr(param, " caps=");
9774  	if (pos)
9775  		res->caps = strtol(pos + 6, NULL, 16);
9776  
9777  	pos = os_strstr(param, " qual=");
9778  	if (pos)
9779  		res->qual = atoi(pos + 6);
9780  
9781  	pos = os_strstr(param, " noise=");
9782  	if (pos)
9783  		res->noise = atoi(pos + 7);
9784  
9785  	pos = os_strstr(param, " level=");
9786  	if (pos)
9787  		res->level = atoi(pos + 7);
9788  
9789  	pos = os_strstr(param, " tsf=");
9790  	if (pos)
9791  		res->tsf = strtoll(pos + 5, NULL, 16);
9792  
9793  	pos = os_strstr(param, " age=");
9794  	if (pos)
9795  		res->age = atoi(pos + 5);
9796  
9797  	pos = os_strstr(param, " est_throughput=");
9798  	if (pos)
9799  		res->est_throughput = atoi(pos + 16);
9800  
9801  	pos = os_strstr(param, " snr=");
9802  	if (pos)
9803  		res->snr = atoi(pos + 5);
9804  
9805  	pos = os_strstr(param, " parent_tsf=");
9806  	if (pos)
9807  		res->parent_tsf = strtoll(pos + 7, NULL, 16);
9808  
9809  	pos = os_strstr(param, " tsf_bssid=");
9810  	if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
9811  		goto fail;
9812  
9813  	pos = os_strstr(param, " ie=");
9814  	if (pos) {
9815  		pos += 4;
9816  		end = os_strchr(pos, ' ');
9817  		if (!end)
9818  			end = pos + os_strlen(pos);
9819  		res->ie_len = (end - pos) / 2;
9820  		if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
9821  			goto fail;
9822  	}
9823  
9824  	pos = os_strstr(param, " beacon_ie=");
9825  	if (pos) {
9826  		pos += 11;
9827  		end = os_strchr(pos, ' ');
9828  		if (!end)
9829  			end = pos + os_strlen(pos);
9830  		res->beacon_ie_len = (end - pos) / 2;
9831  		if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
9832  			       res->beacon_ie_len))
9833  			goto fail;
9834  	}
9835  
9836  	os_get_reltime(&now);
9837  	wpa_bss_update_scan_res(wpa_s, res, &now);
9838  	ret = 0;
9839  fail:
9840  	os_free(res);
9841  
9842  	return ret;
9843  }
9844  
9845  
wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant * wpa_s,char * param)9846  static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
9847  					      char *param)
9848  {
9849  	union wpa_event_data event;
9850  	struct assoc_info *ai;
9851  	char *ctx = NULL;
9852  	int ret = -1;
9853  	struct wpabuf *req_ies = NULL;
9854  	struct wpabuf *resp_ies = NULL;
9855  	struct wpabuf *resp_frame = NULL;
9856  	struct wpabuf *beacon_ies = NULL;
9857  	struct wpabuf *key_replay_ctr = NULL;
9858  	struct wpabuf *ptk_kck = NULL;
9859  	struct wpabuf *ptk_kek = NULL;
9860  	struct wpabuf *fils_pmk = NULL;
9861  	char *str, *pos;
9862  	u8 addr[ETH_ALEN];
9863  	u8 fils_pmkid[PMKID_LEN];
9864  
9865  	os_memset(&event, 0, sizeof(event));
9866  	ai = &event.assoc_info;
9867  
9868  	while ((str = str_token(param, " ", &ctx))) {
9869  		pos = os_strchr(str, '=');
9870  		if (!pos)
9871  			goto fail;
9872  		*pos++ = '\0';
9873  
9874  		if (os_strcmp(str, "reassoc") == 0) {
9875  			ai->reassoc = atoi(pos);
9876  		} else if (os_strcmp(str, "req_ies") == 0) {
9877  			wpabuf_free(req_ies);
9878  			req_ies = wpabuf_parse_bin(pos);
9879  			if (!req_ies)
9880  				goto fail;
9881  			ai->req_ies = wpabuf_head(req_ies);
9882  			ai->req_ies_len = wpabuf_len(req_ies);
9883  		} else if (os_strcmp(str, "resp_ies") == 0) {
9884  			wpabuf_free(resp_ies);
9885  			resp_ies = wpabuf_parse_bin(pos);
9886  			if (!resp_ies)
9887  				goto fail;
9888  			ai->resp_ies = wpabuf_head(resp_ies);
9889  			ai->resp_ies_len = wpabuf_len(resp_ies);
9890  		} else if (os_strcmp(str, "resp_frame") == 0) {
9891  			wpabuf_free(resp_frame);
9892  			resp_frame = wpabuf_parse_bin(pos);
9893  			if (!resp_frame)
9894  				goto fail;
9895  			ai->resp_frame = wpabuf_head(resp_frame);
9896  			ai->resp_frame_len = wpabuf_len(resp_frame);
9897  		} else if (os_strcmp(str, "beacon_ies") == 0) {
9898  			wpabuf_free(beacon_ies);
9899  			beacon_ies = wpabuf_parse_bin(pos);
9900  			if (!beacon_ies)
9901  				goto fail;
9902  			ai->beacon_ies = wpabuf_head(beacon_ies);
9903  			ai->beacon_ies_len = wpabuf_len(beacon_ies);
9904  		} else if (os_strcmp(str, "freq") == 0) {
9905  			ai->freq = atoi(pos);
9906  		} else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
9907  			ai->wmm_params.info_bitmap = atoi(pos);
9908  		} else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
9909  			ai->wmm_params.uapsd_queues = atoi(pos);
9910  		} else if (os_strcmp(str, "addr") == 0) {
9911  			if (hwaddr_aton(pos, addr))
9912  				goto fail;
9913  			ai->addr = addr;
9914  		} else if (os_strcmp(str, "authorized") == 0) {
9915  			ai->authorized = atoi(pos);
9916  		} else if (os_strcmp(str, "key_replay_ctr") == 0) {
9917  			wpabuf_free(key_replay_ctr);
9918  			key_replay_ctr = wpabuf_parse_bin(pos);
9919  			if (!key_replay_ctr)
9920  				goto fail;
9921  			ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
9922  			ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
9923  		} else if (os_strcmp(str, "ptk_kck") == 0) {
9924  			wpabuf_free(ptk_kck);
9925  			ptk_kck = wpabuf_parse_bin(pos);
9926  			if (!ptk_kck)
9927  				goto fail;
9928  			ai->ptk_kck = wpabuf_head(ptk_kck);
9929  			ai->ptk_kck_len = wpabuf_len(ptk_kck);
9930  		} else if (os_strcmp(str, "ptk_kek") == 0) {
9931  			wpabuf_free(ptk_kek);
9932  			ptk_kek = wpabuf_parse_bin(pos);
9933  			if (!ptk_kek)
9934  				goto fail;
9935  			ai->ptk_kek = wpabuf_head(ptk_kek);
9936  			ai->ptk_kek_len = wpabuf_len(ptk_kek);
9937  		} else if (os_strcmp(str, "subnet_status") == 0) {
9938  			ai->subnet_status = atoi(pos);
9939  		} else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
9940  			ai->fils_erp_next_seq_num = atoi(pos);
9941  		} else if (os_strcmp(str, "fils_pmk") == 0) {
9942  			wpabuf_free(fils_pmk);
9943  			fils_pmk = wpabuf_parse_bin(pos);
9944  			if (!fils_pmk)
9945  				goto fail;
9946  			ai->fils_pmk = wpabuf_head(fils_pmk);
9947  			ai->fils_pmk_len = wpabuf_len(fils_pmk);
9948  		} else if (os_strcmp(str, "fils_pmkid") == 0) {
9949  			if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
9950  				goto fail;
9951  			ai->fils_pmkid = fils_pmkid;
9952  		} else {
9953  			goto fail;
9954  		}
9955  	}
9956  
9957  	wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
9958  	ret = 0;
9959  fail:
9960  	wpabuf_free(req_ies);
9961  	wpabuf_free(resp_ies);
9962  	wpabuf_free(resp_frame);
9963  	wpabuf_free(beacon_ies);
9964  	wpabuf_free(key_replay_ctr);
9965  	wpabuf_free(ptk_kck);
9966  	wpabuf_free(ptk_kek);
9967  	wpabuf_free(fils_pmk);
9968  	return ret;
9969  }
9970  
9971  
wpas_ctrl_iface_driver_event(struct wpa_supplicant * wpa_s,char * cmd)9972  static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
9973  {
9974  	char *pos, *param;
9975  	union wpa_event_data event;
9976  	enum wpa_event_type ev;
9977  
9978  	/* <event name> [parameters..] */
9979  
9980  	wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
9981  
9982  	pos = cmd;
9983  	param = os_strchr(pos, ' ');
9984  	if (param)
9985  		*param++ = '\0';
9986  
9987  	os_memset(&event, 0, sizeof(event));
9988  
9989  	if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
9990  		ev = EVENT_INTERFACE_ENABLED;
9991  	} else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
9992  		ev = EVENT_INTERFACE_DISABLED;
9993  	} else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
9994  		ev = EVENT_AVOID_FREQUENCIES;
9995  		if (param == NULL)
9996  			param = "";
9997  		if (freq_range_list_parse(&event.freq_range, param) < 0)
9998  			return -1;
9999  		wpa_supplicant_event(wpa_s, ev, &event);
10000  		os_free(event.freq_range.range);
10001  		return 0;
10002  	} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
10003  		return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
10004  	} else if (os_strcmp(cmd, "ASSOC") == 0) {
10005  		return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
10006  	} else {
10007  		wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
10008  			cmd);
10009  		return -1;
10010  	}
10011  
10012  	wpa_supplicant_event(wpa_s, ev, &event);
10013  
10014  	return 0;
10015  }
10016  
10017  
wpas_ctrl_iface_eapol_rx(struct wpa_supplicant * wpa_s,char * cmd)10018  static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
10019  {
10020  	char *pos;
10021  	u8 src[ETH_ALEN], *buf;
10022  	int used;
10023  	size_t len;
10024  
10025  	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
10026  
10027  	pos = cmd;
10028  	used = hwaddr_aton2(pos, src);
10029  	if (used < 0)
10030  		return -1;
10031  	pos += used;
10032  	while (*pos == ' ')
10033  		pos++;
10034  
10035  	len = os_strlen(pos);
10036  	if (len & 1)
10037  		return -1;
10038  	len /= 2;
10039  
10040  	buf = os_malloc(len);
10041  	if (buf == NULL)
10042  		return -1;
10043  
10044  	if (hexstr2bin(pos, buf, len) < 0) {
10045  		os_free(buf);
10046  		return -1;
10047  	}
10048  
10049  	wpa_supplicant_rx_eapol(wpa_s, src, buf, len, FRAME_ENCRYPTION_UNKNOWN);
10050  	os_free(buf);
10051  
10052  	return 0;
10053  }
10054  
10055  
wpas_ctrl_iface_eapol_tx(struct wpa_supplicant * wpa_s,char * cmd)10056  static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
10057  {
10058  	char *pos;
10059  	u8 dst[ETH_ALEN], *buf;
10060  	int used, ret;
10061  	size_t len;
10062  	unsigned int prev;
10063  
10064  	wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
10065  
10066  	pos = cmd;
10067  	used = hwaddr_aton2(pos, dst);
10068  	if (used < 0)
10069  		return -1;
10070  	pos += used;
10071  	while (*pos == ' ')
10072  		pos++;
10073  
10074  	len = os_strlen(pos);
10075  	if (len & 1)
10076  		return -1;
10077  	len /= 2;
10078  
10079  	buf = os_malloc(len);
10080  	if (!buf || hexstr2bin(pos, buf, len) < 0) {
10081  		os_free(buf);
10082  		return -1;
10083  	}
10084  
10085  	prev = wpa_s->ext_eapol_frame_io;
10086  	wpa_s->ext_eapol_frame_io = 0;
10087  	ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
10088  	wpa_s->ext_eapol_frame_io = prev;
10089  	os_free(buf);
10090  
10091  	return ret;
10092  }
10093  
10094  
ipv4_hdr_checksum(const void * buf,size_t len)10095  static u16 ipv4_hdr_checksum(const void *buf, size_t len)
10096  {
10097  	size_t i;
10098  	u32 sum = 0;
10099  	const u16 *pos = buf;
10100  
10101  	for (i = 0; i < len / 2; i++)
10102  		sum += *pos++;
10103  
10104  	while (sum >> 16)
10105  		sum = (sum & 0xffff) + (sum >> 16);
10106  
10107  	return sum ^ 0xffff;
10108  }
10109  
10110  
10111  #define HWSIM_PACKETLEN 1500
10112  #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
10113  
wpas_data_test_rx(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)10114  static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
10115  			      size_t len)
10116  {
10117  	struct wpa_supplicant *wpa_s = ctx;
10118  	const struct ether_header *eth;
10119  	struct ip ip;
10120  	const u8 *pos;
10121  	unsigned int i;
10122  	char extra[30];
10123  
10124  	if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
10125  		wpa_printf(MSG_DEBUG,
10126  			   "test data: RX - ignore unexpected length %d",
10127  			   (int) len);
10128  		return;
10129  	}
10130  
10131  	eth = (const struct ether_header *) buf;
10132  	os_memcpy(&ip, eth + 1, sizeof(ip));
10133  	pos = &buf[sizeof(*eth) + sizeof(ip)];
10134  
10135  	if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
10136  		wpa_printf(MSG_DEBUG,
10137  			   "test data: RX - ignore unexpected IP header");
10138  		return;
10139  	}
10140  
10141  	for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
10142  		if (*pos != (u8) i) {
10143  			wpa_printf(MSG_DEBUG,
10144  				   "test data: RX - ignore mismatching payload");
10145  			return;
10146  		}
10147  		pos++;
10148  	}
10149  	extra[0] = '\0';
10150  	if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
10151  		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
10152  	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
10153  		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
10154  }
10155  
10156  
wpas_ctrl_iface_data_test_config(struct wpa_supplicant * wpa_s,char * cmd)10157  static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
10158  					    char *cmd)
10159  {
10160  	int enabled = atoi(cmd);
10161  	char *pos;
10162  	const char *ifname;
10163  
10164  	if (!enabled) {
10165  		if (wpa_s->l2_test) {
10166  			l2_packet_deinit(wpa_s->l2_test);
10167  			wpa_s->l2_test = NULL;
10168  			wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
10169  		}
10170  		return 0;
10171  	}
10172  
10173  	if (wpa_s->l2_test)
10174  		return 0;
10175  
10176  	pos = os_strstr(cmd, " ifname=");
10177  	if (pos)
10178  		ifname = pos + 8;
10179  	else
10180  		ifname = wpa_s->ifname;
10181  
10182  	wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
10183  					ETHERTYPE_IP, wpas_data_test_rx,
10184  					wpa_s, 1);
10185  	if (wpa_s->l2_test == NULL)
10186  		return -1;
10187  
10188  	wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
10189  
10190  	return 0;
10191  }
10192  
10193  
wpas_ctrl_iface_data_test_tx(struct wpa_supplicant * wpa_s,char * cmd)10194  static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
10195  {
10196  	u8 dst[ETH_ALEN], src[ETH_ALEN];
10197  	char *pos, *pos2;
10198  	int used;
10199  	long int val;
10200  	u8 tos;
10201  	u8 buf[2 + HWSIM_PACKETLEN];
10202  	struct ether_header *eth;
10203  	struct ip *ip;
10204  	u8 *dpos;
10205  	unsigned int i;
10206  	size_t send_len = HWSIM_IP_LEN;
10207  
10208  	if (wpa_s->l2_test == NULL)
10209  		return -1;
10210  
10211  	/* format: <dst> <src> <tos> [len=<length>] */
10212  
10213  	pos = cmd;
10214  	used = hwaddr_aton2(pos, dst);
10215  	if (used < 0)
10216  		return -1;
10217  	pos += used;
10218  	while (*pos == ' ')
10219  		pos++;
10220  	used = hwaddr_aton2(pos, src);
10221  	if (used < 0)
10222  		return -1;
10223  	pos += used;
10224  
10225  	val = strtol(pos, &pos2, 0);
10226  	if (val < 0 || val > 0xff)
10227  		return -1;
10228  	tos = val;
10229  
10230  	pos = os_strstr(pos2, " len=");
10231  	if (pos) {
10232  		i = atoi(pos + 5);
10233  		if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
10234  			return -1;
10235  		send_len = i;
10236  	}
10237  
10238  	eth = (struct ether_header *) &buf[2];
10239  	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
10240  	os_memcpy(eth->ether_shost, src, ETH_ALEN);
10241  	eth->ether_type = htons(ETHERTYPE_IP);
10242  	ip = (struct ip *) (eth + 1);
10243  	os_memset(ip, 0, sizeof(*ip));
10244  	ip->ip_hl = 5;
10245  	ip->ip_v = 4;
10246  	ip->ip_ttl = 64;
10247  	ip->ip_tos = tos;
10248  	ip->ip_len = htons(send_len);
10249  	ip->ip_p = 1;
10250  	ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
10251  	ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
10252  	ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
10253  	dpos = (u8 *) (ip + 1);
10254  	for (i = 0; i < send_len - sizeof(*ip); i++)
10255  		*dpos++ = i;
10256  
10257  	if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
10258  			   sizeof(struct ether_header) + send_len) < 0)
10259  		return -1;
10260  
10261  	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
10262  		" tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
10263  
10264  	return 0;
10265  }
10266  
10267  
wpas_ctrl_iface_data_test_frame(struct wpa_supplicant * wpa_s,char * cmd)10268  static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
10269  					   char *cmd)
10270  {
10271  	u8 *buf;
10272  	struct ether_header *eth;
10273  	struct l2_packet_data *l2 = NULL;
10274  	size_t len;
10275  	u16 ethertype;
10276  	int res = -1;
10277  
10278  	len = os_strlen(cmd);
10279  	if (len & 1 || len < ETH_HLEN * 2)
10280  		return -1;
10281  	len /= 2;
10282  
10283  	buf = os_malloc(len);
10284  	if (buf == NULL)
10285  		return -1;
10286  
10287  	if (hexstr2bin(cmd, buf, len) < 0)
10288  		goto done;
10289  
10290  	eth = (struct ether_header *) buf;
10291  	ethertype = ntohs(eth->ether_type);
10292  
10293  	l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
10294  			    wpas_data_test_rx, wpa_s, 1);
10295  	if (l2 == NULL)
10296  		goto done;
10297  
10298  	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
10299  	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
10300  done:
10301  	if (l2)
10302  		l2_packet_deinit(l2);
10303  	os_free(buf);
10304  
10305  	return res < 0 ? -1 : 0;
10306  }
10307  
10308  
wpas_ctrl_event_test_cb(void * eloop_ctx,void * timeout_ctx)10309  static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
10310  {
10311  	struct wpa_supplicant *wpa_s = eloop_ctx;
10312  	int i, count = (intptr_t) timeout_ctx;
10313  
10314  	wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
10315  		   count);
10316  	for (i = 0; i < count; i++) {
10317  		wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
10318  			     i + 1, count);
10319  	}
10320  }
10321  
10322  
wpas_ctrl_event_test(struct wpa_supplicant * wpa_s,const char * cmd)10323  static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
10324  {
10325  	int count;
10326  
10327  	count = atoi(cmd);
10328  	if (count <= 0)
10329  		return -1;
10330  
10331  	return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
10332  				      (void *) (intptr_t) count);
10333  }
10334  
10335  
wpas_get_hex_buf(const char * val,struct wpabuf ** ret)10336  static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
10337  {
10338  	struct wpabuf *buf;
10339  	size_t len;
10340  
10341  	len = os_strlen(val);
10342  	if (len & 1)
10343  		return -1;
10344  	len /= 2;
10345  
10346  	if (len == 0) {
10347  		buf = NULL;
10348  	} else {
10349  		buf = wpabuf_alloc(len);
10350  		if (!buf)
10351  			return -1;
10352  
10353  		if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
10354  			wpabuf_free(buf);
10355  			return -1;
10356  		}
10357  	}
10358  
10359  	*ret = buf;
10360  	return 0;
10361  }
10362  
10363  
wpas_ctrl_test_assoc_ie(struct wpa_supplicant * wpa_s,const char * cmd)10364  static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
10365  				   const char *cmd)
10366  {
10367  	struct wpabuf *buf;
10368  
10369  	if (wpas_get_hex_buf(cmd, &buf) < 0)
10370  		return -1;
10371  	wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
10372  	return 0;
10373  }
10374  
10375  
wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant * wpa_s,const char * cmd)10376  static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s,
10377  					 const char *cmd)
10378  {
10379  	struct wpabuf *buf;
10380  
10381  	if (wpas_get_hex_buf(cmd, &buf) < 0)
10382  		return -1;
10383  	wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf);
10384  	return 0;
10385  }
10386  
10387  
wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant * wpa_s,const char * cmd)10388  static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
10389  					 const char *cmd)
10390  {
10391  	struct wpabuf *buf;
10392  
10393  	if (wpas_get_hex_buf(cmd, &buf) < 0)
10394  		return -1;
10395  	wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf);
10396  	return 0;
10397  }
10398  
10399  
wpas_ctrl_test_rsnxe_data(struct wpa_supplicant * wpa_s,const char * cmd)10400  static int wpas_ctrl_test_rsnxe_data(struct wpa_supplicant *wpa_s,
10401  				     const char *cmd)
10402  {
10403  	struct wpabuf *data = NULL, *mask = NULL;
10404  	char *pos;
10405  
10406  	pos = os_strchr(cmd, ' ');
10407  	if (!pos)
10408  		return -1;
10409  	*pos++ = '\0';
10410  
10411  	if (wpas_get_hex_buf(cmd, &data) < 0 ||
10412  	    wpas_get_hex_buf(pos, &mask) < 0 ||
10413  	    wpa_sm_set_test_rsnxe_data(wpa_s->wpa, data, mask) < 0) {
10414  		wpabuf_free(data);
10415  		wpabuf_free(mask);
10416  		return -1;
10417  	}
10418  
10419  	return 0;
10420  }
10421  
10422  
wpas_ctrl_reset_pn(struct wpa_supplicant * wpa_s)10423  static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
10424  {
10425  	u8 zero[WPA_TK_MAX_LEN];
10426  
10427  	if (wpa_s->last_tk_alg == WPA_ALG_NONE)
10428  		return -1;
10429  
10430  	wpa_printf(MSG_INFO, "TESTING: Reset PN");
10431  	os_memset(zero, 0, sizeof(zero));
10432  
10433  	/* First, use a zero key to avoid any possible duplicate key avoidance
10434  	 * in the driver. */
10435  	if (wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
10436  			    wpa_s->last_tk_key_idx, 1, zero, 6,
10437  			    zero, wpa_s->last_tk_len,
10438  			    KEY_FLAG_PAIRWISE_RX_TX) < 0)
10439  		return -1;
10440  
10441  	/* Set the previously configured key to reset its TSC/RSC */
10442  	return wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg,
10443  			       wpa_s->last_tk_addr,
10444  			       wpa_s->last_tk_key_idx, 1, zero, 6,
10445  			       wpa_s->last_tk, wpa_s->last_tk_len,
10446  			       KEY_FLAG_PAIRWISE_RX_TX);
10447  }
10448  
10449  
wpas_ctrl_key_request(struct wpa_supplicant * wpa_s,const char * cmd)10450  static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
10451  {
10452  	const char *pos = cmd;
10453  	int error, pairwise;
10454  
10455  	error = atoi(pos);
10456  	pos = os_strchr(pos, ' ');
10457  	if (!pos)
10458  		return -1;
10459  	pairwise = atoi(pos);
10460  	wpa_sm_key_request(wpa_s->wpa, error, pairwise);
10461  	return 0;
10462  }
10463  
10464  
wpas_ctrl_resend_assoc(struct wpa_supplicant * wpa_s)10465  static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
10466  {
10467  #ifdef CONFIG_SME
10468  	struct wpa_driver_associate_params params;
10469  	int ret;
10470  
10471  	os_memset(&params, 0, sizeof(params));
10472  	params.bssid = wpa_s->bssid;
10473  	params.ssid = wpa_s->sme.ssid;
10474  	params.ssid_len = wpa_s->sme.ssid_len;
10475  	params.freq.freq = wpa_s->sme.freq;
10476  	if (wpa_s->last_assoc_req_wpa_ie) {
10477  		params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
10478  		params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
10479  	}
10480  	params.pairwise_suite = wpa_s->pairwise_cipher;
10481  	params.group_suite = wpa_s->group_cipher;
10482  	params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
10483  	params.key_mgmt_suite = wpa_s->key_mgmt;
10484  	params.wpa_proto = wpa_s->wpa_proto;
10485  	params.mgmt_frame_protection = wpa_s->sme.mfp;
10486  	params.spp_amsdu = wpa_s->sme.spp_amsdu;
10487  	params.rrm_used = wpa_s->rrm.rrm_used;
10488  	if (wpa_s->sme.prev_bssid_set)
10489  		params.prev_bssid = wpa_s->sme.prev_bssid;
10490  	wpa_printf(MSG_INFO, "TESTING: Resend association request");
10491  	ret = wpa_drv_associate(wpa_s, &params);
10492  	wpa_s->testing_resend_assoc = 1;
10493  	return ret;
10494  #else /* CONFIG_SME */
10495  	return -1;
10496  #endif /* CONFIG_SME */
10497  }
10498  
10499  
wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant * wpa_s,const char * cmd)10500  static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s,
10501  					  const char *cmd)
10502  {
10503  	u8 dtok = 1;
10504  	int exponent = 10;
10505  	int mantissa = 8192;
10506  	u8 min_twt = 255;
10507  	unsigned long long twt = 0;
10508  	bool requestor = true;
10509  	int setup_cmd = 0;
10510  	bool trigger = true;
10511  	bool implicit = true;
10512  	bool flow_type = true;
10513  	int flow_id = 0;
10514  	bool protection = false;
10515  	u8 twt_channel = 0;
10516  	u8 control = BIT(4); /* Control field (IEEE Std 802.11ax-2021,
10517  			      * Figure 9-687 - Control field format):
10518  			      * B4 = TWT Information Frame Disabled */
10519  	const char *tok_s;
10520  
10521  	tok_s = os_strstr(cmd, " dialog=");
10522  	if (tok_s)
10523  		dtok = atoi(tok_s + os_strlen(" dialog="));
10524  
10525  	tok_s = os_strstr(cmd, " exponent=");
10526  	if (tok_s)
10527  		exponent = atoi(tok_s + os_strlen(" exponent="));
10528  
10529  	tok_s = os_strstr(cmd, " mantissa=");
10530  	if (tok_s)
10531  		mantissa = atoi(tok_s + os_strlen(" mantissa="));
10532  
10533  	tok_s = os_strstr(cmd, " min_twt=");
10534  	if (tok_s)
10535  		min_twt = atoi(tok_s + os_strlen(" min_twt="));
10536  
10537  	tok_s = os_strstr(cmd, " setup_cmd=");
10538  	if (tok_s)
10539  		setup_cmd = atoi(tok_s + os_strlen(" setup_cmd="));
10540  
10541  	tok_s = os_strstr(cmd, " twt=");
10542  	if (tok_s &&
10543  	    sscanf(tok_s + os_strlen(" twt="), "%llu", &twt) != 1)
10544  		return -1;
10545  
10546  	tok_s = os_strstr(cmd, " requestor=");
10547  	if (tok_s)
10548  		requestor = atoi(tok_s + os_strlen(" requestor="));
10549  
10550  	tok_s = os_strstr(cmd, " trigger=");
10551  	if (tok_s)
10552  		trigger = atoi(tok_s + os_strlen(" trigger="));
10553  
10554  	tok_s = os_strstr(cmd, " implicit=");
10555  	if (tok_s)
10556  		implicit = atoi(tok_s + os_strlen(" implicit="));
10557  
10558  	tok_s = os_strstr(cmd, " flow_type=");
10559  	if (tok_s)
10560  		flow_type = atoi(tok_s + os_strlen(" flow_type="));
10561  
10562  	tok_s = os_strstr(cmd, " flow_id=");
10563  	if (tok_s)
10564  		flow_id = atoi(tok_s + os_strlen(" flow_id="));
10565  
10566  	tok_s = os_strstr(cmd, " protection=");
10567  	if (tok_s)
10568  		protection = atoi(tok_s + os_strlen(" protection="));
10569  
10570  	tok_s = os_strstr(cmd, " twt_channel=");
10571  	if (tok_s)
10572  		twt_channel = atoi(tok_s + os_strlen(" twt_channel="));
10573  
10574  	tok_s = os_strstr(cmd, " control=");
10575  	if (tok_s)
10576  		control = atoi(tok_s + os_strlen(" control="));
10577  
10578  	return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt,
10579  				   setup_cmd, twt, requestor, trigger, implicit,
10580  				   flow_type, flow_id, protection, twt_channel,
10581  				   control);
10582  }
10583  
10584  
wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant * wpa_s,const char * cmd)10585  static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
10586  					     const char *cmd)
10587  {
10588  	u8 flags = 0x1;
10589  	const char *tok_s;
10590  
10591  	tok_s = os_strstr(cmd, " flags=");
10592  	if (tok_s)
10593  		flags = atoi(tok_s + os_strlen(" flags="));
10594  
10595  	return wpas_twt_send_teardown(wpa_s, flags);
10596  }
10597  
10598  #endif /* CONFIG_TESTING_OPTIONS */
10599  
10600  
wpas_ctrl_vendor_elem_add(struct wpa_supplicant * wpa_s,char * cmd)10601  static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
10602  {
10603  	char *pos = cmd;
10604  	int frame;
10605  	size_t len;
10606  	struct wpabuf *buf;
10607  	struct ieee802_11_elems elems;
10608  
10609  	frame = atoi(pos);
10610  	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10611  		return -1;
10612  	wpa_s = wpas_vendor_elem(wpa_s, frame);
10613  
10614  	pos = os_strchr(pos, ' ');
10615  	if (pos == NULL)
10616  		return -1;
10617  	pos++;
10618  
10619  	len = os_strlen(pos);
10620  	if (len == 0)
10621  		return 0;
10622  	if (len & 1)
10623  		return -1;
10624  	len /= 2;
10625  
10626  	buf = wpabuf_alloc(len);
10627  	if (buf == NULL)
10628  		return -1;
10629  
10630  	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
10631  		wpabuf_free(buf);
10632  		return -1;
10633  	}
10634  
10635  	if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
10636  	    ParseFailed) {
10637  		wpabuf_free(buf);
10638  		return -1;
10639  	}
10640  
10641  	if (wpa_s->vendor_elem[frame] == NULL) {
10642  		wpa_s->vendor_elem[frame] = buf;
10643  		goto update_ies;
10644  	}
10645  
10646  	if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
10647  		wpabuf_free(buf);
10648  		return -1;
10649  	}
10650  
10651  	wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
10652  	wpabuf_free(buf);
10653  
10654  update_ies:
10655  	wpas_vendor_elem_update(wpa_s);
10656  
10657  	if (frame == VENDOR_ELEM_PROBE_REQ ||
10658  	    frame == VENDOR_ELEM_PROBE_REQ_P2P)
10659  		wpa_supplicant_set_default_scan_ies(wpa_s);
10660  
10661  	return 0;
10662  }
10663  
10664  
wpas_ctrl_vendor_elem_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)10665  static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
10666  				     char *buf, size_t buflen)
10667  {
10668  	int frame = atoi(cmd);
10669  
10670  	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10671  		return -1;
10672  	wpa_s = wpas_vendor_elem(wpa_s, frame);
10673  
10674  	if (wpa_s->vendor_elem[frame] == NULL)
10675  		return 0;
10676  
10677  	return wpa_snprintf_hex(buf, buflen,
10678  				wpabuf_head_u8(wpa_s->vendor_elem[frame]),
10679  				wpabuf_len(wpa_s->vendor_elem[frame]));
10680  }
10681  
10682  
wpas_ctrl_vendor_elem_remove(struct wpa_supplicant * wpa_s,char * cmd)10683  static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
10684  {
10685  	char *pos = cmd;
10686  	int frame;
10687  	size_t len;
10688  	u8 *buf;
10689  	struct ieee802_11_elems elems;
10690  	int res;
10691  
10692  	frame = atoi(pos);
10693  	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10694  		return -1;
10695  	wpa_s = wpas_vendor_elem(wpa_s, frame);
10696  
10697  	pos = os_strchr(pos, ' ');
10698  	if (pos == NULL)
10699  		return -1;
10700  	pos++;
10701  
10702  	if (*pos == '*') {
10703  		wpabuf_free(wpa_s->vendor_elem[frame]);
10704  		wpa_s->vendor_elem[frame] = NULL;
10705  		wpas_vendor_elem_update(wpa_s);
10706  		return 0;
10707  	}
10708  
10709  	if (wpa_s->vendor_elem[frame] == NULL)
10710  		return -1;
10711  
10712  	len = os_strlen(pos);
10713  	if (len == 0)
10714  		return 0;
10715  	if (len & 1)
10716  		return -1;
10717  	len /= 2;
10718  
10719  	buf = os_malloc(len);
10720  	if (buf == NULL)
10721  		return -1;
10722  
10723  	if (hexstr2bin(pos, buf, len) < 0) {
10724  		os_free(buf);
10725  		return -1;
10726  	}
10727  
10728  	if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
10729  		os_free(buf);
10730  		return -1;
10731  	}
10732  
10733  	res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
10734  	os_free(buf);
10735  	return res;
10736  }
10737  
10738  
10739  #ifndef CONFIG_NO_RRM
10740  
wpas_ctrl_neighbor_rep_cb(void * ctx,struct wpabuf * neighbor_rep)10741  static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
10742  {
10743  	struct wpa_supplicant *wpa_s = ctx;
10744  	size_t len;
10745  	const u8 *data;
10746  
10747  	/*
10748  	 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
10749  	 * BSSID[6]
10750  	 * BSSID Information[4]
10751  	 * Operating Class[1]
10752  	 * Channel Number[1]
10753  	 * PHY Type[1]
10754  	 * Optional Subelements[variable]
10755  	 */
10756  #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
10757  
10758  	if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
10759  		wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
10760  		goto out;
10761  	}
10762  
10763  	data = wpabuf_head_u8(neighbor_rep);
10764  	len = wpabuf_len(neighbor_rep);
10765  
10766  	while (len >= 2 + NR_IE_MIN_LEN) {
10767  		const u8 *nr;
10768  		char lci[256 * 2 + 1];
10769  		char civic[256 * 2 + 1];
10770  		u8 nr_len = data[1];
10771  		const u8 *pos = data, *end;
10772  
10773  		if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
10774  		    nr_len < NR_IE_MIN_LEN) {
10775  			wpa_dbg(wpa_s, MSG_DEBUG,
10776  				"CTRL: Invalid Neighbor Report element: id=%u len=%u",
10777  				data[0], nr_len);
10778  			goto out;
10779  		}
10780  
10781  		if (2U + nr_len > len) {
10782  			wpa_dbg(wpa_s, MSG_DEBUG,
10783  				"CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
10784  				data[0], len, nr_len);
10785  			goto out;
10786  		}
10787  		pos += 2;
10788  		end = pos + nr_len;
10789  
10790  		nr = pos;
10791  		pos += NR_IE_MIN_LEN;
10792  
10793  		lci[0] = '\0';
10794  		civic[0] = '\0';
10795  		while (end - pos > 2) {
10796  			u8 s_id, s_len;
10797  
10798  			s_id = *pos++;
10799  			s_len = *pos++;
10800  			if (s_len > end - pos)
10801  				goto out;
10802  			if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
10803  				/* Measurement Token[1] */
10804  				/* Measurement Report Mode[1] */
10805  				/* Measurement Type[1] */
10806  				/* Measurement Report[variable] */
10807  				switch (pos[2]) {
10808  				case MEASURE_TYPE_LCI:
10809  					if (lci[0])
10810  						break;
10811  					wpa_snprintf_hex(lci, sizeof(lci),
10812  							 pos, s_len);
10813  					break;
10814  				case MEASURE_TYPE_LOCATION_CIVIC:
10815  					if (civic[0])
10816  						break;
10817  					wpa_snprintf_hex(civic, sizeof(civic),
10818  							 pos, s_len);
10819  					break;
10820  				}
10821  			}
10822  
10823  			pos += s_len;
10824  		}
10825  
10826  		wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
10827  			"bssid=" MACSTR
10828  			" info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
10829  			MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
10830  			nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
10831  			nr[ETH_ALEN + 6],
10832  			lci[0] ? " lci=" : "", lci,
10833  			civic[0] ? " civic=" : "", civic);
10834  
10835  		data = end;
10836  		len -= 2 + nr_len;
10837  	}
10838  
10839  out:
10840  	wpabuf_free(neighbor_rep);
10841  }
10842  
10843  
wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant * wpa_s,char * cmd)10844  static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
10845  					     char *cmd)
10846  {
10847  	struct wpa_ssid_value ssid, *ssid_p = NULL;
10848  	int ret, lci = 0, civic = 0;
10849  	char *ssid_s;
10850  
10851  	ssid_s = os_strstr(cmd, "ssid=");
10852  	if (ssid_s) {
10853  		if (ssid_parse(ssid_s + 5, &ssid)) {
10854  			wpa_msg(wpa_s, MSG_INFO,
10855  				"CTRL: Send Neighbor Report: bad SSID");
10856  			return -1;
10857  		}
10858  
10859  		ssid_p = &ssid;
10860  
10861  		/*
10862  		 * Move cmd after the SSID text that may include "lci" or
10863  		 * "civic".
10864  		 */
10865  		cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
10866  		if (cmd)
10867  			cmd++;
10868  
10869  	}
10870  
10871  	if (cmd && os_strstr(cmd, "lci"))
10872  		lci = 1;
10873  
10874  	if (cmd && os_strstr(cmd, "civic"))
10875  		civic = 1;
10876  
10877  	ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
10878  						 wpas_ctrl_neighbor_rep_cb,
10879  						 wpa_s);
10880  
10881  	return ret;
10882  }
10883  
10884  #endif /* CONFIG_NO_RRM */
10885  
10886  
wpas_ctrl_iface_erp_flush(struct wpa_supplicant * wpa_s)10887  static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
10888  {
10889  	eapol_sm_erp_flush(wpa_s->eapol);
10890  	return 0;
10891  }
10892  
10893  
wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant * wpa_s,char * cmd)10894  static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
10895  					 char *cmd)
10896  {
10897  	char *token, *context = NULL;
10898  	unsigned int enable = ~0, type = 0;
10899  	u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
10900  	u8 *addr = NULL, *mask = NULL;
10901  
10902  	while ((token = str_token(cmd, " ", &context))) {
10903  		if (os_strcasecmp(token, "scan") == 0) {
10904  			type |= MAC_ADDR_RAND_SCAN;
10905  		} else if (os_strcasecmp(token, "sched") == 0) {
10906  			type |= MAC_ADDR_RAND_SCHED_SCAN;
10907  		} else if (os_strcasecmp(token, "pno") == 0) {
10908  			type |= MAC_ADDR_RAND_PNO;
10909  		} else if (os_strcasecmp(token, "all") == 0) {
10910  			type = wpa_s->mac_addr_rand_supported;
10911  		} else if (os_strncasecmp(token, "enable=", 7) == 0) {
10912  			enable = atoi(token + 7);
10913  		} else if (os_strncasecmp(token, "addr=", 5) == 0) {
10914  			addr = _addr;
10915  			if (hwaddr_aton(token + 5, addr)) {
10916  				wpa_printf(MSG_INFO,
10917  					   "CTRL: Invalid MAC address: %s",
10918  					   token);
10919  				return -1;
10920  			}
10921  		} else if (os_strncasecmp(token, "mask=", 5) == 0) {
10922  			mask = _mask;
10923  			if (hwaddr_aton(token + 5, mask)) {
10924  				wpa_printf(MSG_INFO,
10925  					   "CTRL: Invalid MAC address mask: %s",
10926  					   token);
10927  				return -1;
10928  			}
10929  		} else {
10930  			wpa_printf(MSG_INFO,
10931  				   "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
10932  				   token);
10933  			return -1;
10934  		}
10935  	}
10936  
10937  	if (!type) {
10938  		wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
10939  		return -1;
10940  	}
10941  
10942  	if (enable > 1) {
10943  		wpa_printf(MSG_INFO,
10944  			   "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
10945  		return -1;
10946  	}
10947  
10948  	if (!enable)
10949  		return wpas_disable_mac_addr_randomization(wpa_s, type);
10950  
10951  	return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
10952  }
10953  
10954  
wpas_ctrl_iface_pmksa(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)10955  static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
10956  				 char *buf, size_t buflen)
10957  {
10958  	size_t reply_len;
10959  
10960  	reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
10961  #ifdef CONFIG_AP
10962  	reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
10963  					      buflen - reply_len);
10964  #endif /* CONFIG_AP */
10965  	return reply_len;
10966  }
10967  
10968  
wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant * wpa_s)10969  static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
10970  {
10971  	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
10972  	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
10973  #ifdef CONFIG_AP
10974  	wpas_ap_pmksa_cache_flush(wpa_s);
10975  #endif /* CONFIG_AP */
10976  }
10977  
10978  #ifdef CONFIG_P2P
10979  #ifdef CONFIG_PASN
10980  
10981  #ifdef CONFIG_TESTING_OPTIONS
p2p_ctrl_get_pasn_ptk(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)10982  static int p2p_ctrl_get_pasn_ptk(struct wpa_supplicant *wpa_s, char *buf,
10983  				 size_t buflen)
10984  {
10985  	const u8 *ptk;
10986  	size_t ptk_len;
10987  
10988  	if (wpas_p2p_get_pasn_ptk(wpa_s, &ptk, &ptk_len))
10989  		return -1;
10990  	return wpa_snprintf_hex(buf, buflen, ptk, ptk_len);
10991  }
10992  #endif /* CONFIG_TESTING_OPTIONS */
10993  
10994  #endif /* CONFIG_PASN */
10995  #endif /* CONFIG_P2P */
10996  
10997  #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
10998  
wpas_ctrl_iface_pmksa_get(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)10999  static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
11000  				     const char *cmd, char *buf, size_t buflen)
11001  {
11002  	struct rsn_pmksa_cache_entry *entry;
11003  	struct wpa_ssid *ssid;
11004  	char *pos, *pos2, *end;
11005  	int ret;
11006  	struct os_reltime now;
11007  
11008  	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
11009  	if (!ssid)
11010  		return -1;
11011  
11012  	pos = buf;
11013  	end = buf + buflen;
11014  
11015  	os_get_reltime(&now);
11016  
11017  	/*
11018  	 * Entry format:
11019  	 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
11020  	 * <expiration in seconds> <akmp> <opportunistic>
11021  	 * [FILS Cache Identifier]
11022  	 */
11023  
11024  	for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
11025  	     entry = entry->next) {
11026  		if (entry->network_ctx != ssid)
11027  			continue;
11028  
11029  		pos2 = pos;
11030  		ret = os_snprintf(pos2, end - pos2, MACSTR " ",
11031  				  MAC2STR(entry->aa));
11032  		if (os_snprintf_error(end - pos2, ret))
11033  			break;
11034  		pos2 += ret;
11035  
11036  		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
11037  					 PMKID_LEN);
11038  
11039  		ret = os_snprintf(pos2, end - pos2, " ");
11040  		if (os_snprintf_error(end - pos2, ret))
11041  			break;
11042  		pos2 += ret;
11043  
11044  		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
11045  					 entry->pmk_len);
11046  
11047  		ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
11048  				  (int) (entry->reauth_time - now.sec),
11049  				  (int) (entry->expiration - now.sec),
11050  				  entry->akmp,
11051  				  entry->opportunistic);
11052  		if (os_snprintf_error(end - pos2, ret))
11053  			break;
11054  		pos2 += ret;
11055  
11056  		if (entry->fils_cache_id_set) {
11057  			ret = os_snprintf(pos2, end - pos2, " %02x%02x",
11058  					  entry->fils_cache_id[0],
11059  					  entry->fils_cache_id[1]);
11060  			if (os_snprintf_error(end - pos2, ret))
11061  				break;
11062  			pos2 += ret;
11063  		}
11064  
11065  		ret = os_snprintf(pos2, end - pos2, "\n");
11066  		if (os_snprintf_error(end - pos2, ret))
11067  			break;
11068  		pos2 += ret;
11069  
11070  		pos = pos2;
11071  	}
11072  
11073  	return pos - buf;
11074  }
11075  
11076  
wpas_ctrl_iface_pmksa_add(struct wpa_supplicant * wpa_s,char * cmd)11077  static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
11078  				     char *cmd)
11079  {
11080  	struct rsn_pmksa_cache_entry *entry;
11081  	struct wpa_ssid *ssid;
11082  	char *pos, *pos2;
11083  	int ret = -1;
11084  	struct os_reltime now;
11085  	int reauth_time = 0, expiration = 0, i;
11086  
11087  	/*
11088  	 * Entry format:
11089  	 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
11090  	 * <expiration in seconds> <akmp> <opportunistic>
11091  	 * [FILS Cache Identifier]
11092  	 */
11093  
11094  	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
11095  	if (!ssid)
11096  		return -1;
11097  
11098  	pos = os_strchr(cmd, ' ');
11099  	if (!pos)
11100  		return -1;
11101  	pos++;
11102  
11103  	entry = os_zalloc(sizeof(*entry));
11104  	if (!entry)
11105  		return -1;
11106  
11107  	if (hwaddr_aton(pos, entry->aa))
11108  		goto fail;
11109  
11110  	pos = os_strchr(pos, ' ');
11111  	if (!pos)
11112  		goto fail;
11113  	pos++;
11114  
11115  	if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
11116  		goto fail;
11117  
11118  	pos = os_strchr(pos, ' ');
11119  	if (!pos)
11120  		goto fail;
11121  	pos++;
11122  
11123  	pos2 = os_strchr(pos, ' ');
11124  	if (!pos2)
11125  		goto fail;
11126  	entry->pmk_len = (pos2 - pos) / 2;
11127  	if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
11128  	    hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
11129  		goto fail;
11130  
11131  	pos = os_strchr(pos, ' ');
11132  	if (!pos)
11133  		goto fail;
11134  	pos++;
11135  
11136  	if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
11137  		   &entry->akmp, &entry->opportunistic) != 4)
11138  		goto fail;
11139  	if (reauth_time > expiration)
11140  		goto fail;
11141  	for (i = 0; i < 4; i++) {
11142  		pos = os_strchr(pos, ' ');
11143  		if (!pos) {
11144  			if (i < 3)
11145  				goto fail;
11146  			break;
11147  		}
11148  		pos++;
11149  	}
11150  	if (pos) {
11151  		if (hexstr2bin(pos, entry->fils_cache_id,
11152  			       FILS_CACHE_ID_LEN) < 0)
11153  			goto fail;
11154  		entry->fils_cache_id_set = 1;
11155  	}
11156  	os_get_reltime(&now);
11157  	entry->expiration = now.sec + expiration;
11158  	entry->reauth_time = now.sec + reauth_time;
11159  
11160  	entry->network_ctx = ssid;
11161  	os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
11162  
11163  	entry->external = true;
11164  
11165  	wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
11166  	entry = NULL;
11167  	ret = 0;
11168  fail:
11169  	os_free(entry);
11170  	return ret;
11171  }
11172  
11173  
11174  #ifdef CONFIG_MESH
11175  
wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)11176  static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
11177  					  const char *cmd, char *buf,
11178  					  size_t buflen)
11179  {
11180  	u8 spa[ETH_ALEN];
11181  
11182  	if (!wpa_s->ifmsh)
11183  		return -1;
11184  
11185  	if (os_strcasecmp(cmd, "any") == 0)
11186  		return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
11187  
11188  	if (hwaddr_aton(cmd, spa))
11189  		return -1;
11190  
11191  	return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
11192  }
11193  
11194  
wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant * wpa_s,char * cmd)11195  static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
11196  					  char *cmd)
11197  {
11198  	/*
11199  	 * We do not check mesh interface existence because PMKSA should be
11200  	 * stored before wpa_s->ifmsh creation to suppress commit message
11201  	 * creation.
11202  	 */
11203  	return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
11204  }
11205  
11206  #endif /* CONFIG_MESH */
11207  #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
11208  
11209  
11210  #ifdef CONFIG_FILS
wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant * wpa_s,const char * cmd)11211  static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
11212  					    const char *cmd)
11213  {
11214  	struct fils_hlp_req *req;
11215  	const char *pos;
11216  
11217  	/* format: <dst> <packet starting from ethertype> */
11218  
11219  	req = os_zalloc(sizeof(*req));
11220  	if (!req)
11221  		return -1;
11222  
11223  	if (hwaddr_aton(cmd, req->dst))
11224  		goto fail;
11225  
11226  	pos = os_strchr(cmd, ' ');
11227  	if (!pos)
11228  		goto fail;
11229  	pos++;
11230  	req->pkt = wpabuf_parse_bin(pos);
11231  	if (!req->pkt)
11232  		goto fail;
11233  
11234  	dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
11235  	return 0;
11236  fail:
11237  	wpabuf_free(req->pkt);
11238  	os_free(req);
11239  	return -1;
11240  }
11241  #endif /* CONFIG_FILS */
11242  
11243  
wpas_ctrl_cmd_debug_level(const char * cmd)11244  int wpas_ctrl_cmd_debug_level(const char *cmd)
11245  {
11246  	if (os_strcmp(cmd, "PING") == 0 ||
11247  	    os_strncmp(cmd, "BSS ", 4) == 0 ||
11248  	    os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
11249  	    os_strncmp(cmd, "STATUS", 6) == 0 ||
11250  	    os_strncmp(cmd, "STA ", 4) == 0 ||
11251  	    os_strncmp(cmd, "STA-", 4) == 0)
11252  		return MSG_EXCESSIVE;
11253  	return MSG_DEBUG;
11254  }
11255  
11256  
11257  #ifndef CONFIG_NO_ROBUST_AV
wpas_ctrl_iface_configure_mscs(struct wpa_supplicant * wpa_s,const char * cmd)11258  static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
11259  					  const char *cmd)
11260  {
11261  	size_t frame_classifier_len;
11262  	const char *pos, *end;
11263  	struct robust_av_data *robust_av = &wpa_s->robust_av;
11264  	int val;
11265  
11266  	/*
11267  	 * format:
11268  	 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
11269  	 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
11270  	 */
11271  	os_memset(robust_av, 0, sizeof(struct robust_av_data));
11272  	if (os_strncmp(cmd, "add ", 4) == 0) {
11273  		robust_av->request_type = SCS_REQ_ADD;
11274  	} else if (os_strcmp(cmd, "remove") == 0) {
11275  		robust_av->request_type = SCS_REQ_REMOVE;
11276  		robust_av->valid_config = false;
11277  		return wpas_send_mscs_req(wpa_s);
11278  	} else if (os_strncmp(cmd, "change ", 7) == 0) {
11279  		robust_av->request_type = SCS_REQ_CHANGE;
11280  	} else {
11281  		return -1;
11282  	}
11283  
11284  	pos = os_strstr(cmd, "up_bitmap=");
11285  	if (!pos)
11286  		return -1;
11287  
11288  	val = hex2byte(pos + 10);
11289  	if (val < 0)
11290  		return -1;
11291  	robust_av->up_bitmap = val;
11292  
11293  	pos = os_strstr(cmd, "up_limit=");
11294  	if (!pos)
11295  		return -1;
11296  
11297  	robust_av->up_limit = atoi(pos + 9);
11298  
11299  	pos = os_strstr(cmd, "stream_timeout=");
11300  	if (!pos)
11301  		return -1;
11302  
11303  	robust_av->stream_timeout = atoi(pos + 15);
11304  	if (robust_av->stream_timeout == 0)
11305  		return -1;
11306  
11307  	pos = os_strstr(cmd, "frame_classifier=");
11308  	if (!pos)
11309  		return -1;
11310  
11311  	pos += 17;
11312  	end = os_strchr(pos, ' ');
11313  	if (!end)
11314  		end = pos + os_strlen(pos);
11315  
11316  	frame_classifier_len = (end - pos) / 2;
11317  	if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
11318  	    hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
11319  		return -1;
11320  
11321  	robust_av->frame_classifier_len = frame_classifier_len;
11322  	robust_av->valid_config = true;
11323  
11324  	return wpas_send_mscs_req(wpa_s);
11325  }
11326  #endif /* CONFIG_NO_ROBUST_AV */
11327  
11328  
11329  #ifdef CONFIG_PASN
wpas_ctrl_iface_pasn_start(struct wpa_supplicant * wpa_s,char * cmd)11330  static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
11331  {
11332  	char *token, *context = NULL;
11333  	u8 bssid[ETH_ALEN];
11334  	int akmp = -1, cipher = -1, got_bssid = 0;
11335  	u16 group = 0xFFFF;
11336  	u8 *comeback = NULL;
11337  	size_t comeback_len = 0;
11338  	int id = 0, ret = -1;
11339  
11340  	/*
11341  	 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
11342  	 *    [comeback=<hexdump>]
11343  	 */
11344  	while ((token = str_token(cmd, " ", &context))) {
11345  		if (os_strncmp(token, "bssid=", 6) == 0) {
11346  			if (hwaddr_aton(token + 6, bssid))
11347  				goto out;
11348  			got_bssid = 1;
11349  		} else if (os_strcmp(token, "akmp=PASN") == 0) {
11350  			akmp = WPA_KEY_MGMT_PASN;
11351  #ifdef CONFIG_IEEE80211R
11352  		} else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
11353  			akmp = WPA_KEY_MGMT_FT_PSK;
11354  		} else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
11355  			akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
11356  		} else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
11357  			akmp = WPA_KEY_MGMT_FT_IEEE8021X;
11358  #endif /* CONFIG_IEEE80211R */
11359  #ifdef CONFIG_SAE
11360  		} else if (os_strcmp(token, "akmp=SAE") == 0) {
11361  			akmp = WPA_KEY_MGMT_SAE;
11362  		} else if (os_strcmp(token, "akmp=SAE-EXT-KEY") == 0) {
11363  			akmp = WPA_KEY_MGMT_SAE_EXT_KEY;
11364  #endif /* CONFIG_SAE */
11365  #ifdef CONFIG_FILS
11366  		} else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
11367  			akmp = WPA_KEY_MGMT_FILS_SHA256;
11368  		} else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
11369  			akmp = WPA_KEY_MGMT_FILS_SHA384;
11370  #endif /* CONFIG_FILS */
11371  		} else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
11372  			cipher = WPA_CIPHER_CCMP_256;
11373  		} else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
11374  			cipher = WPA_CIPHER_GCMP_256;
11375  		} else if (os_strcmp(token, "cipher=CCMP") == 0) {
11376  			cipher = WPA_CIPHER_CCMP;
11377  		} else if (os_strcmp(token, "cipher=GCMP") == 0) {
11378  			cipher = WPA_CIPHER_GCMP;
11379  		} else if (os_strncmp(token, "group=", 6) == 0) {
11380  			group = atoi(token + 6);
11381  		} else if (os_strncmp(token, "nid=", 4) == 0) {
11382  			id = atoi(token + 4);
11383  		} else if (os_strncmp(token, "comeback=", 9) == 0) {
11384  			comeback_len = os_strlen(token + 9);
11385  			if (comeback || !comeback_len || comeback_len % 2)
11386  				goto out;
11387  
11388  			comeback_len /= 2;
11389  			comeback = os_malloc(comeback_len);
11390  			if (!comeback ||
11391  			    hexstr2bin(token + 9, comeback, comeback_len))
11392  				goto out;
11393  		} else {
11394  			wpa_printf(MSG_DEBUG,
11395  				   "CTRL: PASN Invalid parameter: '%s'",
11396  				   token);
11397  			goto out;
11398  		}
11399  	}
11400  
11401  	if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
11402  		wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
11403  		goto out;
11404  	}
11405  
11406  	ret = wpas_pasn_auth_start(wpa_s, wpa_s->own_addr, bssid, akmp, cipher,
11407  				   group, id, comeback, comeback_len);
11408  out:
11409  	os_free(comeback);
11410  	return ret;
11411  }
11412  
11413  
wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant * wpa_s,const char * cmd)11414  static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
11415  					       const char *cmd)
11416  {
11417  	u8 bssid[ETH_ALEN];
11418  
11419  	if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
11420  		wpa_printf(MSG_DEBUG,
11421  			   "CTRL: PASN_DEAUTH without valid BSSID");
11422  		return -1;
11423  	}
11424  
11425  	return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid);
11426  }
11427  
11428  
11429  #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_iface_pasn_driver(struct wpa_supplicant * wpa_s,const char * cmd)11430  static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s,
11431  				       const char *cmd)
11432  {
11433  	union wpa_event_data event;
11434  	const char *pos = cmd;
11435  	u8 addr[ETH_ALEN];
11436  
11437  	os_memset(&event, 0, sizeof(event));
11438  
11439  	if (os_strncmp(pos, "auth ", 5) == 0)
11440  		event.pasn_auth.action = PASN_ACTION_AUTH;
11441  	else if (os_strncmp(pos, "del ", 4) == 0)
11442  		event.pasn_auth.action =
11443  			PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT;
11444  	else
11445  		return -1;
11446  
11447  	pos = os_strchr(pos, ' ');
11448  	if (!pos)
11449  		return -1;
11450  	pos++;
11451  	while (hwaddr_aton(pos, addr) == 0) {
11452  		struct pasn_peer *peer;
11453  
11454  		if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS)
11455  			return -1;
11456  		peer = &event.pasn_auth.peer[event.pasn_auth.num_peers];
11457  		os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN);
11458  		os_memcpy(peer->peer_addr, addr, ETH_ALEN);
11459  		event.pasn_auth.num_peers++;
11460  
11461  		pos = os_strchr(pos, ' ');
11462  		if (!pos)
11463  			break;
11464  		pos++;
11465  	}
11466  
11467  	wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event);
11468  	return 0;
11469  }
11470  #endif /* CONFIG_TESTING_OPTIONS */
11471  
11472  #endif /* CONFIG_PASN */
11473  
11474  
11475  #ifndef CONFIG_NO_ROBUST_AV
11476  
set_type4_frame_classifier(const char * cmd,struct type4_params * param)11477  static int set_type4_frame_classifier(const char *cmd,
11478  				      struct type4_params *param)
11479  {
11480  	const char *pos, *end;
11481  	u8 classifier_mask = 0;
11482  	int ret;
11483  	char addr[INET6_ADDRSTRLEN];
11484  	size_t alen;
11485  
11486  	if (os_strstr(cmd, "ip_version=ipv4")) {
11487  		param->ip_version = IPV4;
11488  	} else if (os_strstr(cmd, "ip_version=ipv6")) {
11489  		param->ip_version = IPV6;
11490  	} else {
11491  		wpa_printf(MSG_ERROR, "IP version missing/invalid");
11492  		return -1;
11493  	}
11494  
11495  	classifier_mask |= BIT(0);
11496  
11497  	pos = os_strstr(cmd, "src_ip=");
11498  	if (pos) {
11499  		pos += 7;
11500  		end = os_strchr(pos, ' ');
11501  		if (!end)
11502  			end = pos + os_strlen(pos);
11503  
11504  		alen = end - pos;
11505  		if (alen >= INET6_ADDRSTRLEN)
11506  			return -1;
11507  		os_memcpy(addr, pos, alen);
11508  		addr[alen] = '\0';
11509  		if (param->ip_version == IPV4)
11510  			ret = inet_pton(AF_INET, addr,
11511  					&param->ip_params.v4.src_ip);
11512  		else
11513  			ret = inet_pton(AF_INET6, addr,
11514  					&param->ip_params.v6.src_ip);
11515  
11516  		if (ret != 1) {
11517  			wpa_printf(MSG_ERROR,
11518  				   "Error converting src IP address to binary ret=%d",
11519  				   ret);
11520  			return -1;
11521  		}
11522  
11523  		classifier_mask |= BIT(1);
11524  	}
11525  
11526  	pos = os_strstr(cmd, "dst_ip=");
11527  	if (pos) {
11528  		pos += 7;
11529  		end = os_strchr(pos, ' ');
11530  		if (!end)
11531  			end = pos + os_strlen(pos);
11532  
11533  		alen = end - pos;
11534  		if (alen >= INET6_ADDRSTRLEN)
11535  			return -1;
11536  		os_memcpy(addr, pos, alen);
11537  		addr[alen] = '\0';
11538  		if (param->ip_version == IPV4)
11539  			ret = inet_pton(AF_INET, addr,
11540  					&param->ip_params.v4.dst_ip);
11541  		else
11542  			ret = inet_pton(AF_INET6, addr,
11543  					&param->ip_params.v6.dst_ip);
11544  
11545  		if (ret != 1) {
11546  			wpa_printf(MSG_ERROR,
11547  				   "Error converting dst IP address to binary ret=%d",
11548  				   ret);
11549  			return -1;
11550  		}
11551  
11552  		classifier_mask |= BIT(2);
11553  	}
11554  
11555  	pos = os_strstr(cmd, "src_port=");
11556  	if (pos && atoi(pos + 9) > 0) {
11557  		if (param->ip_version == IPV4)
11558  			param->ip_params.v4.src_port = atoi(pos + 9);
11559  		else
11560  			param->ip_params.v6.src_port = atoi(pos + 9);
11561  		classifier_mask |= BIT(3);
11562  	}
11563  
11564  	pos = os_strstr(cmd, "dst_port=");
11565  	if (pos && atoi(pos + 9) > 0) {
11566  		if (param->ip_version == IPV4)
11567  			param->ip_params.v4.dst_port = atoi(pos + 9);
11568  		else
11569  			param->ip_params.v6.dst_port = atoi(pos + 9);
11570  		classifier_mask |= BIT(4);
11571  	}
11572  
11573  	pos = os_strstr(cmd, "dscp=");
11574  	if (pos && atoi(pos + 5) > 0) {
11575  		if (param->ip_version == IPV4)
11576  			param->ip_params.v4.dscp = atoi(pos + 5);
11577  		else
11578  			param->ip_params.v6.dscp = atoi(pos + 5);
11579  		classifier_mask |= BIT(5);
11580  	}
11581  
11582  	if (param->ip_version == IPV4) {
11583  		pos = os_strstr(cmd, "protocol=");
11584  		if (pos) {
11585  			if (os_strstr(pos, "udp")) {
11586  				param->ip_params.v4.protocol = 17;
11587  			} else if (os_strstr(pos, "tcp")) {
11588  				param->ip_params.v4.protocol = 6;
11589  			} else if (os_strstr(pos, "esp")) {
11590  				param->ip_params.v4.protocol = 50;
11591  			} else {
11592  				wpa_printf(MSG_ERROR, "Invalid protocol");
11593  				return -1;
11594  			}
11595  			classifier_mask |= BIT(6);
11596  		}
11597  	} else {
11598  		pos = os_strstr(cmd, "next_header=");
11599  		if (pos) {
11600  			if (os_strstr(pos, "udp")) {
11601  				param->ip_params.v6.next_header = 17;
11602  			} else if (os_strstr(pos, "tcp")) {
11603  				param->ip_params.v6.next_header = 6;
11604  			} else if (os_strstr(pos, "esp")) {
11605  				param->ip_params.v6.next_header = 50;
11606  			} else {
11607  				wpa_printf(MSG_ERROR, "Invalid next header");
11608  				return -1;
11609  			}
11610  
11611  			classifier_mask |= BIT(6);
11612  		}
11613  
11614  		pos = os_strstr(cmd, "flow_label=");
11615  		if (pos) {
11616  			pos += 11;
11617  			end = os_strchr(pos, ' ');
11618  			if (!end)
11619  				end = pos + os_strlen(pos);
11620  
11621  			if (end - pos != 6 ||
11622  			    hexstr2bin(pos, param->ip_params.v6.flow_label,
11623  				       3) ||
11624  			    param->ip_params.v6.flow_label[0] > 0x0F) {
11625  				wpa_printf(MSG_ERROR, "Invalid flow label");
11626  				return -1;
11627  			}
11628  
11629  			classifier_mask |= BIT(7);
11630  		}
11631  	}
11632  
11633  	param->classifier_mask = classifier_mask;
11634  	return 0;
11635  }
11636  
11637  
set_type10_frame_classifier(const char * cmd,struct type10_params * param)11638  static int set_type10_frame_classifier(const char *cmd,
11639  				       struct type10_params *param)
11640  {
11641  	const char *pos, *end;
11642  	size_t filter_len;
11643  
11644  	pos = os_strstr(cmd, "prot_instance=");
11645  	if (!pos) {
11646  		wpa_printf(MSG_ERROR, "Protocol instance missing");
11647  		return -1;
11648  	}
11649  	param->prot_instance = atoi(pos + 14);
11650  
11651  	pos = os_strstr(cmd, "prot_number=");
11652  	if (!pos) {
11653  		wpa_printf(MSG_ERROR, "Protocol number missing");
11654  		return -1;
11655  	}
11656  	if (os_strstr(pos, "udp")) {
11657  		param->prot_number = 17;
11658  	} else if (os_strstr(pos, "tcp")) {
11659  		param->prot_number = 6;
11660  	} else if (os_strstr(pos, "esp")) {
11661  		param->prot_number = 50;
11662  	} else {
11663  		wpa_printf(MSG_ERROR, "Invalid protocol number");
11664  		return -1;
11665  	}
11666  
11667  	pos = os_strstr(cmd, "filter_value=");
11668  	if (!pos) {
11669  		wpa_printf(MSG_ERROR,
11670  			   "Classifier parameter filter_value missing");
11671  		return -1;
11672  	}
11673  
11674  	pos += 13;
11675  	end = os_strchr(pos, ' ');
11676  	if (!end)
11677  		end = pos + os_strlen(pos);
11678  
11679  	filter_len = (end - pos) / 2;
11680  	param->filter_value = os_malloc(filter_len);
11681  	if (!param->filter_value)
11682  		return -1;
11683  
11684  	if (hexstr2bin(pos, param->filter_value, filter_len)) {
11685  		wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos);
11686  		goto free;
11687  	}
11688  
11689  	pos = os_strstr(cmd, "filter_mask=");
11690  	if (!pos) {
11691  		wpa_printf(MSG_ERROR,
11692  			   "Classifier parameter filter_mask missing");
11693  		goto free;
11694  	}
11695  
11696  	pos += 12;
11697  	end = os_strchr(pos, ' ');
11698  	if (!end)
11699  		end = pos + os_strlen(pos);
11700  
11701  	if (filter_len != (size_t) (end - pos) / 2) {
11702  		wpa_printf(MSG_ERROR,
11703  			   "Filter mask length mismatch expected=%zu received=%zu",
11704  			   filter_len, (size_t) (end - pos) / 2);
11705  		goto free;
11706  	}
11707  
11708  	param->filter_mask = os_malloc(filter_len);
11709  	if (!param->filter_mask)
11710  		goto free;
11711  
11712  	if (hexstr2bin(pos, param->filter_mask, filter_len)) {
11713  		wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos);
11714  		os_free(param->filter_mask);
11715  		param->filter_mask = NULL;
11716  		goto free;
11717  	}
11718  
11719  	param->filter_len = filter_len;
11720  	return 0;
11721  free:
11722  	os_free(param->filter_value);
11723  	param->filter_value = NULL;
11724  	return -1;
11725  }
11726  
11727  
scs_parse_type4(struct tclas_element * elem,const char * pos)11728  static int scs_parse_type4(struct tclas_element *elem, const char *pos)
11729  {
11730  	struct type4_params type4_param = { 0 };
11731  
11732  	if (set_type4_frame_classifier(pos, &type4_param) == -1) {
11733  		wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4");
11734  		return -1;
11735  	}
11736  
11737  	os_memcpy(&elem->frame_classifier.type4_param,
11738  		  &type4_param, sizeof(struct type4_params));
11739  	return 0;
11740  }
11741  
11742  
scs_parse_type10(struct tclas_element * elem,const char * pos)11743  static int scs_parse_type10(struct tclas_element *elem, const char *pos)
11744  {
11745  	struct type10_params type10_param = { 0 };
11746  
11747  	if (set_type10_frame_classifier(pos, &type10_param) == -1) {
11748  		wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10");
11749  		return -1;
11750  	}
11751  
11752  	os_memcpy(&elem->frame_classifier.type10_param,
11753  		  &type10_param, sizeof(struct type10_params));
11754  	return 0;
11755  }
11756  
11757  
wpas_ctrl_iface_configure_scs(struct wpa_supplicant * wpa_s,char * cmd)11758  static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s,
11759  					 char *cmd)
11760  {
11761  	char *pos1, *pos;
11762  	struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req;
11763  	struct scs_desc_elem desc_elem = { 0 };
11764  	int val;
11765  	unsigned int num_scs_desc = 0;
11766  
11767  	if (wpa_s->ongoing_scs_req) {
11768  		wpa_printf(MSG_ERROR, "%s: SCS Request already in queue",
11769  			   __func__);
11770  		return -1;
11771  	}
11772  
11773  	/**
11774  	 * format:
11775  	 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>]
11776  	 * [classifier_type=<4|10>]
11777  	 * [classifier params based on classifier type]
11778  	 * [tclas_processing=<0|1>]
11779  	 * [qos_characteristics] <up/down/direct> [min_si=<decimal number>]
11780  	 * [max_si=<decimal number>] [min_data_rate=<decimal number>]
11781  	 * [delay_bound=<decimal number>] [max_msdu=<decimal number>]
11782  	 * [service_start_time=<decimal number>]
11783  	 * [service_start_time_link_id=<decimal number>]
11784  	 * [mean_data_rate=<decimal number>] [burst_size=<decimal number>]
11785  	 * [msdu_lifetime=<decimal number>]
11786  	 * [msdu_delivery_info=<decimal number>] [medium_time=<decimal number>]
11787  	 * [scs_id=<decimal number>] ...
11788  	 */
11789  	pos1 = os_strstr(cmd, "scs_id=");
11790  	if (!pos1) {
11791  		wpa_printf(MSG_ERROR, "SCSID not present");
11792  		return -1;
11793  	}
11794  
11795  	free_up_scs_desc(scs_data);
11796  
11797  	while (pos1) {
11798  		struct scs_desc_elem *n1;
11799  		struct active_scs_elem *active_scs_desc;
11800  		char *next_scs_desc, *pos2;
11801  		unsigned int num_tclas_elem = 0;
11802  		bool scsid_active = false, tclas_present = false;
11803  		struct qos_characteristics *qos_elem = &desc_elem.qos_char_elem;
11804  
11805  		desc_elem.scs_id = atoi(pos1 + 7);
11806  		pos1 += 7;
11807  
11808  		next_scs_desc = os_strstr(pos1, "scs_id=");
11809  		if (next_scs_desc) {
11810  			char temp[20];
11811  
11812  			os_snprintf(temp, sizeof(temp), "scs_id=%d ",
11813  				    desc_elem.scs_id);
11814  			if (os_strstr(next_scs_desc, temp)) {
11815  				wpa_printf(MSG_ERROR,
11816  					   "Multiple SCS descriptors configured with same SCSID(=%d)",
11817  					   desc_elem.scs_id);
11818  				goto free_scs_desc;
11819  			}
11820  			pos1[next_scs_desc - pos1 - 1] = '\0';
11821  		}
11822  
11823  		dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids,
11824  				 struct active_scs_elem, list) {
11825  			if (desc_elem.scs_id == active_scs_desc->scs_id) {
11826  				scsid_active = true;
11827  				break;
11828  			}
11829  		}
11830  
11831  		if (os_strstr(pos1, "add ")) {
11832  			desc_elem.request_type = SCS_REQ_ADD;
11833  			if (scsid_active) {
11834  				wpa_printf(MSG_ERROR, "SCSID %d already active",
11835  					   desc_elem.scs_id);
11836  				return -1;
11837  			}
11838  		} else if (os_strstr(pos1, "remove")) {
11839  			desc_elem.request_type = SCS_REQ_REMOVE;
11840  			if (!scsid_active) {
11841  				wpa_printf(MSG_ERROR, "SCSID %d not active",
11842  					   desc_elem.scs_id);
11843  				return -1;
11844  			}
11845  			goto scs_desc_end;
11846  		} else if (os_strstr(pos1, "change ")) {
11847  			desc_elem.request_type = SCS_REQ_CHANGE;
11848  			if (!scsid_active) {
11849  				wpa_printf(MSG_ERROR, "SCSID %d not active",
11850  					   desc_elem.scs_id);
11851  				return -1;
11852  			}
11853  		} else {
11854  			wpa_printf(MSG_ERROR, "SCS Request type invalid");
11855  			goto free_scs_desc;
11856  		}
11857  
11858  		pos1 = os_strstr(pos1, "scs_up=");
11859  		if (!pos1) {
11860  			wpa_printf(MSG_ERROR,
11861  				   "Intra-Access user priority not present");
11862  			goto free_scs_desc;
11863  		}
11864  
11865  		val = atoi(pos1 + 7);
11866  		if (val < 0 || val > 7) {
11867  			wpa_printf(MSG_ERROR,
11868  				   "Intra-Access user priority invalid %d",
11869  				   val);
11870  			goto free_scs_desc;
11871  		}
11872  
11873  		desc_elem.intra_access_priority = val;
11874  		desc_elem.scs_up_avail = true;
11875  
11876  		pos = os_strstr(pos1, "classifier_type=");
11877  		if (!pos) {
11878  			wpa_printf(MSG_ERROR, "classifier type empty");
11879  			goto qos_characteristics;
11880  		}
11881  		tclas_present = true;
11882  
11883  		while (pos) {
11884  			struct tclas_element elem = { 0 }, *n;
11885  			char *next_tclas_elem;
11886  
11887  			val = atoi(pos + 16);
11888  			if (val != 4 && val != 10) {
11889  				wpa_printf(MSG_ERROR,
11890  					   "classifier type invalid %d", val);
11891  				goto free_scs_desc;
11892  			}
11893  
11894  			elem.classifier_type = val;
11895  			pos += 16;
11896  
11897  			next_tclas_elem = os_strstr(pos, "classifier_type=");
11898  			if (next_tclas_elem) {
11899  				pos1 = next_tclas_elem;
11900  				pos[next_tclas_elem - pos - 1] = '\0';
11901  			}
11902  
11903  			switch (val) {
11904  			case 4:
11905  				if (scs_parse_type4(&elem, pos) < 0)
11906  					goto free_scs_desc;
11907  				break;
11908  			case 10:
11909  				if (scs_parse_type10(&elem, pos) < 0)
11910  					goto free_scs_desc;
11911  				break;
11912  			}
11913  
11914  			n = os_realloc(desc_elem.tclas_elems,
11915  				       (num_tclas_elem + 1) * sizeof(elem));
11916  			if (!n)
11917  				goto free_scs_desc;
11918  
11919  			desc_elem.tclas_elems = n;
11920  			os_memcpy((u8 *) desc_elem.tclas_elems +
11921  				  num_tclas_elem * sizeof(elem),
11922  				  &elem, sizeof(elem));
11923  			num_tclas_elem++;
11924  			desc_elem.num_tclas_elem = num_tclas_elem;
11925  			pos = next_tclas_elem;
11926  		}
11927  
11928  		if (desc_elem.num_tclas_elem > 1) {
11929  			pos1 = os_strstr(pos1, "tclas_processing=");
11930  			if (!pos1) {
11931  				wpa_printf(MSG_ERROR, "tclas_processing empty");
11932  				goto free_scs_desc;
11933  			}
11934  
11935  			val = atoi(pos1 + 17);
11936  			if (val != 0 && val != 1) {
11937  				wpa_printf(MSG_ERROR,
11938  					   "tclas_processing invalid");
11939  				goto free_scs_desc;
11940  			}
11941  
11942  			desc_elem.tclas_processing = val;
11943  		}
11944  
11945  	qos_characteristics:
11946  		pos1 = os_strstr(pos1, "qos_characteristics");
11947  		if (!pos1 && !tclas_present)
11948  			goto free_scs_desc;
11949  		if (!pos1)
11950  			goto scs_desc_end;
11951  
11952  		qos_elem->available = true;
11953  		if (os_strstr(pos1, "up ")) {
11954  			qos_elem->direction = SCS_DIRECTION_UP;
11955  			if (tclas_present) {
11956  				wpa_printf(MSG_ERROR,
11957  					   "TCLAS with direction:UP not allowed");
11958  				goto free_scs_desc;
11959  			}
11960  		} else if (os_strstr(pos1, "down ")) {
11961  			qos_elem->direction = SCS_DIRECTION_DOWN;
11962  		} else if (os_strstr(pos1, "direct ")) {
11963  			qos_elem->direction = SCS_DIRECTION_DIRECT;
11964  		}
11965  
11966  		pos1 = os_strstr(pos1, "min_si=");
11967  		if (!pos1) {
11968  			wpa_printf(MSG_ERROR, "Min SI is required");
11969  			goto free_scs_desc;
11970  		}
11971  		qos_elem->min_si = atoi(pos1 + 7);
11972  
11973  		pos1 = os_strstr(pos1, "max_si=");
11974  		if (!pos1) {
11975  			wpa_printf(MSG_ERROR, "Max SI is required");
11976  			goto free_scs_desc;
11977  		}
11978  		qos_elem->max_si = atoi(pos1 + 7);
11979  
11980  		if (qos_elem->min_si && qos_elem->max_si &&
11981  		    qos_elem->max_si < qos_elem->min_si) {
11982  			wpa_printf(MSG_ERROR, "Invalid Max SI");
11983  			goto free_scs_desc;
11984  		}
11985  
11986  		pos1 = os_strstr(pos1, "min_data_rate=");
11987  		if (!pos1) {
11988  			wpa_printf(MSG_ERROR, "Min data rate is required");
11989  			goto free_scs_desc;
11990  		}
11991  		qos_elem->min_data_rate = atoi(pos1 + 14);
11992  
11993  		pos1 = os_strstr(pos1, "delay_bound=");
11994  		if (!pos1) {
11995  			wpa_printf(MSG_ERROR, "Delay Bound is required");
11996  			goto free_scs_desc;
11997  		}
11998  		qos_elem->delay_bound = atoi(pos1 + 12);
11999  
12000  		if (qos_elem->min_data_rate >= BIT(24) ||
12001  		    qos_elem->delay_bound >= BIT(24)) {
12002  			wpa_printf(MSG_ERROR,
12003  				   "Invalid min_data_rate or delay_bound");
12004  			goto free_scs_desc;
12005  		}
12006  
12007  		pos2 = os_strstr(pos1, "max_msdu=");
12008  		if (pos2) {
12009  			qos_elem->max_msdu_size = atoi(pos2 + 9);
12010  			qos_elem->mask |= SCS_QOS_BIT_MAX_MSDU_SIZE;
12011  		}
12012  
12013  		pos2 = os_strstr(pos1, "service_start_time=");
12014  		if (pos2) {
12015  			qos_elem->service_start_time = atoi(pos2 + 19);
12016  			qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME;
12017  		}
12018  
12019  		pos2 = os_strstr(pos1, "service_start_time_link_id=");
12020  		if (pos2) {
12021  			qos_elem->service_start_time_link_id = atoi(pos2 + 27);
12022  			qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME_LINKID;
12023  		}
12024  
12025  		pos2 = os_strstr(pos1, "mean_data_rate=");
12026  		if (pos2) {
12027  			qos_elem->mean_data_rate = atoi(pos2 + 15);
12028  			qos_elem->mask |= SCS_QOS_BIT_MEAN_DATA_RATE;
12029  		}
12030  
12031  		pos2 = os_strstr(pos1, "burst_size=");
12032  		if (pos2) {
12033  			qos_elem->burst_size = atoi(pos2 + 11);
12034  			qos_elem->mask |=
12035  				SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE;
12036  		}
12037  
12038  		pos2 = os_strstr(pos1, "msdu_lifetime=");
12039  		if (pos2) {
12040  			qos_elem->msdu_lifetime = atoi(pos2 + 14);
12041  			qos_elem->mask |= SCS_QOS_BIT_MSDU_LIFETIME;
12042  		}
12043  
12044  		pos2 = os_strstr(pos1, "msdu_delivery_info=");
12045  		if (pos2) {
12046  			qos_elem->msdu_delivery_info = atoi(pos2 + 19);
12047  			qos_elem->mask |= SCS_QOS_BIT_MSDU_DELIVERY_INFO;
12048  		}
12049  
12050  		pos2 = os_strstr(pos1, "medium_time=");
12051  		if (pos2) {
12052  			qos_elem->medium_time = atoi(pos2 + 12);
12053  			qos_elem->mask |= SCS_QOS_BIT_MEDIUM_TIME;
12054  		}
12055  
12056  scs_desc_end:
12057  		n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) *
12058  				sizeof(struct scs_desc_elem));
12059  		if (!n1)
12060  			goto free_scs_desc;
12061  
12062  		scs_data->scs_desc_elems = n1;
12063  		os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc *
12064  			  sizeof(desc_elem), &desc_elem, sizeof(desc_elem));
12065  		num_scs_desc++;
12066  		scs_data->num_scs_desc = num_scs_desc;
12067  		pos1 = next_scs_desc;
12068  		os_memset(&desc_elem, 0, sizeof(desc_elem));
12069  	}
12070  
12071  	return wpas_send_scs_req(wpa_s);
12072  
12073  free_scs_desc:
12074  	free_up_tclas_elem(&desc_elem);
12075  	free_up_scs_desc(scs_data);
12076  	return -1;
12077  }
12078  
12079  
wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant * wpa_s,const char * cmd)12080  static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s,
12081  					  const char *cmd)
12082  {
12083  	char *pos;
12084  	struct dscp_policy_status *policy = NULL, *n;
12085  	int num_policies = 0, ret = -1;
12086  	struct dscp_resp_data resp_data;
12087  
12088  	/*
12089  	 * format:
12090  	 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
12091  	 */
12092  
12093  	os_memset(&resp_data, 0, sizeof(resp_data));
12094  
12095  	resp_data.more = os_strstr(cmd, "more") != NULL;
12096  
12097  	if (os_strstr(cmd, "reset")) {
12098  		resp_data.reset = true;
12099  		resp_data.solicited = false;
12100  		goto send_resp;
12101  	}
12102  
12103  	resp_data.solicited = os_strstr(cmd, "solicited") != NULL;
12104  
12105  	pos = os_strstr(cmd, "policy_id=");
12106  	while (pos) {
12107  		n = os_realloc(policy, (num_policies + 1) * sizeof(*policy));
12108  		if (!n)
12109  			goto fail;
12110  
12111  		policy = n;
12112  		pos += 10;
12113  		policy[num_policies].id = atoi(pos);
12114  		if (policy[num_policies].id == 0) {
12115  			wpa_printf(MSG_ERROR, "DSCP: Invalid policy id");
12116  			goto fail;
12117  		}
12118  
12119  		pos = os_strstr(pos, "status=");
12120  		if (!pos) {
12121  			wpa_printf(MSG_ERROR,
12122  				   "DSCP: Status is not found for a policy");
12123  			goto fail;
12124  		}
12125  
12126  		pos += 7;
12127  		policy[num_policies].status = atoi(pos);
12128  		num_policies++;
12129  
12130  		pos = os_strstr(pos, "policy_id");
12131  	}
12132  
12133  	resp_data.policy = policy;
12134  	resp_data.num_policies = num_policies;
12135  send_resp:
12136  	ret = wpas_send_dscp_response(wpa_s, &resp_data);
12137  	if (ret)
12138  		wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response");
12139  fail:
12140  	os_free(policy);
12141  	return ret;
12142  }
12143  
12144  
wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant * wpa_s,const char * cmd)12145  static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
12146  					   const char *cmd)
12147  {
12148  	char *pos;
12149  
12150  	/*
12151  	 * format:
12152  	 * Wildcard DSCP query
12153  	 * <wildcard>
12154  	 *
12155  	 * DSCP query with a domain name attribute:
12156  	 * [domain_name=<string>]
12157  	 */
12158  
12159  	if (os_strstr(cmd, "wildcard")) {
12160  		wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
12161  		return wpas_send_dscp_query(wpa_s, NULL, 0);
12162  	}
12163  
12164  	pos = os_strstr(cmd, "domain_name=");
12165  	if (!pos || !os_strlen(pos + 12)) {
12166  		wpa_printf(MSG_ERROR, "QM: Domain name not preset");
12167  		return -1;
12168  	}
12169  
12170  	return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
12171  }
12172  
12173  #endif /* CONFIG_NO_ROBUST_AV */
12174  
12175  
wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)12176  static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
12177  					   char *buf, size_t buflen)
12178  {
12179  	int ret, i;
12180  	char *pos, *end;
12181  	struct wpa_mlo_signal_info mlo_si;
12182  
12183  	if (!wpa_s->valid_links)
12184  		return -1;
12185  
12186  	ret = wpa_drv_mlo_signal_poll(wpa_s, &mlo_si);
12187  	if (ret)
12188  		return -1;
12189  
12190  	pos = buf;
12191  	end = buf + buflen;
12192  
12193  	for_each_link(mlo_si.valid_links, i) {
12194  		ret = os_snprintf(pos, end - pos,
12195  				  "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n"
12196  				  "NOISE=%d\nFREQUENCY=%u\n",
12197  				  i, mlo_si.links[i].data.signal,
12198  				  mlo_si.links[i].data.current_tx_rate / 1000,
12199  				  mlo_si.links[i].current_noise,
12200  				  mlo_si.links[i].frequency);
12201  		if (os_snprintf_error(end - pos, ret))
12202  			return -1;
12203  		pos += ret;
12204  
12205  		if (mlo_si.links[i].chanwidth != CHAN_WIDTH_UNKNOWN) {
12206  			ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
12207  					  channel_width_to_string(
12208  						  mlo_si.links[i].chanwidth));
12209  			if (os_snprintf_error(end - pos, ret))
12210  				return -1;
12211  			pos += ret;
12212  		}
12213  
12214  		if (mlo_si.links[i].center_frq1 > 0) {
12215  			ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
12216  					  mlo_si.links[i].center_frq1);
12217  			if (os_snprintf_error(end - pos, ret))
12218  				return -1;
12219  			pos += ret;
12220  		}
12221  
12222  		if (mlo_si.links[i].center_frq2 > 0) {
12223  			ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
12224  					  mlo_si.links[i].center_frq2);
12225  			if (os_snprintf_error(end - pos, ret))
12226  				return -1;
12227  			pos += ret;
12228  		}
12229  
12230  		if (mlo_si.links[i].data.avg_signal) {
12231  			ret = os_snprintf(pos, end - pos,
12232  					  "AVG_RSSI=%d\n",
12233  					  mlo_si.links[i].data.avg_signal);
12234  			if (os_snprintf_error(end - pos, ret))
12235  				return -1;
12236  			pos += ret;
12237  		}
12238  
12239  		if (mlo_si.links[i].data.avg_beacon_signal) {
12240  			ret = os_snprintf(
12241  				pos, end - pos, "AVG_BEACON_RSSI=%d\n",
12242  				mlo_si.links[i].data.avg_beacon_signal);
12243  			if (os_snprintf_error(end - pos, ret))
12244  				return -1;
12245  			pos += ret;
12246  		}
12247  	}
12248  
12249  	return pos - buf;
12250  }
12251  
12252  
wpas_ctrl_iface_mlo_status(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)12253  static int wpas_ctrl_iface_mlo_status(struct wpa_supplicant *wpa_s,
12254  				      char *buf, size_t buflen)
12255  {
12256  	int ret, i;
12257  	char *pos, *end;
12258  
12259  	if (!wpa_s->valid_links)
12260  		return -1;
12261  
12262  	pos = buf;
12263  	end = buf + buflen;
12264  
12265  	for_each_link(wpa_s->valid_links, i) {
12266  		ret = os_snprintf(pos, end - pos, "link_id=%d\nfreq=%u\n"
12267  				  "ap_link_addr=" MACSTR
12268  				  "\nsta_link_addr=" MACSTR "\n",
12269  				  i, wpa_s->links[i].freq,
12270  				  MAC2STR(wpa_s->links[i].bssid),
12271  				  MAC2STR(wpa_s->links[i].addr));
12272  		if (os_snprintf_error(end - pos, ret))
12273  			return pos - buf;
12274  		pos += ret;
12275  	}
12276  
12277  	return pos - buf;
12278  }
12279  
12280  
12281  #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_ml_probe(struct wpa_supplicant * wpa_s,char * cmd)12282  static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd)
12283  {
12284  	char *token, *context = NULL;
12285  	u8 bssid[ETH_ALEN];
12286  	int mld_id = -1, link_id = -1;
12287  	struct wpa_bss *bss;
12288  	int *freqs;
12289  
12290  	os_memset(bssid, 0, sizeof(bssid));
12291  
12292  	while ((token = str_token(cmd, " ", &context))) {
12293  		if (os_strncmp(token, "bssid=", 6) == 0) {
12294  			if (hwaddr_aton(token + 6, bssid))
12295  				return -1;
12296  		} else if (os_strncmp(token, "mld_id=", 7) == 0) {
12297  			mld_id = atoi(token + 7);
12298  		} else if (os_strncmp(token, "link_id=", 8) == 0) {
12299  			link_id = atoi(token + 8);
12300  		}
12301  	}
12302  
12303  	if (is_zero_ether_addr(bssid)) {
12304  		wpa_printf(MSG_DEBUG,
12305  			   "MLD: Failed parsing ML probe request arguments");
12306  		return -1;
12307  	}
12308  
12309  	bss = wpa_bss_get_bssid(wpa_s, bssid);
12310  	if (!bss) {
12311  		wpa_printf(MSG_DEBUG,
12312  			   "MLD: Unknown BSS for " MACSTR, MAC2STR(bssid));
12313  		return -1;
12314  	}
12315  
12316  	if (wpa_s->sched_scanning || wpa_s->scanning ||
12317  	    (wpa_s->wpa_state > WPA_SCANNING &&
12318  	     wpa_s->wpa_state != WPA_COMPLETED)) {
12319  		wpa_printf(MSG_DEBUG,
12320  			   "MLO: Ongoing scan: Reject ML probe request");
12321  		return -1;
12322  	}
12323  
12324  	freqs = os_malloc(sizeof(int) * 2);
12325  	if (!freqs)
12326  		return -1;
12327  
12328  	freqs[0] = bss->freq;
12329  	freqs[1] = 0;
12330  
12331  	wpa_s->manual_scan_passive = 0;
12332  	wpa_s->manual_scan_use_id = 0;
12333  	wpa_s->manual_scan_only_new = 0;
12334  	wpa_s->scan_id_count = 0;
12335  	wpa_s->scan_res_handler = scan_only_handler;
12336  	os_free(wpa_s->manual_scan_freqs);
12337  	wpa_s->manual_scan_freqs = freqs;
12338  
12339  	os_memcpy(wpa_s->ml_probe_bssid, bssid, ETH_ALEN);
12340  	wpa_s->ml_probe_mld_id = mld_id;
12341  	if (link_id >= 0)
12342  		wpa_s->ml_probe_links = BIT(link_id);
12343  
12344  	wpa_s->normal_scans = 0;
12345  	wpa_s->scan_req = MANUAL_SCAN_REQ;
12346  	wpa_s->after_wps = 0;
12347  	wpa_s->known_wps_freq = 0;
12348  	wpa_supplicant_req_scan(wpa_s, 0, 0);
12349  
12350  	return 0;
12351  }
12352  #endif /* CONFIG_TESTING_OPTIONS */
12353  
12354  
12355  #ifdef CONFIG_NAN_USD
12356  
wpas_ctrl_nan_publish(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)12357  static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
12358  				 char *buf, size_t buflen)
12359  {
12360  	char *token, *context = NULL;
12361  	int publish_id;
12362  	struct nan_publish_params params;
12363  	const char *service_name = NULL;
12364  	struct wpabuf *ssi = NULL;
12365  	int ret = -1;
12366  	enum nan_service_protocol_type srv_proto_type = 0;
12367  	int *freq_list = NULL;
12368  	bool p2p = false;
12369  
12370  	os_memset(&params, 0, sizeof(params));
12371  	/* USD shall use both solicited and unsolicited transmissions */
12372  	params.unsolicited = true;
12373  	params.solicited = true;
12374  	/* USD shall require FSD without GAS */
12375  	params.fsd = true;
12376  	params.freq = NAN_USD_DEFAULT_FREQ;
12377  
12378  	while ((token = str_token(cmd, " ", &context))) {
12379  		if (os_strncmp(token, "service_name=", 13) == 0) {
12380  			service_name = token + 13;
12381  			continue;
12382  		}
12383  
12384  		if (os_strncmp(token, "ttl=", 4) == 0) {
12385  			params.ttl = atoi(token + 4);
12386  			continue;
12387  		}
12388  
12389  		if (os_strncmp(token, "freq=", 5) == 0) {
12390  			params.freq = atoi(token + 5);
12391  			continue;
12392  		}
12393  
12394  		if (os_strncmp(token, "freq_list=", 10) == 0) {
12395  			char *pos = token + 10;
12396  
12397  			if (os_strcmp(pos, "all") == 0) {
12398  				os_free(freq_list);
12399  				freq_list = wpas_nan_usd_all_freqs(wpa_s);
12400  				params.freq_list = freq_list;
12401  				continue;
12402  			}
12403  
12404  			while (pos && pos[0]) {
12405  				int_array_add_unique(&freq_list, atoi(pos));
12406  				pos = os_strchr(pos, ',');
12407  				if (pos)
12408  					pos++;
12409  			}
12410  
12411  			params.freq_list = freq_list;
12412  			continue;
12413  		}
12414  
12415  		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12416  			srv_proto_type = atoi(token + 15);
12417  			continue;
12418  		}
12419  
12420  		if (os_strncmp(token, "ssi=", 4) == 0) {
12421  			if (ssi)
12422  				goto fail;
12423  			ssi = wpabuf_parse_bin(token + 4);
12424  			if (!ssi)
12425  				goto fail;
12426  			continue;
12427  		}
12428  
12429  		if (os_strcmp(token, "p2p=1") == 0) {
12430  			p2p = true;
12431  			continue;
12432  		}
12433  
12434  		if (os_strcmp(token, "solicited=0") == 0) {
12435  			params.solicited = false;
12436  			continue;
12437  		}
12438  
12439  		if (os_strcmp(token, "unsolicited=0") == 0) {
12440  			params.unsolicited = false;
12441  			continue;
12442  		}
12443  
12444  		if (os_strcmp(token, "fsd=0") == 0) {
12445  			params.fsd = false;
12446  			continue;
12447  		}
12448  
12449  		wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
12450  			   token);
12451  		goto fail;
12452  	}
12453  
12454  	publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
12455  					  ssi, &params, p2p);
12456  	if (publish_id > 0)
12457  		ret = os_snprintf(buf, buflen, "%d", publish_id);
12458  fail:
12459  	wpabuf_free(ssi);
12460  	os_free(freq_list);
12461  	return ret;
12462  }
12463  
12464  
wpas_ctrl_nan_cancel_publish(struct wpa_supplicant * wpa_s,char * cmd)12465  static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s,
12466  					char *cmd)
12467  {
12468  	char *token, *context = NULL;
12469  	int publish_id = 0;
12470  
12471  	while ((token = str_token(cmd, " ", &context))) {
12472  		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12473  			continue;
12474  		wpa_printf(MSG_INFO,
12475  			   "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
12476  			   token);
12477  		return -1;
12478  	}
12479  
12480  	if (publish_id <= 0) {
12481  		wpa_printf(MSG_INFO,
12482  			   "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
12483  		return -1;
12484  	}
12485  
12486  	wpas_nan_usd_cancel_publish(wpa_s, publish_id);
12487  	return 0;
12488  }
12489  
12490  
wpas_ctrl_nan_update_publish(struct wpa_supplicant * wpa_s,char * cmd)12491  static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s,
12492  					char *cmd)
12493  {
12494  	char *token, *context = NULL;
12495  	int publish_id = 0;
12496  	struct wpabuf *ssi = NULL;
12497  	int ret = -1;
12498  
12499  	while ((token = str_token(cmd, " ", &context))) {
12500  		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12501  			continue;
12502  		if (os_strncmp(token, "ssi=", 4) == 0) {
12503  			if (ssi)
12504  				goto fail;
12505  			ssi = wpabuf_parse_bin(token + 4);
12506  			if (!ssi)
12507  				goto fail;
12508  			continue;
12509  		}
12510  		wpa_printf(MSG_INFO,
12511  			   "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
12512  			   token);
12513  		goto fail;
12514  	}
12515  
12516  	if (publish_id <= 0) {
12517  		wpa_printf(MSG_INFO,
12518  			   "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
12519  		goto fail;
12520  	}
12521  
12522  	ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi);
12523  fail:
12524  	wpabuf_free(ssi);
12525  	return ret;
12526  }
12527  
12528  
wpas_ctrl_nan_subscribe(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)12529  static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
12530  				   char *buf, size_t buflen)
12531  {
12532  	char *token, *context = NULL;
12533  	int subscribe_id;
12534  	struct nan_subscribe_params params;
12535  	const char *service_name = NULL;
12536  	struct wpabuf *ssi = NULL;
12537  	int ret = -1;
12538  	enum nan_service_protocol_type srv_proto_type = 0;
12539  	int *freq_list = NULL;
12540  	bool p2p = false;
12541  
12542  	os_memset(&params, 0, sizeof(params));
12543  	params.freq = NAN_USD_DEFAULT_FREQ;
12544  
12545  	while ((token = str_token(cmd, " ", &context))) {
12546  		if (os_strncmp(token, "service_name=", 13) == 0) {
12547  			service_name = token + 13;
12548  			continue;
12549  		}
12550  
12551  		if (os_strcmp(token, "active=1") == 0) {
12552  			params.active = true;
12553  			continue;
12554  		}
12555  
12556  		if (os_strncmp(token, "ttl=", 4) == 0) {
12557  			params.ttl = atoi(token + 4);
12558  			continue;
12559  		}
12560  
12561  		if (os_strncmp(token, "freq=", 5) == 0) {
12562  			params.freq = atoi(token + 5);
12563  			continue;
12564  		}
12565  
12566  		if (os_strncmp(token, "freq_list=", 10) == 0) {
12567  			char *pos = token + 10;
12568  
12569  			if (os_strcmp(pos, "all") == 0) {
12570  				os_free(freq_list);
12571  				freq_list = wpas_nan_usd_all_freqs(wpa_s);
12572  				params.freq_list = freq_list;
12573  				continue;
12574  			}
12575  
12576  			while (pos && pos[0]) {
12577  				int_array_add_unique(&freq_list, atoi(pos));
12578  				pos = os_strchr(pos, ',');
12579  				if (pos)
12580  					pos++;
12581  			}
12582  
12583  			params.freq_list = freq_list;
12584  			continue;
12585  		}
12586  
12587  		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12588  			srv_proto_type = atoi(token + 15);
12589  			continue;
12590  		}
12591  
12592  		if (os_strncmp(token, "ssi=", 4) == 0) {
12593  			if (ssi)
12594  				goto fail;
12595  			ssi = wpabuf_parse_bin(token + 4);
12596  			if (!ssi)
12597  				goto fail;
12598  			continue;
12599  		}
12600  
12601  		if (os_strcmp(token, "p2p=1") == 0) {
12602  			p2p = true;
12603  			continue;
12604  		}
12605  
12606  		wpa_printf(MSG_INFO,
12607  			   "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
12608  			   token);
12609  		goto fail;
12610  	}
12611  
12612  	subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
12613  					      srv_proto_type, ssi,
12614  					      &params, p2p);
12615  	if (subscribe_id > 0)
12616  		ret = os_snprintf(buf, buflen, "%d", subscribe_id);
12617  fail:
12618  	wpabuf_free(ssi);
12619  	os_free(freq_list);
12620  	return ret;
12621  }
12622  
12623  
wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant * wpa_s,char * cmd)12624  static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s,
12625  					  char *cmd)
12626  {
12627  	char *token, *context = NULL;
12628  	int subscribe_id = 0;
12629  
12630  	while ((token = str_token(cmd, " ", &context))) {
12631  		if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
12632  			continue;
12633  		wpa_printf(MSG_INFO,
12634  			   "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
12635  			   token);
12636  		return -1;
12637  	}
12638  
12639  	if (subscribe_id <= 0) {
12640  		wpa_printf(MSG_INFO,
12641  			   "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
12642  		return -1;
12643  	}
12644  
12645  	wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id);
12646  	return 0;
12647  }
12648  
12649  
wpas_ctrl_nan_transmit(struct wpa_supplicant * wpa_s,char * cmd)12650  static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd)
12651  {
12652  	char *token, *context = NULL;
12653  	int handle = 0;
12654  	int req_instance_id = 0;
12655  	struct wpabuf *ssi = NULL;
12656  	u8 peer_addr[ETH_ALEN];
12657  	int ret = -1;
12658  
12659  	os_memset(peer_addr, 0, ETH_ALEN);
12660  
12661  	while ((token = str_token(cmd, " ", &context))) {
12662  		if (sscanf(token, "handle=%i", &handle) == 1)
12663  			continue;
12664  
12665  		if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
12666  			continue;
12667  
12668  		if (os_strncmp(token, "address=", 8) == 0) {
12669  			if (hwaddr_aton(token + 8, peer_addr) < 0)
12670  				return -1;
12671  			continue;
12672  		}
12673  
12674  		if (os_strncmp(token, "ssi=", 4) == 0) {
12675  			if (ssi)
12676  				goto fail;
12677  			ssi = wpabuf_parse_bin(token + 4);
12678  			if (!ssi)
12679  				goto fail;
12680  			continue;
12681  		}
12682  
12683  		wpa_printf(MSG_INFO,
12684  			   "CTRL: Invalid NAN_TRANSMIT parameter: %s",
12685  			   token);
12686  		goto fail;
12687  	}
12688  
12689  	if (handle <= 0) {
12690  		wpa_printf(MSG_INFO,
12691  			   "CTRL: Invalid or missing NAN_TRANSMIT handle");
12692  		goto fail;
12693  	}
12694  
12695  	if (is_zero_ether_addr(peer_addr)) {
12696  		wpa_printf(MSG_INFO,
12697  			   "CTRL: Invalid or missing NAN_TRANSMIT address");
12698  		goto fail;
12699  	}
12700  
12701  	ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
12702  				    req_instance_id);
12703  fail:
12704  	wpabuf_free(ssi);
12705  	return ret;
12706  }
12707  
12708  
wpas_ctrl_nan_unpause_publish(struct wpa_supplicant * wpa_s,char * cmd)12709  static int wpas_ctrl_nan_unpause_publish(struct wpa_supplicant *wpa_s,
12710  					 char *cmd)
12711  {
12712  	char *token, *context = NULL;
12713  	int publish_id = 0;
12714  	int peer_instance_id = 0;
12715  	u8 peer_addr[ETH_ALEN];
12716  
12717  	os_memset(peer_addr, 0, ETH_ALEN);
12718  
12719  	while ((token = str_token(cmd, " ", &context))) {
12720  		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12721  			continue;
12722  
12723  		if (sscanf(token, "peer_instance_id=%i",
12724  			   &peer_instance_id) == 1)
12725  			continue;
12726  
12727  		if (os_strncmp(token, "peer=", 5) == 0) {
12728  			if (hwaddr_aton(token + 5, peer_addr) < 0)
12729  				return -1;
12730  			continue;
12731  		}
12732  
12733  		wpa_printf(MSG_INFO,
12734  			   "CTRL: Invalid NAN_UNPAUSE_PUBLISH parameter: %s",
12735  			   token);
12736  		return -1;
12737  	}
12738  
12739  	if (publish_id <= 0) {
12740  		wpa_printf(MSG_INFO,
12741  			   "CTRL: Invalid or missing NAN_UNPAUSE_PUBLIH publish_id");
12742  		return -1;
12743  	}
12744  
12745  	if (is_zero_ether_addr(peer_addr)) {
12746  		wpa_printf(MSG_INFO,
12747  			   "CTRL: Invalid or missing NAN_UNPAUSE_PUBLISH address");
12748  		return -1;
12749  	}
12750  
12751  	return wpas_nan_usd_unpause_publish(wpa_s, publish_id, peer_instance_id,
12752  					    peer_addr);
12753  }
12754  
12755  #endif /* CONFIG_NAN_USD */
12756  
12757  
wpa_supplicant_ctrl_iface_process(struct wpa_supplicant * wpa_s,char * buf,size_t * resp_len)12758  char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
12759  					 char *buf, size_t *resp_len)
12760  {
12761  	char *reply;
12762  	const int reply_size = 4096;
12763  	int reply_len;
12764  
12765  	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
12766  	    os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
12767  	    os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
12768  	    os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12769  		if (wpa_debug_show_keys)
12770  			wpa_dbg(wpa_s, MSG_DEBUG,
12771  				"Control interface command '%s'", buf);
12772  		else
12773  			wpa_dbg(wpa_s, MSG_DEBUG,
12774  				"Control interface command '%s [REMOVED]'",
12775  				os_strncmp(buf, WPA_CTRL_RSP,
12776  					   os_strlen(WPA_CTRL_RSP)) == 0 ?
12777  				WPA_CTRL_RSP :
12778  				(os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
12779  				 "SET_NETWORK" : "key-add"));
12780  	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
12781  		   os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
12782  		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
12783  				      (const u8 *) buf, os_strlen(buf));
12784  	} else {
12785  		int level = wpas_ctrl_cmd_debug_level(buf);
12786  		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
12787  	}
12788  
12789  	reply = os_malloc(reply_size);
12790  	if (reply == NULL) {
12791  		*resp_len = 1;
12792  		return NULL;
12793  	}
12794  
12795  	os_memcpy(reply, "OK\n", 3);
12796  	reply_len = 3;
12797  
12798  	if (os_strcmp(buf, "PING") == 0) {
12799  		os_memcpy(reply, "PONG\n", 5);
12800  		reply_len = 5;
12801  	} else if (os_strcmp(buf, "IFNAME") == 0) {
12802  		reply_len = os_strlen(wpa_s->ifname);
12803  		os_memcpy(reply, wpa_s->ifname, reply_len);
12804  	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
12805  		if (wpa_debug_reopen_file() < 0)
12806  			reply_len = -1;
12807  	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
12808  		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
12809  	} else if (os_strcmp(buf, "MIB") == 0) {
12810  		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
12811  		if (reply_len >= 0) {
12812  			reply_len += eapol_sm_get_mib(wpa_s->eapol,
12813  						      reply + reply_len,
12814  						      reply_size - reply_len);
12815  #ifdef CONFIG_MACSEC
12816  			reply_len += ieee802_1x_kay_get_mib(
12817  				wpa_s->kay, reply + reply_len,
12818  				reply_size - reply_len);
12819  #endif /* CONFIG_MACSEC */
12820  		}
12821  	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
12822  		reply_len = wpa_supplicant_ctrl_iface_status(
12823  			wpa_s, buf + 6, reply, reply_size);
12824  	} else if (os_strcmp(buf, "PMKSA") == 0) {
12825  		reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
12826  	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
12827  		wpas_ctrl_iface_pmksa_flush(wpa_s);
12828  #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
12829  	} else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
12830  		reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
12831  						      reply, reply_size);
12832  	} else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
12833  		if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
12834  			reply_len = -1;
12835  #ifdef CONFIG_MESH
12836  	} else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
12837  		reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
12838  							   reply, reply_size);
12839  	} else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12840  		if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
12841  			reply_len = -1;
12842  #endif /* CONFIG_MESH */
12843  #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
12844  	} else if (os_strncmp(buf, "SET ", 4) == 0) {
12845  		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
12846  			reply_len = -1;
12847  	} else if (os_strncmp(buf, "DUMP", 4) == 0) {
12848  		reply_len = wpa_config_dump_values(wpa_s->conf,
12849  						   reply, reply_size);
12850  	} else if (os_strncmp(buf, "GET ", 4) == 0) {
12851  		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
12852  							  reply, reply_size);
12853  	} else if (os_strcmp(buf, "LOGON") == 0) {
12854  		eapol_sm_notify_logoff(wpa_s->eapol, false);
12855  	} else if (os_strcmp(buf, "LOGOFF") == 0) {
12856  		eapol_sm_notify_logoff(wpa_s->eapol, true);
12857  	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
12858  		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12859  			reply_len = -1;
12860  		else
12861  			wpas_request_connection(wpa_s);
12862  	} else if (os_strcmp(buf, "REATTACH") == 0) {
12863  		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
12864  		    !wpa_s->current_ssid)
12865  			reply_len = -1;
12866  		else {
12867  			wpa_s->reattach = 1;
12868  			wpas_request_connection(wpa_s);
12869  		}
12870  	} else if (os_strcmp(buf, "RECONNECT") == 0) {
12871  		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12872  			reply_len = -1;
12873  		else if (wpa_s->disconnected)
12874  			wpas_request_connection(wpa_s);
12875  #ifdef IEEE8021X_EAPOL
12876  	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
12877  		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
12878  			reply_len = -1;
12879  #endif /* IEEE8021X_EAPOL */
12880  #ifdef CONFIG_IEEE80211R
12881  	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
12882  		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
12883  			reply_len = -1;
12884  #endif /* CONFIG_IEEE80211R */
12885  #ifdef CONFIG_WPS
12886  	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
12887  		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
12888  		if (res == -2) {
12889  			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12890  			reply_len = 17;
12891  		} else if (res)
12892  			reply_len = -1;
12893  	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
12894  		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
12895  		if (res == -2) {
12896  			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12897  			reply_len = 17;
12898  		} else if (res)
12899  			reply_len = -1;
12900  	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
12901  		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
12902  							      reply,
12903  							      reply_size);
12904  	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
12905  		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
12906  			wpa_s, buf + 14, reply, reply_size);
12907  	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
12908  		if (wpas_wps_cancel(wpa_s))
12909  			reply_len = -1;
12910  #ifdef CONFIG_WPS_NFC
12911  	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
12912  		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
12913  			reply_len = -1;
12914  	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
12915  		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
12916  			reply_len = -1;
12917  	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
12918  		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
12919  			wpa_s, buf + 21, reply, reply_size);
12920  	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
12921  		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
12922  			wpa_s, buf + 14, reply, reply_size);
12923  	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
12924  		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
12925  							       buf + 17))
12926  			reply_len = -1;
12927  	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
12928  		reply_len = wpas_ctrl_nfc_get_handover_req(
12929  			wpa_s, buf + 21, reply, reply_size);
12930  	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
12931  		reply_len = wpas_ctrl_nfc_get_handover_sel(
12932  			wpa_s, buf + 21, reply, reply_size);
12933  	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
12934  		if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
12935  			reply_len = -1;
12936  #endif /* CONFIG_WPS_NFC */
12937  	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
12938  		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
12939  			reply_len = -1;
12940  #ifdef CONFIG_AP
12941  	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
12942  		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
12943  			wpa_s, buf + 11, reply, reply_size);
12944  #endif /* CONFIG_AP */
12945  #ifdef CONFIG_WPS_ER
12946  	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
12947  		if (wpas_wps_er_start(wpa_s, NULL))
12948  			reply_len = -1;
12949  	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
12950  		if (wpas_wps_er_start(wpa_s, buf + 13))
12951  			reply_len = -1;
12952  	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
12953  		wpas_wps_er_stop(wpa_s);
12954  	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
12955  		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
12956  			reply_len = -1;
12957  	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
12958  		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
12959  		if (ret == -2) {
12960  			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12961  			reply_len = 17;
12962  		} else if (ret == -3) {
12963  			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
12964  			reply_len = 18;
12965  		} else if (ret == -4) {
12966  			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
12967  			reply_len = 20;
12968  		} else if (ret)
12969  			reply_len = -1;
12970  	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
12971  		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
12972  			reply_len = -1;
12973  	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
12974  		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
12975  								buf + 18))
12976  			reply_len = -1;
12977  	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
12978  		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
12979  			reply_len = -1;
12980  #ifdef CONFIG_WPS_NFC
12981  	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
12982  		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
12983  			wpa_s, buf + 24, reply, reply_size);
12984  #endif /* CONFIG_WPS_NFC */
12985  #endif /* CONFIG_WPS_ER */
12986  #endif /* CONFIG_WPS */
12987  #ifdef CONFIG_IBSS_RSN
12988  	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
12989  		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
12990  			reply_len = -1;
12991  #endif /* CONFIG_IBSS_RSN */
12992  #ifdef CONFIG_MESH
12993  	} else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
12994  		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12995  			wpa_s, buf + 19, reply, reply_size);
12996  	} else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
12997  		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12998  			wpa_s, "", reply, reply_size);
12999  	} else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
13000  		if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
13001  			reply_len = -1;
13002  	} else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
13003  		if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
13004  								buf + 18))
13005  			reply_len = -1;
13006  	} else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
13007  		if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
13008  			reply_len = -1;
13009  	} else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
13010  		if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
13011  			reply_len = -1;
13012  	} else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
13013  		if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
13014  			reply_len = -1;
13015  #endif /* CONFIG_MESH */
13016  #ifdef CONFIG_P2P
13017  	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
13018  		if (p2p_ctrl_find(wpa_s, buf + 8))
13019  			reply_len = -1;
13020  	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
13021  		if (p2p_ctrl_find(wpa_s, ""))
13022  			reply_len = -1;
13023  	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
13024  		wpas_p2p_stop_find(wpa_s);
13025  	} else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
13026  		if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
13027  			reply_len = -1;
13028  	} else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
13029  		if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
13030  			reply_len = -1;
13031  	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
13032  		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
13033  					     reply_size);
13034  	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
13035  		if (p2p_ctrl_listen(wpa_s, buf + 11))
13036  			reply_len = -1;
13037  	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
13038  		if (p2p_ctrl_listen(wpa_s, ""))
13039  			reply_len = -1;
13040  	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
13041  		if (wpas_p2p_group_remove(wpa_s, buf + 17))
13042  			reply_len = -1;
13043  	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
13044  		if (p2p_ctrl_group_add(wpa_s, ""))
13045  			reply_len = -1;
13046  	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
13047  		if (p2p_ctrl_group_add(wpa_s, buf + 14))
13048  			reply_len = -1;
13049  	} else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
13050  		reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
13051  						  reply_size);
13052  	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
13053  		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
13054  			reply_len = -1;
13055  	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
13056  		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
13057  	} else if (os_strcmp(buf, "P2P_GET_DIRA") == 0) {
13058  		reply_len = wpas_p2p_get_dira(wpa_s, reply, reply_size);
13059  	} else if (os_strncmp(buf, "P2P_VALIDATE_DIRA ", 18) == 0) {
13060  		reply_len = p2p_ctrl_validate_dira(wpa_s, buf + 18,
13061  						   reply, reply_size);
13062  #ifdef CONFIG_PASN
13063  #ifdef CONFIG_TESTING_OPTIONS
13064  	} else if (os_strcmp(buf, "P2P_GET_PASNPTK") == 0) {
13065  		reply_len = p2p_ctrl_get_pasn_ptk(wpa_s, reply, reply_size);
13066  #endif /* CONFIG_TESTING_OPTIONS */
13067  #endif /* CONFIG_PASN */
13068  	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
13069  		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
13070  						   reply_size);
13071  	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
13072  		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
13073  			reply_len = -1;
13074  	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
13075  		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
13076  			reply_len = -1;
13077  	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
13078  		wpas_p2p_sd_service_update(wpa_s);
13079  	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
13080  		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
13081  			reply_len = -1;
13082  	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
13083  		wpas_p2p_service_flush(wpa_s);
13084  	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
13085  		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
13086  			reply_len = -1;
13087  	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
13088  		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
13089  			reply_len = -1;
13090  	} else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
13091  		if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
13092  			reply_len = -1;
13093  	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
13094  		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
13095  			reply_len = -1;
13096  	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
13097  		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
13098  			reply_len = -1;
13099  	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
13100  		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
13101  					      reply_size);
13102  	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
13103  		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
13104  			reply_len = -1;
13105  	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
13106  		p2p_ctrl_flush(wpa_s);
13107  	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
13108  		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
13109  			reply_len = -1;
13110  	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
13111  		if (wpas_p2p_cancel(wpa_s))
13112  			reply_len = -1;
13113  	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
13114  		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
13115  			reply_len = -1;
13116  	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
13117  		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
13118  			reply_len = -1;
13119  	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
13120  		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
13121  			reply_len = -1;
13122  	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
13123  		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
13124  			reply_len = -1;
13125  	} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
13126  		if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
13127  			reply_len = -1;
13128  	} else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
13129  		if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
13130  			reply_len = -1;
13131  	} else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
13132  		if (wpas_p2p_lo_stop(wpa_s))
13133  			reply_len = -1;
13134  	} else if (os_strcmp(buf, "P2P_REMOVE_IDENTITY") == 0) {
13135  		if (wpas_p2p_remove_all_identity(wpa_s))
13136  			reply_len = -1;
13137  #ifdef CONFIG_TESTING_OPTIONS
13138  	} else if (os_strncmp(buf, "P2P_PMK_GET", 12) == 0) {
13139  		reply_len = p2p_ctrl_pmk_get(wpa_s, reply, reply_size);
13140  #endif /* CONFIG_TESTING_OPTIONS */
13141  #endif /* CONFIG_P2P */
13142  #ifdef CONFIG_WIFI_DISPLAY
13143  	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
13144  		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
13145  			reply_len = -1;
13146  	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
13147  		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
13148  						     reply, reply_size);
13149  #endif /* CONFIG_WIFI_DISPLAY */
13150  #ifdef CONFIG_INTERWORKING
13151  	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
13152  		if (interworking_fetch_anqp(wpa_s) < 0)
13153  			reply_len = -1;
13154  	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
13155  		interworking_stop_fetch_anqp(wpa_s);
13156  	} else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
13157  		if (ctrl_interworking_select(wpa_s, NULL) < 0)
13158  			reply_len = -1;
13159  	} else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
13160  		if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
13161  			reply_len = -1;
13162  	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
13163  		if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
13164  			reply_len = -1;
13165  	} else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
13166  		int id;
13167  
13168  		id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
13169  		if (id < 0)
13170  			reply_len = -1;
13171  		else {
13172  			reply_len = os_snprintf(reply, reply_size, "%d\n", id);
13173  			if (os_snprintf_error(reply_size, reply_len))
13174  				reply_len = -1;
13175  		}
13176  	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
13177  		if (get_anqp(wpa_s, buf + 9) < 0)
13178  			reply_len = -1;
13179  	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
13180  		if (gas_request(wpa_s, buf + 12) < 0)
13181  			reply_len = -1;
13182  	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
13183  		reply_len = gas_response_get(wpa_s, buf + 17, reply,
13184  					     reply_size);
13185  #endif /* CONFIG_INTERWORKING */
13186  #ifdef CONFIG_HS20
13187  	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
13188  		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
13189  			reply_len = -1;
13190  	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
13191  		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
13192  			reply_len = -1;
13193  #endif /* CONFIG_HS20 */
13194  	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
13195  	{
13196  		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
13197  			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
13198  			reply_len = -1;
13199  		else {
13200  			/*
13201  			 * Notify response from timeout to allow the control
13202  			 * interface response to be sent first.
13203  			 */
13204  			eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
13205  					       wpa_s, NULL);
13206  		}
13207  	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
13208  		if (wpa_supplicant_reload_configuration(wpa_s))
13209  			reply_len = -1;
13210  	} else if (os_strcmp(buf, "TERMINATE") == 0) {
13211  		wpa_supplicant_terminate_proc(wpa_s->global);
13212  	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
13213  		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
13214  			reply_len = -1;
13215  	} else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
13216  		reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
13217  			wpa_s, buf + 12, reply, reply_size);
13218  	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
13219  		/* deprecated backwards compatibility alias for BSSID_IGNORE */
13220  		reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
13221  			wpa_s, buf + 9, reply, reply_size);
13222  	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
13223  		reply_len = wpa_supplicant_ctrl_iface_log_level(
13224  			wpa_s, buf + 9, reply, reply_size);
13225  	} else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
13226  		reply_len = wpa_supplicant_ctrl_iface_list_networks(
13227  			wpa_s, buf + 14, reply, reply_size);
13228  	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
13229  		reply_len = wpa_supplicant_ctrl_iface_list_networks(
13230  			wpa_s, NULL, reply, reply_size);
13231  	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
13232  		wpas_request_disconnection(wpa_s);
13233  	} else if (os_strcmp(buf, "SCAN") == 0) {
13234  		wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
13235  	} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
13236  		wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
13237  	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
13238  		reply_len = wpa_supplicant_ctrl_iface_scan_results(
13239  			wpa_s, reply, reply_size);
13240  	} else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
13241  		if (wpas_abort_ongoing_scan(wpa_s) < 0)
13242  			reply_len = -1;
13243  	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
13244  		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
13245  			reply_len = -1;
13246  	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
13247  		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
13248  			reply_len = -1;
13249  	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
13250  		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
13251  			reply_len = -1;
13252  	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
13253  		reply_len = wpa_supplicant_ctrl_iface_add_network(
13254  			wpa_s, reply, reply_size);
13255  	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
13256  		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
13257  			reply_len = -1;
13258  	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
13259  		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
13260  			reply_len = -1;
13261  	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
13262  		reply_len = wpa_supplicant_ctrl_iface_get_network(
13263  			wpa_s, buf + 12, reply, reply_size);
13264  	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
13265  		if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
13266  							  wpa_s))
13267  			reply_len = -1;
13268  	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
13269  		reply_len = wpa_supplicant_ctrl_iface_list_creds(
13270  			wpa_s, reply, reply_size);
13271  	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
13272  		reply_len = wpa_supplicant_ctrl_iface_add_cred(
13273  			wpa_s, reply, reply_size);
13274  	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
13275  		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
13276  			reply_len = -1;
13277  	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
13278  		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
13279  			reply_len = -1;
13280  	} else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
13281  		reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
13282  							       reply,
13283  							       reply_size);
13284  #ifndef CONFIG_NO_CONFIG_WRITE
13285  	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
13286  		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
13287  			reply_len = -1;
13288  #endif /* CONFIG_NO_CONFIG_WRITE */
13289  	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
13290  		reply_len = wpa_supplicant_ctrl_iface_get_capability(
13291  			wpa_s, buf + 15, reply, reply_size);
13292  	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
13293  		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
13294  			reply_len = -1;
13295  	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
13296  		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
13297  			reply_len = -1;
13298  	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
13299  		reply_len = wpa_supplicant_global_iface_list(
13300  			wpa_s->global, reply, reply_size);
13301  	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
13302  		reply_len = wpa_supplicant_global_iface_interfaces(
13303  			wpa_s->global, buf + 10, reply, reply_size);
13304  	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
13305  		reply_len = wpa_supplicant_ctrl_iface_bss(
13306  			wpa_s, buf + 4, reply, reply_size);
13307  #ifdef CONFIG_AP
13308  	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
13309  		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
13310  	} else if (os_strncmp(buf, "STA ", 4) == 0) {
13311  		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
13312  					      reply_size);
13313  	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
13314  		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
13315  						   reply_size);
13316  	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
13317  		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
13318  			reply_len = -1;
13319  	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
13320  		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
13321  			reply_len = -1;
13322  	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
13323  		if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
13324  			reply_len = -1;
13325  	} else if (os_strcmp(buf, "STOP_AP") == 0) {
13326  		if (wpas_ap_stop_ap(wpa_s))
13327  			reply_len = -1;
13328  	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
13329  		if (wpas_ap_update_beacon(wpa_s))
13330  			reply_len = -1;
13331  	} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
13332  		if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
13333  			if (ap_ctrl_iface_acl_add_mac(wpa_s,
13334  						      DENY_UNLESS_ACCEPTED,
13335  						      buf + 19) ||
13336  			    ap_ctrl_iface_set_acl(wpa_s))
13337  				reply_len = -1;
13338  		} else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
13339  			if (ap_ctrl_iface_acl_del_mac(wpa_s,
13340  						      DENY_UNLESS_ACCEPTED,
13341  						      buf + 19) ||
13342  			    ap_ctrl_iface_set_acl(wpa_s) ||
13343  			    ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13344  				reply_len = -1;
13345  		} else if (os_strcmp(buf + 11, "SHOW") == 0) {
13346  			reply_len = ap_ctrl_iface_acl_show_mac(
13347  				wpa_s, DENY_UNLESS_ACCEPTED,
13348  				reply, reply_size);
13349  		} else if (os_strcmp(buf + 11, "CLEAR") == 0) {
13350  			ap_ctrl_iface_acl_clear_list(wpa_s,
13351  						     DENY_UNLESS_ACCEPTED);
13352  			if (ap_ctrl_iface_set_acl(wpa_s) ||
13353  			    ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13354  				reply_len = -1;
13355  		} else {
13356  			reply_len = -1;
13357  		}
13358  	} else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
13359  		if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
13360  			if (ap_ctrl_iface_acl_add_mac(wpa_s,
13361  						      ACCEPT_UNLESS_DENIED,
13362  						      buf + 17) ||
13363  			    ap_ctrl_iface_set_acl(wpa_s) ||
13364  			    ap_ctrl_iface_disassoc_deny_mac(wpa_s))
13365  				reply_len = -1;
13366  		} else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
13367  			if (ap_ctrl_iface_acl_del_mac(wpa_s,
13368  						      ACCEPT_UNLESS_DENIED,
13369  						      buf + 17) ||
13370  			    ap_ctrl_iface_set_acl(wpa_s))
13371  				reply_len = -1;
13372  		} else if (os_strcmp(buf + 9, "SHOW") == 0) {
13373  			reply_len = ap_ctrl_iface_acl_show_mac(
13374  				wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size);
13375  		} else if (os_strcmp(buf + 9, "CLEAR") == 0) {
13376  			ap_ctrl_iface_acl_clear_list(wpa_s,
13377  						     ACCEPT_UNLESS_DENIED);
13378  			if (ap_ctrl_iface_set_acl(wpa_s))
13379  				reply_len = -1;
13380  		} else {
13381  			reply_len = -1;
13382  		}
13383  #endif /* CONFIG_AP */
13384  	} else if (os_strcmp(buf, "SUSPEND") == 0) {
13385  		wpas_notify_suspend(wpa_s->global);
13386  	} else if (os_strcmp(buf, "RESUME") == 0) {
13387  		wpas_notify_resume(wpa_s->global);
13388  #ifdef CONFIG_TESTING_OPTIONS
13389  	} else if (os_strcmp(buf, "DROP_SA") == 0) {
13390  		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
13391  #endif /* CONFIG_TESTING_OPTIONS */
13392  	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
13393  		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
13394  			reply_len = -1;
13395  	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
13396  		wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
13397  	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
13398  		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
13399  			reply_len = -1;
13400  	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
13401  		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
13402  							       buf + 17))
13403  			reply_len = -1;
13404  	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
13405  		wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
13406  #ifdef CONFIG_TDLS
13407  	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
13408  		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
13409  			reply_len = -1;
13410  	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
13411  		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
13412  			reply_len = -1;
13413  	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
13414  		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
13415  			reply_len = -1;
13416  	} else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
13417  		if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
13418  							       buf + 17))
13419  			reply_len = -1;
13420  	} else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
13421  		if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
13422  								      buf + 24))
13423  			reply_len = -1;
13424  	} else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
13425  		reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
13426  			wpa_s, buf + 17, reply, reply_size);
13427  #endif /* CONFIG_TDLS */
13428  #ifndef CONFIG_NO_WMM_AC
13429  	} else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
13430  		reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
13431  	} else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
13432  		if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
13433  			reply_len = -1;
13434  	} else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
13435  		if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
13436  			reply_len = -1;
13437  #endif /* CONFIG_NO_WMM_AC */
13438  	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
13439  		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
13440  						       reply_size);
13441  	} else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
13442  		if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
13443  			reply_len = -1;
13444  	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
13445  		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
13446  						       reply_size);
13447  #ifdef CONFIG_AUTOSCAN
13448  	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
13449  		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
13450  			reply_len = -1;
13451  #endif /* CONFIG_AUTOSCAN */
13452  	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
13453  		reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
13454  							 reply_size);
13455  	} else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
13456  		reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply,
13457  							  reply_size);
13458  #ifdef ANDROID
13459  	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
13460  		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
13461  						      reply_size);
13462  #endif /* ANDROID */
13463  	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
13464  		reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
13465  						      reply_size);
13466  	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
13467  		pmksa_cache_clear_current(wpa_s->wpa);
13468  		eapol_sm_request_reauth(wpa_s->eapol);
13469  #ifdef CONFIG_WNM
13470  	} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
13471  		if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
13472  			reply_len = -1;
13473  	} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
13474  		if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
13475  				reply_len = -1;
13476  	} else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
13477  		if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
13478  			reply_len = -1;
13479  #endif /* CONFIG_WNM */
13480  #ifdef CONFIG_WNM_AP
13481  	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
13482  		if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
13483  			reply_len = -1;
13484  	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
13485  		if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13))
13486  			reply_len = -1;
13487  	} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
13488  		if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
13489  			reply_len = -1;
13490  #endif /* CONFIG_WNM_AP */
13491  	} else if (os_strcmp(buf, "FLUSH") == 0) {
13492  		wpa_supplicant_ctrl_iface_flush(wpa_s);
13493  	} else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
13494  		reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
13495  						 reply_size);
13496  #ifdef CONFIG_TESTING_OPTIONS
13497  	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
13498  		if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
13499  			reply_len = -1;
13500  	} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
13501  		wpas_ctrl_iface_mgmt_tx_done(wpa_s);
13502  	} else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
13503  		if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
13504  			reply_len = -1;
13505  	} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
13506  		if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
13507  			reply_len = -1;
13508  	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
13509  		if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
13510  			reply_len = -1;
13511  	} else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
13512  		if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
13513  			reply_len = -1;
13514  	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
13515  		if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
13516  			reply_len = -1;
13517  	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
13518  		if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
13519  			reply_len = -1;
13520  	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
13521  		if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
13522  			reply_len = -1;
13523  	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
13524  		if (testing_set_fail_pattern(true, buf + 16) < 0)
13525  			reply_len = -1;
13526  	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
13527  		reply_len = testing_get_fail_pattern(true, reply, reply_size);
13528  	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
13529  		if (testing_set_fail_pattern(false, buf + 10) < 0)
13530  			reply_len = -1;
13531  	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
13532  		reply_len = testing_get_fail_pattern(false, reply, reply_size);
13533  	} else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
13534  		if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
13535  			reply_len = -1;
13536  	} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
13537  		if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
13538  			reply_len = -1;
13539  	} else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) {
13540  		if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0)
13541  			reply_len = -1;
13542  	} else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) {
13543  		if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0)
13544  			reply_len = -1;
13545  	} else if (os_strcmp(buf, "RESET_PN") == 0) {
13546  		if (wpas_ctrl_reset_pn(wpa_s) < 0)
13547  			reply_len = -1;
13548  	} else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
13549  		if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
13550  			reply_len = -1;
13551  	} else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
13552  		if (wpas_ctrl_resend_assoc(wpa_s) < 0)
13553  			reply_len = -1;
13554  	} else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
13555  		sme_event_unprot_disconnect(
13556  			wpa_s, wpa_s->bssid, NULL,
13557  			WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13558  	} else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) {
13559  		if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9))
13560  			reply_len = -1;
13561  	} else if (os_strcmp(buf, "TWT_SETUP") == 0) {
13562  		if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
13563  			reply_len = -1;
13564  	} else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
13565  		if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
13566  			reply_len = -1;
13567  	} else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) {
13568  		if (wpas_ctrl_iface_send_twt_teardown(wpa_s, ""))
13569  			reply_len = -1;
13570  	} else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) {
13571  		if (wpas_ctrl_ml_probe(wpa_s, buf + 13))
13572  			reply_len = -1;
13573  	} else if (os_strncmp(buf, "TEST_RSNXE_DATA ", 16) == 0) {
13574  		if (wpas_ctrl_test_rsnxe_data(wpa_s, buf + 16) < 0)
13575  			reply_len = -1;
13576  #endif /* CONFIG_TESTING_OPTIONS */
13577  	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
13578  		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
13579  			reply_len = -1;
13580  	} else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
13581  		reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
13582  						      reply_size);
13583  	} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
13584  		if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
13585  			reply_len = -1;
13586  #ifndef CONFIG_NO_RRM
13587  	} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
13588  		if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
13589  			reply_len = -1;
13590  #endif /* CONFIG_NO_RRM */
13591  	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
13592  		wpas_ctrl_iface_erp_flush(wpa_s);
13593  	} else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
13594  		if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
13595  			reply_len = -1;
13596  	} else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
13597  		reply_len = wpas_ctrl_iface_get_pref_freq_list(
13598  			wpa_s, buf + 19, reply, reply_size);
13599  #ifdef CONFIG_FILS
13600  	} else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
13601  		if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
13602  			reply_len = -1;
13603  	} else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
13604  		wpas_flush_fils_hlp_req(wpa_s);
13605  #endif /* CONFIG_FILS */
13606  #ifdef CONFIG_DPP
13607  	} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
13608  		int res;
13609  
13610  		res = wpas_dpp_qr_code(wpa_s, buf + 12);
13611  		if (res < 0) {
13612  			reply_len = -1;
13613  		} else {
13614  			reply_len = os_snprintf(reply, reply_size, "%d", res);
13615  			if (os_snprintf_error(reply_size, reply_len))
13616  				reply_len = -1;
13617  		}
13618  	} else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
13619  		int res;
13620  
13621  		res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
13622  		if (res < 0) {
13623  			reply_len = -1;
13624  		} else {
13625  			reply_len = os_snprintf(reply, reply_size, "%d", res);
13626  			if (os_snprintf_error(reply_size, reply_len))
13627  				reply_len = -1;
13628  		}
13629  	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
13630  		int res;
13631  
13632  		res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
13633  		if (res < 0) {
13634  			reply_len = -1;
13635  		} else {
13636  			reply_len = os_snprintf(reply, reply_size, "%d", res);
13637  			if (os_snprintf_error(reply_size, reply_len))
13638  				reply_len = -1;
13639  		}
13640  	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
13641  		int res;
13642  
13643  		res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
13644  		if (res < 0) {
13645  			reply_len = -1;
13646  		} else {
13647  			reply_len = os_snprintf(reply, reply_size, "%d", res);
13648  			if (os_snprintf_error(reply_size, reply_len))
13649  				reply_len = -1;
13650  		}
13651  	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
13652  		int res;
13653  
13654  		res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
13655  		if (res < 0) {
13656  			reply_len = -1;
13657  		} else {
13658  			reply_len = os_snprintf(reply, reply_size, "%d", res);
13659  			if (os_snprintf_error(reply_size, reply_len))
13660  				reply_len = -1;
13661  		}
13662  	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
13663  		if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
13664  			reply_len = -1;
13665  	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
13666  		const char *uri;
13667  
13668  		uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
13669  		if (!uri) {
13670  			reply_len = -1;
13671  		} else {
13672  			reply_len = os_snprintf(reply, reply_size, "%s", uri);
13673  			if (os_snprintf_error(reply_size, reply_len))
13674  				reply_len = -1;
13675  		}
13676  	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
13677  		reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
13678  					       reply, reply_size);
13679  	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
13680  		if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
13681  				      os_strchr(buf + 18, ' ')) < 0)
13682  			reply_len = -1;
13683  	} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
13684  		if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
13685  			reply_len = -1;
13686  	} else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
13687  		if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
13688  			reply_len = -1;
13689  	} else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
13690  		wpas_dpp_stop(wpa_s);
13691  		wpas_dpp_listen_stop(wpa_s);
13692  	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
13693  		int res;
13694  
13695  		res = dpp_configurator_add(wpa_s->dpp, buf + 20);
13696  		if (res < 0) {
13697  			reply_len = -1;
13698  		} else {
13699  			reply_len = os_snprintf(reply, reply_size, "%d", res);
13700  			if (os_snprintf_error(reply_size, reply_len))
13701  				reply_len = -1;
13702  		}
13703  	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) {
13704  		if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0)
13705  			reply_len = -1;
13706  	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
13707  		if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
13708  			reply_len = -1;
13709  	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
13710  		if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
13711  			reply_len = -1;
13712  	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
13713  		reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
13714  							atoi(buf + 25),
13715  							reply, reply_size);
13716  	} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
13717  		int res;
13718  
13719  		res = wpas_dpp_pkex_add(wpa_s, buf + 12);
13720  		if (res < 0) {
13721  			reply_len = -1;
13722  		} else {
13723  			reply_len = os_snprintf(reply, reply_size, "%d", res);
13724  			if (os_snprintf_error(reply_size, reply_len))
13725  				reply_len = -1;
13726  		}
13727  	} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
13728  		if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
13729  			reply_len = -1;
13730  	} else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) {
13731  		if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0)
13732  			reply_len = -1;
13733  #ifdef CONFIG_DPP2
13734  	} else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
13735  		if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
13736  			reply_len = -1;
13737  	} else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
13738  		if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
13739  			reply_len = -1;
13740  	} else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
13741  		dpp_controller_stop(wpa_s->dpp);
13742  	} else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
13743  		if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
13744  			reply_len = -1;
13745  	} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
13746  		wpas_dpp_chirp_stop(wpa_s);
13747  	} else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
13748  		if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0)
13749  			reply_len = -1;
13750  	} else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) {
13751  		if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0)
13752  			reply_len = -1;
13753  #endif /* CONFIG_DPP2 */
13754  #ifdef CONFIG_DPP3
13755  	} else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) {
13756  		if (wpas_dpp_push_button(wpa_s, NULL) < 0)
13757  			reply_len = -1;
13758  	} else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) {
13759  		if (wpas_dpp_push_button(wpa_s, buf + 15) < 0)
13760  			reply_len = -1;
13761  #endif /* CONFIG_DPP3 */
13762  #endif /* CONFIG_DPP */
13763  #ifdef CONFIG_NAN_USD
13764  	} else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
13765  		reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply,
13766  						  reply_size);
13767  	} else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
13768  		if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0)
13769  			reply_len = -1;
13770  	} else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
13771  		if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0)
13772  			reply_len = -1;
13773  	} else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
13774  		reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply,
13775  						    reply_size);
13776  	} else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
13777  		if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0)
13778  			reply_len = -1;
13779  	} else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
13780  		if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
13781  			reply_len = -1;
13782  	} else if (os_strncmp(buf, "NAN_UNPAUSE_PUBLISH ", 20) == 0) {
13783  		if (wpas_ctrl_nan_unpause_publish(wpa_s, buf + 20) < 0)
13784  			reply_len = -1;
13785  	} else if (os_strcmp(buf, "NAN_FLUSH") == 0) {
13786  		wpas_nan_usd_flush(wpa_s);
13787  #endif /* CONFIG_NAN_USD */
13788  #ifdef CONFIG_PASN
13789  	} else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
13790  		if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
13791  			reply_len = -1;
13792  	} else if (os_strcmp(buf, "PASN_STOP") == 0) {
13793  		wpas_pasn_auth_stop(wpa_s);
13794  	} else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
13795  		reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
13796  	} else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
13797  		if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
13798  			reply_len = -1;
13799  #ifdef CONFIG_TESTING_OPTIONS
13800  	} else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) {
13801  		if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0)
13802  			reply_len = -1;
13803  #endif /* CONFIG_TESTING_OPTIONS */
13804  #endif /* CONFIG_PASN */
13805  #ifndef CONFIG_NO_ROBUST_AV
13806  	} else if (os_strncmp(buf, "MSCS ", 5) == 0) {
13807  		if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
13808  			reply_len = -1;
13809  	} else if (os_strncmp(buf, "SCS ", 4) == 0) {
13810  		if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
13811  			reply_len = -1;
13812  	} else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
13813  		if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
13814  			reply_len = -1;
13815  	} else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
13816  		if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
13817  			reply_len = -1;
13818  #endif /* CONFIG_NO_ROBUST_AV */
13819  	} else if (os_strcmp(buf, "MLO_STATUS") == 0) {
13820  		reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply,
13821  						       reply_size);
13822  	} else if (os_strcmp(buf, "MLO_SIGNAL_POLL") == 0) {
13823  		reply_len = wpas_ctrl_iface_mlo_signal_poll(wpa_s, reply,
13824  							    reply_size);
13825  	} else if (os_strcmp(buf, "NEW_RANDOM_MAC_ADDRESS") == 0) {
13826  		enum wpas_mac_addr_style mac_addr_style =
13827  			wpa_s->conf->preassoc_mac_addr;
13828  
13829  		wpa_s->conf->preassoc_mac_addr = WPAS_MAC_ADDR_STYLE_RANDOM;
13830  		if (wpas_update_random_addr_disassoc(wpa_s) != 1)
13831  			reply_len = -1;
13832  		wpa_s->conf->preassoc_mac_addr = mac_addr_style;
13833  	} else {
13834  		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
13835  		reply_len = 16;
13836  	}
13837  
13838  	if (reply_len < 0) {
13839  		os_memcpy(reply, "FAIL\n", 5);
13840  		reply_len = 5;
13841  	}
13842  
13843  	*resp_len = reply_len;
13844  	return reply;
13845  }
13846  
13847  
wpa_supplicant_global_iface_add(struct wpa_global * global,char * cmd)13848  static int wpa_supplicant_global_iface_add(struct wpa_global *global,
13849  					   char *cmd)
13850  {
13851  	struct wpa_interface iface;
13852  	char *pos, *extra;
13853  	struct wpa_supplicant *wpa_s;
13854  	unsigned int create_iface = 0;
13855  	u8 mac_addr[ETH_ALEN];
13856  	enum wpa_driver_if_type type = WPA_IF_STATION;
13857  
13858  	/*
13859  	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
13860  	 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
13861  	 */
13862  	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
13863  
13864  	os_memset(&iface, 0, sizeof(iface));
13865  
13866  	do {
13867  		iface.ifname = pos = cmd;
13868  		pos = os_strchr(pos, '\t');
13869  		if (pos)
13870  			*pos++ = '\0';
13871  		if (iface.ifname[0] == '\0')
13872  			return -1;
13873  		if (pos == NULL)
13874  			break;
13875  
13876  		iface.confname = pos;
13877  		pos = os_strchr(pos, '\t');
13878  		if (pos)
13879  			*pos++ = '\0';
13880  		if (iface.confname[0] == '\0')
13881  			iface.confname = NULL;
13882  		if (pos == NULL)
13883  			break;
13884  
13885  		iface.driver = pos;
13886  		pos = os_strchr(pos, '\t');
13887  		if (pos)
13888  			*pos++ = '\0';
13889  		if (iface.driver[0] == '\0')
13890  			iface.driver = NULL;
13891  		if (pos == NULL)
13892  			break;
13893  
13894  		iface.ctrl_interface = pos;
13895  		pos = os_strchr(pos, '\t');
13896  		if (pos)
13897  			*pos++ = '\0';
13898  		if (iface.ctrl_interface[0] == '\0')
13899  			iface.ctrl_interface = NULL;
13900  		if (pos == NULL)
13901  			break;
13902  
13903  		iface.driver_param = pos;
13904  		pos = os_strchr(pos, '\t');
13905  		if (pos)
13906  			*pos++ = '\0';
13907  		if (iface.driver_param[0] == '\0')
13908  			iface.driver_param = NULL;
13909  		if (pos == NULL)
13910  			break;
13911  
13912  		iface.bridge_ifname = pos;
13913  		pos = os_strchr(pos, '\t');
13914  		if (pos)
13915  			*pos++ = '\0';
13916  		if (iface.bridge_ifname[0] == '\0')
13917  			iface.bridge_ifname = NULL;
13918  		if (pos == NULL)
13919  			break;
13920  
13921  		extra = pos;
13922  		pos = os_strchr(pos, '\t');
13923  		if (pos)
13924  			*pos++ = '\0';
13925  		if (!extra[0])
13926  			break;
13927  
13928  		if (os_strcmp(extra, "create") == 0) {
13929  			create_iface = 1;
13930  			if (!pos)
13931  				break;
13932  
13933  			if (os_strcmp(pos, "sta") == 0) {
13934  				type = WPA_IF_STATION;
13935  			} else if (os_strcmp(pos, "ap") == 0) {
13936  				type = WPA_IF_AP_BSS;
13937  			} else {
13938  				wpa_printf(MSG_DEBUG,
13939  					   "INTERFACE_ADD unsupported interface type: '%s'",
13940  					   pos);
13941  				return -1;
13942  			}
13943  		} else {
13944  			wpa_printf(MSG_DEBUG,
13945  				   "INTERFACE_ADD unsupported extra parameter: '%s'",
13946  				   extra);
13947  			return -1;
13948  		}
13949  	} while (0);
13950  
13951  	if (create_iface) {
13952  		wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
13953  			   iface.ifname);
13954  		if (!global->ifaces)
13955  			return -1;
13956  		if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
13957  				   NULL, NULL, NULL, mac_addr, NULL) < 0) {
13958  			wpa_printf(MSG_ERROR,
13959  				   "CTRL_IFACE interface creation failed");
13960  			return -1;
13961  		}
13962  
13963  		wpa_printf(MSG_DEBUG,
13964  			   "CTRL_IFACE interface '%s' created with MAC addr: "
13965  			   MACSTR, iface.ifname, MAC2STR(mac_addr));
13966  	}
13967  
13968  	if (wpa_supplicant_get_iface(global, iface.ifname))
13969  		goto fail;
13970  
13971  	wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
13972  	if (!wpa_s)
13973  		goto fail;
13974  	wpa_s->added_vif = create_iface;
13975  	return 0;
13976  
13977  fail:
13978  	if (create_iface) {
13979  		/* wpa_supplicant does not create multi-BSS AP, so collapse to
13980  		 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
13981  		wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
13982  	}
13983  	return -1;
13984  }
13985  
13986  
wpa_supplicant_global_iface_remove(struct wpa_global * global,char * cmd)13987  static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
13988  					      char *cmd)
13989  {
13990  	struct wpa_supplicant *wpa_s;
13991  	int ret;
13992  	unsigned int delete_iface;
13993  
13994  	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
13995  
13996  	wpa_s = wpa_supplicant_get_iface(global, cmd);
13997  	if (wpa_s == NULL)
13998  		return -1;
13999  	delete_iface = wpa_s->added_vif;
14000  	ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
14001  	if (!ret && delete_iface) {
14002  		wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
14003  			   cmd);
14004  		/* wpa_supplicant does not create multi-BSS AP, so collapse to
14005  		 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
14006  		ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
14007  	}
14008  	return ret;
14009  }
14010  
14011  
wpa_free_iface_info(struct wpa_interface_info * iface)14012  static void wpa_free_iface_info(struct wpa_interface_info *iface)
14013  {
14014  	struct wpa_interface_info *prev;
14015  
14016  	while (iface) {
14017  		prev = iface;
14018  		iface = iface->next;
14019  
14020  		os_free(prev->ifname);
14021  		os_free(prev->desc);
14022  		os_free(prev);
14023  	}
14024  }
14025  
14026  
wpa_supplicant_global_iface_list(struct wpa_global * global,char * buf,int len)14027  static int wpa_supplicant_global_iface_list(struct wpa_global *global,
14028  					    char *buf, int len)
14029  {
14030  	int i, res;
14031  	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
14032  	char *pos, *end;
14033  
14034  	for (i = 0; wpa_drivers[i]; i++) {
14035  		const struct wpa_driver_ops *drv = wpa_drivers[i];
14036  		if (drv->get_interfaces == NULL)
14037  			continue;
14038  		tmp = drv->get_interfaces(global->drv_priv[i]);
14039  		if (tmp == NULL)
14040  			continue;
14041  
14042  		if (last == NULL)
14043  			iface = last = tmp;
14044  		else
14045  			last->next = tmp;
14046  		while (last->next)
14047  			last = last->next;
14048  	}
14049  
14050  	pos = buf;
14051  	end = buf + len;
14052  	for (tmp = iface; tmp; tmp = tmp->next) {
14053  		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
14054  				  tmp->drv_name, tmp->ifname,
14055  				  tmp->desc ? tmp->desc : "");
14056  		if (os_snprintf_error(end - pos, res)) {
14057  			*pos = '\0';
14058  			break;
14059  		}
14060  		pos += res;
14061  	}
14062  
14063  	wpa_free_iface_info(iface);
14064  
14065  	return pos - buf;
14066  }
14067  
14068  
wpa_supplicant_global_iface_interfaces(struct wpa_global * global,const char * input,char * buf,int len)14069  static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
14070  						  const char *input,
14071  						  char *buf, int len)
14072  {
14073  	int res;
14074  	char *pos, *end;
14075  	struct wpa_supplicant *wpa_s;
14076  	int show_ctrl = 0;
14077  
14078  	if (input)
14079  		show_ctrl = !!os_strstr(input, "ctrl");
14080  
14081  	wpa_s = global->ifaces;
14082  	pos = buf;
14083  	end = buf + len;
14084  
14085  	while (wpa_s) {
14086  		if (show_ctrl)
14087  			res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
14088  					  wpa_s->ifname,
14089  					  wpa_s->conf->ctrl_interface ?
14090  					  wpa_s->conf->ctrl_interface : "N/A");
14091  		else
14092  			res = os_snprintf(pos, end - pos, "%s\n",
14093  					  wpa_s->ifname);
14094  
14095  		if (os_snprintf_error(end - pos, res)) {
14096  			*pos = '\0';
14097  			break;
14098  		}
14099  		pos += res;
14100  		wpa_s = wpa_s->next;
14101  	}
14102  	return pos - buf;
14103  }
14104  
14105  
wpas_global_ctrl_iface_ifname(struct wpa_global * global,const char * ifname,char * cmd,size_t * resp_len)14106  static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
14107  					    const char *ifname,
14108  					    char *cmd, size_t *resp_len)
14109  {
14110  	struct wpa_supplicant *wpa_s;
14111  
14112  	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14113  		if (os_strcmp(ifname, wpa_s->ifname) == 0)
14114  			break;
14115  	}
14116  
14117  	if (wpa_s == NULL) {
14118  		char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
14119  		if (resp)
14120  			*resp_len = os_strlen(resp);
14121  		else
14122  			*resp_len = 1;
14123  		return resp;
14124  	}
14125  
14126  	return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
14127  }
14128  
14129  
wpas_global_ctrl_iface_redir_p2p(struct wpa_global * global,char * buf,size_t * resp_len)14130  static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
14131  					       char *buf, size_t *resp_len)
14132  {
14133  #ifdef CONFIG_P2P
14134  	static const char * cmd[] = {
14135  		"LIST_NETWORKS",
14136  		"P2P_FIND",
14137  		"P2P_STOP_FIND",
14138  		"P2P_LISTEN",
14139  		"P2P_GROUP_ADD",
14140  		"P2P_GET_PASSPHRASE",
14141  		"P2P_SERVICE_UPDATE",
14142  		"P2P_SERVICE_FLUSH",
14143  		"P2P_FLUSH",
14144  		"P2P_CANCEL",
14145  		"P2P_PRESENCE_REQ",
14146  		"P2P_EXT_LISTEN",
14147  #ifdef CONFIG_AP
14148  		"STA-FIRST",
14149  #endif /* CONFIG_AP */
14150  		"P2P_GET_DIRA",
14151  		"P2P_VALIDATE_DIRA",
14152  		NULL
14153  	};
14154  	static const char * prefix[] = {
14155  #ifdef ANDROID
14156  		"DRIVER ",
14157  #endif /* ANDROID */
14158  		"GET_CAPABILITY ",
14159  		"GET_NETWORK ",
14160  		"REMOVE_NETWORK ",
14161  		"P2P_FIND ",
14162  		"P2P_CONNECT ",
14163  		"P2P_LISTEN ",
14164  		"P2P_GROUP_REMOVE ",
14165  		"P2P_GROUP_ADD ",
14166  		"P2P_GROUP_MEMBER ",
14167  		"P2P_PROV_DISC ",
14168  		"P2P_SERV_DISC_REQ ",
14169  		"P2P_SERV_DISC_CANCEL_REQ ",
14170  		"P2P_SERV_DISC_RESP ",
14171  		"P2P_SERV_DISC_EXTERNAL ",
14172  		"P2P_SERVICE_ADD ",
14173  		"P2P_SERVICE_DEL ",
14174  		"P2P_SERVICE_REP ",
14175  		"P2P_REJECT ",
14176  		"P2P_INVITE ",
14177  		"P2P_PEER ",
14178  		"P2P_SET ",
14179  		"P2P_UNAUTHORIZE ",
14180  		"P2P_PRESENCE_REQ ",
14181  		"P2P_EXT_LISTEN ",
14182  		"P2P_REMOVE_CLIENT ",
14183  		"WPS_NFC_TOKEN ",
14184  		"WPS_NFC_TAG_READ ",
14185  		"NFC_GET_HANDOVER_SEL ",
14186  		"NFC_GET_HANDOVER_REQ ",
14187  		"NFC_REPORT_HANDOVER ",
14188  		"P2P_ASP_PROVISION ",
14189  		"P2P_ASP_PROVISION_RESP ",
14190  		"NAN_",
14191  #ifdef CONFIG_AP
14192  		"STA ",
14193  		"STA-NEXT ",
14194  #endif /* CONFIG_AP */
14195  		NULL
14196  	};
14197  	int found = 0;
14198  	int i;
14199  
14200  	if (global->p2p_init_wpa_s == NULL)
14201  		return NULL;
14202  
14203  	for (i = 0; !found && cmd[i]; i++) {
14204  		if (os_strcmp(buf, cmd[i]) == 0)
14205  			found = 1;
14206  	}
14207  
14208  	for (i = 0; !found && prefix[i]; i++) {
14209  		if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
14210  			found = 1;
14211  	}
14212  
14213  	if (found)
14214  		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
14215  							 buf, resp_len);
14216  #endif /* CONFIG_P2P */
14217  	return NULL;
14218  }
14219  
14220  
wpas_global_ctrl_iface_redir_wfd(struct wpa_global * global,char * buf,size_t * resp_len)14221  static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
14222  					       char *buf, size_t *resp_len)
14223  {
14224  #ifdef CONFIG_WIFI_DISPLAY
14225  	if (global->p2p_init_wpa_s == NULL)
14226  		return NULL;
14227  	if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
14228  	    os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
14229  		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
14230  							 buf, resp_len);
14231  #endif /* CONFIG_WIFI_DISPLAY */
14232  	return NULL;
14233  }
14234  
14235  
wpas_global_ctrl_iface_redir(struct wpa_global * global,char * buf,size_t * resp_len)14236  static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
14237  					   char *buf, size_t *resp_len)
14238  {
14239  	char *ret;
14240  
14241  	ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
14242  	if (ret)
14243  		return ret;
14244  
14245  	ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
14246  	if (ret)
14247  		return ret;
14248  
14249  	return NULL;
14250  }
14251  
14252  
wpas_global_ctrl_iface_set(struct wpa_global * global,char * cmd)14253  static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
14254  {
14255  	char *value;
14256  
14257  	value = os_strchr(cmd, ' ');
14258  	if (value == NULL)
14259  		return -1;
14260  	*value++ = '\0';
14261  
14262  	wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
14263  
14264  #ifdef CONFIG_WIFI_DISPLAY
14265  	if (os_strcasecmp(cmd, "wifi_display") == 0) {
14266  		wifi_display_enable(global, !!atoi(value));
14267  		return 0;
14268  	}
14269  #endif /* CONFIG_WIFI_DISPLAY */
14270  
14271  	/* Restore cmd to its original value to allow redirection */
14272  	value[-1] = ' ';
14273  
14274  	return -1;
14275  }
14276  
14277  
wpas_global_ctrl_iface_dup_network(struct wpa_global * global,char * cmd)14278  static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
14279  					      char *cmd)
14280  {
14281  	struct wpa_supplicant *wpa_s[2]; /* src, dst */
14282  	char *p;
14283  	unsigned int i;
14284  
14285  	/* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
14286  	 * <variable name> */
14287  
14288  	for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
14289  		p = os_strchr(cmd, ' ');
14290  		if (p == NULL)
14291  			return -1;
14292  		*p = '\0';
14293  
14294  		wpa_s[i] = global->ifaces;
14295  		for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
14296  			if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
14297  				break;
14298  		}
14299  
14300  		if (!wpa_s[i]) {
14301  			wpa_printf(MSG_DEBUG,
14302  				   "CTRL_IFACE: Could not find iface=%s", cmd);
14303  			return -1;
14304  		}
14305  
14306  		cmd = p + 1;
14307  	}
14308  
14309  	return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
14310  }
14311  
14312  
14313  #ifndef CONFIG_NO_CONFIG_WRITE
wpas_global_ctrl_iface_save_config(struct wpa_global * global)14314  static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
14315  {
14316  	int ret = 0, saved = 0;
14317  	struct wpa_supplicant *wpa_s;
14318  
14319  	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14320  		if (!wpa_s->conf->update_config) {
14321  			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
14322  			continue;
14323  		}
14324  
14325  		if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
14326  			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
14327  			ret = 1;
14328  		} else {
14329  			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
14330  			saved++;
14331  		}
14332  	}
14333  
14334  	if (!saved && !ret) {
14335  		wpa_dbg(wpa_s, MSG_DEBUG,
14336  			"CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
14337  		ret = 1;
14338  	}
14339  
14340  	return ret;
14341  }
14342  #endif /* CONFIG_NO_CONFIG_WRITE */
14343  
14344  
wpas_global_ctrl_iface_status(struct wpa_global * global,char * buf,size_t buflen)14345  static int wpas_global_ctrl_iface_status(struct wpa_global *global,
14346  					 char *buf, size_t buflen)
14347  {
14348  	char *pos, *end;
14349  	int ret;
14350  	struct wpa_supplicant *wpa_s;
14351  
14352  	pos = buf;
14353  	end = buf + buflen;
14354  
14355  #ifdef CONFIG_P2P
14356  	if (global->p2p && !global->p2p_disabled) {
14357  		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
14358  				  "\n"
14359  				  "p2p_state=%s\n",
14360  				  MAC2STR(global->p2p_dev_addr),
14361  				  p2p_get_state_txt(global->p2p));
14362  		if (os_snprintf_error(end - pos, ret))
14363  			return pos - buf;
14364  		pos += ret;
14365  	} else if (global->p2p) {
14366  		ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
14367  		if (os_snprintf_error(end - pos, ret))
14368  			return pos - buf;
14369  		pos += ret;
14370  	}
14371  #endif /* CONFIG_P2P */
14372  
14373  #ifdef CONFIG_WIFI_DISPLAY
14374  	ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
14375  			  !!global->wifi_display);
14376  	if (os_snprintf_error(end - pos, ret))
14377  		return pos - buf;
14378  	pos += ret;
14379  #endif /* CONFIG_WIFI_DISPLAY */
14380  
14381  	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14382  		ret = os_snprintf(pos, end - pos, "ifname=%s\n"
14383  				  "address=" MACSTR "\n",
14384  				  wpa_s->ifname, MAC2STR(wpa_s->own_addr));
14385  		if (os_snprintf_error(end - pos, ret))
14386  			return pos - buf;
14387  		pos += ret;
14388  	}
14389  
14390  	return pos - buf;
14391  }
14392  
14393  
14394  #ifdef CONFIG_FST
14395  
wpas_global_ctrl_iface_fst_attach(struct wpa_global * global,char * cmd,char * buf,size_t reply_size)14396  static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
14397  					     char *cmd, char *buf,
14398  					     size_t reply_size)
14399  {
14400  	char ifname[IFNAMSIZ + 1];
14401  	struct fst_iface_cfg cfg;
14402  	struct wpa_supplicant *wpa_s;
14403  	struct fst_wpa_obj iface_obj;
14404  
14405  	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
14406  		wpa_s = wpa_supplicant_get_iface(global, ifname);
14407  		if (wpa_s) {
14408  			if (wpa_s->fst) {
14409  				wpa_printf(MSG_INFO, "FST: Already attached");
14410  				return -1;
14411  			}
14412  			fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
14413  			wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
14414  						&iface_obj, &cfg);
14415  			if (wpa_s->fst)
14416  				return os_snprintf(buf, reply_size, "OK\n");
14417  		}
14418  	}
14419  
14420  	return -1;
14421  }
14422  
14423  
wpas_global_ctrl_iface_fst_detach(struct wpa_global * global,char * cmd,char * buf,size_t reply_size)14424  static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
14425  					     char *cmd, char *buf,
14426  					     size_t reply_size)
14427  {
14428  	char ifname[IFNAMSIZ + 1];
14429  	struct wpa_supplicant *wpa_s;
14430  
14431  	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
14432  		wpa_s = wpa_supplicant_get_iface(global, ifname);
14433  		if (wpa_s) {
14434  			if (!fst_iface_detach(ifname)) {
14435  				wpa_s->fst = NULL;
14436  				return os_snprintf(buf, reply_size, "OK\n");
14437  			}
14438  		}
14439  	}
14440  
14441  	return -1;
14442  }
14443  
14444  #endif /* CONFIG_FST */
14445  
14446  
wpa_supplicant_global_ctrl_iface_process(struct wpa_global * global,char * buf,size_t * resp_len)14447  char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
14448  						char *buf, size_t *resp_len)
14449  {
14450  	char *reply;
14451  	const int reply_size = 2048;
14452  	int reply_len;
14453  	int level = MSG_DEBUG;
14454  
14455  	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
14456  		char *pos = os_strchr(buf + 7, ' ');
14457  		if (pos) {
14458  			*pos++ = '\0';
14459  			return wpas_global_ctrl_iface_ifname(global,
14460  							     buf + 7, pos,
14461  							     resp_len);
14462  		}
14463  	}
14464  
14465  	reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
14466  	if (reply)
14467  		return reply;
14468  
14469  	if (os_strcmp(buf, "PING") == 0)
14470  		level = MSG_EXCESSIVE;
14471  	wpa_hexdump_ascii(level, "RX global ctrl_iface",
14472  			  (const u8 *) buf, os_strlen(buf));
14473  
14474  	reply = os_malloc(reply_size);
14475  	if (reply == NULL) {
14476  		*resp_len = 1;
14477  		return NULL;
14478  	}
14479  
14480  	os_memcpy(reply, "OK\n", 3);
14481  	reply_len = 3;
14482  
14483  	if (os_strcmp(buf, "PING") == 0) {
14484  		os_memcpy(reply, "PONG\n", 5);
14485  		reply_len = 5;
14486  	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
14487  		if (wpa_supplicant_global_iface_add(global, buf + 14))
14488  			reply_len = -1;
14489  	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
14490  		if (wpa_supplicant_global_iface_remove(global, buf + 17))
14491  			reply_len = -1;
14492  	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
14493  		reply_len = wpa_supplicant_global_iface_list(
14494  			global, reply, reply_size);
14495  	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
14496  		reply_len = wpa_supplicant_global_iface_interfaces(
14497  			global, buf + 10, reply, reply_size);
14498  #ifdef CONFIG_FST
14499  	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
14500  		reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
14501  							      reply,
14502  							      reply_size);
14503  	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
14504  		reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
14505  							      reply,
14506  							      reply_size);
14507  	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
14508  		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
14509  #endif /* CONFIG_FST */
14510  	} else if (os_strcmp(buf, "TERMINATE") == 0) {
14511  		wpa_supplicant_terminate_proc(global);
14512  	} else if (os_strcmp(buf, "SUSPEND") == 0) {
14513  		wpas_notify_suspend(global);
14514  	} else if (os_strcmp(buf, "RESUME") == 0) {
14515  		wpas_notify_resume(global);
14516  	} else if (os_strncmp(buf, "SET ", 4) == 0) {
14517  		if (wpas_global_ctrl_iface_set(global, buf + 4)) {
14518  #ifdef CONFIG_P2P
14519  			if (global->p2p_init_wpa_s) {
14520  				os_free(reply);
14521  				/* Check if P2P redirection would work for this
14522  				 * command. */
14523  				return wpa_supplicant_ctrl_iface_process(
14524  					global->p2p_init_wpa_s,
14525  					buf, resp_len);
14526  			}
14527  #endif /* CONFIG_P2P */
14528  			reply_len = -1;
14529  		}
14530  	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
14531  		if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
14532  			reply_len = -1;
14533  #ifndef CONFIG_NO_CONFIG_WRITE
14534  	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
14535  		if (wpas_global_ctrl_iface_save_config(global))
14536  			reply_len = -1;
14537  #endif /* CONFIG_NO_CONFIG_WRITE */
14538  	} else if (os_strcmp(buf, "STATUS") == 0) {
14539  		reply_len = wpas_global_ctrl_iface_status(global, reply,
14540  							  reply_size);
14541  #ifdef CONFIG_MODULE_TESTS
14542  	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
14543  		if (wpas_module_tests() < 0)
14544  			reply_len = -1;
14545  #endif /* CONFIG_MODULE_TESTS */
14546  	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
14547  		if (wpa_debug_reopen_file() < 0)
14548  			reply_len = -1;
14549  	} else {
14550  		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
14551  		reply_len = 16;
14552  	}
14553  
14554  	if (reply_len < 0) {
14555  		os_memcpy(reply, "FAIL\n", 5);
14556  		reply_len = 5;
14557  	}
14558  
14559  	*resp_len = reply_len;
14560  	return reply;
14561  }
14562