• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "utils/includes.h"
16 
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "common/version.h"
20 #include "common/ieee802_11_defs.h"
21 #include "common/wpa_ctrl.h"
22 #include "eap_peer/eap.h"
23 #include "eapol_supp/eapol_supp_sm.h"
24 #include "rsn_supp/wpa.h"
25 #include "rsn_supp/preauth.h"
26 #include "rsn_supp/pmksa_cache.h"
27 #include "l2_packet/l2_packet.h"
28 #include "wps/wps.h"
29 #include "config.h"
30 #include "wpa_supplicant_i.h"
31 #include "driver_i.h"
32 #include "wps_supplicant.h"
33 #include "ibss_rsn.h"
34 #include "ap.h"
35 #include "p2p_supplicant.h"
36 #include "p2p/p2p.h"
37 #include "notify.h"
38 #include "bss.h"
39 #include "scan.h"
40 #include "ctrl_iface.h"
41 #include "blacklist.h"
42 
43 extern struct wpa_driver_ops *wpa_drivers[];
44 
45 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
46 					    char *buf, int len);
47 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
48 						  char *buf, int len);
49 
50 
wpa_supplicant_ctrl_iface_set(struct wpa_supplicant * wpa_s,char * cmd)51 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
52 					 char *cmd)
53 {
54 	char *value;
55 	int ret = 0;
56 
57 	value = os_strchr(cmd, ' ');
58 	if (value == NULL)
59 		return -1;
60 	*value++ = '\0';
61 
62 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
63 	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
64 		eapol_sm_configure(wpa_s->eapol,
65 				   atoi(value), -1, -1, -1);
66 	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
67 		eapol_sm_configure(wpa_s->eapol,
68 				   -1, atoi(value), -1, -1);
69 	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
70 		eapol_sm_configure(wpa_s->eapol,
71 				   -1, -1, atoi(value), -1);
72 	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
73 		eapol_sm_configure(wpa_s->eapol,
74 				   -1, -1, -1, atoi(value));
75 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
76 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
77 				     atoi(value)))
78 			ret = -1;
79 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
80 		   0) {
81 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
82 				     atoi(value)))
83 			ret = -1;
84 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
85 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
86 			ret = -1;
87 	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
88 		wpa_s->wps_fragment_size = atoi(value);
89 #ifdef CONFIG_WPS_TESTING
90 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
91 		long int val;
92 		val = strtol(value, NULL, 0);
93 		if (val < 0 || val > 0xff) {
94 			ret = -1;
95 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
96 				   "wps_version_number %ld", val);
97 		} else {
98 			wps_version_number = val;
99 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
100 				   "version %u.%u",
101 				   (wps_version_number & 0xf0) >> 4,
102 				   wps_version_number & 0x0f);
103 		}
104 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
105 		wps_testing_dummy_cred = atoi(value);
106 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
107 			   wps_testing_dummy_cred);
108 #endif /* CONFIG_WPS_TESTING */
109 	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
110 		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
111 			ret = -1;
112 #ifdef CONFIG_TDLS_TESTING
113 	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
114 		extern unsigned int tdls_testing;
115 		tdls_testing = strtol(value, NULL, 0);
116 		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
117 #endif /* CONFIG_TDLS_TESTING */
118 #ifdef CONFIG_TDLS
119 	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
120 		int disabled = atoi(value);
121 		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
122 		if (disabled) {
123 			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
124 				ret = -1;
125 		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
126 			ret = -1;
127 		wpa_tdls_enable(wpa_s->wpa, !disabled);
128 #endif /* CONFIG_TDLS */
129 	} else {
130 		value[-1] = '=';
131 		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
132 		if (ret == 0)
133 			wpa_supplicant_update_config(wpa_s);
134 	}
135 
136 	return ret;
137 }
138 
139 
wpa_supplicant_ctrl_iface_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)140 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
141 					 char *cmd, char *buf, size_t buflen)
142 {
143 	int res = -1;
144 
145 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
146 
147 	if (os_strcmp(cmd, "version") == 0) {
148 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
149 	} else if (os_strcasecmp(cmd, "country") == 0) {
150 		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
151 			res = os_snprintf(buf, buflen, "%c%c",
152 					  wpa_s->conf->country[0],
153 					  wpa_s->conf->country[1]);
154 	}
155 
156 	if (res < 0 || (unsigned int) res >= buflen)
157 		return -1;
158 	return res;
159 }
160 
161 
162 #ifdef IEEE8021X_EAPOL
wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant * wpa_s,char * addr)163 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
164 					     char *addr)
165 {
166 	u8 bssid[ETH_ALEN];
167 	struct wpa_ssid *ssid = wpa_s->current_ssid;
168 
169 	if (hwaddr_aton(addr, bssid)) {
170 		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
171 			   "'%s'", addr);
172 		return -1;
173 	}
174 
175 	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
176 	rsn_preauth_deinit(wpa_s->wpa);
177 	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
178 		return -1;
179 
180 	return 0;
181 }
182 #endif /* IEEE8021X_EAPOL */
183 
184 
185 #ifdef CONFIG_PEERKEY
186 /* MLME-STKSTART.request(peer) */
wpa_supplicant_ctrl_iface_stkstart(struct wpa_supplicant * wpa_s,char * addr)187 static int wpa_supplicant_ctrl_iface_stkstart(
188 	struct wpa_supplicant *wpa_s, char *addr)
189 {
190 	u8 peer[ETH_ALEN];
191 
192 	if (hwaddr_aton(addr, peer)) {
193 		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
194 			   "address '%s'", addr);
195 		return -1;
196 	}
197 
198 	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
199 		   MAC2STR(peer));
200 
201 	return wpa_sm_stkstart(wpa_s->wpa, peer);
202 }
203 #endif /* CONFIG_PEERKEY */
204 
205 
206 #ifdef CONFIG_TDLS
207 
wpa_supplicant_ctrl_iface_tdls_discover(struct wpa_supplicant * wpa_s,char * addr)208 static int wpa_supplicant_ctrl_iface_tdls_discover(
209 	struct wpa_supplicant *wpa_s, char *addr)
210 {
211 	u8 peer[ETH_ALEN];
212 
213 	if (hwaddr_aton(addr, peer)) {
214 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
215 			   "address '%s'", addr);
216 		return -1;
217 	}
218 
219 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
220 		   MAC2STR(peer));
221 
222 	return wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
223 }
224 
225 
wpa_supplicant_ctrl_iface_tdls_setup(struct wpa_supplicant * wpa_s,char * addr)226 static int wpa_supplicant_ctrl_iface_tdls_setup(
227 	struct wpa_supplicant *wpa_s, char *addr)
228 {
229 	u8 peer[ETH_ALEN];
230 	int ret;
231 
232 	if (hwaddr_aton(addr, peer)) {
233 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
234 			   "address '%s'", addr);
235 		return -1;
236 	}
237 
238 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
239 		   MAC2STR(peer));
240 
241 	ret = wpa_tdls_reneg(wpa_s->wpa, peer);
242 	if (ret)
243 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
244 	return ret;
245 }
246 
247 
wpa_supplicant_ctrl_iface_tdls_teardown(struct wpa_supplicant * wpa_s,char * addr)248 static int wpa_supplicant_ctrl_iface_tdls_teardown(
249 	struct wpa_supplicant *wpa_s, char *addr)
250 {
251 	u8 peer[ETH_ALEN];
252 
253 	if (hwaddr_aton(addr, peer)) {
254 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
255 			   "address '%s'", addr);
256 		return -1;
257 	}
258 
259 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
260 		   MAC2STR(peer));
261 
262 	return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
263 }
264 
265 #endif /* CONFIG_TDLS */
266 
267 
268 #ifdef CONFIG_IEEE80211R
wpa_supplicant_ctrl_iface_ft_ds(struct wpa_supplicant * wpa_s,char * addr)269 static int wpa_supplicant_ctrl_iface_ft_ds(
270 	struct wpa_supplicant *wpa_s, char *addr)
271 {
272 	u8 target_ap[ETH_ALEN];
273 	struct wpa_bss *bss;
274 	const u8 *mdie;
275 
276 	if (hwaddr_aton(addr, target_ap)) {
277 		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
278 			   "address '%s'", addr);
279 		return -1;
280 	}
281 
282 	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
283 
284 	bss = wpa_bss_get_bssid(wpa_s, target_ap);
285 	if (bss)
286 		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
287 	else
288 		mdie = NULL;
289 
290 	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
291 }
292 #endif /* CONFIG_IEEE80211R */
293 
294 
295 #ifdef CONFIG_WPS
wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant * wpa_s,char * cmd)296 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
297 					     char *cmd)
298 {
299 	u8 bssid[ETH_ALEN], *_bssid = bssid;
300 #ifdef CONFIG_P2P
301 	u8 p2p_dev_addr[ETH_ALEN];
302 #endif /* CONFIG_P2P */
303 #ifdef CONFIG_AP
304 	u8 *_p2p_dev_addr = NULL;
305 #endif /* CONFIG_AP */
306 #ifdef ANDROID_BRCM_P2P_PATCH
307 	struct wpa_supplicant *iface;
308 #endif
309 	if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
310 		_bssid = NULL;
311 #ifdef CONFIG_P2P
312 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
313 		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
314 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
315 				   "P2P Device Address '%s'",
316 				   cmd + 13);
317 			return -1;
318 		}
319 		_p2p_dev_addr = p2p_dev_addr;
320 #endif /* CONFIG_P2P */
321 	} else if (hwaddr_aton(cmd, bssid)) {
322 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
323 			   cmd);
324 		return -1;
325 	}
326 
327 #if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_AP)
328 	for (iface = wpa_s->global->ifaces; iface; iface = iface->next)	{
329 		if (iface->ap_iface){
330 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: iface 0x%08x wpa_s->ap_iface %p", (u32)iface, iface->ap_iface);
331 			wpa_supplicant_ap_wps_pbc(iface, _bssid, _p2p_dev_addr);
332 			return 0;
333 		}
334 		else
335 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: ap_iface is not set iface 0x%08x", (u32)iface);
336 	}
337 #elif defined CONFIG_AP
338 	if (wpa_s->ap_iface)
339 		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
340 #endif /* CONFIG_AP */
341 
342 	return wpas_wps_start_pbc(wpa_s, _bssid, 0);
343 }
344 
345 
wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)346 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
347 					     char *cmd, char *buf,
348 					     size_t buflen)
349 {
350 	u8 bssid[ETH_ALEN], *_bssid = bssid;
351 	char *pin;
352 	int ret;
353 
354 #if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_AP)
355 	struct wpa_supplicant *iface;
356 #endif
357 
358 	pin = os_strchr(cmd, ' ');
359 	if (pin)
360 		*pin++ = '\0';
361 
362 	if (os_strcmp(cmd, "any") == 0)
363 		_bssid = NULL;
364 	else if (hwaddr_aton(cmd, bssid)) {
365 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
366 			   cmd);
367 		return -1;
368 	}
369 
370 #if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_AP)
371 	for (iface = wpa_s->global->ifaces; iface; iface = iface->next)	{
372 		if (iface->ap_iface){
373 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: iface 0x%08x wpa_s->ap_iface %p", (u32)iface, iface->ap_iface);
374 			/* Call the wps registrar for the main interface */
375 			wpa_supplicant_ap_wps_pin(iface, _bssid, pin,
376 							 buf, buflen);
377 			return 0;
378 		}
379 		else
380 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: ap_iface is not set iface 0x%08x", (u32)iface);
381 	}
382 #elif defined CONFIG_AP
383 	if (wpa_s->ap_iface)
384 		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
385 						 buf, buflen);
386 #endif /* CONFIG_AP */
387 
388 	if (pin) {
389 		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
390 					 DEV_PW_DEFAULT);
391 		if (ret < 0)
392 			return -1;
393 		ret = os_snprintf(buf, buflen, "%s", pin);
394 		if (ret < 0 || (size_t) ret >= buflen)
395 			return -1;
396 		return ret;
397 	}
398 
399 	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
400 	if (ret < 0)
401 		return -1;
402 
403 	/* Return the generated PIN */
404 	ret = os_snprintf(buf, buflen, "%08d", ret);
405 	if (ret < 0 || (size_t) ret >= buflen)
406 		return -1;
407 	return ret;
408 }
409 
410 
wpa_supplicant_ctrl_iface_wps_check_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)411 static int wpa_supplicant_ctrl_iface_wps_check_pin(
412 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
413 {
414 	char pin[9];
415 	size_t len;
416 	char *pos;
417 	int ret;
418 
419 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
420 			      (u8 *) cmd, os_strlen(cmd));
421 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
422 		if (*pos < '0' || *pos > '9')
423 			continue;
424 		pin[len++] = *pos;
425 		if (len == 9) {
426 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
427 			return -1;
428 		}
429 	}
430 	if (len != 4 && len != 8) {
431 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
432 		return -1;
433 	}
434 	pin[len] = '\0';
435 
436 	if (len == 8) {
437 		unsigned int pin_val;
438 		pin_val = atoi(pin);
439 		if (!wps_pin_valid(pin_val)) {
440 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
441 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
442 			if (ret < 0 || (size_t) ret >= buflen)
443 				return -1;
444 			return ret;
445 		}
446 	}
447 
448 	ret = os_snprintf(buf, buflen, "%s", pin);
449 	if (ret < 0 || (size_t) ret >= buflen)
450 		return -1;
451 
452 	return ret;
453 }
454 
455 
456 #ifdef CONFIG_WPS_OOB
wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant * wpa_s,char * cmd)457 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
458 					     char *cmd)
459 {
460 	char *path, *method, *name;
461 
462 	path = os_strchr(cmd, ' ');
463 	if (path == NULL)
464 		return -1;
465 	*path++ = '\0';
466 
467 	method = os_strchr(path, ' ');
468 	if (method == NULL)
469 		return -1;
470 	*method++ = '\0';
471 
472 	name = os_strchr(method, ' ');
473 	if (name != NULL)
474 		*name++ = '\0';
475 
476 	return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
477 }
478 #endif /* CONFIG_WPS_OOB */
479 
480 
wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant * wpa_s,char * cmd)481 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
482 					     char *cmd)
483 {
484 	u8 bssid[ETH_ALEN];
485 	char *pin;
486 	char *new_ssid;
487 	char *new_auth;
488 	char *new_encr;
489 	char *new_key;
490 	struct wps_new_ap_settings ap;
491 
492 	pin = os_strchr(cmd, ' ');
493 	if (pin == NULL)
494 		return -1;
495 	*pin++ = '\0';
496 
497 	if (hwaddr_aton(cmd, bssid)) {
498 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
499 			   cmd);
500 		return -1;
501 	}
502 
503 	new_ssid = os_strchr(pin, ' ');
504 	if (new_ssid == NULL)
505 		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
506 	*new_ssid++ = '\0';
507 
508 	new_auth = os_strchr(new_ssid, ' ');
509 	if (new_auth == NULL)
510 		return -1;
511 	*new_auth++ = '\0';
512 
513 	new_encr = os_strchr(new_auth, ' ');
514 	if (new_encr == NULL)
515 		return -1;
516 	*new_encr++ = '\0';
517 
518 	new_key = os_strchr(new_encr, ' ');
519 	if (new_key == NULL)
520 		return -1;
521 	*new_key++ = '\0';
522 
523 	os_memset(&ap, 0, sizeof(ap));
524 	ap.ssid_hex = new_ssid;
525 	ap.auth = new_auth;
526 	ap.encr = new_encr;
527 	ap.key_hex = new_key;
528 	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
529 }
530 
531 
532 #ifdef CONFIG_AP
wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)533 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
534 						char *cmd, char *buf,
535 						size_t buflen)
536 {
537 	int timeout = 300;
538 	char *pos;
539 	const char *pin_txt;
540 
541 	if (!wpa_s->ap_iface)
542 		return -1;
543 
544 	pos = os_strchr(cmd, ' ');
545 	if (pos)
546 		*pos++ = '\0';
547 
548 	if (os_strcmp(cmd, "disable") == 0) {
549 		wpas_wps_ap_pin_disable(wpa_s);
550 		return os_snprintf(buf, buflen, "OK\n");
551 	}
552 
553 	if (os_strcmp(cmd, "random") == 0) {
554 		if (pos)
555 			timeout = atoi(pos);
556 		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
557 		if (pin_txt == NULL)
558 			return -1;
559 		return os_snprintf(buf, buflen, "%s", pin_txt);
560 	}
561 
562 	if (os_strcmp(cmd, "get") == 0) {
563 		pin_txt = wpas_wps_ap_pin_get(wpa_s);
564 		if (pin_txt == NULL)
565 			return -1;
566 		return os_snprintf(buf, buflen, "%s", pin_txt);
567 	}
568 
569 	if (os_strcmp(cmd, "set") == 0) {
570 		char *pin;
571 		if (pos == NULL)
572 			return -1;
573 		pin = pos;
574 		pos = os_strchr(pos, ' ');
575 		if (pos) {
576 			*pos++ = '\0';
577 			timeout = atoi(pos);
578 		}
579 		if (os_strlen(pin) > buflen)
580 			return -1;
581 		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
582 			return -1;
583 		return os_snprintf(buf, buflen, "%s", pin);
584 	}
585 
586 	return -1;
587 }
588 #endif /* CONFIG_AP */
589 
590 
591 #ifdef CONFIG_WPS_ER
wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant * wpa_s,char * cmd)592 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
593 						char *cmd)
594 {
595 	char *uuid = cmd, *pin, *pos;
596 	u8 addr_buf[ETH_ALEN], *addr = NULL;
597 	pin = os_strchr(uuid, ' ');
598 	if (pin == NULL)
599 		return -1;
600 	*pin++ = '\0';
601 	pos = os_strchr(pin, ' ');
602 	if (pos) {
603 		*pos++ = '\0';
604 		if (hwaddr_aton(pos, addr_buf) == 0)
605 			addr = addr_buf;
606 	}
607 	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
608 }
609 
610 
wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant * wpa_s,char * cmd)611 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
612 						  char *cmd)
613 {
614 	char *uuid = cmd, *pin;
615 	pin = os_strchr(uuid, ' ');
616 	if (pin == NULL)
617 		return -1;
618 	*pin++ = '\0';
619 	return wpas_wps_er_learn(wpa_s, uuid, pin);
620 }
621 
622 
wpa_supplicant_ctrl_iface_wps_er_set_config(struct wpa_supplicant * wpa_s,char * cmd)623 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
624 	struct wpa_supplicant *wpa_s, char *cmd)
625 {
626 	char *uuid = cmd, *id;
627 	id = os_strchr(uuid, ' ');
628 	if (id == NULL)
629 		return -1;
630 	*id++ = '\0';
631 	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
632 }
633 
634 
wpa_supplicant_ctrl_iface_wps_er_config(struct wpa_supplicant * wpa_s,char * cmd)635 static int wpa_supplicant_ctrl_iface_wps_er_config(
636 	struct wpa_supplicant *wpa_s, char *cmd)
637 {
638 	char *pin;
639 	char *new_ssid;
640 	char *new_auth;
641 	char *new_encr;
642 	char *new_key;
643 	struct wps_new_ap_settings ap;
644 
645 	pin = os_strchr(cmd, ' ');
646 	if (pin == NULL)
647 		return -1;
648 	*pin++ = '\0';
649 
650 	new_ssid = os_strchr(pin, ' ');
651 	if (new_ssid == NULL)
652 		return -1;
653 	*new_ssid++ = '\0';
654 
655 	new_auth = os_strchr(new_ssid, ' ');
656 	if (new_auth == NULL)
657 		return -1;
658 	*new_auth++ = '\0';
659 
660 	new_encr = os_strchr(new_auth, ' ');
661 	if (new_encr == NULL)
662 		return -1;
663 	*new_encr++ = '\0';
664 
665 	new_key = os_strchr(new_encr, ' ');
666 	if (new_key == NULL)
667 		return -1;
668 	*new_key++ = '\0';
669 
670 	os_memset(&ap, 0, sizeof(ap));
671 	ap.ssid_hex = new_ssid;
672 	ap.auth = new_auth;
673 	ap.encr = new_encr;
674 	ap.key_hex = new_key;
675 	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
676 }
677 #endif /* CONFIG_WPS_ER */
678 
679 #endif /* CONFIG_WPS */
680 
681 
682 #ifdef CONFIG_IBSS_RSN
wpa_supplicant_ctrl_iface_ibss_rsn(struct wpa_supplicant * wpa_s,char * addr)683 static int wpa_supplicant_ctrl_iface_ibss_rsn(
684 	struct wpa_supplicant *wpa_s, char *addr)
685 {
686 	u8 peer[ETH_ALEN];
687 
688 	if (hwaddr_aton(addr, peer)) {
689 		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
690 			   "address '%s'", addr);
691 		return -1;
692 	}
693 
694 	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
695 		   MAC2STR(peer));
696 
697 	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
698 }
699 #endif /* CONFIG_IBSS_RSN */
700 
701 
wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant * wpa_s,char * rsp)702 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
703 					      char *rsp)
704 {
705 #ifdef IEEE8021X_EAPOL
706 	char *pos, *id_pos;
707 	int id;
708 	struct wpa_ssid *ssid;
709 	struct eap_peer_config *eap;
710 
711 	pos = os_strchr(rsp, '-');
712 	if (pos == NULL)
713 		return -1;
714 	*pos++ = '\0';
715 	id_pos = pos;
716 	pos = os_strchr(pos, ':');
717 	if (pos == NULL)
718 		return -1;
719 	*pos++ = '\0';
720 	id = atoi(id_pos);
721 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
722 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
723 			      (u8 *) pos, os_strlen(pos));
724 
725 	ssid = wpa_config_get_network(wpa_s->conf, id);
726 	if (ssid == NULL) {
727 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
728 			   "to update", id);
729 		return -1;
730 	}
731 	eap = &ssid->eap;
732 
733 	if (os_strcmp(rsp, "IDENTITY") == 0) {
734 		os_free(eap->identity);
735 		eap->identity = (u8 *) os_strdup(pos);
736 		eap->identity_len = os_strlen(pos);
737 		eap->pending_req_identity = 0;
738 		if (ssid == wpa_s->current_ssid)
739 			wpa_s->reassociate = 1;
740 	} else if (os_strcmp(rsp, "PASSWORD") == 0) {
741 		os_free(eap->password);
742 		eap->password = (u8 *) os_strdup(pos);
743 		eap->password_len = os_strlen(pos);
744 		eap->pending_req_password = 0;
745 		if (ssid == wpa_s->current_ssid)
746 			wpa_s->reassociate = 1;
747 	} else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
748 		os_free(eap->new_password);
749 		eap->new_password = (u8 *) os_strdup(pos);
750 		eap->new_password_len = os_strlen(pos);
751 		eap->pending_req_new_password = 0;
752 		if (ssid == wpa_s->current_ssid)
753 			wpa_s->reassociate = 1;
754 	} else if (os_strcmp(rsp, "PIN") == 0) {
755 		os_free(eap->pin);
756 		eap->pin = os_strdup(pos);
757 		eap->pending_req_pin = 0;
758 		if (ssid == wpa_s->current_ssid)
759 			wpa_s->reassociate = 1;
760 	} else if (os_strcmp(rsp, "OTP") == 0) {
761 		os_free(eap->otp);
762 		eap->otp = (u8 *) os_strdup(pos);
763 		eap->otp_len = os_strlen(pos);
764 		os_free(eap->pending_req_otp);
765 		eap->pending_req_otp = NULL;
766 		eap->pending_req_otp_len = 0;
767 	} else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
768 		os_free(eap->private_key_passwd);
769 		eap->private_key_passwd = (u8 *) os_strdup(pos);
770 		eap->pending_req_passphrase = 0;
771 		if (ssid == wpa_s->current_ssid)
772 			wpa_s->reassociate = 1;
773 	} else {
774 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
775 		return -1;
776 	}
777 
778 	return 0;
779 #else /* IEEE8021X_EAPOL */
780 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
781 	return -1;
782 #endif /* IEEE8021X_EAPOL */
783 }
784 
785 
wpa_supplicant_ctrl_iface_status(struct wpa_supplicant * wpa_s,const char * params,char * buf,size_t buflen)786 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
787 					    const char *params,
788 					    char *buf, size_t buflen)
789 {
790 	char *pos, *end, tmp[30];
791 	int res, verbose, ret;
792 
793 #if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_P2P)
794 	/* We have to send status command to p2p interface if p2p_interface is started
795 	 * otherwise we can send it to primary interface
796 	*/
797 	struct wpa_supplicant* ifs;
798 	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
799 		if ( (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO ) ||(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT )) {
800 			wpa_s = ifs;
801 			break;
802 		}
803 	}
804 #endif /* defined ANDROID_BRCM_P2P_PATCH && defined CONFIG_P2P */
805 
806 	verbose = os_strcmp(params, "-VERBOSE") == 0;
807 	pos = buf;
808 	end = buf + buflen;
809 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
810 		struct wpa_ssid *ssid = wpa_s->current_ssid;
811 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
812 				  MAC2STR(wpa_s->bssid));
813 		if (ret < 0 || ret >= end - pos)
814 			return pos - buf;
815 		pos += ret;
816 		if (ssid) {
817 			u8 *_ssid = ssid->ssid;
818 			size_t ssid_len = ssid->ssid_len;
819 			u8 ssid_buf[MAX_SSID_LEN];
820 			if (ssid_len == 0) {
821 				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
822 				if (_res < 0)
823 					ssid_len = 0;
824 				else
825 					ssid_len = _res;
826 				_ssid = ssid_buf;
827 			}
828 			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
829 					  wpa_ssid_txt(_ssid, ssid_len),
830 					  ssid->id);
831 			if (ret < 0 || ret >= end - pos)
832 				return pos - buf;
833 			pos += ret;
834 
835 			if (ssid->id_str) {
836 				ret = os_snprintf(pos, end - pos,
837 						  "id_str=%s\n",
838 						  ssid->id_str);
839 				if (ret < 0 || ret >= end - pos)
840 					return pos - buf;
841 				pos += ret;
842 			}
843 
844 			switch (ssid->mode) {
845 			case WPAS_MODE_INFRA:
846 				ret = os_snprintf(pos, end - pos,
847 						  "mode=station\n");
848 				break;
849 			case WPAS_MODE_IBSS:
850 				ret = os_snprintf(pos, end - pos,
851 						  "mode=IBSS\n");
852 				break;
853 			case WPAS_MODE_AP:
854 				ret = os_snprintf(pos, end - pos,
855 						  "mode=AP\n");
856 				break;
857 			case WPAS_MODE_P2P_GO:
858 				ret = os_snprintf(pos, end - pos,
859 						  "mode=P2P GO\n");
860 				break;
861 			case WPAS_MODE_P2P_GROUP_FORMATION:
862 				ret = os_snprintf(pos, end - pos,
863 						  "mode=P2P GO - group "
864 						  "formation\n");
865 				break;
866 			default:
867 				ret = 0;
868 				break;
869 			}
870 			if (ret < 0 || ret >= end - pos)
871 				return pos - buf;
872 			pos += ret;
873 		}
874 
875 #ifdef CONFIG_AP
876 		if (wpa_s->ap_iface) {
877 			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
878 							    end - pos,
879 							    verbose);
880 		} else
881 #endif /* CONFIG_AP */
882 		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
883 	}
884 	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
885 			  wpa_supplicant_state_txt(wpa_s->wpa_state));
886 	if (ret < 0 || ret >= end - pos)
887 		return pos - buf;
888 	pos += ret;
889 
890 	if (wpa_s->l2 &&
891 	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
892 		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
893 		if (ret < 0 || ret >= end - pos)
894 			return pos - buf;
895 		pos += ret;
896 	}
897 
898 #ifdef CONFIG_P2P
899 	if (wpa_s->global->p2p) {
900 		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
901 				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
902 		if (ret < 0 || ret >= end - pos)
903 			return pos - buf;
904 		pos += ret;
905 	}
906 #endif /* CONFIG_P2P */
907 
908 	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
909 			  MAC2STR(wpa_s->own_addr));
910 	if (ret < 0 || ret >= end - pos)
911 		return pos - buf;
912 	pos += ret;
913 
914 	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
915 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
916 		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
917 					  verbose);
918 		if (res >= 0)
919 			pos += res;
920 	}
921 
922 	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
923 	if (res >= 0)
924 		pos += res;
925 
926 	return pos - buf;
927 }
928 
929 
wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant * wpa_s,char * cmd)930 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
931 					   char *cmd)
932 {
933 	char *pos;
934 	int id;
935 	struct wpa_ssid *ssid;
936 	u8 bssid[ETH_ALEN];
937 
938 	/* cmd: "<network id> <BSSID>" */
939 	pos = os_strchr(cmd, ' ');
940 	if (pos == NULL)
941 		return -1;
942 	*pos++ = '\0';
943 	id = atoi(cmd);
944 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
945 	if (hwaddr_aton(pos, bssid)) {
946 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
947 		return -1;
948 	}
949 
950 	ssid = wpa_config_get_network(wpa_s->conf, id);
951 	if (ssid == NULL) {
952 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
953 			   "to update", id);
954 		return -1;
955 	}
956 
957 	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
958 	ssid->bssid_set = !is_zero_ether_addr(bssid);
959 
960 	return 0;
961 }
962 
963 
964 extern int wpa_debug_level;
965 extern int wpa_debug_timestamp;
966 
wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)967 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
968 					char *cmd, char *buf, size_t buflen)
969 {
970 	char *pos, *end, *stamp;
971 	int ret;
972 
973 	if (cmd == NULL)
974 		return -1;
975 	/* cmd: "LOG_LEVEL [<level>]" */
976 	if (*cmd == '\0') {
977 		pos = buf;
978 		end = buf + buflen;
979 		ret = os_snprintf(pos, end-pos, "Current level: %d\n"
980 			"{0-EXCESSIVE, 1-MSGDUMP, 2-DEBUG, 3-INFO, 4-WARNING, 5-ERROR}\n"
981 			"Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp);
982 		if ((ret < 0) || (ret >= end - pos))
983 			ret = 0;
984 		return ret;
985 	}
986 
987 	cmd++;
988 	stamp = os_strchr(cmd, ' ');
989 	if (stamp) {
990 		*stamp++ = '\0';
991 		while (*stamp == ' ')
992 			stamp++;
993 	}
994 
995 	if (cmd && os_strlen(cmd))
996 		wpa_debug_level = atoi(cmd);
997 
998 	if (stamp && os_strlen(stamp))
999 		wpa_debug_timestamp = atoi(stamp);
1000 
1001 	os_memcpy(buf, "OK\n", 3);
1002 	return 3;
1003 }
1004 
1005 
wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1006 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1007 					char *cmd, char *buf, size_t buflen)
1008 {
1009 	u8 bssid[ETH_ALEN];
1010 	struct wpa_blacklist *e;
1011 	char *pos, *end;
1012 	int ret;
1013 
1014 	/* cmd: "BLACKLIST [<BSSID>]" */
1015 	if (*cmd == '\0') {
1016 		pos = buf;
1017 		end = buf + buflen;
1018 		e = wpa_s->blacklist;
1019 		while (e) {
1020 			ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid));
1021 			if ((ret < 0) || (ret >= end - pos))
1022 				return pos - buf;
1023 			pos += ret;
1024 			e = e->next;
1025 		}
1026 		return pos - buf;
1027 	}
1028 
1029 	cmd++;
1030 	if (os_strncmp(cmd, "clear", 5) == 0) {
1031 		wpa_blacklist_clear(wpa_s);
1032 		os_memcpy(buf, "OK\n", 3);
1033 		return 3;
1034 	}
1035 
1036 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1037 	if (hwaddr_aton(cmd, bssid)) {
1038 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd);
1039 		return -1;
1040 	}
1041 
1042 	/* Add the BSSID twice, so its count will be 2, causing it to be
1043 	   skipped when processing scan results. */
1044 	ret = wpa_blacklist_add(wpa_s, bssid);
1045 	if (ret < 0)
1046 		return -1;
1047 	ret = wpa_blacklist_add(wpa_s, bssid);
1048 	if (ret < 0)
1049 		return -1;
1050 	os_memcpy(buf, "OK\n", 3);
1051 	return 3;
1052 }
1053 
1054 
wpa_supplicant_ctrl_iface_list_networks(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1055 static int wpa_supplicant_ctrl_iface_list_networks(
1056 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1057 {
1058 	char *pos, *end;
1059 	struct wpa_ssid *ssid;
1060 	int ret;
1061 
1062 	pos = buf;
1063 	end = buf + buflen;
1064 	ret = os_snprintf(pos, end - pos,
1065 			  "network id / ssid / bssid / flags\n");
1066 	if (ret < 0 || ret >= end - pos)
1067 		return pos - buf;
1068 	pos += ret;
1069 
1070 	ssid = wpa_s->conf->ssid;
1071 	while (ssid) {
1072 		ret = os_snprintf(pos, end - pos, "%d\t%s",
1073 				  ssid->id,
1074 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1075 		if (ret < 0 || ret >= end - pos)
1076 			return pos - buf;
1077 		pos += ret;
1078 		if (ssid->bssid_set) {
1079 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1080 					  MAC2STR(ssid->bssid));
1081 		} else {
1082 			ret = os_snprintf(pos, end - pos, "\tany");
1083 		}
1084 		if (ret < 0 || ret >= end - pos)
1085 			return pos - buf;
1086 		pos += ret;
1087 		ret = os_snprintf(pos, end - pos, "\t%s%s%s",
1088 				  ssid == wpa_s->current_ssid ?
1089 				  "[CURRENT]" : "",
1090 				  ssid->disabled ? "[DISABLED]" : "",
1091 				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1092 				  "");
1093 		if (ret < 0 || ret >= end - pos)
1094 			return pos - buf;
1095 		pos += ret;
1096 		ret = os_snprintf(pos, end - pos, "\n");
1097 		if (ret < 0 || ret >= end - pos)
1098 			return pos - buf;
1099 		pos += ret;
1100 
1101 		ssid = ssid->next;
1102 	}
1103 
1104 	return pos - buf;
1105 }
1106 
1107 
wpa_supplicant_cipher_txt(char * pos,char * end,int cipher)1108 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1109 {
1110 	int first = 1, ret;
1111 	ret = os_snprintf(pos, end - pos, "-");
1112 	if (ret < 0 || ret >= end - pos)
1113 		return pos;
1114 	pos += ret;
1115 	if (cipher & WPA_CIPHER_NONE) {
1116 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
1117 		if (ret < 0 || ret >= end - pos)
1118 			return pos;
1119 		pos += ret;
1120 		first = 0;
1121 	}
1122 	if (cipher & WPA_CIPHER_WEP40) {
1123 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
1124 		if (ret < 0 || ret >= end - pos)
1125 			return pos;
1126 		pos += ret;
1127 		first = 0;
1128 	}
1129 	if (cipher & WPA_CIPHER_WEP104) {
1130 		ret = os_snprintf(pos, end - pos, "%sWEP104",
1131 				  first ? "" : "+");
1132 		if (ret < 0 || ret >= end - pos)
1133 			return pos;
1134 		pos += ret;
1135 		first = 0;
1136 	}
1137 	if (cipher & WPA_CIPHER_TKIP) {
1138 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
1139 		if (ret < 0 || ret >= end - pos)
1140 			return pos;
1141 		pos += ret;
1142 		first = 0;
1143 	}
1144 	if (cipher & WPA_CIPHER_CCMP) {
1145 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
1146 		if (ret < 0 || ret >= end - pos)
1147 			return pos;
1148 		pos += ret;
1149 		first = 0;
1150 	}
1151 	return pos;
1152 }
1153 
1154 
wpa_supplicant_ie_txt(char * pos,char * end,const char * proto,const u8 * ie,size_t ie_len)1155 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1156 				    const u8 *ie, size_t ie_len)
1157 {
1158 	struct wpa_ie_data data;
1159 	int first, ret;
1160 
1161 	ret = os_snprintf(pos, end - pos, "[%s-", proto);
1162 	if (ret < 0 || ret >= end - pos)
1163 		return pos;
1164 	pos += ret;
1165 
1166 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1167 		ret = os_snprintf(pos, end - pos, "?]");
1168 		if (ret < 0 || ret >= end - pos)
1169 			return pos;
1170 		pos += ret;
1171 		return pos;
1172 	}
1173 
1174 	first = 1;
1175 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1176 		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
1177 		if (ret < 0 || ret >= end - pos)
1178 			return pos;
1179 		pos += ret;
1180 		first = 0;
1181 	}
1182 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
1183 		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1184 		if (ret < 0 || ret >= end - pos)
1185 			return pos;
1186 		pos += ret;
1187 		first = 0;
1188 	}
1189 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1190 		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1191 		if (ret < 0 || ret >= end - pos)
1192 			return pos;
1193 		pos += ret;
1194 		first = 0;
1195 	}
1196 #ifdef CONFIG_IEEE80211R
1197 	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1198 		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1199 				  first ? "" : "+");
1200 		if (ret < 0 || ret >= end - pos)
1201 			return pos;
1202 		pos += ret;
1203 		first = 0;
1204 	}
1205 	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1206 		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1207 				  first ? "" : "+");
1208 		if (ret < 0 || ret >= end - pos)
1209 			return pos;
1210 		pos += ret;
1211 		first = 0;
1212 	}
1213 #endif /* CONFIG_IEEE80211R */
1214 #ifdef CONFIG_IEEE80211W
1215 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1216 		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1217 				  first ? "" : "+");
1218 		if (ret < 0 || ret >= end - pos)
1219 			return pos;
1220 		pos += ret;
1221 		first = 0;
1222 	}
1223 	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1224 		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1225 				  first ? "" : "+");
1226 		if (ret < 0 || ret >= end - pos)
1227 			return pos;
1228 		pos += ret;
1229 		first = 0;
1230 	}
1231 #endif /* CONFIG_IEEE80211W */
1232 
1233 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1234 
1235 	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1236 		ret = os_snprintf(pos, end - pos, "-preauth");
1237 		if (ret < 0 || ret >= end - pos)
1238 			return pos;
1239 		pos += ret;
1240 	}
1241 
1242 	ret = os_snprintf(pos, end - pos, "]");
1243 	if (ret < 0 || ret >= end - pos)
1244 		return pos;
1245 	pos += ret;
1246 
1247 	return pos;
1248 }
1249 
1250 
1251 #ifdef CONFIG_WPS
wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant * wpa_s,char * pos,char * end,struct wpabuf * wps_ie)1252 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1253 					    char *pos, char *end,
1254 					    struct wpabuf *wps_ie)
1255 {
1256 	int ret;
1257 	const char *txt;
1258 
1259 	if (wps_ie == NULL)
1260 		return pos;
1261 	if (wps_is_selected_pbc_registrar(wps_ie))
1262 		txt = "[WPS-PBC]";
1263 #ifdef CONFIG_WPS2
1264 	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
1265 		txt = "[WPS-AUTH]";
1266 #endif /* CONFIG_WPS2 */
1267 	else if (wps_is_selected_pin_registrar(wps_ie))
1268 		txt = "[WPS-PIN]";
1269 	else
1270 		txt = "[WPS]";
1271 
1272 	ret = os_snprintf(pos, end - pos, "%s", txt);
1273 	if (ret >= 0 && ret < end - pos)
1274 		pos += ret;
1275 	wpabuf_free(wps_ie);
1276 	return pos;
1277 }
1278 #endif /* CONFIG_WPS */
1279 
1280 
wpa_supplicant_wps_ie_txt(struct wpa_supplicant * wpa_s,char * pos,char * end,const struct wpa_bss * bss)1281 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
1282 					char *pos, char *end,
1283 					const struct wpa_bss *bss)
1284 {
1285 #ifdef CONFIG_WPS
1286 	struct wpabuf *wps_ie;
1287 	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1288 	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
1289 #else /* CONFIG_WPS */
1290 	return pos;
1291 #endif /* CONFIG_WPS */
1292 }
1293 
1294 
1295 /* 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)1296 static int wpa_supplicant_ctrl_iface_scan_result(
1297 	struct wpa_supplicant *wpa_s,
1298 	const struct wpa_bss *bss, char *buf, size_t buflen)
1299 {
1300 	char *pos, *end;
1301 	int ret;
1302 	const u8 *ie, *ie2, *p2p;
1303 
1304 	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
1305 	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
1306 	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
1307 	    0)
1308 		return 0; /* Do not show P2P listen discovery results here */
1309 
1310 	pos = buf;
1311 	end = buf + buflen;
1312 
1313 	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
1314 			  MAC2STR(bss->bssid), bss->freq, bss->level);
1315 	if (ret < 0 || ret >= end - pos)
1316 		return -1;
1317 	pos += ret;
1318 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1319 	if (ie)
1320 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1321 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1322 	if (ie2)
1323 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1324 	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
1325 	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1326 		ret = os_snprintf(pos, end - pos, "[WEP]");
1327 		if (ret < 0 || ret >= end - pos)
1328 			return -1;
1329 		pos += ret;
1330 	}
1331 	if (bss->caps & IEEE80211_CAP_IBSS) {
1332 		ret = os_snprintf(pos, end - pos, "[IBSS]");
1333 		if (ret < 0 || ret >= end - pos)
1334 			return -1;
1335 		pos += ret;
1336 	}
1337 	if (bss->caps & IEEE80211_CAP_ESS) {
1338 		ret = os_snprintf(pos, end - pos, "[ESS]");
1339 		if (ret < 0 || ret >= end - pos)
1340 			return -1;
1341 		pos += ret;
1342 	}
1343 	if (p2p) {
1344 		ret = os_snprintf(pos, end - pos, "[P2P]");
1345 		if (ret < 0 || ret >= end - pos)
1346 			return -1;
1347 		pos += ret;
1348 	}
1349 
1350 	ret = os_snprintf(pos, end - pos, "\t%s",
1351 			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
1352 	if (ret < 0 || ret >= end - pos)
1353 		return -1;
1354 	pos += ret;
1355 
1356 	ret = os_snprintf(pos, end - pos, "\n");
1357 	if (ret < 0 || ret >= end - pos)
1358 		return -1;
1359 	pos += ret;
1360 
1361 	return pos - buf;
1362 }
1363 
1364 
wpa_supplicant_ctrl_iface_scan_results(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1365 static int wpa_supplicant_ctrl_iface_scan_results(
1366 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1367 {
1368 	char *pos, *end;
1369 	struct wpa_bss *bss;
1370 	int ret;
1371 
1372 	pos = buf;
1373 	end = buf + buflen;
1374 	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
1375 			  "flags / ssid\n");
1376 	if (ret < 0 || ret >= end - pos)
1377 		return pos - buf;
1378 	pos += ret;
1379 
1380 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1381 		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
1382 							    end - pos);
1383 		if (ret < 0 || ret >= end - pos)
1384 			return pos - buf;
1385 		pos += ret;
1386 	}
1387 
1388 	return pos - buf;
1389 }
1390 
1391 
wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant * wpa_s,char * cmd)1392 static int wpa_supplicant_ctrl_iface_select_network(
1393 	struct wpa_supplicant *wpa_s, char *cmd)
1394 {
1395 	int id;
1396 	struct wpa_ssid *ssid;
1397 
1398 	/* cmd: "<network id>" or "any" */
1399 	if (os_strcmp(cmd, "any") == 0) {
1400 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
1401 		ssid = NULL;
1402 	} else {
1403 		id = atoi(cmd);
1404 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
1405 
1406 		ssid = wpa_config_get_network(wpa_s->conf, id);
1407 		if (ssid == NULL) {
1408 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1409 				   "network id=%d", id);
1410 			return -1;
1411 		}
1412 		if (ssid->disabled == 2) {
1413 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1414 				   "SELECT_NETWORK with persistent P2P group");
1415 			return -1;
1416 		}
1417 	}
1418 
1419 	wpa_supplicant_select_network(wpa_s, ssid);
1420 
1421 	return 0;
1422 }
1423 
1424 
wpa_supplicant_ctrl_iface_enable_network(struct wpa_supplicant * wpa_s,char * cmd)1425 static int wpa_supplicant_ctrl_iface_enable_network(
1426 	struct wpa_supplicant *wpa_s, char *cmd)
1427 {
1428 	int id;
1429 	struct wpa_ssid *ssid;
1430 
1431 	/* cmd: "<network id>" or "all" */
1432 	if (os_strcmp(cmd, "all") == 0) {
1433 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
1434 		ssid = NULL;
1435 	} else {
1436 		id = atoi(cmd);
1437 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
1438 
1439 		ssid = wpa_config_get_network(wpa_s->conf, id);
1440 		if (ssid == NULL) {
1441 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1442 				   "network id=%d", id);
1443 			return -1;
1444 		}
1445 		if (ssid->disabled == 2) {
1446 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1447 				   "ENABLE_NETWORK with persistent P2P group");
1448 			return -1;
1449 		}
1450 	}
1451 	wpa_supplicant_enable_network(wpa_s, ssid);
1452 
1453 	return 0;
1454 }
1455 
1456 
wpa_supplicant_ctrl_iface_disable_network(struct wpa_supplicant * wpa_s,char * cmd)1457 static int wpa_supplicant_ctrl_iface_disable_network(
1458 	struct wpa_supplicant *wpa_s, char *cmd)
1459 {
1460 	int id;
1461 	struct wpa_ssid *ssid;
1462 
1463 	/* cmd: "<network id>" or "all" */
1464 	if (os_strcmp(cmd, "all") == 0) {
1465 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
1466 		ssid = NULL;
1467 	} else {
1468 		id = atoi(cmd);
1469 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
1470 
1471 		ssid = wpa_config_get_network(wpa_s->conf, id);
1472 		if (ssid == NULL) {
1473 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1474 				   "network id=%d", id);
1475 			return -1;
1476 		}
1477 		if (ssid->disabled == 2) {
1478 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1479 				   "DISABLE_NETWORK with persistent P2P "
1480 				   "group");
1481 			return -1;
1482 		}
1483 	}
1484 	wpa_supplicant_disable_network(wpa_s, ssid);
1485 
1486 	return 0;
1487 }
1488 
1489 
wpa_supplicant_ctrl_iface_add_network(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1490 static int wpa_supplicant_ctrl_iface_add_network(
1491 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1492 {
1493 	struct wpa_ssid *ssid;
1494 	int ret;
1495 
1496 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1497 
1498 	ssid = wpa_config_add_network(wpa_s->conf);
1499 	if (ssid == NULL)
1500 		return -1;
1501 
1502 	wpas_notify_network_added(wpa_s, ssid);
1503 
1504 	ssid->disabled = 1;
1505 	wpa_config_set_network_defaults(ssid);
1506 
1507 	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1508 	if (ret < 0 || (size_t) ret >= buflen)
1509 		return -1;
1510 	return ret;
1511 }
1512 
1513 
wpa_supplicant_ctrl_iface_remove_network(struct wpa_supplicant * wpa_s,char * cmd)1514 static int wpa_supplicant_ctrl_iface_remove_network(
1515 	struct wpa_supplicant *wpa_s, char *cmd)
1516 {
1517 	int id;
1518 	struct wpa_ssid *ssid;
1519 
1520 	/* cmd: "<network id>" or "all" */
1521 	if (os_strcmp(cmd, "all") == 0) {
1522 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1523 		ssid = wpa_s->conf->ssid;
1524 		while (ssid) {
1525 			struct wpa_ssid *remove_ssid = ssid;
1526 			id = ssid->id;
1527 			ssid = ssid->next;
1528 			wpas_notify_network_removed(wpa_s, remove_ssid);
1529 			wpa_config_remove_network(wpa_s->conf, id);
1530 		}
1531 		if (wpa_s->current_ssid) {
1532 			eapol_sm_invalidate_cached_session(wpa_s->eapol);
1533 			wpa_sm_set_config(wpa_s->wpa, NULL);
1534 			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1535 			wpa_supplicant_disassociate(wpa_s,
1536 				                    WLAN_REASON_DEAUTH_LEAVING);
1537 		}
1538 		return 0;
1539 	}
1540 
1541 	id = atoi(cmd);
1542 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1543 
1544 	ssid = wpa_config_get_network(wpa_s->conf, id);
1545 	if (ssid == NULL ||
1546 	    wpa_config_remove_network(wpa_s->conf, id) < 0) {
1547 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1548 			   "id=%d", id);
1549 		return -1;
1550 	}
1551 
1552 	if (ssid == wpa_s->current_ssid) {
1553 		/*
1554 		 * Invalidate the EAP session cache if the current network is
1555 		 * removed.
1556 		 */
1557 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1558 		wpa_sm_set_config(wpa_s->wpa, NULL);
1559 		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1560 
1561 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1562 	}
1563 
1564 	return 0;
1565 }
1566 
1567 
wpa_supplicant_ctrl_iface_set_network(struct wpa_supplicant * wpa_s,char * cmd)1568 static int wpa_supplicant_ctrl_iface_set_network(
1569 	struct wpa_supplicant *wpa_s, char *cmd)
1570 {
1571 	int id;
1572 	struct wpa_ssid *ssid;
1573 	char *name, *value;
1574 
1575 	/* cmd: "<network id> <variable name> <value>" */
1576 	name = os_strchr(cmd, ' ');
1577 	if (name == NULL)
1578 		return -1;
1579 	*name++ = '\0';
1580 
1581 	value = os_strchr(name, ' ');
1582 	if (value == NULL)
1583 		return -1;
1584 	*value++ = '\0';
1585 
1586 	id = atoi(cmd);
1587 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1588 		   id, name);
1589 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1590 			      (u8 *) value, os_strlen(value));
1591 
1592 	ssid = wpa_config_get_network(wpa_s->conf, id);
1593 	if (ssid == NULL) {
1594 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1595 			   "id=%d", id);
1596 		return -1;
1597 	}
1598 
1599 	if (wpa_config_set(ssid, name, value, 0) < 0) {
1600 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1601 			   "variable '%s'", name);
1602 		return -1;
1603 	}
1604 
1605 	if (wpa_s->current_ssid == ssid) {
1606 		/*
1607 		 * Invalidate the EAP session cache if anything in the current
1608 		 * configuration changes.
1609 		 */
1610 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1611 	}
1612 
1613 	if ((os_strcmp(name, "psk") == 0 &&
1614 	     value[0] == '"' && ssid->ssid_len) ||
1615 	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1616 		wpa_config_update_psk(ssid);
1617 	else if (os_strcmp(name, "priority") == 0)
1618 		wpa_config_update_prio_list(wpa_s->conf);
1619 
1620 	return 0;
1621 }
1622 
1623 
wpa_supplicant_ctrl_iface_get_network(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1624 static int wpa_supplicant_ctrl_iface_get_network(
1625 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1626 {
1627 	int id;
1628 	size_t res;
1629 	struct wpa_ssid *ssid;
1630 	char *name, *value;
1631 
1632 	/* cmd: "<network id> <variable name>" */
1633 	name = os_strchr(cmd, ' ');
1634 	if (name == NULL || buflen == 0)
1635 		return -1;
1636 	*name++ = '\0';
1637 
1638 	id = atoi(cmd);
1639 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1640 		   id, name);
1641 
1642 	ssid = wpa_config_get_network(wpa_s->conf, id);
1643 	if (ssid == NULL) {
1644 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1645 			   "id=%d", id);
1646 		return -1;
1647 	}
1648 
1649 	value = wpa_config_get_no_key(ssid, name);
1650 	if (value == NULL) {
1651 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1652 			   "variable '%s'", name);
1653 		return -1;
1654 	}
1655 
1656 	res = os_strlcpy(buf, value, buflen);
1657 	if (res >= buflen) {
1658 		os_free(value);
1659 		return -1;
1660 	}
1661 
1662 	os_free(value);
1663 
1664 	return res;
1665 }
1666 
1667 
1668 #ifndef CONFIG_NO_CONFIG_WRITE
wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant * wpa_s)1669 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1670 {
1671 	int ret;
1672 
1673 	if (!wpa_s->conf->update_config) {
1674 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1675 			   "to update configuration (update_config=0)");
1676 		return -1;
1677 	}
1678 
1679 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1680 	if (ret) {
1681 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1682 			   "update configuration");
1683 	} else {
1684 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1685 			   " updated");
1686 	}
1687 
1688 	return ret;
1689 }
1690 #endif /* CONFIG_NO_CONFIG_WRITE */
1691 
1692 
ctrl_iface_get_capability_pairwise(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1693 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1694 					      struct wpa_driver_capa *capa,
1695 					      char *buf, size_t buflen)
1696 {
1697 	int ret, first = 1;
1698 	char *pos, *end;
1699 	size_t len;
1700 
1701 	pos = buf;
1702 	end = pos + buflen;
1703 
1704 	if (res < 0) {
1705 		if (strict)
1706 			return 0;
1707 		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1708 		if (len >= buflen)
1709 			return -1;
1710 		return len;
1711 	}
1712 
1713 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1714 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1715 		if (ret < 0 || ret >= end - pos)
1716 			return pos - buf;
1717 		pos += ret;
1718 		first = 0;
1719 	}
1720 
1721 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1722 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1723 		if (ret < 0 || ret >= end - pos)
1724 			return pos - buf;
1725 		pos += ret;
1726 		first = 0;
1727 	}
1728 
1729 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1730 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1731 		if (ret < 0 || ret >= end - pos)
1732 			return pos - buf;
1733 		pos += ret;
1734 		first = 0;
1735 	}
1736 
1737 	return pos - buf;
1738 }
1739 
1740 
ctrl_iface_get_capability_group(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1741 static int ctrl_iface_get_capability_group(int res, char *strict,
1742 					   struct wpa_driver_capa *capa,
1743 					   char *buf, size_t buflen)
1744 {
1745 	int ret, first = 1;
1746 	char *pos, *end;
1747 	size_t len;
1748 
1749 	pos = buf;
1750 	end = pos + buflen;
1751 
1752 	if (res < 0) {
1753 		if (strict)
1754 			return 0;
1755 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1756 		if (len >= buflen)
1757 			return -1;
1758 		return len;
1759 	}
1760 
1761 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1762 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1763 		if (ret < 0 || ret >= end - pos)
1764 			return pos - buf;
1765 		pos += ret;
1766 		first = 0;
1767 	}
1768 
1769 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1770 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1771 		if (ret < 0 || ret >= end - pos)
1772 			return pos - buf;
1773 		pos += ret;
1774 		first = 0;
1775 	}
1776 
1777 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1778 		ret = os_snprintf(pos, end - pos, "%sWEP104",
1779 				  first ? "" : " ");
1780 		if (ret < 0 || ret >= end - pos)
1781 			return pos - buf;
1782 		pos += ret;
1783 		first = 0;
1784 	}
1785 
1786 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1787 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1788 		if (ret < 0 || ret >= end - pos)
1789 			return pos - buf;
1790 		pos += ret;
1791 		first = 0;
1792 	}
1793 
1794 	return pos - buf;
1795 }
1796 
1797 
ctrl_iface_get_capability_key_mgmt(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1798 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1799 					      struct wpa_driver_capa *capa,
1800 					      char *buf, size_t buflen)
1801 {
1802 	int ret;
1803 	char *pos, *end;
1804 	size_t len;
1805 
1806 	pos = buf;
1807 	end = pos + buflen;
1808 
1809 	if (res < 0) {
1810 		if (strict)
1811 			return 0;
1812 		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1813 				 "NONE", buflen);
1814 		if (len >= buflen)
1815 			return -1;
1816 		return len;
1817 	}
1818 
1819 	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1820 	if (ret < 0 || ret >= end - pos)
1821 		return pos - buf;
1822 	pos += ret;
1823 
1824 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1825 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1826 		ret = os_snprintf(pos, end - pos, " WPA-EAP");
1827 		if (ret < 0 || ret >= end - pos)
1828 			return pos - buf;
1829 		pos += ret;
1830 	}
1831 
1832 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1833 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1834 		ret = os_snprintf(pos, end - pos, " WPA-PSK");
1835 		if (ret < 0 || ret >= end - pos)
1836 			return pos - buf;
1837 		pos += ret;
1838 	}
1839 
1840 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1841 		ret = os_snprintf(pos, end - pos, " WPA-NONE");
1842 		if (ret < 0 || ret >= end - pos)
1843 			return pos - buf;
1844 		pos += ret;
1845 	}
1846 
1847 	return pos - buf;
1848 }
1849 
1850 
ctrl_iface_get_capability_proto(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1851 static int ctrl_iface_get_capability_proto(int res, char *strict,
1852 					   struct wpa_driver_capa *capa,
1853 					   char *buf, size_t buflen)
1854 {
1855 	int ret, first = 1;
1856 	char *pos, *end;
1857 	size_t len;
1858 
1859 	pos = buf;
1860 	end = pos + buflen;
1861 
1862 	if (res < 0) {
1863 		if (strict)
1864 			return 0;
1865 		len = os_strlcpy(buf, "RSN WPA", buflen);
1866 		if (len >= buflen)
1867 			return -1;
1868 		return len;
1869 	}
1870 
1871 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1872 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1873 		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1874 		if (ret < 0 || ret >= end - pos)
1875 			return pos - buf;
1876 		pos += ret;
1877 		first = 0;
1878 	}
1879 
1880 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1881 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1882 		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1883 		if (ret < 0 || ret >= end - pos)
1884 			return pos - buf;
1885 		pos += ret;
1886 		first = 0;
1887 	}
1888 
1889 	return pos - buf;
1890 }
1891 
1892 
ctrl_iface_get_capability_auth_alg(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1893 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1894 					      struct wpa_driver_capa *capa,
1895 					      char *buf, size_t buflen)
1896 {
1897 	int ret, first = 1;
1898 	char *pos, *end;
1899 	size_t len;
1900 
1901 	pos = buf;
1902 	end = pos + buflen;
1903 
1904 	if (res < 0) {
1905 		if (strict)
1906 			return 0;
1907 		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1908 		if (len >= buflen)
1909 			return -1;
1910 		return len;
1911 	}
1912 
1913 	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1914 		ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1915 		if (ret < 0 || ret >= end - pos)
1916 			return pos - buf;
1917 		pos += ret;
1918 		first = 0;
1919 	}
1920 
1921 	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1922 		ret = os_snprintf(pos, end - pos, "%sSHARED",
1923 				  first ? "" : " ");
1924 		if (ret < 0 || ret >= end - pos)
1925 			return pos - buf;
1926 		pos += ret;
1927 		first = 0;
1928 	}
1929 
1930 	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1931 		ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1932 		if (ret < 0 || ret >= end - pos)
1933 			return pos - buf;
1934 		pos += ret;
1935 		first = 0;
1936 	}
1937 
1938 	return pos - buf;
1939 }
1940 
1941 
wpa_supplicant_ctrl_iface_get_capability(struct wpa_supplicant * wpa_s,const char * _field,char * buf,size_t buflen)1942 static int wpa_supplicant_ctrl_iface_get_capability(
1943 	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1944 	size_t buflen)
1945 {
1946 	struct wpa_driver_capa capa;
1947 	int res;
1948 	char *strict;
1949 	char field[30];
1950 	size_t len;
1951 
1952 	/* Determine whether or not strict checking was requested */
1953 	len = os_strlcpy(field, _field, sizeof(field));
1954 	if (len >= sizeof(field))
1955 		return -1;
1956 	strict = os_strchr(field, ' ');
1957 	if (strict != NULL) {
1958 		*strict++ = '\0';
1959 		if (os_strcmp(strict, "strict") != 0)
1960 			return -1;
1961 	}
1962 
1963 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1964 		field, strict ? strict : "");
1965 
1966 	if (os_strcmp(field, "eap") == 0) {
1967 		return eap_get_names(buf, buflen);
1968 	}
1969 
1970 	res = wpa_drv_get_capa(wpa_s, &capa);
1971 
1972 	if (os_strcmp(field, "pairwise") == 0)
1973 		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1974 							  buf, buflen);
1975 
1976 	if (os_strcmp(field, "group") == 0)
1977 		return ctrl_iface_get_capability_group(res, strict, &capa,
1978 						       buf, buflen);
1979 
1980 	if (os_strcmp(field, "key_mgmt") == 0)
1981 		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1982 							  buf, buflen);
1983 
1984 	if (os_strcmp(field, "proto") == 0)
1985 		return ctrl_iface_get_capability_proto(res, strict, &capa,
1986 						       buf, buflen);
1987 
1988 	if (os_strcmp(field, "auth_alg") == 0)
1989 		return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1990 							  buf, buflen);
1991 
1992 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1993 		   field);
1994 
1995 	return -1;
1996 }
1997 
1998 
wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)1999 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
2000 					 const char *cmd, char *buf,
2001 					 size_t buflen)
2002 {
2003 	u8 bssid[ETH_ALEN];
2004 	size_t i;
2005 	struct wpa_bss *bss;
2006 	int ret;
2007 	char *pos, *end;
2008 	const u8 *ie, *ie2;
2009 
2010 	if (os_strcmp(cmd, "FIRST") == 0)
2011 		bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
2012 	else if (os_strncmp(cmd, "ID-", 3) == 0) {
2013 		i = atoi(cmd + 3);
2014 		bss = wpa_bss_get_id(wpa_s, i);
2015 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2016 		i = atoi(cmd + 5);
2017 		bss = wpa_bss_get_id(wpa_s, i);
2018 		if (bss) {
2019 			struct dl_list *next = bss->list_id.next;
2020 			if (next == &wpa_s->bss_id)
2021 				bss = NULL;
2022 			else
2023 				bss = dl_list_entry(next, struct wpa_bss,
2024 						    list_id);
2025 		}
2026 	} else if (hwaddr_aton(cmd, bssid) == 0)
2027 		bss = wpa_bss_get_bssid(wpa_s, bssid);
2028 	else {
2029 		struct wpa_bss *tmp;
2030 		i = atoi(cmd);
2031 		bss = NULL;
2032 		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
2033 		{
2034 			if (i-- == 0) {
2035 				bss = tmp;
2036 				break;
2037 			}
2038 		}
2039 	}
2040 
2041 	if (bss == NULL)
2042 		return 0;
2043 
2044 	pos = buf;
2045 	end = buf + buflen;
2046 	ret = os_snprintf(pos, end - pos,
2047 			  "id=%u\n"
2048 			  "bssid=" MACSTR "\n"
2049 			  "freq=%d\n"
2050 			  "beacon_int=%d\n"
2051 			  "capabilities=0x%04x\n"
2052 			  "qual=%d\n"
2053 			  "noise=%d\n"
2054 			  "level=%d\n"
2055 			  "tsf=%016llu\n"
2056 			  "ie=",
2057 			  bss->id,
2058 			  MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
2059 			  bss->caps, bss->qual, bss->noise, bss->level,
2060 			  (unsigned long long) bss->tsf);
2061 	if (ret < 0 || ret >= end - pos)
2062 		return pos - buf;
2063 	pos += ret;
2064 
2065 	ie = (const u8 *) (bss + 1);
2066 	for (i = 0; i < bss->ie_len; i++) {
2067 		ret = os_snprintf(pos, end - pos, "%02x", *ie++);
2068 		if (ret < 0 || ret >= end - pos)
2069 			return pos - buf;
2070 		pos += ret;
2071 	}
2072 	if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
2073 		ret = os_snprintf(pos, end - pos, "[P2P]");
2074 		if (ret < 0 || ret >= end - pos)
2075 			return pos - buf;
2076 		pos += ret;
2077 	}
2078 
2079 	ret = os_snprintf(pos, end - pos, "\n");
2080 	if (ret < 0 || ret >= end - pos)
2081 		return pos - buf;
2082 	pos += ret;
2083 
2084 	ret = os_snprintf(pos, end - pos, "flags=");
2085 	if (ret < 0 || ret >= end - pos)
2086 		return pos - buf;
2087 	pos += ret;
2088 
2089 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2090 	if (ie)
2091 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2092 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2093 	if (ie2)
2094 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2095 	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2096 	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2097 		ret = os_snprintf(pos, end - pos, "[WEP]");
2098 		if (ret < 0 || ret >= end - pos)
2099 			return pos - buf;
2100 		pos += ret;
2101 	}
2102 	if (bss->caps & IEEE80211_CAP_IBSS) {
2103 		ret = os_snprintf(pos, end - pos, "[IBSS]");
2104 		if (ret < 0 || ret >= end - pos)
2105 			return pos - buf;
2106 		pos += ret;
2107 	}
2108 	if (bss->caps & IEEE80211_CAP_ESS) {
2109 		ret = os_snprintf(pos, end - pos, "[ESS]");
2110 		if (ret < 0 || ret >= end - pos)
2111 			return pos - buf;
2112 		pos += ret;
2113 	}
2114 
2115 	ret = os_snprintf(pos, end - pos, "\n");
2116 	if (ret < 0 || ret >= end - pos)
2117 		return pos - buf;
2118 	pos += ret;
2119 
2120 	ret = os_snprintf(pos, end - pos, "ssid=%s\n",
2121 			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
2122 	if (ret < 0 || ret >= end - pos)
2123 		return pos - buf;
2124 	pos += ret;
2125 
2126 #ifdef CONFIG_WPS
2127 	ie = (const u8 *) (bss + 1);
2128 	ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
2129 	if (ret < 0 || ret >= end - pos)
2130 		return pos - buf;
2131 	pos += ret;
2132 #endif /* CONFIG_WPS */
2133 
2134 #ifdef CONFIG_P2P
2135 	ie = (const u8 *) (bss + 1);
2136 	ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
2137 	if (ret < 0 || ret >= end - pos)
2138 		return pos - buf;
2139 	pos += ret;
2140 #endif /* CONFIG_P2P */
2141 
2142 	return pos - buf;
2143 }
2144 
2145 
wpa_supplicant_ctrl_iface_ap_scan(struct wpa_supplicant * wpa_s,char * cmd)2146 static int wpa_supplicant_ctrl_iface_ap_scan(
2147 	struct wpa_supplicant *wpa_s, char *cmd)
2148 {
2149 	int ap_scan = atoi(cmd);
2150 	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
2151 }
2152 
2153 
wpa_supplicant_ctrl_iface_scan_interval(struct wpa_supplicant * wpa_s,char * cmd)2154 static int wpa_supplicant_ctrl_iface_scan_interval(
2155 	struct wpa_supplicant *wpa_s, char *cmd)
2156 {
2157 	int scan_int = atoi(cmd);
2158 	if (scan_int < 0)
2159 		return -1;
2160 	wpa_s->scan_interval = scan_int;
2161 	return 0;
2162 }
2163 
2164 
wpa_supplicant_ctrl_iface_bss_expire_age(struct wpa_supplicant * wpa_s,char * cmd)2165 static int wpa_supplicant_ctrl_iface_bss_expire_age(
2166 	struct wpa_supplicant *wpa_s, char *cmd)
2167 {
2168 	int expire_age = atoi(cmd);
2169 	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
2170 }
2171 
2172 
wpa_supplicant_ctrl_iface_bss_expire_count(struct wpa_supplicant * wpa_s,char * cmd)2173 static int wpa_supplicant_ctrl_iface_bss_expire_count(
2174 	struct wpa_supplicant *wpa_s, char *cmd)
2175 {
2176 	int expire_count = atoi(cmd);
2177 	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
2178 }
2179 
2180 
wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant * wpa_s)2181 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
2182 {
2183 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
2184 	/* MLME-DELETEKEYS.request */
2185 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
2186 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
2187 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
2188 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
2189 #ifdef CONFIG_IEEE80211W
2190 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
2191 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
2192 #endif /* CONFIG_IEEE80211W */
2193 
2194 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
2195 			0);
2196 	/* MLME-SETPROTECTION.request(None) */
2197 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
2198 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
2199 				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
2200 	wpa_sm_drop_sa(wpa_s->wpa);
2201 }
2202 
2203 
wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant * wpa_s,char * addr)2204 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
2205 					  char *addr)
2206 {
2207 	u8 bssid[ETH_ALEN];
2208 	struct wpa_bss *bss;
2209 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2210 
2211 	if (hwaddr_aton(addr, bssid)) {
2212 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
2213 			   "address '%s'", addr);
2214 		return -1;
2215 	}
2216 
2217 	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
2218 
2219 	bss = wpa_bss_get_bssid(wpa_s, bssid);
2220 	if (!bss) {
2221 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
2222 			   "from BSS table");
2223 		return -1;
2224 	}
2225 
2226 	/*
2227 	 * TODO: Find best network configuration block from configuration to
2228 	 * allow roaming to other networks
2229 	 */
2230 
2231 	if (!ssid) {
2232 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
2233 			   "configuration known for the target AP");
2234 		return -1;
2235 	}
2236 
2237 	wpa_s->reassociate = 1;
2238 	wpa_supplicant_connect(wpa_s, bss, ssid);
2239 
2240 	return 0;
2241 }
2242 
2243 
2244 #ifdef CONFIG_P2P
p2p_ctrl_find(struct wpa_supplicant * wpa_s,char * cmd)2245 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
2246 {
2247 	unsigned int timeout = atoi(cmd);
2248 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
2249 
2250 	if (os_strstr(cmd, "type=social"))
2251 		type = P2P_FIND_ONLY_SOCIAL;
2252 	else if (os_strstr(cmd, "type=progressive"))
2253 		type = P2P_FIND_PROGRESSIVE;
2254 
2255 	return wpas_p2p_find(wpa_s, timeout, type, 0, NULL);
2256 }
2257 
2258 
p2p_ctrl_connect(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2259 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
2260 			    char *buf, size_t buflen)
2261 {
2262 	u8 addr[ETH_ALEN];
2263 	char *pos, *pos2;
2264 	char *pin = NULL;
2265 	enum p2p_wps_method wps_method;
2266 	int new_pin;
2267 	int ret;
2268 	int persistent_group;
2269 	int join;
2270 	int auth;
2271 	int go_intent = -1;
2272 	int freq = 0;
2273 
2274 	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent]
2275 	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
2276 
2277 	if (hwaddr_aton(cmd, addr))
2278 		return -1;
2279 
2280 	pos = cmd + 17;
2281 	if (*pos != ' ')
2282 		return -1;
2283 	pos++;
2284 
2285 	persistent_group = os_strstr(pos, " persistent") != NULL;
2286 	join = os_strstr(pos, " join") != NULL;
2287 	auth = os_strstr(pos, " auth") != NULL;
2288 
2289 	pos2 = os_strstr(pos, " go_intent=");
2290 	if (pos2) {
2291 		pos2 += 11;
2292 		go_intent = atoi(pos2);
2293 		if (go_intent < 0 || go_intent > 15)
2294 			return -1;
2295 	}
2296 
2297 	pos2 = os_strstr(pos, " freq=");
2298 	if (pos2) {
2299 		pos2 += 6;
2300 		freq = atoi(pos2);
2301 		if (freq <= 0)
2302 			return -1;
2303 	}
2304 
2305 	if (os_strncmp(pos, "pin", 3) == 0) {
2306 		/* Request random PIN (to be displayed) and enable the PIN */
2307 		wps_method = WPS_PIN_DISPLAY;
2308 	} else if (os_strncmp(pos, "pbc", 3) == 0) {
2309 		wps_method = WPS_PBC;
2310 	} else {
2311 		pin = pos;
2312 		pos = os_strchr(pin, ' ');
2313 		wps_method = WPS_PIN_KEYPAD;
2314 		if (pos) {
2315 			*pos++ = '\0';
2316 			if (os_strncmp(pos, "label", 5) == 0)
2317 				wps_method = WPS_PIN_LABEL;
2318 			else if (os_strncmp(pos, "display", 7) == 0)
2319 				wps_method = WPS_PIN_DISPLAY;
2320 		}
2321 	}
2322 
2323 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
2324 				   persistent_group, join, auth, go_intent,
2325 				   freq);
2326 	if (new_pin == -2) {
2327 		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
2328 		return 25;
2329 	}
2330 	if (new_pin == -3) {
2331 		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
2332 		return 25;
2333 	}
2334 	if (new_pin < 0)
2335 		return -1;
2336 	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
2337 		ret = os_snprintf(buf, buflen, "%08d", new_pin);
2338 		if (ret < 0 || (size_t) ret >= buflen)
2339 			return -1;
2340 		return ret;
2341 	}
2342 
2343 	os_memcpy(buf, "OK\n", 3);
2344 	return 3;
2345 }
2346 
2347 
p2p_ctrl_listen(struct wpa_supplicant * wpa_s,char * cmd)2348 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
2349 {
2350 	unsigned int timeout = atoi(cmd);
2351 	return wpas_p2p_listen(wpa_s, timeout);
2352 }
2353 
2354 
p2p_ctrl_prov_disc(struct wpa_supplicant * wpa_s,char * cmd)2355 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
2356 {
2357 	u8 addr[ETH_ALEN];
2358 	char *pos;
2359 
2360 	/* <addr> <config method> */
2361 
2362 	if (hwaddr_aton(cmd, addr))
2363 		return -1;
2364 
2365 	pos = cmd + 17;
2366 	if (*pos != ' ')
2367 		return -1;
2368 	pos++;
2369 
2370 	return wpas_p2p_prov_disc(wpa_s, addr, pos);
2371 }
2372 
2373 
p2p_get_passphrase(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)2374 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
2375 			      size_t buflen)
2376 {
2377 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2378 
2379 #ifdef ANDROID_BRCM_P2P_PATCH
2380 	struct wpa_supplicant *ifs = NULL;
2381 
2382 	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
2383 		if((ifs->ap_iface) &&
2384 			(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO)) {
2385 			ssid = ifs->current_ssid;
2386 		}
2387 	}
2388 #endif
2389 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
2390 	    ssid->passphrase == NULL)
2391 		return -1;
2392 
2393 	os_strlcpy(buf, ssid->passphrase, buflen);
2394 	return os_strlen(buf);
2395 }
2396 
2397 
p2p_ctrl_serv_disc_req(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2398 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
2399 				  char *buf, size_t buflen)
2400 {
2401 	u64 ref;
2402 	int res;
2403 	u8 dst_buf[ETH_ALEN], *dst;
2404 	struct wpabuf *tlvs;
2405 	char *pos;
2406 	size_t len;
2407 
2408 	if (hwaddr_aton(cmd, dst_buf))
2409 		return -1;
2410 	dst = dst_buf;
2411 	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
2412 	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
2413 		dst = NULL;
2414 	pos = cmd + 17;
2415 	if (*pos != ' ')
2416 		return -1;
2417 	pos++;
2418 
2419 	if (os_strncmp(pos, "upnp ", 5) == 0) {
2420 		u8 version;
2421 		pos += 5;
2422 		if (hexstr2bin(pos, &version, 1) < 0)
2423 			return -1;
2424 		pos += 2;
2425 		if (*pos != ' ')
2426 			return -1;
2427 		pos++;
2428 		ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, dst,
2429 							       version, pos);
2430 	} else {
2431 		len = os_strlen(pos);
2432 		if (len & 1)
2433 			return -1;
2434 		len /= 2;
2435 		tlvs = wpabuf_alloc(len);
2436 		if (tlvs == NULL)
2437 			return -1;
2438 		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
2439 			wpabuf_free(tlvs);
2440 			return -1;
2441 		}
2442 
2443 		ref = (unsigned long) wpas_p2p_sd_request(wpa_s, dst, tlvs);
2444 		wpabuf_free(tlvs);
2445 	}
2446 	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
2447 	if (res < 0 || (unsigned) res >= buflen)
2448 		return -1;
2449 	return res;
2450 }
2451 
2452 
p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant * wpa_s,char * cmd)2453 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
2454 					 char *cmd)
2455 {
2456 	long long unsigned val;
2457 	u64 req;
2458 	if (sscanf(cmd, "%llx", &val) != 1)
2459 		return -1;
2460 	req = val;
2461 	return wpas_p2p_sd_cancel_request(wpa_s, (void *) (unsigned long) req);
2462 }
2463 
2464 
p2p_ctrl_serv_disc_resp(struct wpa_supplicant * wpa_s,char * cmd)2465 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
2466 {
2467 	int freq;
2468 	u8 dst[ETH_ALEN];
2469 	u8 dialog_token;
2470 	struct wpabuf *resp_tlvs;
2471 	char *pos, *pos2;
2472 	size_t len;
2473 
2474 	pos = os_strchr(cmd, ' ');
2475 	if (pos == NULL)
2476 		return -1;
2477 	*pos++ = '\0';
2478 	freq = atoi(cmd);
2479 	if (freq == 0)
2480 		return -1;
2481 
2482 	if (hwaddr_aton(pos, dst))
2483 		return -1;
2484 	pos += 17;
2485 	if (*pos != ' ')
2486 		return -1;
2487 	pos++;
2488 
2489 	pos2 = os_strchr(pos, ' ');
2490 	if (pos2 == NULL)
2491 		return -1;
2492 	*pos2++ = '\0';
2493 	dialog_token = atoi(pos);
2494 
2495 	len = os_strlen(pos2);
2496 	if (len & 1)
2497 		return -1;
2498 	len /= 2;
2499 	resp_tlvs = wpabuf_alloc(len);
2500 	if (resp_tlvs == NULL)
2501 		return -1;
2502 	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
2503 		wpabuf_free(resp_tlvs);
2504 		return -1;
2505 	}
2506 
2507 	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
2508 	wpabuf_free(resp_tlvs);
2509 	return 0;
2510 }
2511 
2512 
p2p_ctrl_serv_disc_external(struct wpa_supplicant * wpa_s,char * cmd)2513 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
2514 				       char *cmd)
2515 {
2516 	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
2517 	return 0;
2518 }
2519 
2520 
p2p_ctrl_service_add_bonjour(struct wpa_supplicant * wpa_s,char * cmd)2521 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
2522 					char *cmd)
2523 {
2524 	char *pos;
2525 	size_t len;
2526 	struct wpabuf *query, *resp;
2527 
2528 	pos = os_strchr(cmd, ' ');
2529 	if (pos == NULL)
2530 		return -1;
2531 	*pos++ = '\0';
2532 
2533 	len = os_strlen(cmd);
2534 	if (len & 1)
2535 		return -1;
2536 	len /= 2;
2537 	query = wpabuf_alloc(len);
2538 	if (query == NULL)
2539 		return -1;
2540 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2541 		wpabuf_free(query);
2542 		return -1;
2543 	}
2544 
2545 	len = os_strlen(pos);
2546 	if (len & 1) {
2547 		wpabuf_free(query);
2548 		return -1;
2549 	}
2550 	len /= 2;
2551 	resp = wpabuf_alloc(len);
2552 	if (resp == NULL) {
2553 		wpabuf_free(query);
2554 		return -1;
2555 	}
2556 	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
2557 		wpabuf_free(query);
2558 		wpabuf_free(resp);
2559 		return -1;
2560 	}
2561 
2562 	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
2563 		wpabuf_free(query);
2564 		wpabuf_free(resp);
2565 		return -1;
2566 	}
2567 	return 0;
2568 }
2569 
2570 
p2p_ctrl_service_add_upnp(struct wpa_supplicant * wpa_s,char * cmd)2571 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2572 {
2573 	char *pos;
2574 	u8 version;
2575 
2576 	pos = os_strchr(cmd, ' ');
2577 	if (pos == NULL)
2578 		return -1;
2579 	*pos++ = '\0';
2580 
2581 	if (hexstr2bin(cmd, &version, 1) < 0)
2582 		return -1;
2583 
2584 	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
2585 }
2586 
2587 
p2p_ctrl_service_add(struct wpa_supplicant * wpa_s,char * cmd)2588 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
2589 {
2590 	char *pos;
2591 
2592 	pos = os_strchr(cmd, ' ');
2593 	if (pos == NULL)
2594 		return -1;
2595 	*pos++ = '\0';
2596 
2597 	if (os_strcmp(cmd, "bonjour") == 0)
2598 		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
2599 	if (os_strcmp(cmd, "upnp") == 0)
2600 		return p2p_ctrl_service_add_upnp(wpa_s, pos);
2601 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2602 	return -1;
2603 }
2604 
2605 
p2p_ctrl_service_del_bonjour(struct wpa_supplicant * wpa_s,char * cmd)2606 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
2607 					char *cmd)
2608 {
2609 	size_t len;
2610 	struct wpabuf *query;
2611 	int ret;
2612 
2613 	len = os_strlen(cmd);
2614 	if (len & 1)
2615 		return -1;
2616 	len /= 2;
2617 	query = wpabuf_alloc(len);
2618 	if (query == NULL)
2619 		return -1;
2620 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2621 		wpabuf_free(query);
2622 		return -1;
2623 	}
2624 
2625 	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2626 	wpabuf_free(query);
2627 	return ret;
2628 }
2629 
2630 
p2p_ctrl_service_del_upnp(struct wpa_supplicant * wpa_s,char * cmd)2631 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2632 {
2633 	char *pos;
2634 	u8 version;
2635 
2636 	pos = os_strchr(cmd, ' ');
2637 	if (pos == NULL)
2638 		return -1;
2639 	*pos++ = '\0';
2640 
2641 	if (hexstr2bin(cmd, &version, 1) < 0)
2642 		return -1;
2643 
2644 	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
2645 }
2646 
2647 
p2p_ctrl_service_del(struct wpa_supplicant * wpa_s,char * cmd)2648 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
2649 {
2650 	char *pos;
2651 
2652 	pos = os_strchr(cmd, ' ');
2653 	if (pos == NULL)
2654 		return -1;
2655 	*pos++ = '\0';
2656 
2657 	if (os_strcmp(cmd, "bonjour") == 0)
2658 		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
2659 	if (os_strcmp(cmd, "upnp") == 0)
2660 		return p2p_ctrl_service_del_upnp(wpa_s, pos);
2661 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2662 	return -1;
2663 }
2664 
2665 
p2p_ctrl_reject(struct wpa_supplicant * wpa_s,char * cmd)2666 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
2667 {
2668 	u8 addr[ETH_ALEN];
2669 
2670 	/* <addr> */
2671 
2672 	if (hwaddr_aton(cmd, addr))
2673 		return -1;
2674 
2675 	return wpas_p2p_reject(wpa_s, addr);
2676 }
2677 
2678 
p2p_ctrl_invite_persistent(struct wpa_supplicant * wpa_s,char * cmd)2679 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
2680 {
2681 	char *pos;
2682 	int id;
2683 	struct wpa_ssid *ssid;
2684 	u8 peer[ETH_ALEN];
2685 
2686 	id = atoi(cmd);
2687 	pos = os_strstr(cmd, " peer=");
2688 	if (pos) {
2689 		pos += 6;
2690 		if (hwaddr_aton(pos, peer))
2691 			return -1;
2692 	}
2693 	ssid = wpa_config_get_network(wpa_s->conf, id);
2694 	if (ssid == NULL || ssid->disabled != 2) {
2695 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2696 			   "for persistent P2P group",
2697 			   id);
2698 		return -1;
2699 	}
2700 
2701 	return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
2702 }
2703 
2704 
p2p_ctrl_invite_group(struct wpa_supplicant * wpa_s,char * cmd)2705 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
2706 {
2707 	char *pos;
2708 	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
2709 
2710 	pos = os_strstr(cmd, " peer=");
2711 	if (!pos)
2712 		return -1;
2713 
2714 	*pos = '\0';
2715 	pos += 6;
2716 	if (hwaddr_aton(pos, peer)) {
2717 		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
2718 		return -1;
2719 	}
2720 
2721 	pos = os_strstr(pos, " go_dev_addr=");
2722 	if (pos) {
2723 		pos += 13;
2724 		if (hwaddr_aton(pos, go_dev_addr)) {
2725 			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
2726 				   pos);
2727 			return -1;
2728 		}
2729 		go_dev = go_dev_addr;
2730 	}
2731 
2732 	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
2733 }
2734 
2735 
p2p_ctrl_invite(struct wpa_supplicant * wpa_s,char * cmd)2736 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
2737 {
2738 	if (os_strncmp(cmd, "persistent=", 11) == 0)
2739 		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
2740 	if (os_strncmp(cmd, "group=", 6) == 0)
2741 		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
2742 
2743 	return -1;
2744 }
2745 
2746 
p2p_ctrl_group_add_persistent(struct wpa_supplicant * wpa_s,char * cmd,int freq)2747 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
2748 					 char *cmd, int freq)
2749 {
2750 	int id;
2751 	struct wpa_ssid *ssid;
2752 
2753 	id = atoi(cmd);
2754 	ssid = wpa_config_get_network(wpa_s->conf, id);
2755 	if (ssid == NULL || ssid->disabled != 2) {
2756 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2757 			   "for persistent P2P group",
2758 			   id);
2759 		return -1;
2760 	}
2761 
2762 	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
2763 }
2764 
2765 
p2p_ctrl_group_add(struct wpa_supplicant * wpa_s,char * cmd)2766 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
2767 {
2768 	int freq = 0;
2769 	char *pos;
2770 
2771 	pos = os_strstr(cmd, "freq=");
2772 	if (pos)
2773 		freq = atoi(pos + 5);
2774 
2775 	if (os_strncmp(cmd, "persistent=", 11) == 0)
2776 		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
2777 	if (os_strcmp(cmd, "persistent") == 0 ||
2778 	    os_strncmp(cmd, "persistent ", 11) == 0)
2779 		return wpas_p2p_group_add(wpa_s, 1, freq);
2780 	if (os_strncmp(cmd, "freq=", 5) == 0)
2781 		return wpas_p2p_group_add(wpa_s, 0, freq);
2782 
2783 	wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
2784 		   cmd);
2785 	return -1;
2786 }
2787 
2788 
p2p_ctrl_peer(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2789 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
2790 			 char *buf, size_t buflen)
2791 {
2792 	u8 addr[ETH_ALEN], *addr_ptr;
2793 	int next;
2794 
2795 	if (!wpa_s->global->p2p)
2796 		return -1;
2797 
2798 	if (os_strcmp(cmd, "FIRST") == 0) {
2799 		addr_ptr = NULL;
2800 		next = 0;
2801 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2802 		if (hwaddr_aton(cmd + 5, addr) < 0)
2803 			return -1;
2804 		addr_ptr = addr;
2805 		next = 1;
2806 	} else {
2807 		if (hwaddr_aton(cmd, addr) < 0)
2808 			return -1;
2809 		addr_ptr = addr;
2810 		next = 0;
2811 	}
2812 
2813 	return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next,
2814 				 buf, buflen);
2815 }
2816 
2817 #ifdef ANDROID_BRCM_P2P_PATCH
p2p_get_apif(struct wpa_supplicant * wpa_s)2818 struct wpa_supplicant* p2p_get_apif(struct wpa_supplicant* wpa_s)
2819 {
2820 	struct wpa_supplicant* iface;
2821 	for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
2822 		if (iface->ap_iface)
2823 			return iface;
2824 	return wpa_s;
2825 }
p2p_get_clientif(struct wpa_supplicant * wpa_s)2826 struct wpa_supplicant* p2p_get_clientif(struct wpa_supplicant* wpa_s)
2827 {
2828 	struct wpa_supplicant* iface;
2829 	for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
2830 		if (iface->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
2831 			return iface;
2832 	return wpa_s;
2833 }
2834 #endif
2835 
p2p_ctrl_set(struct wpa_supplicant * wpa_s,char * cmd)2836 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
2837 {
2838 	char *param;
2839 
2840 	if (wpa_s->global->p2p == NULL)
2841 		return -1;
2842 
2843 	param = os_strchr(cmd, ' ');
2844 	if (param == NULL)
2845 		return -1;
2846 	*param++ = '\0';
2847 
2848 	if (os_strcmp(cmd, "discoverability") == 0) {
2849 		p2p_set_client_discoverability(wpa_s->global->p2p,
2850 					       atoi(param));
2851 		return 0;
2852 	}
2853 
2854 	if (os_strcmp(cmd, "managed") == 0) {
2855 		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
2856 		return 0;
2857 	}
2858 
2859 	if (os_strcmp(cmd, "listen_channel") == 0) {
2860 		return p2p_set_listen_channel(wpa_s->global->p2p, 81,
2861 					      atoi(param));
2862 	}
2863 
2864 	if (os_strcmp(cmd, "ssid_postfix") == 0) {
2865 		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
2866 					    os_strlen(param));
2867 	}
2868 
2869 	if (os_strcmp(cmd, "noa") == 0) {
2870 		char *pos;
2871 		int count, start, duration;
2872 		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
2873 		count = atoi(param);
2874 		pos = os_strchr(param, ',');
2875 		if (pos == NULL)
2876 			return -1;
2877 		pos++;
2878 		start = atoi(pos);
2879 		pos = os_strchr(pos, ',');
2880 		if (pos == NULL)
2881 			return -1;
2882 		pos++;
2883 		duration = atoi(pos);
2884 		if (count < 0 || count > 255 || start < 0 || duration < 0)
2885 			return -1;
2886 		if (count == 0 && duration > 0)
2887 			return -1;
2888 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
2889 			   "start=%d duration=%d", count, start, duration);
2890 #ifdef ANDROID_BRCM_P2P_PATCH
2891 		return wpas_p2p_set_noa(p2p_get_apif(wpa_s), count, start, duration);
2892 #else
2893 		return wpas_p2p_set_noa(wpa_s, count, start, duration);
2894 #endif
2895 	}
2896 
2897 	if (os_strcmp(cmd, "ps") == 0)
2898 #ifdef ANDROID_BRCM_P2P_PATCH
2899 		return wpas_drv_set_p2p_powersave(p2p_get_clientif(wpa_s), atoi(param), -1, -1);
2900 #else
2901 		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
2902 #endif
2903 
2904 	if (os_strcmp(cmd, "oppps") == 0)
2905 #ifdef ANDROID_BRCM_P2P_PATCH
2906 		return wpas_drv_set_p2p_powersave(p2p_get_apif(wpa_s), -1, atoi(param), -1);
2907 #else
2908 		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
2909 #endif
2910 
2911 	if (os_strcmp(cmd, "ctwindow") == 0)
2912 #ifdef ANDROID_BRCM_P2P_PATCH
2913 		return wpa_drv_set_p2p_powersave(p2p_get_apif(wpa_s), -1, -1, atoi(param));
2914 #else
2915 		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
2916 #endif
2917 
2918 	if (os_strcmp(cmd, "disabled") == 0) {
2919 		wpa_s->global->p2p_disabled = atoi(param);
2920 		wpa_printf(MSG_DEBUG, "P2P functionality %s",
2921 			   wpa_s->global->p2p_disabled ?
2922 			   "disabled" : "enabled");
2923 		if (wpa_s->global->p2p_disabled) {
2924 			wpas_p2p_stop_find(wpa_s);
2925 			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2926 			p2p_flush(wpa_s->global->p2p);
2927 		}
2928 		return 0;
2929 	}
2930 
2931 	if (os_strcmp(cmd, "disabled") == 0) {
2932 		wpa_s->global->p2p_disabled = atoi(param);
2933 		wpa_printf(MSG_DEBUG, "P2P functionality %s",
2934 			   wpa_s->global->p2p_disabled ?
2935 			   "disabled" : "enabled");
2936 		if (wpa_s->global->p2p_disabled) {
2937 			wpas_p2p_stop_find(wpa_s);
2938 			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2939 			p2p_flush(wpa_s->global->p2p);
2940 		}
2941 		return 0;
2942 	}
2943 
2944 	if (os_strcmp(cmd, "force_long_sd") == 0) {
2945 		wpa_s->force_long_sd = atoi(param);
2946 		return 0;
2947 	}
2948 
2949 	if (os_strcmp(cmd, "peer_filter") == 0) {
2950 		u8 addr[ETH_ALEN];
2951 		if (hwaddr_aton(param, addr))
2952 			return -1;
2953 		p2p_set_peer_filter(wpa_s->global->p2p, addr);
2954 		return 0;
2955 	}
2956 
2957 	if (os_strcmp(cmd, "cross_connect") == 0)
2958 		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
2959 
2960 	if (os_strcmp(cmd, "go_apsd") == 0) {
2961 		if (os_strcmp(param, "disable") == 0)
2962 			wpa_s->set_ap_uapsd = 0;
2963 		else {
2964 			wpa_s->set_ap_uapsd = 1;
2965 			wpa_s->ap_uapsd = atoi(param);
2966 		}
2967 		return 0;
2968 	}
2969 
2970 	if (os_strcmp(cmd, "client_apsd") == 0) {
2971 		if (os_strcmp(param, "disable") == 0)
2972 			wpa_s->set_sta_uapsd = 0;
2973 		else {
2974 			int be, bk, vi, vo;
2975 			char *pos;
2976 			/* format: BE,BK,VI,VO;max SP Length */
2977 			be = atoi(param);
2978 			pos = os_strchr(param, ',');
2979 			if (pos == NULL)
2980 				return -1;
2981 			pos++;
2982 			bk = atoi(pos);
2983 			pos = os_strchr(pos, ',');
2984 			if (pos == NULL)
2985 				return -1;
2986 			pos++;
2987 			vi = atoi(pos);
2988 			pos = os_strchr(pos, ',');
2989 			if (pos == NULL)
2990 				return -1;
2991 			pos++;
2992 			vo = atoi(pos);
2993 			/* ignore max SP Length for now */
2994 
2995 			wpa_s->set_sta_uapsd = 1;
2996 			wpa_s->sta_uapsd = 0;
2997 			if (be)
2998 				wpa_s->sta_uapsd |= BIT(0);
2999 			if (bk)
3000 				wpa_s->sta_uapsd |= BIT(1);
3001 			if (vi)
3002 				wpa_s->sta_uapsd |= BIT(2);
3003 			if (vo)
3004 				wpa_s->sta_uapsd |= BIT(3);
3005 		}
3006 		return 0;
3007 	}
3008 
3009 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
3010 		   cmd);
3011 
3012 	return -1;
3013 }
3014 
3015 
p2p_ctrl_presence_req(struct wpa_supplicant * wpa_s,char * cmd)3016 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
3017 {
3018 	char *pos, *pos2;
3019 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
3020 
3021 	if (cmd[0]) {
3022 		pos = os_strchr(cmd, ' ');
3023 		if (pos == NULL)
3024 			return -1;
3025 		*pos++ = '\0';
3026 		dur1 = atoi(cmd);
3027 
3028 		pos2 = os_strchr(pos, ' ');
3029 		if (pos2)
3030 			*pos2++ = '\0';
3031 		int1 = atoi(pos);
3032 	} else
3033 		pos2 = NULL;
3034 
3035 	if (pos2) {
3036 		pos = os_strchr(pos2, ' ');
3037 		if (pos == NULL)
3038 			return -1;
3039 		*pos++ = '\0';
3040 		dur2 = atoi(pos2);
3041 		int2 = atoi(pos);
3042 	}
3043 
3044 	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
3045 }
3046 
3047 
p2p_ctrl_ext_listen(struct wpa_supplicant * wpa_s,char * cmd)3048 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
3049 {
3050 	char *pos;
3051 	unsigned int period = 0, interval = 0;
3052 
3053 	if (cmd[0]) {
3054 		pos = os_strchr(cmd, ' ');
3055 		if (pos == NULL)
3056 			return -1;
3057 		*pos++ = '\0';
3058 		period = atoi(cmd);
3059 		interval = atoi(pos);
3060 	}
3061 
3062 	return wpas_p2p_ext_listen(wpa_s, period, interval);
3063 }
3064 
3065 #endif /* CONFIG_P2P */
3066 
3067 
wpa_supplicant_ctrl_iface_sta_autoconnect(struct wpa_supplicant * wpa_s,char * cmd)3068 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
3069 	struct wpa_supplicant *wpa_s, char *cmd)
3070 {
3071 	wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
3072 	return 0;
3073 }
3074 
3075 
wpa_supplicant_signal_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3076 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
3077 				      size_t buflen)
3078 {
3079 	struct wpa_signal_info si;
3080 	int ret;
3081 
3082 	ret = wpa_drv_signal_poll(wpa_s, &si);
3083 	if (ret)
3084 		return -1;
3085 
3086 	ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
3087 			  "NOISE=%d\nFREQUENCY=%u\n",
3088 			  si.current_signal, si.current_txrate / 1000,
3089 			  si.current_noise, si.frequency);
3090 	if (ret < 0 || (unsigned int) ret > buflen)
3091 		return -1;
3092 	return ret;
3093 }
3094 
3095 
wpa_supplicant_driver_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3096 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
3097 				     char *buf, size_t buflen)
3098 {
3099 	int ret;
3100 
3101 	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
3102 	if (ret == 0)
3103 		ret = sprintf(buf, "%s\n", "OK");
3104 	return ret;
3105 }
3106 
3107 
wpa_supplicant_ctrl_iface_process(struct wpa_supplicant * wpa_s,char * buf,size_t * resp_len)3108 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
3109 					 char *buf, size_t *resp_len)
3110 {
3111 	char *reply;
3112 	const int reply_size = 4096;
3113 	int ctrl_rsp = 0;
3114 	int reply_len;
3115 
3116 	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
3117 	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3118 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
3119 				      (const u8 *) buf, os_strlen(buf));
3120 	} else {
3121 		int level = MSG_DEBUG;
3122 		if (os_strcmp(buf, "PING") == 0)
3123 			level = MSG_EXCESSIVE;
3124 		wpa_hexdump_ascii(level, "RX ctrl_iface",
3125 				  (const u8 *) buf, os_strlen(buf));
3126 	}
3127 
3128 	reply = os_malloc(reply_size);
3129 	if (reply == NULL) {
3130 		*resp_len = 1;
3131 		return NULL;
3132 	}
3133 
3134 	os_memcpy(reply, "OK\n", 3);
3135 	reply_len = 3;
3136 
3137 	if (os_strcmp(buf, "PING") == 0) {
3138 		os_memcpy(reply, "PONG\n", 5);
3139 		reply_len = 5;
3140 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
3141 		if (wpa_debug_reopen_file() < 0)
3142 			reply_len = -1;
3143 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
3144 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
3145 	} else if (os_strcmp(buf, "MIB") == 0) {
3146 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
3147 		if (reply_len >= 0) {
3148 			int res;
3149 			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
3150 					       reply_size - reply_len);
3151 			if (res < 0)
3152 				reply_len = -1;
3153 			else
3154 				reply_len += res;
3155 		}
3156 	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
3157 		reply_len = wpa_supplicant_ctrl_iface_status(
3158 			wpa_s, buf + 6, reply, reply_size);
3159 	} else if (os_strcmp(buf, "PMKSA") == 0) {
3160 		reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
3161 						    reply_size);
3162 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
3163 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
3164 			reply_len = -1;
3165 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
3166 		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
3167 							  reply, reply_size);
3168 	} else if (os_strcmp(buf, "LOGON") == 0) {
3169 		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
3170 	} else if (os_strcmp(buf, "LOGOFF") == 0) {
3171 		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
3172 	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
3173 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3174 			reply_len = -1;
3175 		else {
3176 			wpa_s->disconnected = 0;
3177 			wpa_s->reassociate = 1;
3178 			wpa_supplicant_req_scan(wpa_s, 0, 0);
3179 		}
3180 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
3181 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3182 			reply_len = -1;
3183 		else if (wpa_s->disconnected) {
3184 			wpa_s->disconnected = 0;
3185 			wpa_s->reassociate = 1;
3186 			wpa_supplicant_req_scan(wpa_s, 0, 0);
3187 		}
3188 #ifdef IEEE8021X_EAPOL
3189 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
3190 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
3191 			reply_len = -1;
3192 #endif /* IEEE8021X_EAPOL */
3193 #ifdef CONFIG_PEERKEY
3194 	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
3195 		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
3196 			reply_len = -1;
3197 #endif /* CONFIG_PEERKEY */
3198 #ifdef CONFIG_IEEE80211R
3199 	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
3200 		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
3201 			reply_len = -1;
3202 #endif /* CONFIG_IEEE80211R */
3203 #ifdef CONFIG_WPS
3204 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
3205 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
3206 		if (res == -2) {
3207 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3208 			reply_len = 17;
3209 		} else if (res)
3210 			reply_len = -1;
3211 	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
3212 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
3213 		if (res == -2) {
3214 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3215 			reply_len = 17;
3216 		} else if (res)
3217 			reply_len = -1;
3218 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
3219 		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
3220 							      reply,
3221 							      reply_size);
3222 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
3223 		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
3224 			wpa_s, buf + 14, reply, reply_size);
3225 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
3226 		if (wpas_wps_cancel(wpa_s))
3227 			reply_len = -1;
3228 #ifdef CONFIG_WPS_OOB
3229 	} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
3230 		if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
3231 			reply_len = -1;
3232 #endif /* CONFIG_WPS_OOB */
3233 	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
3234 		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
3235 			reply_len = -1;
3236 #ifdef CONFIG_AP
3237 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
3238 		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
3239 			wpa_s, buf + 11, reply, reply_size);
3240 #endif /* CONFIG_AP */
3241 #ifdef CONFIG_WPS_ER
3242 	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
3243 		if (wpas_wps_er_start(wpa_s, NULL))
3244 			reply_len = -1;
3245 	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
3246 		if (wpas_wps_er_start(wpa_s, buf + 13))
3247 			reply_len = -1;
3248 	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
3249 		if (wpas_wps_er_stop(wpa_s))
3250 			reply_len = -1;
3251 	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
3252 		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
3253 			reply_len = -1;
3254 	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
3255 		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
3256 		if (ret == -2) {
3257 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3258 			reply_len = 17;
3259 		} else if (ret == -3) {
3260 			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
3261 			reply_len = 18;
3262 		} else if (ret == -4) {
3263 			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
3264 			reply_len = 20;
3265 		} else if (ret)
3266 			reply_len = -1;
3267 	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
3268 		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
3269 			reply_len = -1;
3270 	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
3271 		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
3272 								buf + 18))
3273 			reply_len = -1;
3274 	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
3275 		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
3276 			reply_len = -1;
3277 #endif /* CONFIG_WPS_ER */
3278 #endif /* CONFIG_WPS */
3279 #ifdef CONFIG_IBSS_RSN
3280 	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
3281 		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
3282 			reply_len = -1;
3283 #endif /* CONFIG_IBSS_RSN */
3284 #ifdef CONFIG_P2P
3285 	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
3286 		if (p2p_ctrl_find(wpa_s, buf + 9))
3287 			reply_len = -1;
3288 	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
3289 		if (p2p_ctrl_find(wpa_s, ""))
3290 			reply_len = -1;
3291 	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
3292 		wpas_p2p_stop_find(wpa_s);
3293 	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
3294 		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
3295 					     reply_size);
3296 	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
3297 		if (p2p_ctrl_listen(wpa_s, buf + 11))
3298 			reply_len = -1;
3299 	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
3300 		if (p2p_ctrl_listen(wpa_s, ""))
3301 			reply_len = -1;
3302 	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
3303 		if (wpas_p2p_group_remove(wpa_s, buf + 17))
3304 			reply_len = -1;
3305 	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
3306 		if (wpas_p2p_group_add(wpa_s, 0, 0))
3307 			reply_len = -1;
3308 	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
3309 		if (p2p_ctrl_group_add(wpa_s, buf + 14))
3310 			reply_len = -1;
3311 	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
3312 		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
3313 			reply_len = -1;
3314 	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
3315 		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
3316 	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
3317 		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
3318 						   reply_size);
3319 	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
3320 		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
3321 			reply_len = -1;
3322 	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
3323 		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
3324 			reply_len = -1;
3325 	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
3326 		wpas_p2p_sd_service_update(wpa_s);
3327 	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
3328 		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
3329 			reply_len = -1;
3330 	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
3331 		wpas_p2p_service_flush(wpa_s);
3332 	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
3333 		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
3334 			reply_len = -1;
3335 	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
3336 		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
3337 			reply_len = -1;
3338 	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
3339 		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
3340 			reply_len = -1;
3341 	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
3342 		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
3343 			reply_len = -1;
3344 	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
3345 		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
3346 					      reply_size);
3347 	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
3348 		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
3349 			reply_len = -1;
3350 	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
3351 		os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
3352 		wpa_s->force_long_sd = 0;
3353 		if (wpa_s->global->p2p)
3354 			p2p_flush(wpa_s->global->p2p);
3355 	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
3356 		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
3357 			reply_len = -1;
3358 	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
3359 		if (wpas_p2p_cancel(wpa_s))
3360 			reply_len = -1;
3361 	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
3362 	#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_P2P)
3363 		/* We have to send presence command to p2p interface if p2p_interface is started
3364 		 * otherwise we can send it to primary interface
3365 		*/
3366 		struct wpa_supplicant* ifs;
3367 		for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
3368 			if ( (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO ) ||(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT )) {
3369 				wpa_s = ifs;
3370 				break;
3371 			}
3372 		}
3373 	#endif /* defined ANDROID_BRCM_P2P_PATCH && defined CONFIG_P2P */
3374 		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
3375 			reply_len = -1;
3376 	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
3377 		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
3378 			reply_len = -1;
3379 	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
3380 		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
3381 			reply_len = -1;
3382 	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
3383 		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
3384 			reply_len = -1;
3385 #endif /* CONFIG_P2P */
3386 	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
3387 	{
3388 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
3389 			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
3390 			reply_len = -1;
3391 		else
3392 			ctrl_rsp = 1;
3393 	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
3394 		if (wpa_supplicant_reload_configuration(wpa_s))
3395 			reply_len = -1;
3396 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
3397 		wpa_supplicant_terminate_proc(wpa_s->global);
3398 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
3399 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
3400 			reply_len = -1;
3401 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
3402 		reply_len = wpa_supplicant_ctrl_iface_log_level(wpa_s, buf + 9,
3403 							reply, reply_size);
3404 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
3405 		reply_len = wpa_supplicant_ctrl_iface_blacklist(wpa_s, buf + 9,
3406 							reply, reply_size);
3407 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
3408 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
3409 			wpa_s, reply, reply_size);
3410 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
3411 		wpa_s->reassociate = 0;
3412 		wpa_s->disconnected = 1;
3413 		wpa_supplicant_deauthenticate(wpa_s,
3414 					      WLAN_REASON_DEAUTH_LEAVING);
3415 	} else if (os_strcmp(buf, "SCAN") == 0) {
3416 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3417 			reply_len = -1;
3418 		else {
3419 			if (!wpa_s->scanning &&
3420 			    ((wpa_s->wpa_state <= WPA_SCANNING) ||
3421 			     (wpa_s->wpa_state == WPA_COMPLETED))) {
3422 				wpa_s->scan_req = 2;
3423 				wpa_supplicant_req_scan(wpa_s, 0, 0);
3424 			} else {
3425 				wpa_printf(MSG_DEBUG, "Ongoing scan action - "
3426 					   "reject new request");
3427 				reply_len = os_snprintf(reply, reply_size,
3428 							"FAIL-BUSY\n");
3429 			}
3430 		}
3431 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
3432 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
3433 			wpa_s, reply, reply_size);
3434 	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
3435 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
3436 			reply_len = -1;
3437 	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
3438 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
3439 			reply_len = -1;
3440 	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
3441 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
3442 			reply_len = -1;
3443 	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
3444 		reply_len = wpa_supplicant_ctrl_iface_add_network(
3445 			wpa_s, reply, reply_size);
3446 	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
3447 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
3448 			reply_len = -1;
3449 	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3450 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
3451 			reply_len = -1;
3452 	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
3453 		reply_len = wpa_supplicant_ctrl_iface_get_network(
3454 			wpa_s, buf + 12, reply, reply_size);
3455 #ifndef CONFIG_NO_CONFIG_WRITE
3456 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
3457 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
3458 			reply_len = -1;
3459 #endif /* CONFIG_NO_CONFIG_WRITE */
3460 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
3461 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
3462 			wpa_s, buf + 15, reply, reply_size);
3463 	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
3464 		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
3465 			reply_len = -1;
3466 	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
3467 		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
3468 			reply_len = -1;
3469 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3470 		reply_len = wpa_supplicant_global_iface_list(
3471 			wpa_s->global, reply, reply_size);
3472 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
3473 		reply_len = wpa_supplicant_global_iface_interfaces(
3474 			wpa_s->global, reply, reply_size);
3475 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
3476 		reply_len = wpa_supplicant_ctrl_iface_bss(
3477 			wpa_s, buf + 4, reply, reply_size);
3478 #ifdef CONFIG_AP
3479 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
3480 		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
3481 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
3482 		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
3483 					      reply_size);
3484 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
3485 		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
3486 						   reply_size);
3487 #endif /* CONFIG_AP */
3488 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
3489 		wpas_notify_suspend(wpa_s->global);
3490 	} else if (os_strcmp(buf, "RESUME") == 0) {
3491 		wpas_notify_resume(wpa_s->global);
3492 	} else if (os_strcmp(buf, "DROP_SA") == 0) {
3493 		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
3494 	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
3495 		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
3496 			reply_len = -1;
3497 	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
3498 		if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
3499 			reply_len = -1;
3500 	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
3501 		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
3502 			reply_len = -1;
3503 	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
3504 		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
3505 							       buf + 17))
3506 			reply_len = -1;
3507 #ifdef CONFIG_TDLS
3508 	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
3509 		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
3510 			reply_len = -1;
3511 	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
3512 		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
3513 			reply_len = -1;
3514 	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
3515 		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
3516 			reply_len = -1;
3517 #endif /* CONFIG_TDLS */
3518 	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
3519 		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
3520 						       reply_size);
3521 	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
3522 		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
3523 						      reply_size);
3524 	} else {
3525 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3526 		reply_len = 16;
3527 	}
3528 
3529 	if (reply_len < 0) {
3530 		os_memcpy(reply, "FAIL\n", 5);
3531 		reply_len = 5;
3532 	}
3533 
3534 	if (ctrl_rsp)
3535 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
3536 
3537 	*resp_len = reply_len;
3538 	return reply;
3539 }
3540 
3541 
wpa_supplicant_global_iface_add(struct wpa_global * global,char * cmd)3542 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
3543 					   char *cmd)
3544 {
3545 	struct wpa_interface iface;
3546 	char *pos;
3547 
3548 	/*
3549 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
3550 	 * TAB<bridge_ifname>
3551 	 */
3552 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
3553 
3554 	os_memset(&iface, 0, sizeof(iface));
3555 
3556 	do {
3557 		iface.ifname = pos = cmd;
3558 		pos = os_strchr(pos, '\t');
3559 		if (pos)
3560 			*pos++ = '\0';
3561 		if (iface.ifname[0] == '\0')
3562 			return -1;
3563 		if (pos == NULL)
3564 			break;
3565 
3566 		iface.confname = pos;
3567 		pos = os_strchr(pos, '\t');
3568 		if (pos)
3569 			*pos++ = '\0';
3570 		if (iface.confname[0] == '\0')
3571 			iface.confname = NULL;
3572 		if (pos == NULL)
3573 			break;
3574 
3575 		iface.driver = pos;
3576 		pos = os_strchr(pos, '\t');
3577 		if (pos)
3578 			*pos++ = '\0';
3579 		if (iface.driver[0] == '\0')
3580 			iface.driver = NULL;
3581 		if (pos == NULL)
3582 			break;
3583 
3584 		iface.ctrl_interface = pos;
3585 		pos = os_strchr(pos, '\t');
3586 		if (pos)
3587 			*pos++ = '\0';
3588 		if (iface.ctrl_interface[0] == '\0')
3589 			iface.ctrl_interface = NULL;
3590 		if (pos == NULL)
3591 			break;
3592 
3593 		iface.driver_param = pos;
3594 		pos = os_strchr(pos, '\t');
3595 		if (pos)
3596 			*pos++ = '\0';
3597 		if (iface.driver_param[0] == '\0')
3598 			iface.driver_param = NULL;
3599 		if (pos == NULL)
3600 			break;
3601 
3602 		iface.bridge_ifname = pos;
3603 		pos = os_strchr(pos, '\t');
3604 		if (pos)
3605 			*pos++ = '\0';
3606 		if (iface.bridge_ifname[0] == '\0')
3607 			iface.bridge_ifname = NULL;
3608 		if (pos == NULL)
3609 			break;
3610 	} while (0);
3611 
3612 	if (wpa_supplicant_get_iface(global, iface.ifname))
3613 		return -1;
3614 
3615 	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
3616 }
3617 
3618 
wpa_supplicant_global_iface_remove(struct wpa_global * global,char * cmd)3619 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
3620 					      char *cmd)
3621 {
3622 	struct wpa_supplicant *wpa_s;
3623 
3624 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
3625 
3626 	wpa_s = wpa_supplicant_get_iface(global, cmd);
3627 	if (wpa_s == NULL)
3628 		return -1;
3629 	return wpa_supplicant_remove_iface(global, wpa_s, 0);
3630 }
3631 
3632 
wpa_free_iface_info(struct wpa_interface_info * iface)3633 static void wpa_free_iface_info(struct wpa_interface_info *iface)
3634 {
3635 	struct wpa_interface_info *prev;
3636 
3637 	while (iface) {
3638 		prev = iface;
3639 		iface = iface->next;
3640 
3641 		os_free(prev->ifname);
3642 		os_free(prev->desc);
3643 		os_free(prev);
3644 	}
3645 }
3646 
3647 
wpa_supplicant_global_iface_list(struct wpa_global * global,char * buf,int len)3648 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
3649 					    char *buf, int len)
3650 {
3651 	int i, res;
3652 	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
3653 	char *pos, *end;
3654 
3655 	for (i = 0; wpa_drivers[i]; i++) {
3656 		struct wpa_driver_ops *drv = wpa_drivers[i];
3657 		if (drv->get_interfaces == NULL)
3658 			continue;
3659 		tmp = drv->get_interfaces(global->drv_priv[i]);
3660 		if (tmp == NULL)
3661 			continue;
3662 
3663 		if (last == NULL)
3664 			iface = last = tmp;
3665 		else
3666 			last->next = tmp;
3667 		while (last->next)
3668 			last = last->next;
3669 	}
3670 
3671 	pos = buf;
3672 	end = buf + len;
3673 	for (tmp = iface; tmp; tmp = tmp->next) {
3674 		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
3675 				  tmp->drv_name, tmp->ifname,
3676 				  tmp->desc ? tmp->desc : "");
3677 		if (res < 0 || res >= end - pos) {
3678 			*pos = '\0';
3679 			break;
3680 		}
3681 		pos += res;
3682 	}
3683 
3684 	wpa_free_iface_info(iface);
3685 
3686 	return pos - buf;
3687 }
3688 
3689 
wpa_supplicant_global_iface_interfaces(struct wpa_global * global,char * buf,int len)3690 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
3691 						  char *buf, int len)
3692 {
3693 	int res;
3694 	char *pos, *end;
3695 	struct wpa_supplicant *wpa_s;
3696 
3697 	wpa_s = global->ifaces;
3698 	pos = buf;
3699 	end = buf + len;
3700 
3701 	while (wpa_s) {
3702 		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
3703 		if (res < 0 || res >= end - pos) {
3704 			*pos = '\0';
3705 			break;
3706 		}
3707 		pos += res;
3708 		wpa_s = wpa_s->next;
3709 	}
3710 	return pos - buf;
3711 }
3712 
3713 
wpa_supplicant_global_ctrl_iface_process(struct wpa_global * global,char * buf,size_t * resp_len)3714 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
3715 						char *buf, size_t *resp_len)
3716 {
3717 	char *reply;
3718 	const int reply_size = 2048;
3719 	int reply_len;
3720 
3721 	wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
3722 			  (const u8 *) buf, os_strlen(buf));
3723 
3724 	reply = os_malloc(reply_size);
3725 	if (reply == NULL) {
3726 		*resp_len = 1;
3727 		return NULL;
3728 	}
3729 
3730 	os_memcpy(reply, "OK\n", 3);
3731 	reply_len = 3;
3732 
3733 	if (os_strcmp(buf, "PING") == 0) {
3734 		os_memcpy(reply, "PONG\n", 5);
3735 		reply_len = 5;
3736 	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
3737 		if (wpa_supplicant_global_iface_add(global, buf + 14))
3738 			reply_len = -1;
3739 	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
3740 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
3741 			reply_len = -1;
3742 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3743 		reply_len = wpa_supplicant_global_iface_list(
3744 			global, reply, reply_size);
3745 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
3746 		reply_len = wpa_supplicant_global_iface_interfaces(
3747 			global, reply, reply_size);
3748 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
3749 		wpa_supplicant_terminate_proc(global);
3750 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
3751 		wpas_notify_suspend(global);
3752 	} else if (os_strcmp(buf, "RESUME") == 0) {
3753 		wpas_notify_resume(global);
3754 	} else {
3755 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3756 		reply_len = 16;
3757 	}
3758 
3759 	if (reply_len < 0) {
3760 		os_memcpy(reply, "FAIL\n", 5);
3761 		reply_len = 5;
3762 	}
3763 
3764 	*resp_len = reply_len;
3765 	return reply;
3766 }
3767