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