• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/version.h"
14 #include "common/ieee802_11_defs.h"
15 #include "common/ieee802_11_common.h"
16 #include "common/wpa_ctrl.h"
17 #include "eap_peer/eap.h"
18 #include "eapol_supp/eapol_supp_sm.h"
19 #include "rsn_supp/wpa.h"
20 #include "rsn_supp/preauth.h"
21 #include "rsn_supp/pmksa_cache.h"
22 #include "l2_packet/l2_packet.h"
23 #include "wps/wps.h"
24 #include "config.h"
25 #include "wpa_supplicant_i.h"
26 #include "driver_i.h"
27 #include "wps_supplicant.h"
28 #include "ibss_rsn.h"
29 #include "ap.h"
30 #include "p2p_supplicant.h"
31 #include "p2p/p2p.h"
32 #include "hs20_supplicant.h"
33 #include "wifi_display.h"
34 #include "notify.h"
35 #include "bss.h"
36 #include "scan.h"
37 #include "ctrl_iface.h"
38 #include "interworking.h"
39 #include "blacklist.h"
40 #include "autoscan.h"
41 #include "wnm_sta.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 
pno_start(struct wpa_supplicant * wpa_s)51 static int pno_start(struct wpa_supplicant *wpa_s)
52 {
53 	int ret;
54 	size_t i, num_ssid;
55 	struct wpa_ssid *ssid;
56 	struct wpa_driver_scan_params params;
57 
58 	if (wpa_s->pno)
59 		return 0;
60 
61 	if (wpa_s->wpa_state == WPA_SCANNING) {
62 		wpa_supplicant_cancel_sched_scan(wpa_s);
63 		wpa_supplicant_cancel_scan(wpa_s);
64 	}
65 
66 	os_memset(&params, 0, sizeof(params));
67 
68 	num_ssid = 0;
69 	ssid = wpa_s->conf->ssid;
70 	while (ssid) {
71 		if (!wpas_network_disabled(wpa_s, ssid))
72 			num_ssid++;
73 		ssid = ssid->next;
74 	}
75 	if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
76 		wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
77 			   "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
78 		num_ssid = WPAS_MAX_SCAN_SSIDS;
79 	}
80 
81 	if (num_ssid == 0) {
82 		wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
83 		return -1;
84 	}
85 
86 	params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
87 					num_ssid);
88 	if (params.filter_ssids == NULL)
89 		return -1;
90 	i = 0;
91 	ssid = wpa_s->conf->ssid;
92 	while (ssid) {
93 		if (!wpas_network_disabled(wpa_s, ssid)) {
94 			params.ssids[i].ssid = ssid->ssid;
95 			params.ssids[i].ssid_len = ssid->ssid_len;
96 			params.num_ssids++;
97 			os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
98 				  ssid->ssid_len);
99 			params.filter_ssids[i].ssid_len = ssid->ssid_len;
100 			params.num_filter_ssids++;
101 			i++;
102 			if (i == num_ssid)
103 				break;
104 		}
105 		ssid = ssid->next;
106 	}
107 
108 	if (wpa_s->conf->filter_rssi)
109 		params.filter_rssi = wpa_s->conf->filter_rssi;
110 
111 	ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
112 	os_free(params.filter_ssids);
113 	if (ret == 0)
114 		wpa_s->pno = 1;
115 	return ret;
116 }
117 
118 
pno_stop(struct wpa_supplicant * wpa_s)119 static int pno_stop(struct wpa_supplicant *wpa_s)
120 {
121 	int ret = 0;
122 
123 	if (wpa_s->pno) {
124 		wpa_s->pno = 0;
125 		ret = wpa_drv_stop_sched_scan(wpa_s);
126 	}
127 
128 	if (wpa_s->wpa_state == WPA_SCANNING)
129 		wpa_supplicant_req_scan(wpa_s, 0, 0);
130 
131 	return ret;
132 }
133 
134 
set_bssid_filter(struct wpa_supplicant * wpa_s,char * val)135 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
136 {
137 	char *pos;
138 	u8 addr[ETH_ALEN], *filter = NULL, *n;
139 	size_t count = 0;
140 
141 	pos = val;
142 	while (pos) {
143 		if (*pos == '\0')
144 			break;
145 		if (hwaddr_aton(pos, addr)) {
146 			os_free(filter);
147 			return -1;
148 		}
149 		n = os_realloc_array(filter, count + 1, ETH_ALEN);
150 		if (n == NULL) {
151 			os_free(filter);
152 			return -1;
153 		}
154 		filter = n;
155 		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
156 		count++;
157 
158 		pos = os_strchr(pos, ' ');
159 		if (pos)
160 			pos++;
161 	}
162 
163 	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
164 	os_free(wpa_s->bssid_filter);
165 	wpa_s->bssid_filter = filter;
166 	wpa_s->bssid_filter_count = count;
167 
168 	return 0;
169 }
170 
171 
set_disallow_aps(struct wpa_supplicant * wpa_s,char * val)172 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
173 {
174 	char *pos;
175 	u8 addr[ETH_ALEN], *bssid = NULL, *n;
176 	struct wpa_ssid_value *ssid = NULL, *ns;
177 	size_t count = 0, ssid_count = 0;
178 	struct wpa_ssid *c;
179 
180 	/*
181 	 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ��
182 	 * SSID_SPEC ::= ssid <SSID_HEX>
183 	 * BSSID_SPEC ::= bssid <BSSID_HEX>
184 	 */
185 
186 	pos = val;
187 	while (pos) {
188 		if (*pos == '\0')
189 			break;
190 		if (os_strncmp(pos, "bssid ", 6) == 0) {
191 			int res;
192 			pos += 6;
193 			res = hwaddr_aton2(pos, addr);
194 			if (res < 0) {
195 				os_free(ssid);
196 				os_free(bssid);
197 				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
198 					   "BSSID value '%s'", pos);
199 				return -1;
200 			}
201 			pos += res;
202 			n = os_realloc_array(bssid, count + 1, ETH_ALEN);
203 			if (n == NULL) {
204 				os_free(ssid);
205 				os_free(bssid);
206 				return -1;
207 			}
208 			bssid = n;
209 			os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
210 			count++;
211 		} else if (os_strncmp(pos, "ssid ", 5) == 0) {
212 			char *end;
213 			pos += 5;
214 
215 			end = pos;
216 			while (*end) {
217 				if (*end == '\0' || *end == ' ')
218 					break;
219 				end++;
220 			}
221 
222 			ns = os_realloc_array(ssid, ssid_count + 1,
223 					      sizeof(struct wpa_ssid_value));
224 			if (ns == NULL) {
225 				os_free(ssid);
226 				os_free(bssid);
227 				return -1;
228 			}
229 			ssid = ns;
230 
231 			if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
232 			    hexstr2bin(pos, ssid[ssid_count].ssid,
233 				       (end - pos) / 2) < 0) {
234 				os_free(ssid);
235 				os_free(bssid);
236 				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
237 					   "SSID value '%s'", pos);
238 				return -1;
239 			}
240 			ssid[ssid_count].ssid_len = (end - pos) / 2;
241 			wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
242 					  ssid[ssid_count].ssid,
243 					  ssid[ssid_count].ssid_len);
244 			ssid_count++;
245 			pos = end;
246 		} else {
247 			wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
248 				   "'%s'", pos);
249 			os_free(ssid);
250 			os_free(bssid);
251 			return -1;
252 		}
253 
254 		pos = os_strchr(pos, ' ');
255 		if (pos)
256 			pos++;
257 	}
258 
259 	wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
260 	os_free(wpa_s->disallow_aps_bssid);
261 	wpa_s->disallow_aps_bssid = bssid;
262 	wpa_s->disallow_aps_bssid_count = count;
263 
264 	wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
265 	os_free(wpa_s->disallow_aps_ssid);
266 	wpa_s->disallow_aps_ssid = ssid;
267 	wpa_s->disallow_aps_ssid_count = ssid_count;
268 
269 	if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
270 		return 0;
271 
272 	c = wpa_s->current_ssid;
273 	if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
274 		return 0;
275 
276 	if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
277 	    !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
278 		return 0;
279 
280 	wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
281 		   "because current AP was marked disallowed");
282 
283 #ifdef CONFIG_SME
284 	wpa_s->sme.prev_bssid_set = 0;
285 #endif /* CONFIG_SME */
286 	wpa_s->reassociate = 1;
287 	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
288 	wpa_supplicant_req_scan(wpa_s, 0, 0);
289 
290 	return 0;
291 }
292 
293 
wpa_supplicant_ctrl_iface_set(struct wpa_supplicant * wpa_s,char * cmd)294 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
295 					 char *cmd)
296 {
297 	char *value;
298 	int ret = 0;
299 
300 	value = os_strchr(cmd, ' ');
301 	if (value == NULL)
302 		return -1;
303 	*value++ = '\0';
304 
305 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
306 	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
307 		eapol_sm_configure(wpa_s->eapol,
308 				   atoi(value), -1, -1, -1);
309 	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
310 		eapol_sm_configure(wpa_s->eapol,
311 				   -1, atoi(value), -1, -1);
312 	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
313 		eapol_sm_configure(wpa_s->eapol,
314 				   -1, -1, atoi(value), -1);
315 	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
316 		eapol_sm_configure(wpa_s->eapol,
317 				   -1, -1, -1, atoi(value));
318 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
319 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
320 				     atoi(value)))
321 			ret = -1;
322 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
323 		   0) {
324 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
325 				     atoi(value)))
326 			ret = -1;
327 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
328 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
329 			ret = -1;
330 	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
331 		wpa_s->wps_fragment_size = atoi(value);
332 #ifdef CONFIG_WPS_TESTING
333 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
334 		long int val;
335 		val = strtol(value, NULL, 0);
336 		if (val < 0 || val > 0xff) {
337 			ret = -1;
338 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
339 				   "wps_version_number %ld", val);
340 		} else {
341 			wps_version_number = val;
342 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
343 				   "version %u.%u",
344 				   (wps_version_number & 0xf0) >> 4,
345 				   wps_version_number & 0x0f);
346 		}
347 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
348 		wps_testing_dummy_cred = atoi(value);
349 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
350 			   wps_testing_dummy_cred);
351 #endif /* CONFIG_WPS_TESTING */
352 	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
353 		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
354 			ret = -1;
355 #ifdef CONFIG_TDLS_TESTING
356 	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
357 		extern unsigned int tdls_testing;
358 		tdls_testing = strtol(value, NULL, 0);
359 		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
360 #endif /* CONFIG_TDLS_TESTING */
361 #ifdef CONFIG_TDLS
362 	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
363 		int disabled = atoi(value);
364 		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
365 		if (disabled) {
366 			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
367 				ret = -1;
368 		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
369 			ret = -1;
370 		wpa_tdls_enable(wpa_s->wpa, !disabled);
371 #endif /* CONFIG_TDLS */
372 	} else if (os_strcasecmp(cmd, "pno") == 0) {
373 		if (atoi(value))
374 			ret = pno_start(wpa_s);
375 		else
376 			ret = pno_stop(wpa_s);
377 	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
378 		int disabled = atoi(value);
379 		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
380 			ret = -1;
381 		else if (disabled)
382 			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
383 	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
384 		if (os_strcmp(value, "disable") == 0)
385 			wpa_s->set_sta_uapsd = 0;
386 		else {
387 			int be, bk, vi, vo;
388 			char *pos;
389 			/* format: BE,BK,VI,VO;max SP Length */
390 			be = atoi(value);
391 			pos = os_strchr(value, ',');
392 			if (pos == NULL)
393 				return -1;
394 			pos++;
395 			bk = atoi(pos);
396 			pos = os_strchr(pos, ',');
397 			if (pos == NULL)
398 				return -1;
399 			pos++;
400 			vi = atoi(pos);
401 			pos = os_strchr(pos, ',');
402 			if (pos == NULL)
403 				return -1;
404 			pos++;
405 			vo = atoi(pos);
406 			/* ignore max SP Length for now */
407 
408 			wpa_s->set_sta_uapsd = 1;
409 			wpa_s->sta_uapsd = 0;
410 			if (be)
411 				wpa_s->sta_uapsd |= BIT(0);
412 			if (bk)
413 				wpa_s->sta_uapsd |= BIT(1);
414 			if (vi)
415 				wpa_s->sta_uapsd |= BIT(2);
416 			if (vo)
417 				wpa_s->sta_uapsd |= BIT(3);
418 		}
419 	} else if (os_strcasecmp(cmd, "ps") == 0) {
420 		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
421 #ifdef CONFIG_WIFI_DISPLAY
422 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
423 		wifi_display_enable(wpa_s->global, !!atoi(value));
424 #endif /* CONFIG_WIFI_DISPLAY */
425 	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
426 		ret = set_bssid_filter(wpa_s, value);
427 	} else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
428 		ret = set_disallow_aps(wpa_s, value);
429 	} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
430 		wpa_s->no_keep_alive = !!atoi(value);
431 	} else {
432 		value[-1] = '=';
433 		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
434 		if (ret == 0)
435 			wpa_supplicant_update_config(wpa_s);
436 	}
437 
438 	return ret;
439 }
440 
441 
wpa_supplicant_ctrl_iface_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)442 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
443 					 char *cmd, char *buf, size_t buflen)
444 {
445 	int res = -1;
446 
447 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
448 
449 	if (os_strcmp(cmd, "version") == 0) {
450 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
451 	} else if (os_strcasecmp(cmd, "country") == 0) {
452 		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
453 			res = os_snprintf(buf, buflen, "%c%c",
454 					  wpa_s->conf->country[0],
455 					  wpa_s->conf->country[1]);
456 #ifdef CONFIG_WIFI_DISPLAY
457 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
458 		res = os_snprintf(buf, buflen, "%d",
459 				  wpa_s->global->wifi_display);
460 		if (res < 0 || (unsigned int) res >= buflen)
461 			return -1;
462 		return res;
463 #endif /* CONFIG_WIFI_DISPLAY */
464 	}
465 
466 	if (res < 0 || (unsigned int) res >= buflen)
467 		return -1;
468 	return res;
469 }
470 
471 
472 #ifdef IEEE8021X_EAPOL
wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant * wpa_s,char * addr)473 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
474 					     char *addr)
475 {
476 	u8 bssid[ETH_ALEN];
477 	struct wpa_ssid *ssid = wpa_s->current_ssid;
478 
479 	if (hwaddr_aton(addr, bssid)) {
480 		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
481 			   "'%s'", addr);
482 		return -1;
483 	}
484 
485 	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
486 	rsn_preauth_deinit(wpa_s->wpa);
487 	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
488 		return -1;
489 
490 	return 0;
491 }
492 #endif /* IEEE8021X_EAPOL */
493 
494 
495 #ifdef CONFIG_PEERKEY
496 /* MLME-STKSTART.request(peer) */
wpa_supplicant_ctrl_iface_stkstart(struct wpa_supplicant * wpa_s,char * addr)497 static int wpa_supplicant_ctrl_iface_stkstart(
498 	struct wpa_supplicant *wpa_s, char *addr)
499 {
500 	u8 peer[ETH_ALEN];
501 
502 	if (hwaddr_aton(addr, peer)) {
503 		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
504 			   "address '%s'", addr);
505 		return -1;
506 	}
507 
508 	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
509 		   MAC2STR(peer));
510 
511 	return wpa_sm_stkstart(wpa_s->wpa, peer);
512 }
513 #endif /* CONFIG_PEERKEY */
514 
515 
516 #ifdef CONFIG_TDLS
517 
wpa_supplicant_ctrl_iface_tdls_discover(struct wpa_supplicant * wpa_s,char * addr)518 static int wpa_supplicant_ctrl_iface_tdls_discover(
519 	struct wpa_supplicant *wpa_s, char *addr)
520 {
521 	u8 peer[ETH_ALEN];
522 	int ret;
523 
524 	if (hwaddr_aton(addr, peer)) {
525 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
526 			   "address '%s'", addr);
527 		return -1;
528 	}
529 
530 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
531 		   MAC2STR(peer));
532 
533 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
534 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
535 	else
536 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
537 
538 	return ret;
539 }
540 
541 
wpa_supplicant_ctrl_iface_tdls_setup(struct wpa_supplicant * wpa_s,char * addr)542 static int wpa_supplicant_ctrl_iface_tdls_setup(
543 	struct wpa_supplicant *wpa_s, char *addr)
544 {
545 	u8 peer[ETH_ALEN];
546 	int ret;
547 
548 	if (hwaddr_aton(addr, peer)) {
549 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
550 			   "address '%s'", addr);
551 		return -1;
552 	}
553 
554 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
555 		   MAC2STR(peer));
556 
557 	wpa_tdls_remove(wpa_s->wpa, peer);
558 
559 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
560 		ret = wpa_tdls_start(wpa_s->wpa, peer);
561 	else
562 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
563 
564 	return ret;
565 }
566 
567 
wpa_supplicant_ctrl_iface_tdls_teardown(struct wpa_supplicant * wpa_s,char * addr)568 static int wpa_supplicant_ctrl_iface_tdls_teardown(
569 	struct wpa_supplicant *wpa_s, char *addr)
570 {
571 	u8 peer[ETH_ALEN];
572 
573 	if (hwaddr_aton(addr, peer)) {
574 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
575 			   "address '%s'", addr);
576 		return -1;
577 	}
578 
579 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
580 		   MAC2STR(peer));
581 
582 	return wpa_tdls_teardown_link(wpa_s->wpa, peer,
583 				      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
584 }
585 
586 #endif /* CONFIG_TDLS */
587 
588 
589 #ifdef CONFIG_IEEE80211R
wpa_supplicant_ctrl_iface_ft_ds(struct wpa_supplicant * wpa_s,char * addr)590 static int wpa_supplicant_ctrl_iface_ft_ds(
591 	struct wpa_supplicant *wpa_s, char *addr)
592 {
593 	u8 target_ap[ETH_ALEN];
594 	struct wpa_bss *bss;
595 	const u8 *mdie;
596 
597 	if (hwaddr_aton(addr, target_ap)) {
598 		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
599 			   "address '%s'", addr);
600 		return -1;
601 	}
602 
603 	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
604 
605 	bss = wpa_bss_get_bssid(wpa_s, target_ap);
606 	if (bss)
607 		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
608 	else
609 		mdie = NULL;
610 
611 	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
612 }
613 #endif /* CONFIG_IEEE80211R */
614 
615 
616 #ifdef CONFIG_WPS
wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant * wpa_s,char * cmd)617 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
618 					     char *cmd)
619 {
620 	u8 bssid[ETH_ALEN], *_bssid = bssid;
621 #ifdef CONFIG_P2P
622 	u8 p2p_dev_addr[ETH_ALEN];
623 #endif /* CONFIG_P2P */
624 #ifdef CONFIG_AP
625 	u8 *_p2p_dev_addr = NULL;
626 #endif /* CONFIG_AP */
627 
628 	if (cmd == NULL || os_strcmp(cmd, "any") == 0 || cmd[0] == '\0') {
629 		_bssid = NULL;
630 #ifdef CONFIG_P2P
631 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
632 		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
633 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
634 				   "P2P Device Address '%s'",
635 				   cmd + 13);
636 			return -1;
637 		}
638 		_p2p_dev_addr = p2p_dev_addr;
639 #endif /* CONFIG_P2P */
640 	} else if (hwaddr_aton(cmd, bssid)) {
641 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
642 			   cmd);
643 		return -1;
644 	}
645 
646 #ifdef CONFIG_AP
647 	if (wpa_s->ap_iface)
648 		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
649 #endif /* CONFIG_AP */
650 
651 	return wpas_wps_start_pbc(wpa_s, _bssid, 0);
652 }
653 
654 
wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)655 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
656 					     char *cmd, char *buf,
657 					     size_t buflen)
658 {
659 	u8 bssid[ETH_ALEN], *_bssid = bssid;
660 	char *pin;
661 	int ret;
662 
663 	pin = os_strchr(cmd, ' ');
664 	if (pin)
665 		*pin++ = '\0';
666 
667 	if (os_strcmp(cmd, "any") == 0)
668 		_bssid = NULL;
669 	else if (os_strcmp(cmd, "get") == 0) {
670 		ret = wps_generate_pin();
671 		goto done;
672 	} else if (hwaddr_aton(cmd, bssid)) {
673 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
674 			   cmd);
675 		return -1;
676 	}
677 
678 #ifdef CONFIG_AP
679 	if (wpa_s->ap_iface) {
680 		int timeout = 0;
681 		char *pos;
682 
683 		if (pin) {
684 			pos = os_strchr(pin, ' ');
685 			if (pos) {
686 				*pos++ = '\0';
687 				timeout = atoi(pos);
688 			}
689 		}
690 
691 		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
692 						 buf, buflen, timeout);
693 	}
694 #endif /* CONFIG_AP */
695 
696 	if (pin) {
697 		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
698 					 DEV_PW_DEFAULT);
699 		if (ret < 0)
700 			return -1;
701 		ret = os_snprintf(buf, buflen, "%s", pin);
702 		if (ret < 0 || (size_t) ret >= buflen)
703 			return -1;
704 		return ret;
705 	}
706 
707 	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
708 	if (ret < 0)
709 		return -1;
710 
711 done:
712 	/* Return the generated PIN */
713 	ret = os_snprintf(buf, buflen, "%08d", ret);
714 	if (ret < 0 || (size_t) ret >= buflen)
715 		return -1;
716 	return ret;
717 }
718 
719 
wpa_supplicant_ctrl_iface_wps_check_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)720 static int wpa_supplicant_ctrl_iface_wps_check_pin(
721 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
722 {
723 	char pin[9];
724 	size_t len;
725 	char *pos;
726 	int ret;
727 
728 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
729 			      (u8 *) cmd, os_strlen(cmd));
730 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
731 		if (*pos < '0' || *pos > '9')
732 			continue;
733 		pin[len++] = *pos;
734 		if (len == 9) {
735 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
736 			return -1;
737 		}
738 	}
739 	if (len != 4 && len != 8) {
740 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
741 		return -1;
742 	}
743 	pin[len] = '\0';
744 
745 	if (len == 8) {
746 		unsigned int pin_val;
747 		pin_val = atoi(pin);
748 		if (!wps_pin_valid(pin_val)) {
749 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
750 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
751 			if (ret < 0 || (size_t) ret >= buflen)
752 				return -1;
753 			return ret;
754 		}
755 	}
756 
757 	ret = os_snprintf(buf, buflen, "%s", pin);
758 	if (ret < 0 || (size_t) ret >= buflen)
759 		return -1;
760 
761 	return ret;
762 }
763 
764 
765 #ifdef CONFIG_WPS_NFC
766 
wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant * wpa_s,char * cmd)767 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
768 					     char *cmd)
769 {
770 	u8 bssid[ETH_ALEN], *_bssid = bssid;
771 
772 	if (cmd == NULL || cmd[0] == '\0')
773 		_bssid = NULL;
774 	else if (hwaddr_aton(cmd, bssid))
775 		return -1;
776 
777 	return wpas_wps_start_nfc(wpa_s, _bssid);
778 }
779 
780 
wpa_supplicant_ctrl_iface_wps_nfc_config_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)781 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
782 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
783 {
784 	int ndef;
785 	struct wpabuf *buf;
786 	int res;
787 	char *pos;
788 
789 	pos = os_strchr(cmd, ' ');
790 	if (pos)
791 		*pos++ = '\0';
792 	if (os_strcmp(cmd, "WPS") == 0)
793 		ndef = 0;
794 	else if (os_strcmp(cmd, "NDEF") == 0)
795 		ndef = 1;
796 	else
797 		return -1;
798 
799 	buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
800 	if (buf == NULL)
801 		return -1;
802 
803 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
804 					 wpabuf_len(buf));
805 	reply[res++] = '\n';
806 	reply[res] = '\0';
807 
808 	wpabuf_free(buf);
809 
810 	return res;
811 }
812 
813 
wpa_supplicant_ctrl_iface_wps_nfc_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)814 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
815 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
816 {
817 	int ndef;
818 	struct wpabuf *buf;
819 	int res;
820 
821 	if (os_strcmp(cmd, "WPS") == 0)
822 		ndef = 0;
823 	else if (os_strcmp(cmd, "NDEF") == 0)
824 		ndef = 1;
825 	else
826 		return -1;
827 
828 	buf = wpas_wps_nfc_token(wpa_s, ndef);
829 	if (buf == NULL)
830 		return -1;
831 
832 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
833 					 wpabuf_len(buf));
834 	reply[res++] = '\n';
835 	reply[res] = '\0';
836 
837 	wpabuf_free(buf);
838 
839 	return res;
840 }
841 
842 
wpa_supplicant_ctrl_iface_wps_nfc_tag_read(struct wpa_supplicant * wpa_s,char * pos)843 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
844 	struct wpa_supplicant *wpa_s, char *pos)
845 {
846 	size_t len;
847 	struct wpabuf *buf;
848 	int ret;
849 
850 	len = os_strlen(pos);
851 	if (len & 0x01)
852 		return -1;
853 	len /= 2;
854 
855 	buf = wpabuf_alloc(len);
856 	if (buf == NULL)
857 		return -1;
858 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
859 		wpabuf_free(buf);
860 		return -1;
861 	}
862 
863 	ret = wpas_wps_nfc_tag_read(wpa_s, buf);
864 	wpabuf_free(buf);
865 
866 	return ret;
867 }
868 
869 
wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int cr)870 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
871 					      char *reply, size_t max_len,
872 					      int cr)
873 {
874 	struct wpabuf *buf;
875 	int res;
876 
877 	buf = wpas_wps_nfc_handover_req(wpa_s, cr);
878 	if (buf == NULL)
879 		return -1;
880 
881 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
882 					 wpabuf_len(buf));
883 	reply[res++] = '\n';
884 	reply[res] = '\0';
885 
886 	wpabuf_free(buf);
887 
888 	return res;
889 }
890 
891 
wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)892 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
893 					  char *cmd, char *reply,
894 					  size_t max_len)
895 {
896 	char *pos;
897 
898 	pos = os_strchr(cmd, ' ');
899 	if (pos == NULL)
900 		return -1;
901 	*pos++ = '\0';
902 
903 	if (os_strcmp(cmd, "NDEF") != 0)
904 		return -1;
905 
906 	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
907 		return wpas_ctrl_nfc_get_handover_req_wps(
908 			wpa_s, reply, max_len, os_strcmp(pos, "WPS-CR") == 0);
909 	}
910 
911 	return -1;
912 }
913 
914 
wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef,int cr,char * uuid)915 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
916 					      char *reply, size_t max_len,
917 					      int ndef, int cr, char *uuid)
918 {
919 	struct wpabuf *buf;
920 	int res;
921 
922 	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
923 	if (buf == NULL)
924 		return -1;
925 
926 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
927 					 wpabuf_len(buf));
928 	reply[res++] = '\n';
929 	reply[res] = '\0';
930 
931 	wpabuf_free(buf);
932 
933 	return res;
934 }
935 
936 
wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)937 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
938 					  char *cmd, char *reply,
939 					  size_t max_len)
940 {
941 	char *pos, *pos2;
942 	int ndef;
943 
944 	pos = os_strchr(cmd, ' ');
945 	if (pos == NULL)
946 		return -1;
947 	*pos++ = '\0';
948 
949 	if (os_strcmp(cmd, "WPS") == 0)
950 		ndef = 0;
951 	else if (os_strcmp(cmd, "NDEF") == 0)
952 		ndef = 1;
953 	else
954 		return -1;
955 
956 	pos2 = os_strchr(pos, ' ');
957 	if (pos2)
958 		*pos2++ = '\0';
959 	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
960 		return wpas_ctrl_nfc_get_handover_sel_wps(
961 			wpa_s, reply, max_len, ndef,
962 			os_strcmp(pos, "WPS-CR") == 0, pos2);
963 	}
964 
965 	return -1;
966 }
967 
968 
wpas_ctrl_nfc_rx_handover_req(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)969 static int wpas_ctrl_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
970 					 char *cmd, char *reply,
971 					 size_t max_len)
972 {
973 	size_t len;
974 	struct wpabuf *buf;
975 	int ret;
976 
977 	len = os_strlen(cmd);
978 	if (len & 0x01)
979 		return -1;
980 	len /= 2;
981 
982 	buf = wpabuf_alloc(len);
983 	if (buf == NULL)
984 		return -1;
985 	if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
986 		wpabuf_free(buf);
987 		return -1;
988 	}
989 
990 	ret = wpas_wps_nfc_rx_handover_req(wpa_s, buf);
991 	wpabuf_free(buf);
992 
993 	return ret;
994 }
995 
996 
wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant * wpa_s,char * cmd)997 static int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
998 					 char *cmd)
999 {
1000 	size_t len;
1001 	struct wpabuf *buf;
1002 	int ret;
1003 
1004 	len = os_strlen(cmd);
1005 	if (len & 0x01)
1006 		return -1;
1007 	len /= 2;
1008 
1009 	buf = wpabuf_alloc(len);
1010 	if (buf == NULL)
1011 		return -1;
1012 	if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
1013 		wpabuf_free(buf);
1014 		return -1;
1015 	}
1016 
1017 	ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf);
1018 	wpabuf_free(buf);
1019 
1020 	return ret;
1021 }
1022 
1023 
wpas_ctrl_nfc_report_handover(struct wpa_supplicant * wpa_s,char * cmd)1024 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1025 					 char *cmd)
1026 {
1027 	size_t len;
1028 	struct wpabuf *req, *sel;
1029 	int ret;
1030 	char *pos, *role, *type, *pos2;
1031 
1032 	role = cmd;
1033 	pos = os_strchr(role, ' ');
1034 	if (pos == NULL)
1035 		return -1;
1036 	*pos++ = '\0';
1037 
1038 	type = pos;
1039 	pos = os_strchr(type, ' ');
1040 	if (pos == NULL)
1041 		return -1;
1042 	*pos++ = '\0';
1043 
1044 	pos2 = os_strchr(pos, ' ');
1045 	if (pos2 == NULL)
1046 		return -1;
1047 	*pos2++ = '\0';
1048 
1049 	len = os_strlen(pos);
1050 	if (len & 0x01)
1051 		return -1;
1052 	len /= 2;
1053 
1054 	req = wpabuf_alloc(len);
1055 	if (req == NULL)
1056 		return -1;
1057 	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1058 		wpabuf_free(req);
1059 		return -1;
1060 	}
1061 
1062 	len = os_strlen(pos2);
1063 	if (len & 0x01) {
1064 		wpabuf_free(req);
1065 		return -1;
1066 	}
1067 	len /= 2;
1068 
1069 	sel = wpabuf_alloc(len);
1070 	if (sel == NULL) {
1071 		wpabuf_free(req);
1072 		return -1;
1073 	}
1074 	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1075 		wpabuf_free(req);
1076 		wpabuf_free(sel);
1077 		return -1;
1078 	}
1079 
1080 	if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1081 		ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1082 	} else {
1083 		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1084 			   "reported: role=%s type=%s", role, type);
1085 		ret = -1;
1086 	}
1087 	wpabuf_free(req);
1088 	wpabuf_free(sel);
1089 
1090 	return ret;
1091 }
1092 
1093 #endif /* CONFIG_WPS_NFC */
1094 
1095 
wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant * wpa_s,char * cmd)1096 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1097 					     char *cmd)
1098 {
1099 	u8 bssid[ETH_ALEN];
1100 	char *pin;
1101 	char *new_ssid;
1102 	char *new_auth;
1103 	char *new_encr;
1104 	char *new_key;
1105 	struct wps_new_ap_settings ap;
1106 
1107 	pin = os_strchr(cmd, ' ');
1108 	if (pin == NULL)
1109 		return -1;
1110 	*pin++ = '\0';
1111 
1112 	if (hwaddr_aton(cmd, bssid)) {
1113 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1114 			   cmd);
1115 		return -1;
1116 	}
1117 
1118 	new_ssid = os_strchr(pin, ' ');
1119 	if (new_ssid == NULL)
1120 		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1121 	*new_ssid++ = '\0';
1122 
1123 	new_auth = os_strchr(new_ssid, ' ');
1124 	if (new_auth == NULL)
1125 		return -1;
1126 	*new_auth++ = '\0';
1127 
1128 	new_encr = os_strchr(new_auth, ' ');
1129 	if (new_encr == NULL)
1130 		return -1;
1131 	*new_encr++ = '\0';
1132 
1133 	new_key = os_strchr(new_encr, ' ');
1134 	if (new_key == NULL)
1135 		return -1;
1136 	*new_key++ = '\0';
1137 
1138 	os_memset(&ap, 0, sizeof(ap));
1139 	ap.ssid_hex = new_ssid;
1140 	ap.auth = new_auth;
1141 	ap.encr = new_encr;
1142 	ap.key_hex = new_key;
1143 	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1144 }
1145 
1146 
1147 #ifdef CONFIG_AP
wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1148 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1149 						char *cmd, char *buf,
1150 						size_t buflen)
1151 {
1152 	int timeout = 300;
1153 	char *pos;
1154 	const char *pin_txt;
1155 
1156 	if (!wpa_s->ap_iface)
1157 		return -1;
1158 
1159 	pos = os_strchr(cmd, ' ');
1160 	if (pos)
1161 		*pos++ = '\0';
1162 
1163 	if (os_strcmp(cmd, "disable") == 0) {
1164 		wpas_wps_ap_pin_disable(wpa_s);
1165 		return os_snprintf(buf, buflen, "OK\n");
1166 	}
1167 
1168 	if (os_strcmp(cmd, "random") == 0) {
1169 		if (pos)
1170 			timeout = atoi(pos);
1171 		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1172 		if (pin_txt == NULL)
1173 			return -1;
1174 		return os_snprintf(buf, buflen, "%s", pin_txt);
1175 	}
1176 
1177 	if (os_strcmp(cmd, "get") == 0) {
1178 		pin_txt = wpas_wps_ap_pin_get(wpa_s);
1179 		if (pin_txt == NULL)
1180 			return -1;
1181 		return os_snprintf(buf, buflen, "%s", pin_txt);
1182 	}
1183 
1184 	if (os_strcmp(cmd, "set") == 0) {
1185 		char *pin;
1186 		if (pos == NULL)
1187 			return -1;
1188 		pin = pos;
1189 		pos = os_strchr(pos, ' ');
1190 		if (pos) {
1191 			*pos++ = '\0';
1192 			timeout = atoi(pos);
1193 		}
1194 		if (os_strlen(pin) > buflen)
1195 			return -1;
1196 		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1197 			return -1;
1198 		return os_snprintf(buf, buflen, "%s", pin);
1199 	}
1200 
1201 	return -1;
1202 }
1203 #endif /* CONFIG_AP */
1204 
1205 
1206 #ifdef CONFIG_WPS_ER
wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant * wpa_s,char * cmd)1207 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1208 						char *cmd)
1209 {
1210 	char *uuid = cmd, *pin, *pos;
1211 	u8 addr_buf[ETH_ALEN], *addr = NULL;
1212 	pin = os_strchr(uuid, ' ');
1213 	if (pin == NULL)
1214 		return -1;
1215 	*pin++ = '\0';
1216 	pos = os_strchr(pin, ' ');
1217 	if (pos) {
1218 		*pos++ = '\0';
1219 		if (hwaddr_aton(pos, addr_buf) == 0)
1220 			addr = addr_buf;
1221 	}
1222 	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
1223 }
1224 
1225 
wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant * wpa_s,char * cmd)1226 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
1227 						  char *cmd)
1228 {
1229 	char *uuid = cmd, *pin;
1230 	pin = os_strchr(uuid, ' ');
1231 	if (pin == NULL)
1232 		return -1;
1233 	*pin++ = '\0';
1234 	return wpas_wps_er_learn(wpa_s, uuid, pin);
1235 }
1236 
1237 
wpa_supplicant_ctrl_iface_wps_er_set_config(struct wpa_supplicant * wpa_s,char * cmd)1238 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
1239 	struct wpa_supplicant *wpa_s, char *cmd)
1240 {
1241 	char *uuid = cmd, *id;
1242 	id = os_strchr(uuid, ' ');
1243 	if (id == NULL)
1244 		return -1;
1245 	*id++ = '\0';
1246 	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
1247 }
1248 
1249 
wpa_supplicant_ctrl_iface_wps_er_config(struct wpa_supplicant * wpa_s,char * cmd)1250 static int wpa_supplicant_ctrl_iface_wps_er_config(
1251 	struct wpa_supplicant *wpa_s, char *cmd)
1252 {
1253 	char *pin;
1254 	char *new_ssid;
1255 	char *new_auth;
1256 	char *new_encr;
1257 	char *new_key;
1258 	struct wps_new_ap_settings ap;
1259 
1260 	pin = os_strchr(cmd, ' ');
1261 	if (pin == NULL)
1262 		return -1;
1263 	*pin++ = '\0';
1264 
1265 	new_ssid = os_strchr(pin, ' ');
1266 	if (new_ssid == NULL)
1267 		return -1;
1268 	*new_ssid++ = '\0';
1269 
1270 	new_auth = os_strchr(new_ssid, ' ');
1271 	if (new_auth == NULL)
1272 		return -1;
1273 	*new_auth++ = '\0';
1274 
1275 	new_encr = os_strchr(new_auth, ' ');
1276 	if (new_encr == NULL)
1277 		return -1;
1278 	*new_encr++ = '\0';
1279 
1280 	new_key = os_strchr(new_encr, ' ');
1281 	if (new_key == NULL)
1282 		return -1;
1283 	*new_key++ = '\0';
1284 
1285 	os_memset(&ap, 0, sizeof(ap));
1286 	ap.ssid_hex = new_ssid;
1287 	ap.auth = new_auth;
1288 	ap.encr = new_encr;
1289 	ap.key_hex = new_key;
1290 	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
1291 }
1292 
1293 
1294 #ifdef CONFIG_WPS_NFC
wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1295 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
1296 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1297 {
1298 	int ndef;
1299 	struct wpabuf *buf;
1300 	int res;
1301 	char *uuid;
1302 
1303 	uuid = os_strchr(cmd, ' ');
1304 	if (uuid == NULL)
1305 		return -1;
1306 	*uuid++ = '\0';
1307 
1308 	if (os_strcmp(cmd, "WPS") == 0)
1309 		ndef = 0;
1310 	else if (os_strcmp(cmd, "NDEF") == 0)
1311 		ndef = 1;
1312 	else
1313 		return -1;
1314 
1315 	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
1316 	if (buf == NULL)
1317 		return -1;
1318 
1319 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1320 					 wpabuf_len(buf));
1321 	reply[res++] = '\n';
1322 	reply[res] = '\0';
1323 
1324 	wpabuf_free(buf);
1325 
1326 	return res;
1327 }
1328 #endif /* CONFIG_WPS_NFC */
1329 #endif /* CONFIG_WPS_ER */
1330 
1331 #endif /* CONFIG_WPS */
1332 
1333 
1334 #ifdef CONFIG_IBSS_RSN
wpa_supplicant_ctrl_iface_ibss_rsn(struct wpa_supplicant * wpa_s,char * addr)1335 static int wpa_supplicant_ctrl_iface_ibss_rsn(
1336 	struct wpa_supplicant *wpa_s, char *addr)
1337 {
1338 	u8 peer[ETH_ALEN];
1339 
1340 	if (hwaddr_aton(addr, peer)) {
1341 		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
1342 			   "address '%s'", addr);
1343 		return -1;
1344 	}
1345 
1346 	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
1347 		   MAC2STR(peer));
1348 
1349 	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
1350 }
1351 #endif /* CONFIG_IBSS_RSN */
1352 
1353 
wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant * wpa_s,char * rsp)1354 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
1355 					      char *rsp)
1356 {
1357 #ifdef IEEE8021X_EAPOL
1358 	char *pos, *id_pos;
1359 	int id;
1360 	struct wpa_ssid *ssid;
1361 
1362 	pos = os_strchr(rsp, '-');
1363 	if (pos == NULL)
1364 		return -1;
1365 	*pos++ = '\0';
1366 	id_pos = pos;
1367 	pos = os_strchr(pos, ':');
1368 	if (pos == NULL)
1369 		return -1;
1370 	*pos++ = '\0';
1371 	id = atoi(id_pos);
1372 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
1373 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1374 			      (u8 *) pos, os_strlen(pos));
1375 
1376 	ssid = wpa_config_get_network(wpa_s->conf, id);
1377 	if (ssid == NULL) {
1378 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1379 			   "to update", id);
1380 		return -1;
1381 	}
1382 
1383 	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
1384 							 pos);
1385 #else /* IEEE8021X_EAPOL */
1386 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1387 	return -1;
1388 #endif /* IEEE8021X_EAPOL */
1389 }
1390 
1391 
wpa_supplicant_ctrl_iface_status(struct wpa_supplicant * wpa_s,const char * params,char * buf,size_t buflen)1392 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
1393 					    const char *params,
1394 					    char *buf, size_t buflen)
1395 {
1396 	char *pos, *end, tmp[30];
1397 	int res, verbose, wps, ret;
1398 
1399 	verbose = os_strcmp(params, "-VERBOSE") == 0;
1400 	wps = os_strcmp(params, "-WPS") == 0;
1401 	pos = buf;
1402 	end = buf + buflen;
1403 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1404 		struct wpa_ssid *ssid = wpa_s->current_ssid;
1405 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1406 				  MAC2STR(wpa_s->bssid));
1407 		if (ret < 0 || ret >= end - pos)
1408 			return pos - buf;
1409 		pos += ret;
1410 		if (ssid) {
1411 			u8 *_ssid = ssid->ssid;
1412 			size_t ssid_len = ssid->ssid_len;
1413 			u8 ssid_buf[MAX_SSID_LEN];
1414 			if (ssid_len == 0) {
1415 				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1416 				if (_res < 0)
1417 					ssid_len = 0;
1418 				else
1419 					ssid_len = _res;
1420 				_ssid = ssid_buf;
1421 			}
1422 			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1423 					  wpa_ssid_txt(_ssid, ssid_len),
1424 					  ssid->id);
1425 			if (ret < 0 || ret >= end - pos)
1426 				return pos - buf;
1427 			pos += ret;
1428 
1429 			if (wps && ssid->passphrase &&
1430 			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1431 			    (ssid->mode == WPAS_MODE_AP ||
1432 			     ssid->mode == WPAS_MODE_P2P_GO)) {
1433 				ret = os_snprintf(pos, end - pos,
1434 						  "passphrase=%s\n",
1435 						  ssid->passphrase);
1436 				if (ret < 0 || ret >= end - pos)
1437 					return pos - buf;
1438 				pos += ret;
1439 			}
1440 			if (ssid->id_str) {
1441 				ret = os_snprintf(pos, end - pos,
1442 						  "id_str=%s\n",
1443 						  ssid->id_str);
1444 				if (ret < 0 || ret >= end - pos)
1445 					return pos - buf;
1446 				pos += ret;
1447 			}
1448 
1449 			switch (ssid->mode) {
1450 			case WPAS_MODE_INFRA:
1451 				ret = os_snprintf(pos, end - pos,
1452 						  "mode=station\n");
1453 				break;
1454 			case WPAS_MODE_IBSS:
1455 				ret = os_snprintf(pos, end - pos,
1456 						  "mode=IBSS\n");
1457 				break;
1458 			case WPAS_MODE_AP:
1459 				ret = os_snprintf(pos, end - pos,
1460 						  "mode=AP\n");
1461 				break;
1462 			case WPAS_MODE_P2P_GO:
1463 				ret = os_snprintf(pos, end - pos,
1464 						  "mode=P2P GO\n");
1465 				break;
1466 			case WPAS_MODE_P2P_GROUP_FORMATION:
1467 				ret = os_snprintf(pos, end - pos,
1468 						  "mode=P2P GO - group "
1469 						  "formation\n");
1470 				break;
1471 			default:
1472 				ret = 0;
1473 				break;
1474 			}
1475 			if (ret < 0 || ret >= end - pos)
1476 				return pos - buf;
1477 			pos += ret;
1478 		}
1479 
1480 #ifdef CONFIG_AP
1481 		if (wpa_s->ap_iface) {
1482 			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1483 							    end - pos,
1484 							    verbose);
1485 		} else
1486 #endif /* CONFIG_AP */
1487 		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1488 	}
1489 #ifdef CONFIG_SAE
1490 	if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
1491 	    wpa_s->sme.sae.state == SAE_ACCEPTED && !wpa_s->ap_iface) {
1492 		ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
1493 				  wpa_s->sme.sae.group);
1494 		if (ret < 0 || ret >= end - pos)
1495 			return pos - buf;
1496 		pos += ret;
1497 	}
1498 #endif /* CONFIG_SAE */
1499 	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1500 			  wpa_supplicant_state_txt(wpa_s->wpa_state));
1501 	if (ret < 0 || ret >= end - pos)
1502 		return pos - buf;
1503 	pos += ret;
1504 
1505 	if (wpa_s->l2 &&
1506 	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1507 		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1508 		if (ret < 0 || ret >= end - pos)
1509 			return pos - buf;
1510 		pos += ret;
1511 	}
1512 
1513 #ifdef CONFIG_P2P
1514 	if (wpa_s->global->p2p) {
1515 		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1516 				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1517 		if (ret < 0 || ret >= end - pos)
1518 			return pos - buf;
1519 		pos += ret;
1520 	}
1521 #endif /* CONFIG_P2P */
1522 
1523 	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1524 			  MAC2STR(wpa_s->own_addr));
1525 	if (ret < 0 || ret >= end - pos)
1526 		return pos - buf;
1527 	pos += ret;
1528 
1529 #ifdef CONFIG_HS20
1530 	if (wpa_s->current_bss &&
1531 	    wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) &&
1532 	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
1533 	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
1534 		ret = os_snprintf(pos, end - pos, "hs20=1\n");
1535 		if (ret < 0 || ret >= end - pos)
1536 			return pos - buf;
1537 		pos += ret;
1538 	}
1539 
1540 	if (wpa_s->current_ssid) {
1541 		struct wpa_cred *cred;
1542 		char *type;
1543 
1544 		for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1545 			if (wpa_s->current_ssid->parent_cred != cred)
1546 				continue;
1547 			if (!cred->domain)
1548 				continue;
1549 
1550 			ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
1551 					  cred->domain);
1552 			if (ret < 0 || ret >= end - pos)
1553 				return pos - buf;
1554 			pos += ret;
1555 
1556 			if (wpa_s->current_bss == NULL ||
1557 			    wpa_s->current_bss->anqp == NULL)
1558 				res = -1;
1559 			else
1560 				res = interworking_home_sp_cred(
1561 					wpa_s, cred,
1562 					wpa_s->current_bss->anqp->domain_name);
1563 			if (res > 0)
1564 				type = "home";
1565 			else if (res == 0)
1566 				type = "roaming";
1567 			else
1568 				type = "unknown";
1569 
1570 			ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
1571 			if (ret < 0 || ret >= end - pos)
1572 				return pos - buf;
1573 			pos += ret;
1574 
1575 			break;
1576 		}
1577 	}
1578 #endif /* CONFIG_HS20 */
1579 
1580 	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1581 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1582 		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1583 					  verbose);
1584 		if (res >= 0)
1585 			pos += res;
1586 	}
1587 
1588 	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1589 	if (res >= 0)
1590 		pos += res;
1591 
1592 #ifdef ANDROID
1593 	wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
1594 		     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
1595 		     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
1596 		     wpa_s->wpa_state,
1597 		     MAC2STR(wpa_s->bssid),
1598 		     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
1599 		     wpa_ssid_txt(wpa_s->current_ssid->ssid,
1600 		     wpa_s->current_ssid->ssid_len) : "");
1601 	if (wpa_s->wpa_state == WPA_COMPLETED) {
1602 		struct wpa_ssid *ssid = wpa_s->current_ssid;
1603 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- connection to "
1604 			MACSTR " completed %s [id=%d id_str=%s]",
1605 			MAC2STR(wpa_s->bssid), "(auth)",
1606 			ssid ? ssid->id : -1,
1607 			ssid && ssid->id_str ? ssid->id_str : "");
1608 	}
1609 #endif /* ANDROID */
1610 
1611 	return pos - buf;
1612 }
1613 
1614 
wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant * wpa_s,char * cmd)1615 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
1616 					   char *cmd)
1617 {
1618 	char *pos;
1619 	int id;
1620 	struct wpa_ssid *ssid;
1621 	u8 bssid[ETH_ALEN];
1622 
1623 	/* cmd: "<network id> <BSSID>" */
1624 	pos = os_strchr(cmd, ' ');
1625 	if (pos == NULL)
1626 		return -1;
1627 	*pos++ = '\0';
1628 	id = atoi(cmd);
1629 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
1630 	if (hwaddr_aton(pos, bssid)) {
1631 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
1632 		return -1;
1633 	}
1634 
1635 	ssid = wpa_config_get_network(wpa_s->conf, id);
1636 	if (ssid == NULL) {
1637 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1638 			   "to update", id);
1639 		return -1;
1640 	}
1641 
1642 	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
1643 	ssid->bssid_set = !is_zero_ether_addr(bssid);
1644 
1645 	return 0;
1646 }
1647 
1648 
wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1649 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1650 					       char *cmd, char *buf,
1651 					       size_t buflen)
1652 {
1653 	u8 bssid[ETH_ALEN];
1654 	struct wpa_blacklist *e;
1655 	char *pos, *end;
1656 	int ret;
1657 
1658 	/* cmd: "BLACKLIST [<BSSID>]" */
1659 	if (*cmd == '\0') {
1660 		pos = buf;
1661 		end = buf + buflen;
1662 		e = wpa_s->blacklist;
1663 		while (e) {
1664 			ret = os_snprintf(pos, end - pos, MACSTR "\n",
1665 					  MAC2STR(e->bssid));
1666 			if (ret < 0 || ret >= end - pos)
1667 				return pos - buf;
1668 			pos += ret;
1669 			e = e->next;
1670 		}
1671 		return pos - buf;
1672 	}
1673 
1674 	cmd++;
1675 	if (os_strncmp(cmd, "clear", 5) == 0) {
1676 		wpa_blacklist_clear(wpa_s);
1677 		os_memcpy(buf, "OK\n", 3);
1678 		return 3;
1679 	}
1680 
1681 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1682 	if (hwaddr_aton(cmd, bssid)) {
1683 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
1684 		return -1;
1685 	}
1686 
1687 	/*
1688 	 * Add the BSSID twice, so its count will be 2, causing it to be
1689 	 * skipped when processing scan results.
1690 	 */
1691 	ret = wpa_blacklist_add(wpa_s, bssid);
1692 	if (ret != 0)
1693 		return -1;
1694 	ret = wpa_blacklist_add(wpa_s, bssid);
1695 	if (ret != 0)
1696 		return -1;
1697 	os_memcpy(buf, "OK\n", 3);
1698 	return 3;
1699 }
1700 
1701 
1702 extern int wpa_debug_level;
1703 extern int wpa_debug_timestamp;
1704 
debug_level_str(int level)1705 static const char * debug_level_str(int level)
1706 {
1707 	switch (level) {
1708 	case MSG_EXCESSIVE:
1709 		return "EXCESSIVE";
1710 	case MSG_MSGDUMP:
1711 		return "MSGDUMP";
1712 	case MSG_DEBUG:
1713 		return "DEBUG";
1714 	case MSG_INFO:
1715 		return "INFO";
1716 	case MSG_WARNING:
1717 		return "WARNING";
1718 	case MSG_ERROR:
1719 		return "ERROR";
1720 	default:
1721 		return "?";
1722 	}
1723 }
1724 
1725 
str_to_debug_level(const char * s)1726 static int str_to_debug_level(const char *s)
1727 {
1728 	if (os_strcasecmp(s, "EXCESSIVE") == 0)
1729 		return MSG_EXCESSIVE;
1730 	if (os_strcasecmp(s, "MSGDUMP") == 0)
1731 		return MSG_MSGDUMP;
1732 	if (os_strcasecmp(s, "DEBUG") == 0)
1733 		return MSG_DEBUG;
1734 	if (os_strcasecmp(s, "INFO") == 0)
1735 		return MSG_INFO;
1736 	if (os_strcasecmp(s, "WARNING") == 0)
1737 		return MSG_WARNING;
1738 	if (os_strcasecmp(s, "ERROR") == 0)
1739 		return MSG_ERROR;
1740 	return -1;
1741 }
1742 
1743 
wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1744 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
1745 					       char *cmd, char *buf,
1746 					       size_t buflen)
1747 {
1748 	char *pos, *end, *stamp;
1749 	int ret;
1750 
1751 	if (cmd == NULL) {
1752 		return -1;
1753 	}
1754 
1755 	/* cmd: "LOG_LEVEL [<level>]" */
1756 	if (*cmd == '\0') {
1757 		pos = buf;
1758 		end = buf + buflen;
1759 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
1760 				  "Timestamp: %d\n",
1761 				  debug_level_str(wpa_debug_level),
1762 				  wpa_debug_timestamp);
1763 		if (ret < 0 || ret >= end - pos)
1764 			ret = 0;
1765 
1766 		return ret;
1767 	}
1768 
1769 	while (*cmd == ' ')
1770 		cmd++;
1771 
1772 	stamp = os_strchr(cmd, ' ');
1773 	if (stamp) {
1774 		*stamp++ = '\0';
1775 		while (*stamp == ' ') {
1776 			stamp++;
1777 		}
1778 	}
1779 
1780 	if (cmd && os_strlen(cmd)) {
1781 		int level = str_to_debug_level(cmd);
1782 		if (level < 0)
1783 			return -1;
1784 		wpa_debug_level = level;
1785 	}
1786 
1787 	if (stamp && os_strlen(stamp))
1788 		wpa_debug_timestamp = atoi(stamp);
1789 
1790 	os_memcpy(buf, "OK\n", 3);
1791 	return 3;
1792 }
1793 
1794 
wpa_supplicant_ctrl_iface_list_networks(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1795 static int wpa_supplicant_ctrl_iface_list_networks(
1796 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1797 {
1798 	char *pos, *end;
1799 	struct wpa_ssid *ssid;
1800 	int ret;
1801 
1802 	pos = buf;
1803 	end = buf + buflen;
1804 	ret = os_snprintf(pos, end - pos,
1805 			  "network id / ssid / bssid / flags\n");
1806 	if (ret < 0 || ret >= end - pos)
1807 		return pos - buf;
1808 	pos += ret;
1809 
1810 	ssid = wpa_s->conf->ssid;
1811 	while (ssid) {
1812 		ret = os_snprintf(pos, end - pos, "%d\t%s",
1813 				  ssid->id,
1814 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1815 		if (ret < 0 || ret >= end - pos)
1816 			return pos - buf;
1817 		pos += ret;
1818 		if (ssid->bssid_set) {
1819 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1820 					  MAC2STR(ssid->bssid));
1821 		} else {
1822 			ret = os_snprintf(pos, end - pos, "\tany");
1823 		}
1824 		if (ret < 0 || ret >= end - pos)
1825 			return pos - buf;
1826 		pos += ret;
1827 		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
1828 				  ssid == wpa_s->current_ssid ?
1829 				  "[CURRENT]" : "",
1830 				  ssid->disabled ? "[DISABLED]" : "",
1831 				  ssid->disabled_until.sec ?
1832 				  "[TEMP-DISABLED]" : "",
1833 				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1834 				  "");
1835 		if (ret < 0 || ret >= end - pos)
1836 			return pos - buf;
1837 		pos += ret;
1838 		ret = os_snprintf(pos, end - pos, "\n");
1839 		if (ret < 0 || ret >= end - pos)
1840 			return pos - buf;
1841 		pos += ret;
1842 
1843 		ssid = ssid->next;
1844 	}
1845 
1846 	return pos - buf;
1847 }
1848 
1849 
wpa_supplicant_cipher_txt(char * pos,char * end,int cipher)1850 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1851 {
1852 	int ret;
1853 	ret = os_snprintf(pos, end - pos, "-");
1854 	if (ret < 0 || ret >= end - pos)
1855 		return pos;
1856 	pos += ret;
1857 	ret = wpa_write_ciphers(pos, end, cipher, "+");
1858 	if (ret < 0)
1859 		return pos;
1860 	pos += ret;
1861 	return pos;
1862 }
1863 
1864 
wpa_supplicant_ie_txt(char * pos,char * end,const char * proto,const u8 * ie,size_t ie_len)1865 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1866 				    const u8 *ie, size_t ie_len)
1867 {
1868 	struct wpa_ie_data data;
1869 	int first, ret;
1870 
1871 	ret = os_snprintf(pos, end - pos, "[%s-", proto);
1872 	if (ret < 0 || ret >= end - pos)
1873 		return pos;
1874 	pos += ret;
1875 
1876 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1877 		ret = os_snprintf(pos, end - pos, "?]");
1878 		if (ret < 0 || ret >= end - pos)
1879 			return pos;
1880 		pos += ret;
1881 		return pos;
1882 	}
1883 
1884 	first = 1;
1885 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1886 		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
1887 		if (ret < 0 || ret >= end - pos)
1888 			return pos;
1889 		pos += ret;
1890 		first = 0;
1891 	}
1892 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
1893 		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1894 		if (ret < 0 || ret >= end - pos)
1895 			return pos;
1896 		pos += ret;
1897 		first = 0;
1898 	}
1899 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1900 		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1901 		if (ret < 0 || ret >= end - pos)
1902 			return pos;
1903 		pos += ret;
1904 		first = 0;
1905 	}
1906 #ifdef CONFIG_IEEE80211R
1907 	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1908 		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1909 				  first ? "" : "+");
1910 		if (ret < 0 || ret >= end - pos)
1911 			return pos;
1912 		pos += ret;
1913 		first = 0;
1914 	}
1915 	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1916 		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1917 				  first ? "" : "+");
1918 		if (ret < 0 || ret >= end - pos)
1919 			return pos;
1920 		pos += ret;
1921 		first = 0;
1922 	}
1923 #endif /* CONFIG_IEEE80211R */
1924 #ifdef CONFIG_IEEE80211W
1925 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1926 		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1927 				  first ? "" : "+");
1928 		if (ret < 0 || ret >= end - pos)
1929 			return pos;
1930 		pos += ret;
1931 		first = 0;
1932 	}
1933 	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1934 		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1935 				  first ? "" : "+");
1936 		if (ret < 0 || ret >= end - pos)
1937 			return pos;
1938 		pos += ret;
1939 		first = 0;
1940 	}
1941 #endif /* CONFIG_IEEE80211W */
1942 
1943 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1944 
1945 	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1946 		ret = os_snprintf(pos, end - pos, "-preauth");
1947 		if (ret < 0 || ret >= end - pos)
1948 			return pos;
1949 		pos += ret;
1950 	}
1951 
1952 	ret = os_snprintf(pos, end - pos, "]");
1953 	if (ret < 0 || ret >= end - pos)
1954 		return pos;
1955 	pos += ret;
1956 
1957 	return pos;
1958 }
1959 
1960 
1961 #ifdef CONFIG_WPS
wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant * wpa_s,char * pos,char * end,struct wpabuf * wps_ie)1962 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1963 					    char *pos, char *end,
1964 					    struct wpabuf *wps_ie)
1965 {
1966 	int ret;
1967 	const char *txt;
1968 
1969 	if (wps_ie == NULL)
1970 		return pos;
1971 	if (wps_is_selected_pbc_registrar(wps_ie))
1972 		txt = "[WPS-PBC]";
1973 #ifdef CONFIG_WPS2
1974 	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
1975 		txt = "[WPS-AUTH]";
1976 #endif /* CONFIG_WPS2 */
1977 	else if (wps_is_selected_pin_registrar(wps_ie))
1978 		txt = "[WPS-PIN]";
1979 	else
1980 		txt = "[WPS]";
1981 
1982 	ret = os_snprintf(pos, end - pos, "%s", txt);
1983 	if (ret >= 0 && ret < end - pos)
1984 		pos += ret;
1985 	wpabuf_free(wps_ie);
1986 	return pos;
1987 }
1988 #endif /* CONFIG_WPS */
1989 
1990 
wpa_supplicant_wps_ie_txt(struct wpa_supplicant * wpa_s,char * pos,char * end,const struct wpa_bss * bss)1991 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
1992 					char *pos, char *end,
1993 					const struct wpa_bss *bss)
1994 {
1995 #ifdef CONFIG_WPS
1996 	struct wpabuf *wps_ie;
1997 	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1998 	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
1999 #else /* CONFIG_WPS */
2000 	return pos;
2001 #endif /* CONFIG_WPS */
2002 }
2003 
2004 
2005 /* 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)2006 static int wpa_supplicant_ctrl_iface_scan_result(
2007 	struct wpa_supplicant *wpa_s,
2008 	const struct wpa_bss *bss, char *buf, size_t buflen)
2009 {
2010 	char *pos, *end;
2011 	int ret;
2012 	const u8 *ie, *ie2, *p2p;
2013 
2014 	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2015 	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2016 	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2017 	    0)
2018 		return 0; /* Do not show P2P listen discovery results here */
2019 
2020 	pos = buf;
2021 	end = buf + buflen;
2022 
2023 	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2024 			  MAC2STR(bss->bssid), bss->freq, bss->level);
2025 	if (ret < 0 || ret >= end - pos)
2026 		return -1;
2027 	pos += ret;
2028 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2029 	if (ie)
2030 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2031 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2032 	if (ie2)
2033 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2034 	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2035 	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2036 		ret = os_snprintf(pos, end - pos, "[WEP]");
2037 		if (ret < 0 || ret >= end - pos)
2038 			return -1;
2039 		pos += ret;
2040 	}
2041 	if (bss->caps & IEEE80211_CAP_IBSS) {
2042 		ret = os_snprintf(pos, end - pos, "[IBSS]");
2043 		if (ret < 0 || ret >= end - pos)
2044 			return -1;
2045 		pos += ret;
2046 	}
2047 	if (bss->caps & IEEE80211_CAP_ESS) {
2048 		ret = os_snprintf(pos, end - pos, "[ESS]");
2049 		if (ret < 0 || ret >= end - pos)
2050 			return -1;
2051 		pos += ret;
2052 	}
2053 	if (p2p) {
2054 		ret = os_snprintf(pos, end - pos, "[P2P]");
2055 		if (ret < 0 || ret >= end - pos)
2056 			return -1;
2057 		pos += ret;
2058 	}
2059 #ifdef CONFIG_HS20
2060 	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2061 		ret = os_snprintf(pos, end - pos, "[HS20]");
2062 		if (ret < 0 || ret >= end - pos)
2063 			return -1;
2064 		pos += ret;
2065 	}
2066 #endif /* CONFIG_HS20 */
2067 
2068 	ret = os_snprintf(pos, end - pos, "\t%s",
2069 			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
2070 	if (ret < 0 || ret >= end - pos)
2071 		return -1;
2072 	pos += ret;
2073 
2074 	ret = os_snprintf(pos, end - pos, "\n");
2075 	if (ret < 0 || ret >= end - pos)
2076 		return -1;
2077 	pos += ret;
2078 
2079 	return pos - buf;
2080 }
2081 
2082 
wpa_supplicant_ctrl_iface_scan_results(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)2083 static int wpa_supplicant_ctrl_iface_scan_results(
2084 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2085 {
2086 	char *pos, *end;
2087 	struct wpa_bss *bss;
2088 	int ret;
2089 
2090 	pos = buf;
2091 	end = buf + buflen;
2092 	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2093 			  "flags / ssid\n");
2094 	if (ret < 0 || ret >= end - pos)
2095 		return pos - buf;
2096 	pos += ret;
2097 
2098 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2099 		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2100 							    end - pos);
2101 		if (ret < 0 || ret >= end - pos)
2102 			return pos - buf;
2103 		pos += ret;
2104 	}
2105 
2106 	return pos - buf;
2107 }
2108 
2109 
wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant * wpa_s,char * cmd)2110 static int wpa_supplicant_ctrl_iface_select_network(
2111 	struct wpa_supplicant *wpa_s, char *cmd)
2112 {
2113 	int id;
2114 	struct wpa_ssid *ssid;
2115 
2116 	/* cmd: "<network id>" or "any" */
2117 	if (os_strcmp(cmd, "any") == 0) {
2118 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
2119 		ssid = NULL;
2120 	} else {
2121 		id = atoi(cmd);
2122 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
2123 
2124 		ssid = wpa_config_get_network(wpa_s->conf, id);
2125 		if (ssid == NULL) {
2126 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2127 				   "network id=%d", id);
2128 			return -1;
2129 		}
2130 		if (ssid->disabled == 2) {
2131 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2132 				   "SELECT_NETWORK with persistent P2P group");
2133 			return -1;
2134 		}
2135 	}
2136 
2137 	wpa_supplicant_select_network(wpa_s, ssid);
2138 
2139 	return 0;
2140 }
2141 
2142 
wpa_supplicant_ctrl_iface_enable_network(struct wpa_supplicant * wpa_s,char * cmd)2143 static int wpa_supplicant_ctrl_iface_enable_network(
2144 	struct wpa_supplicant *wpa_s, char *cmd)
2145 {
2146 	int id;
2147 	struct wpa_ssid *ssid;
2148 
2149 	/* cmd: "<network id>" or "all" */
2150 	if (os_strcmp(cmd, "all") == 0) {
2151 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
2152 		ssid = NULL;
2153 	} else {
2154 		id = atoi(cmd);
2155 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
2156 
2157 		ssid = wpa_config_get_network(wpa_s->conf, id);
2158 		if (ssid == NULL) {
2159 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2160 				   "network id=%d", id);
2161 			return -1;
2162 		}
2163 		if (ssid->disabled == 2) {
2164 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2165 				   "ENABLE_NETWORK with persistent P2P group");
2166 			return -1;
2167 		}
2168 
2169 		if (os_strstr(cmd, " no-connect")) {
2170 			ssid->disabled = 0;
2171 			return 0;
2172 		}
2173 	}
2174 	wpa_supplicant_enable_network(wpa_s, ssid);
2175 
2176 	return 0;
2177 }
2178 
2179 
wpa_supplicant_ctrl_iface_disable_network(struct wpa_supplicant * wpa_s,char * cmd)2180 static int wpa_supplicant_ctrl_iface_disable_network(
2181 	struct wpa_supplicant *wpa_s, char *cmd)
2182 {
2183 	int id;
2184 	struct wpa_ssid *ssid;
2185 
2186 	/* cmd: "<network id>" or "all" */
2187 	if (os_strcmp(cmd, "all") == 0) {
2188 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
2189 		ssid = NULL;
2190 	} else {
2191 		id = atoi(cmd);
2192 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
2193 
2194 		ssid = wpa_config_get_network(wpa_s->conf, id);
2195 		if (ssid == NULL) {
2196 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2197 				   "network id=%d", id);
2198 			return -1;
2199 		}
2200 		if (ssid->disabled == 2) {
2201 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2202 				   "DISABLE_NETWORK with persistent P2P "
2203 				   "group");
2204 			return -1;
2205 		}
2206 	}
2207 	wpa_supplicant_disable_network(wpa_s, ssid);
2208 
2209 	return 0;
2210 }
2211 
2212 
wpa_supplicant_ctrl_iface_add_network(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)2213 static int wpa_supplicant_ctrl_iface_add_network(
2214 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2215 {
2216 	struct wpa_ssid *ssid;
2217 	int ret;
2218 
2219 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
2220 
2221 	ssid = wpa_config_add_network(wpa_s->conf);
2222 	if (ssid == NULL)
2223 		return -1;
2224 
2225 	wpas_notify_network_added(wpa_s, ssid);
2226 
2227 	ssid->disabled = 1;
2228 	wpa_config_set_network_defaults(ssid);
2229 
2230 	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
2231 	if (ret < 0 || (size_t) ret >= buflen)
2232 		return -1;
2233 	return ret;
2234 }
2235 
2236 
wpa_supplicant_ctrl_iface_remove_network(struct wpa_supplicant * wpa_s,char * cmd)2237 static int wpa_supplicant_ctrl_iface_remove_network(
2238 	struct wpa_supplicant *wpa_s, char *cmd)
2239 {
2240 	int id;
2241 	struct wpa_ssid *ssid;
2242 	int was_disabled;
2243 
2244 	/* cmd: "<network id>" or "all" */
2245 	if (os_strcmp(cmd, "all") == 0) {
2246 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
2247 		if (wpa_s->sched_scanning)
2248 			wpa_supplicant_cancel_sched_scan(wpa_s);
2249 
2250 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2251 		if (wpa_s->current_ssid) {
2252 #ifdef CONFIG_SME
2253 			wpa_s->sme.prev_bssid_set = 0;
2254 #endif /* CONFIG_SME */
2255 			wpa_sm_set_config(wpa_s->wpa, NULL);
2256 			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2257 			wpa_supplicant_deauthenticate(
2258 				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2259 		}
2260 		ssid = wpa_s->conf->ssid;
2261 		while (ssid) {
2262 			struct wpa_ssid *remove_ssid = ssid;
2263 			id = ssid->id;
2264 			ssid = ssid->next;
2265 			wpas_notify_network_removed(wpa_s, remove_ssid);
2266 			wpa_config_remove_network(wpa_s->conf, id);
2267 		}
2268 		return 0;
2269 	}
2270 
2271 	id = atoi(cmd);
2272 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
2273 
2274 	ssid = wpa_config_get_network(wpa_s->conf, id);
2275 	if (ssid)
2276 		wpas_notify_network_removed(wpa_s, ssid);
2277 	if (ssid == NULL) {
2278 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2279 			   "id=%d", id);
2280 		return -1;
2281 	}
2282 
2283 	if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2284 #ifdef CONFIG_SME
2285 		wpa_s->sme.prev_bssid_set = 0;
2286 #endif /* CONFIG_SME */
2287 		/*
2288 		 * Invalidate the EAP session cache if the current or
2289 		 * previously used network is removed.
2290 		 */
2291 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2292 	}
2293 
2294 	if (ssid == wpa_s->current_ssid) {
2295 		wpa_sm_set_config(wpa_s->wpa, NULL);
2296 		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2297 
2298 		wpa_supplicant_deauthenticate(wpa_s,
2299 					      WLAN_REASON_DEAUTH_LEAVING);
2300 	}
2301 
2302 	was_disabled = ssid->disabled;
2303 
2304 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2305 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
2306 			   "network id=%d", id);
2307 		return -1;
2308 	}
2309 
2310 	if (!was_disabled && wpa_s->sched_scanning) {
2311 		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2312 			   "network from filters");
2313 		wpa_supplicant_cancel_sched_scan(wpa_s);
2314 		wpa_supplicant_req_scan(wpa_s, 0, 0);
2315 	}
2316 
2317 	return 0;
2318 }
2319 
2320 
wpa_supplicant_ctrl_iface_set_network(struct wpa_supplicant * wpa_s,char * cmd)2321 static int wpa_supplicant_ctrl_iface_set_network(
2322 	struct wpa_supplicant *wpa_s, char *cmd)
2323 {
2324 	int id;
2325 	struct wpa_ssid *ssid;
2326 	char *name, *value;
2327 
2328 	/* cmd: "<network id> <variable name> <value>" */
2329 	name = os_strchr(cmd, ' ');
2330 	if (name == NULL)
2331 		return -1;
2332 	*name++ = '\0';
2333 
2334 	value = os_strchr(name, ' ');
2335 	if (value == NULL)
2336 		return -1;
2337 	*value++ = '\0';
2338 
2339 	id = atoi(cmd);
2340 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
2341 		   id, name);
2342 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2343 			      (u8 *) value, os_strlen(value));
2344 
2345 	ssid = wpa_config_get_network(wpa_s->conf, id);
2346 	if (ssid == NULL) {
2347 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2348 			   "id=%d", id);
2349 		return -1;
2350 	}
2351 
2352 	if (wpa_config_set(ssid, name, value, 0) < 0) {
2353 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
2354 			   "variable '%s'", name);
2355 		return -1;
2356 	}
2357 
2358 	if (os_strcmp(name, "bssid") != 0 &&
2359 	    os_strcmp(name, "priority") != 0)
2360 		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2361 
2362 	if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
2363 		/*
2364 		 * Invalidate the EAP session cache if anything in the current
2365 		 * or previously used configuration changes.
2366 		 */
2367 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
2368 	}
2369 
2370 	if ((os_strcmp(name, "psk") == 0 &&
2371 	     value[0] == '"' && ssid->ssid_len) ||
2372 	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
2373 		wpa_config_update_psk(ssid);
2374 	else if (os_strcmp(name, "priority") == 0)
2375 		wpa_config_update_prio_list(wpa_s->conf);
2376 
2377 	return 0;
2378 }
2379 
2380 
wpa_supplicant_ctrl_iface_get_network(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2381 static int wpa_supplicant_ctrl_iface_get_network(
2382 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2383 {
2384 	int id;
2385 	size_t res;
2386 	struct wpa_ssid *ssid;
2387 	char *name, *value;
2388 
2389 	/* cmd: "<network id> <variable name>" */
2390 	name = os_strchr(cmd, ' ');
2391 	if (name == NULL || buflen == 0)
2392 		return -1;
2393 	*name++ = '\0';
2394 
2395 	id = atoi(cmd);
2396 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
2397 		   id, name);
2398 
2399 	ssid = wpa_config_get_network(wpa_s->conf, id);
2400 	if (ssid == NULL) {
2401 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2402 			   "id=%d", id);
2403 		return -1;
2404 	}
2405 
2406 	value = wpa_config_get_no_key(ssid, name);
2407 	if (value == NULL) {
2408 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
2409 			   "variable '%s'", name);
2410 		return -1;
2411 	}
2412 
2413 	res = os_strlcpy(buf, value, buflen);
2414 	if (res >= buflen) {
2415 		os_free(value);
2416 		return -1;
2417 	}
2418 
2419 	os_free(value);
2420 
2421 	return res;
2422 }
2423 
2424 
wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)2425 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
2426 						char *buf, size_t buflen)
2427 {
2428 	char *pos, *end;
2429 	struct wpa_cred *cred;
2430 	int ret;
2431 
2432 	pos = buf;
2433 	end = buf + buflen;
2434 	ret = os_snprintf(pos, end - pos,
2435 			  "cred id / realm / username / domain / imsi\n");
2436 	if (ret < 0 || ret >= end - pos)
2437 		return pos - buf;
2438 	pos += ret;
2439 
2440 	cred = wpa_s->conf->cred;
2441 	while (cred) {
2442 		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
2443 				  cred->id, cred->realm ? cred->realm : "",
2444 				  cred->username ? cred->username : "",
2445 				  cred->domain ? cred->domain : "",
2446 				  cred->imsi ? cred->imsi : "");
2447 		if (ret < 0 || ret >= end - pos)
2448 			return pos - buf;
2449 		pos += ret;
2450 
2451 		cred = cred->next;
2452 	}
2453 
2454 	return pos - buf;
2455 }
2456 
2457 
wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)2458 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
2459 					      char *buf, size_t buflen)
2460 {
2461 	struct wpa_cred *cred;
2462 	int ret;
2463 
2464 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
2465 
2466 	cred = wpa_config_add_cred(wpa_s->conf);
2467 	if (cred == NULL)
2468 		return -1;
2469 
2470 	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
2471 	if (ret < 0 || (size_t) ret >= buflen)
2472 		return -1;
2473 	return ret;
2474 }
2475 
2476 
wpas_ctrl_remove_cred(struct wpa_supplicant * wpa_s,struct wpa_cred * cred)2477 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
2478 				 struct wpa_cred *cred)
2479 {
2480 	struct wpa_ssid *ssid;
2481 	char str[20];
2482 
2483 	if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) {
2484 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
2485 		return -1;
2486 	}
2487 
2488 	/* Remove any network entry created based on the removed credential */
2489 	ssid = wpa_s->conf->ssid;
2490 	while (ssid) {
2491 		if (ssid->parent_cred == cred) {
2492 			wpa_printf(MSG_DEBUG, "Remove network id %d since it "
2493 				   "used the removed credential", ssid->id);
2494 			os_snprintf(str, sizeof(str), "%d", ssid->id);
2495 			ssid = ssid->next;
2496 			wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
2497 		} else
2498 			ssid = ssid->next;
2499 	}
2500 
2501 	return 0;
2502 }
2503 
2504 
wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant * wpa_s,char * cmd)2505 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
2506 						 char *cmd)
2507 {
2508 	int id;
2509 	struct wpa_cred *cred, *prev;
2510 
2511 	/* cmd: "<cred id>", "all", or "sp_fqdn=<FQDN>" */
2512 	if (os_strcmp(cmd, "all") == 0) {
2513 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
2514 		cred = wpa_s->conf->cred;
2515 		while (cred) {
2516 			prev = cred;
2517 			cred = cred->next;
2518 			wpas_ctrl_remove_cred(wpa_s, prev);
2519 		}
2520 		return 0;
2521 	}
2522 
2523 	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
2524 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
2525 			   cmd + 8);
2526 		cred = wpa_s->conf->cred;
2527 		while (cred) {
2528 			prev = cred;
2529 			cred = cred->next;
2530 			if (prev->domain &&
2531 			    os_strcmp(prev->domain, cmd + 8) == 0)
2532 				wpas_ctrl_remove_cred(wpa_s, prev);
2533 		}
2534 		return 0;
2535 	}
2536 
2537 	id = atoi(cmd);
2538 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
2539 
2540 	cred = wpa_config_get_cred(wpa_s->conf, id);
2541 	return wpas_ctrl_remove_cred(wpa_s, cred);
2542 }
2543 
2544 
wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant * wpa_s,char * cmd)2545 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
2546 					      char *cmd)
2547 {
2548 	int id;
2549 	struct wpa_cred *cred;
2550 	char *name, *value;
2551 
2552 	/* cmd: "<cred id> <variable name> <value>" */
2553 	name = os_strchr(cmd, ' ');
2554 	if (name == NULL)
2555 		return -1;
2556 	*name++ = '\0';
2557 
2558 	value = os_strchr(name, ' ');
2559 	if (value == NULL)
2560 		return -1;
2561 	*value++ = '\0';
2562 
2563 	id = atoi(cmd);
2564 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
2565 		   id, name);
2566 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2567 			      (u8 *) value, os_strlen(value));
2568 
2569 	cred = wpa_config_get_cred(wpa_s->conf, id);
2570 	if (cred == NULL) {
2571 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2572 			   id);
2573 		return -1;
2574 	}
2575 
2576 	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
2577 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
2578 			   "variable '%s'", name);
2579 		return -1;
2580 	}
2581 
2582 	return 0;
2583 }
2584 
2585 
2586 #ifndef CONFIG_NO_CONFIG_WRITE
wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant * wpa_s)2587 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
2588 {
2589 	int ret;
2590 
2591 	if (!wpa_s->conf->update_config) {
2592 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
2593 			   "to update configuration (update_config=0)");
2594 		return -1;
2595 	}
2596 
2597 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2598 	if (ret) {
2599 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
2600 			   "update configuration");
2601 	} else {
2602 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
2603 			   " updated");
2604 	}
2605 
2606 	return ret;
2607 }
2608 #endif /* CONFIG_NO_CONFIG_WRITE */
2609 
2610 
ctrl_iface_get_capability_pairwise(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)2611 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
2612 					      struct wpa_driver_capa *capa,
2613 					      char *buf, size_t buflen)
2614 {
2615 	int ret, first = 1;
2616 	char *pos, *end;
2617 	size_t len;
2618 
2619 	pos = buf;
2620 	end = pos + buflen;
2621 
2622 	if (res < 0) {
2623 		if (strict)
2624 			return 0;
2625 		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
2626 		if (len >= buflen)
2627 			return -1;
2628 		return len;
2629 	}
2630 
2631 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2632 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2633 		if (ret < 0 || ret >= end - pos)
2634 			return pos - buf;
2635 		pos += ret;
2636 		first = 0;
2637 	}
2638 
2639 	if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2640 		ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
2641 		if (ret < 0 || ret >= end - pos)
2642 			return pos - buf;
2643 		pos += ret;
2644 		first = 0;
2645 	}
2646 
2647 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2648 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2649 		if (ret < 0 || ret >= end - pos)
2650 			return pos - buf;
2651 		pos += ret;
2652 		first = 0;
2653 	}
2654 
2655 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2656 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
2657 		if (ret < 0 || ret >= end - pos)
2658 			return pos - buf;
2659 		pos += ret;
2660 		first = 0;
2661 	}
2662 
2663 	return pos - buf;
2664 }
2665 
2666 
ctrl_iface_get_capability_group(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)2667 static int ctrl_iface_get_capability_group(int res, char *strict,
2668 					   struct wpa_driver_capa *capa,
2669 					   char *buf, size_t buflen)
2670 {
2671 	int ret, first = 1;
2672 	char *pos, *end;
2673 	size_t len;
2674 
2675 	pos = buf;
2676 	end = pos + buflen;
2677 
2678 	if (res < 0) {
2679 		if (strict)
2680 			return 0;
2681 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
2682 		if (len >= buflen)
2683 			return -1;
2684 		return len;
2685 	}
2686 
2687 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2688 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2689 		if (ret < 0 || ret >= end - pos)
2690 			return pos - buf;
2691 		pos += ret;
2692 		first = 0;
2693 	}
2694 
2695 	if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2696 		ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
2697 		if (ret < 0 || ret >= end - pos)
2698 			return pos - buf;
2699 		pos += ret;
2700 		first = 0;
2701 	}
2702 
2703 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2704 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2705 		if (ret < 0 || ret >= end - pos)
2706 			return pos - buf;
2707 		pos += ret;
2708 		first = 0;
2709 	}
2710 
2711 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2712 		ret = os_snprintf(pos, end - pos, "%sWEP104",
2713 				  first ? "" : " ");
2714 		if (ret < 0 || ret >= end - pos)
2715 			return pos - buf;
2716 		pos += ret;
2717 		first = 0;
2718 	}
2719 
2720 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2721 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
2722 		if (ret < 0 || ret >= end - pos)
2723 			return pos - buf;
2724 		pos += ret;
2725 		first = 0;
2726 	}
2727 
2728 	return pos - buf;
2729 }
2730 
2731 
ctrl_iface_get_capability_key_mgmt(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)2732 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
2733 					      struct wpa_driver_capa *capa,
2734 					      char *buf, size_t buflen)
2735 {
2736 	int ret;
2737 	char *pos, *end;
2738 	size_t len;
2739 
2740 	pos = buf;
2741 	end = pos + buflen;
2742 
2743 	if (res < 0) {
2744 		if (strict)
2745 			return 0;
2746 		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
2747 				 "NONE", buflen);
2748 		if (len >= buflen)
2749 			return -1;
2750 		return len;
2751 	}
2752 
2753 	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
2754 	if (ret < 0 || ret >= end - pos)
2755 		return pos - buf;
2756 	pos += ret;
2757 
2758 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2759 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2760 		ret = os_snprintf(pos, end - pos, " WPA-EAP");
2761 		if (ret < 0 || ret >= end - pos)
2762 			return pos - buf;
2763 		pos += ret;
2764 	}
2765 
2766 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2767 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2768 		ret = os_snprintf(pos, end - pos, " WPA-PSK");
2769 		if (ret < 0 || ret >= end - pos)
2770 			return pos - buf;
2771 		pos += ret;
2772 	}
2773 
2774 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2775 		ret = os_snprintf(pos, end - pos, " WPA-NONE");
2776 		if (ret < 0 || ret >= end - pos)
2777 			return pos - buf;
2778 		pos += ret;
2779 	}
2780 
2781 	return pos - buf;
2782 }
2783 
2784 
ctrl_iface_get_capability_proto(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)2785 static int ctrl_iface_get_capability_proto(int res, char *strict,
2786 					   struct wpa_driver_capa *capa,
2787 					   char *buf, size_t buflen)
2788 {
2789 	int ret, first = 1;
2790 	char *pos, *end;
2791 	size_t len;
2792 
2793 	pos = buf;
2794 	end = pos + buflen;
2795 
2796 	if (res < 0) {
2797 		if (strict)
2798 			return 0;
2799 		len = os_strlcpy(buf, "RSN WPA", buflen);
2800 		if (len >= buflen)
2801 			return -1;
2802 		return len;
2803 	}
2804 
2805 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2806 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2807 		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
2808 		if (ret < 0 || ret >= end - pos)
2809 			return pos - buf;
2810 		pos += ret;
2811 		first = 0;
2812 	}
2813 
2814 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2815 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2816 		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
2817 		if (ret < 0 || ret >= end - pos)
2818 			return pos - buf;
2819 		pos += ret;
2820 		first = 0;
2821 	}
2822 
2823 	return pos - buf;
2824 }
2825 
2826 
ctrl_iface_get_capability_auth_alg(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)2827 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
2828 					      struct wpa_driver_capa *capa,
2829 					      char *buf, size_t buflen)
2830 {
2831 	int ret, first = 1;
2832 	char *pos, *end;
2833 	size_t len;
2834 
2835 	pos = buf;
2836 	end = pos + buflen;
2837 
2838 	if (res < 0) {
2839 		if (strict)
2840 			return 0;
2841 		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
2842 		if (len >= buflen)
2843 			return -1;
2844 		return len;
2845 	}
2846 
2847 	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
2848 		ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
2849 		if (ret < 0 || ret >= end - pos)
2850 			return pos - buf;
2851 		pos += ret;
2852 		first = 0;
2853 	}
2854 
2855 	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
2856 		ret = os_snprintf(pos, end - pos, "%sSHARED",
2857 				  first ? "" : " ");
2858 		if (ret < 0 || ret >= end - pos)
2859 			return pos - buf;
2860 		pos += ret;
2861 		first = 0;
2862 	}
2863 
2864 	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
2865 		ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
2866 		if (ret < 0 || ret >= end - pos)
2867 			return pos - buf;
2868 		pos += ret;
2869 		first = 0;
2870 	}
2871 
2872 	return pos - buf;
2873 }
2874 
2875 
ctrl_iface_get_capability_modes(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)2876 static int ctrl_iface_get_capability_modes(int res, char *strict,
2877 					   struct wpa_driver_capa *capa,
2878 					   char *buf, size_t buflen)
2879 {
2880 	int ret, first = 1;
2881 	char *pos, *end;
2882 	size_t len;
2883 
2884 	pos = buf;
2885 	end = pos + buflen;
2886 
2887 	if (res < 0) {
2888 		if (strict)
2889 			return 0;
2890 		len = os_strlcpy(buf, "IBSS AP", buflen);
2891 		if (len >= buflen)
2892 			return -1;
2893 		return len;
2894 	}
2895 
2896 	if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
2897 		ret = os_snprintf(pos, end - pos, "%sIBSS", first ? "" : " ");
2898 		if (ret < 0 || ret >= end - pos)
2899 			return pos - buf;
2900 		pos += ret;
2901 		first = 0;
2902 	}
2903 
2904 	if (capa->flags & WPA_DRIVER_FLAGS_AP) {
2905 		ret = os_snprintf(pos, end - pos, "%sAP", first ? "" : " ");
2906 		if (ret < 0 || ret >= end - pos)
2907 			return pos - buf;
2908 		pos += ret;
2909 		first = 0;
2910 	}
2911 
2912 	return pos - buf;
2913 }
2914 
2915 
ctrl_iface_get_capability_channels(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)2916 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
2917 					      char *buf, size_t buflen)
2918 {
2919 	struct hostapd_channel_data *chnl;
2920 	int ret, i, j;
2921 	char *pos, *end, *hmode;
2922 
2923 	pos = buf;
2924 	end = pos + buflen;
2925 
2926 	for (j = 0; j < wpa_s->hw.num_modes; j++) {
2927 		switch (wpa_s->hw.modes[j].mode) {
2928 		case HOSTAPD_MODE_IEEE80211B:
2929 			hmode = "B";
2930 			break;
2931 		case HOSTAPD_MODE_IEEE80211G:
2932 			hmode = "G";
2933 			break;
2934 		case HOSTAPD_MODE_IEEE80211A:
2935 			hmode = "A";
2936 			break;
2937 		case HOSTAPD_MODE_IEEE80211AD:
2938 			hmode = "AD";
2939 			break;
2940 		default:
2941 			continue;
2942 		}
2943 		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
2944 		if (ret < 0 || ret >= end - pos)
2945 			return pos - buf;
2946 		pos += ret;
2947 		chnl = wpa_s->hw.modes[j].channels;
2948 		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
2949 			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
2950 				continue;
2951 			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
2952 			if (ret < 0 || ret >= end - pos)
2953 				return pos - buf;
2954 			pos += ret;
2955 		}
2956 		ret = os_snprintf(pos, end - pos, "\n");
2957 		if (ret < 0 || ret >= end - pos)
2958 			return pos - buf;
2959 		pos += ret;
2960 	}
2961 
2962 	return pos - buf;
2963 }
2964 
2965 
wpa_supplicant_ctrl_iface_get_capability(struct wpa_supplicant * wpa_s,const char * _field,char * buf,size_t buflen)2966 static int wpa_supplicant_ctrl_iface_get_capability(
2967 	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
2968 	size_t buflen)
2969 {
2970 	struct wpa_driver_capa capa;
2971 	int res;
2972 	char *strict;
2973 	char field[30];
2974 	size_t len;
2975 
2976 	/* Determine whether or not strict checking was requested */
2977 	len = os_strlcpy(field, _field, sizeof(field));
2978 	if (len >= sizeof(field))
2979 		return -1;
2980 	strict = os_strchr(field, ' ');
2981 	if (strict != NULL) {
2982 		*strict++ = '\0';
2983 		if (os_strcmp(strict, "strict") != 0)
2984 			return -1;
2985 	}
2986 
2987 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
2988 		field, strict ? strict : "");
2989 
2990 	if (os_strcmp(field, "eap") == 0) {
2991 		return eap_get_names(buf, buflen);
2992 	}
2993 
2994 	res = wpa_drv_get_capa(wpa_s, &capa);
2995 
2996 	if (os_strcmp(field, "pairwise") == 0)
2997 		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
2998 							  buf, buflen);
2999 
3000 	if (os_strcmp(field, "group") == 0)
3001 		return ctrl_iface_get_capability_group(res, strict, &capa,
3002 						       buf, buflen);
3003 
3004 	if (os_strcmp(field, "key_mgmt") == 0)
3005 		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
3006 							  buf, buflen);
3007 
3008 	if (os_strcmp(field, "proto") == 0)
3009 		return ctrl_iface_get_capability_proto(res, strict, &capa,
3010 						       buf, buflen);
3011 
3012 	if (os_strcmp(field, "auth_alg") == 0)
3013 		return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
3014 							  buf, buflen);
3015 
3016 	if (os_strcmp(field, "modes") == 0)
3017 		return ctrl_iface_get_capability_modes(res, strict, &capa,
3018 						       buf, buflen);
3019 
3020 	if (os_strcmp(field, "channels") == 0)
3021 		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
3022 
3023 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3024 		   field);
3025 
3026 	return -1;
3027 }
3028 
3029 
3030 #ifdef CONFIG_INTERWORKING
anqp_add_hex(char * pos,char * end,const char * title,struct wpabuf * data)3031 static char * anqp_add_hex(char *pos, char *end, const char *title,
3032 			   struct wpabuf *data)
3033 {
3034 	char *start = pos;
3035 	size_t i;
3036 	int ret;
3037 	const u8 *d;
3038 
3039 	if (data == NULL)
3040 		return start;
3041 
3042 	ret = os_snprintf(pos, end - pos, "%s=", title);
3043 	if (ret < 0 || ret >= end - pos)
3044 		return start;
3045 	pos += ret;
3046 
3047 	d = wpabuf_head_u8(data);
3048 	for (i = 0; i < wpabuf_len(data); i++) {
3049 		ret = os_snprintf(pos, end - pos, "%02x", *d++);
3050 		if (ret < 0 || ret >= end - pos)
3051 			return start;
3052 		pos += ret;
3053 	}
3054 
3055 	ret = os_snprintf(pos, end - pos, "\n");
3056 	if (ret < 0 || ret >= end - pos)
3057 		return start;
3058 	pos += ret;
3059 
3060 	return pos;
3061 }
3062 #endif /* CONFIG_INTERWORKING */
3063 
3064 
print_bss_info(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,unsigned long mask,char * buf,size_t buflen)3065 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
3066 			  unsigned long mask, char *buf, size_t buflen)
3067 {
3068 	size_t i;
3069 	int ret;
3070 	char *pos, *end;
3071 	const u8 *ie, *ie2;
3072 
3073 	pos = buf;
3074 	end = buf + buflen;
3075 
3076 	if (mask & WPA_BSS_MASK_ID) {
3077 		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
3078 		if (ret < 0 || ret >= end - pos)
3079 			return 0;
3080 		pos += ret;
3081 	}
3082 
3083 	if (mask & WPA_BSS_MASK_BSSID) {
3084 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
3085 				  MAC2STR(bss->bssid));
3086 		if (ret < 0 || ret >= end - pos)
3087 			return 0;
3088 		pos += ret;
3089 	}
3090 
3091 	if (mask & WPA_BSS_MASK_FREQ) {
3092 		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
3093 		if (ret < 0 || ret >= end - pos)
3094 			return 0;
3095 		pos += ret;
3096 	}
3097 
3098 	if (mask & WPA_BSS_MASK_BEACON_INT) {
3099 		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
3100 				  bss->beacon_int);
3101 		if (ret < 0 || ret >= end - pos)
3102 			return 0;
3103 		pos += ret;
3104 	}
3105 
3106 	if (mask & WPA_BSS_MASK_CAPABILITIES) {
3107 		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
3108 				  bss->caps);
3109 		if (ret < 0 || ret >= end - pos)
3110 			return 0;
3111 		pos += ret;
3112 	}
3113 
3114 	if (mask & WPA_BSS_MASK_QUAL) {
3115 		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
3116 		if (ret < 0 || ret >= end - pos)
3117 			return 0;
3118 		pos += ret;
3119 	}
3120 
3121 	if (mask & WPA_BSS_MASK_NOISE) {
3122 		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
3123 		if (ret < 0 || ret >= end - pos)
3124 			return 0;
3125 		pos += ret;
3126 	}
3127 
3128 	if (mask & WPA_BSS_MASK_LEVEL) {
3129 		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
3130 		if (ret < 0 || ret >= end - pos)
3131 			return 0;
3132 		pos += ret;
3133 	}
3134 
3135 	if (mask & WPA_BSS_MASK_TSF) {
3136 		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
3137 				  (unsigned long long) bss->tsf);
3138 		if (ret < 0 || ret >= end - pos)
3139 			return 0;
3140 		pos += ret;
3141 	}
3142 
3143 	if (mask & WPA_BSS_MASK_AGE) {
3144 		struct os_time now;
3145 
3146 		os_get_time(&now);
3147 		ret = os_snprintf(pos, end - pos, "age=%d\n",
3148 				  (int) (now.sec - bss->last_update.sec));
3149 		if (ret < 0 || ret >= end - pos)
3150 			return 0;
3151 		pos += ret;
3152 	}
3153 
3154 	if (mask & WPA_BSS_MASK_IE) {
3155 		ret = os_snprintf(pos, end - pos, "ie=");
3156 		if (ret < 0 || ret >= end - pos)
3157 			return 0;
3158 		pos += ret;
3159 
3160 		ie = (const u8 *) (bss + 1);
3161 		for (i = 0; i < bss->ie_len; i++) {
3162 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
3163 			if (ret < 0 || ret >= end - pos)
3164 				return 0;
3165 			pos += ret;
3166 		}
3167 
3168 		ret = os_snprintf(pos, end - pos, "\n");
3169 		if (ret < 0 || ret >= end - pos)
3170 			return 0;
3171 		pos += ret;
3172 	}
3173 
3174 	if (mask & WPA_BSS_MASK_FLAGS) {
3175 		ret = os_snprintf(pos, end - pos, "flags=");
3176 		if (ret < 0 || ret >= end - pos)
3177 			return 0;
3178 		pos += ret;
3179 
3180 		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3181 		if (ie)
3182 			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
3183 						    2 + ie[1]);
3184 		ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3185 		if (ie2)
3186 			pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
3187 						    2 + ie2[1]);
3188 		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3189 		if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
3190 			ret = os_snprintf(pos, end - pos, "[WEP]");
3191 			if (ret < 0 || ret >= end - pos)
3192 				return 0;
3193 			pos += ret;
3194 		}
3195 		if (bss->caps & IEEE80211_CAP_IBSS) {
3196 			ret = os_snprintf(pos, end - pos, "[IBSS]");
3197 			if (ret < 0 || ret >= end - pos)
3198 				return 0;
3199 			pos += ret;
3200 		}
3201 		if (bss->caps & IEEE80211_CAP_ESS) {
3202 			ret = os_snprintf(pos, end - pos, "[ESS]");
3203 			if (ret < 0 || ret >= end - pos)
3204 				return 0;
3205 			pos += ret;
3206 		}
3207 		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
3208 			ret = os_snprintf(pos, end - pos, "[P2P]");
3209 			if (ret < 0 || ret >= end - pos)
3210 				return 0;
3211 			pos += ret;
3212 		}
3213 #ifdef CONFIG_HS20
3214 		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
3215 			ret = os_snprintf(pos, end - pos, "[HS20]");
3216 			if (ret < 0 || ret >= end - pos)
3217 				return 0;
3218 			pos += ret;
3219 		}
3220 #endif /* CONFIG_HS20 */
3221 
3222 		ret = os_snprintf(pos, end - pos, "\n");
3223 		if (ret < 0 || ret >= end - pos)
3224 			return 0;
3225 		pos += ret;
3226 	}
3227 
3228 	if (mask & WPA_BSS_MASK_SSID) {
3229 		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
3230 				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
3231 		if (ret < 0 || ret >= end - pos)
3232 			return 0;
3233 		pos += ret;
3234 	}
3235 
3236 #ifdef CONFIG_WPS
3237 	if (mask & WPA_BSS_MASK_WPS_SCAN) {
3238 		ie = (const u8 *) (bss + 1);
3239 		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
3240 		if (ret < 0 || ret >= end - pos)
3241 			return 0;
3242 		pos += ret;
3243 	}
3244 #endif /* CONFIG_WPS */
3245 
3246 #ifdef CONFIG_P2P
3247 	if (mask & WPA_BSS_MASK_P2P_SCAN) {
3248 		ie = (const u8 *) (bss + 1);
3249 		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
3250 		if (ret < 0 || ret >= end - pos)
3251 			return 0;
3252 		pos += ret;
3253 	}
3254 #endif /* CONFIG_P2P */
3255 
3256 #ifdef CONFIG_WIFI_DISPLAY
3257 	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
3258 		struct wpabuf *wfd;
3259 		ie = (const u8 *) (bss + 1);
3260 		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
3261 						  WFD_IE_VENDOR_TYPE);
3262 		if (wfd) {
3263 			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
3264 			if (ret < 0 || ret >= end - pos)
3265 				return 0;
3266 			pos += ret;
3267 
3268 			pos += wpa_snprintf_hex(pos, end - pos,
3269 						wpabuf_head(wfd),
3270 						wpabuf_len(wfd));
3271 			wpabuf_free(wfd);
3272 
3273 			ret = os_snprintf(pos, end - pos, "\n");
3274 			if (ret < 0 || ret >= end - pos)
3275 				return 0;
3276 			pos += ret;
3277 		}
3278 	}
3279 #endif /* CONFIG_WIFI_DISPLAY */
3280 
3281 #ifdef CONFIG_INTERWORKING
3282 	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
3283 		struct wpa_bss_anqp *anqp = bss->anqp;
3284 		pos = anqp_add_hex(pos, end, "anqp_venue_name",
3285 				   anqp->venue_name);
3286 		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
3287 				   anqp->network_auth_type);
3288 		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
3289 				   anqp->roaming_consortium);
3290 		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
3291 				   anqp->ip_addr_type_availability);
3292 		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
3293 				   anqp->nai_realm);
3294 		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
3295 		pos = anqp_add_hex(pos, end, "anqp_domain_name",
3296 				   anqp->domain_name);
3297 #ifdef CONFIG_HS20
3298 		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
3299 				   anqp->hs20_operator_friendly_name);
3300 		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
3301 				   anqp->hs20_wan_metrics);
3302 		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
3303 				   anqp->hs20_connection_capability);
3304 #endif /* CONFIG_HS20 */
3305 	}
3306 #endif /* CONFIG_INTERWORKING */
3307 
3308 	if (mask & WPA_BSS_MASK_DELIM) {
3309 		ret = os_snprintf(pos, end - pos, "====\n");
3310 		if (ret < 0 || ret >= end - pos)
3311 			return 0;
3312 		pos += ret;
3313 	}
3314 
3315 	return pos - buf;
3316 }
3317 
3318 
wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)3319 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
3320 					 const char *cmd, char *buf,
3321 					 size_t buflen)
3322 {
3323 	u8 bssid[ETH_ALEN];
3324 	size_t i;
3325 	struct wpa_bss *bss;
3326 	struct wpa_bss *bsslast = NULL;
3327 	struct dl_list *next;
3328 	int ret = 0;
3329 	int len;
3330 	char *ctmp;
3331 	unsigned long mask = WPA_BSS_MASK_ALL;
3332 
3333 	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
3334 		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
3335 			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
3336 					    list_id);
3337 			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
3338 					       list_id);
3339 		} else { /* N1-N2 */
3340 			unsigned int id1, id2;
3341 
3342 			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
3343 				wpa_printf(MSG_INFO, "Wrong BSS range "
3344 					   "format");
3345 				return 0;
3346 			}
3347 
3348 			if (*(cmd + 6) == '-')
3349 				id1 = 0;
3350 			else
3351 				id1 = atoi(cmd + 6);
3352 			ctmp++;
3353 			if (*ctmp >= '0' && *ctmp <= '9')
3354 				id2 = atoi(ctmp);
3355 			else
3356 				id2 = (unsigned int) -1;
3357 			bss = wpa_bss_get_id_range(wpa_s, id1, id2);
3358 			if (id2 == (unsigned int) -1)
3359 				bsslast = dl_list_last(&wpa_s->bss_id,
3360 						       struct wpa_bss,
3361 						       list_id);
3362 			else {
3363 				bsslast = wpa_bss_get_id(wpa_s, id2);
3364 				if (bsslast == NULL && bss && id2 > id1) {
3365 					struct wpa_bss *tmp = bss;
3366 					for (;;) {
3367 						next = tmp->list_id.next;
3368 						if (next == &wpa_s->bss_id)
3369 							break;
3370 						tmp = dl_list_entry(
3371 							next, struct wpa_bss,
3372 							list_id);
3373 						if (tmp->id > id2)
3374 							break;
3375 						bsslast = tmp;
3376 					}
3377 				}
3378 			}
3379 		}
3380 	} else if (os_strncmp(cmd, "FIRST", 5) == 0)
3381 		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
3382 	else if (os_strncmp(cmd, "LAST", 4) == 0)
3383 		bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
3384 	else if (os_strncmp(cmd, "ID-", 3) == 0) {
3385 		i = atoi(cmd + 3);
3386 		bss = wpa_bss_get_id(wpa_s, i);
3387 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
3388 		i = atoi(cmd + 5);
3389 		bss = wpa_bss_get_id(wpa_s, i);
3390 		if (bss) {
3391 			next = bss->list_id.next;
3392 			if (next == &wpa_s->bss_id)
3393 				bss = NULL;
3394 			else
3395 				bss = dl_list_entry(next, struct wpa_bss,
3396 						    list_id);
3397 		}
3398 #ifdef CONFIG_P2P
3399 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
3400 		if (hwaddr_aton(cmd + 13, bssid) == 0)
3401 			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
3402 		else
3403 			bss = NULL;
3404 #endif /* CONFIG_P2P */
3405 	} else if (hwaddr_aton(cmd, bssid) == 0)
3406 		bss = wpa_bss_get_bssid(wpa_s, bssid);
3407 	else {
3408 		struct wpa_bss *tmp;
3409 		i = atoi(cmd);
3410 		bss = NULL;
3411 		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
3412 		{
3413 			if (i-- == 0) {
3414 				bss = tmp;
3415 				break;
3416 			}
3417 		}
3418 	}
3419 
3420 	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
3421 		mask = strtoul(ctmp + 5, NULL, 0x10);
3422 		if (mask == 0)
3423 			mask = WPA_BSS_MASK_ALL;
3424 	}
3425 
3426 	if (bss == NULL)
3427 		return 0;
3428 
3429 	if (bsslast == NULL)
3430 		bsslast = bss;
3431 	do {
3432 		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
3433 		ret += len;
3434 		buf += len;
3435 		buflen -= len;
3436 		if (bss == bsslast) {
3437 			if ((mask & WPA_BSS_MASK_DELIM) && len &&
3438 			    (bss == dl_list_last(&wpa_s->bss_id,
3439 						 struct wpa_bss, list_id)))
3440 				os_snprintf(buf - 5, 5, "####\n");
3441 			break;
3442 		}
3443 		next = bss->list_id.next;
3444 		if (next == &wpa_s->bss_id)
3445 			break;
3446 		bss = dl_list_entry(next, struct wpa_bss, list_id);
3447 	} while (bss && len);
3448 
3449 	return ret;
3450 }
3451 
3452 
wpa_supplicant_ctrl_iface_ap_scan(struct wpa_supplicant * wpa_s,char * cmd)3453 static int wpa_supplicant_ctrl_iface_ap_scan(
3454 	struct wpa_supplicant *wpa_s, char *cmd)
3455 {
3456 	int ap_scan = atoi(cmd);
3457 	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
3458 }
3459 
3460 
wpa_supplicant_ctrl_iface_scan_interval(struct wpa_supplicant * wpa_s,char * cmd)3461 static int wpa_supplicant_ctrl_iface_scan_interval(
3462 	struct wpa_supplicant *wpa_s, char *cmd)
3463 {
3464 	int scan_int = atoi(cmd);
3465 	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
3466 }
3467 
3468 
wpa_supplicant_ctrl_iface_bss_expire_age(struct wpa_supplicant * wpa_s,char * cmd)3469 static int wpa_supplicant_ctrl_iface_bss_expire_age(
3470 	struct wpa_supplicant *wpa_s, char *cmd)
3471 {
3472 	int expire_age = atoi(cmd);
3473 	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
3474 }
3475 
3476 
wpa_supplicant_ctrl_iface_bss_expire_count(struct wpa_supplicant * wpa_s,char * cmd)3477 static int wpa_supplicant_ctrl_iface_bss_expire_count(
3478 	struct wpa_supplicant *wpa_s, char *cmd)
3479 {
3480 	int expire_count = atoi(cmd);
3481 	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
3482 }
3483 
3484 
wpa_supplicant_ctrl_iface_bss_flush(struct wpa_supplicant * wpa_s,char * cmd)3485 static int wpa_supplicant_ctrl_iface_bss_flush(
3486 	struct wpa_supplicant *wpa_s, char *cmd)
3487 {
3488 	int flush_age = atoi(cmd);
3489 
3490 	if (flush_age == 0)
3491 		wpa_bss_flush(wpa_s);
3492 	else
3493 		wpa_bss_flush_by_age(wpa_s, flush_age);
3494 	return 0;
3495 }
3496 
3497 
wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant * wpa_s)3498 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
3499 {
3500 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
3501 	/* MLME-DELETEKEYS.request */
3502 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
3503 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
3504 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
3505 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
3506 #ifdef CONFIG_IEEE80211W
3507 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
3508 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
3509 #endif /* CONFIG_IEEE80211W */
3510 
3511 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
3512 			0);
3513 	/* MLME-SETPROTECTION.request(None) */
3514 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
3515 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
3516 				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
3517 	wpa_sm_drop_sa(wpa_s->wpa);
3518 }
3519 
3520 
wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant * wpa_s,char * addr)3521 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
3522 					  char *addr)
3523 {
3524 #ifdef CONFIG_NO_SCAN_PROCESSING
3525 	return -1;
3526 #else /* CONFIG_NO_SCAN_PROCESSING */
3527 	u8 bssid[ETH_ALEN];
3528 	struct wpa_bss *bss;
3529 	struct wpa_ssid *ssid = wpa_s->current_ssid;
3530 
3531 	if (hwaddr_aton(addr, bssid)) {
3532 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
3533 			   "address '%s'", addr);
3534 		return -1;
3535 	}
3536 
3537 	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
3538 
3539 	if (!ssid) {
3540 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
3541 			   "configuration known for the target AP");
3542 		return -1;
3543 	}
3544 
3545 	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
3546 	if (!bss) {
3547 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
3548 			   "from BSS table");
3549 		return -1;
3550 	}
3551 
3552 	/*
3553 	 * TODO: Find best network configuration block from configuration to
3554 	 * allow roaming to other networks
3555 	 */
3556 
3557 	wpa_s->reassociate = 1;
3558 	wpa_supplicant_connect(wpa_s, bss, ssid);
3559 
3560 	return 0;
3561 #endif /* CONFIG_NO_SCAN_PROCESSING */
3562 }
3563 
3564 
3565 #ifdef CONFIG_P2P
p2p_ctrl_find(struct wpa_supplicant * wpa_s,char * cmd)3566 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
3567 {
3568 	unsigned int timeout = atoi(cmd);
3569 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
3570 	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
3571 	char *pos;
3572 	unsigned int search_delay;
3573 
3574 	if (os_strstr(cmd, "type=social"))
3575 		type = P2P_FIND_ONLY_SOCIAL;
3576 	else if (os_strstr(cmd, "type=progressive"))
3577 		type = P2P_FIND_PROGRESSIVE;
3578 
3579 	pos = os_strstr(cmd, "dev_id=");
3580 	if (pos) {
3581 		pos += 7;
3582 		if (hwaddr_aton(pos, dev_id))
3583 			return -1;
3584 		_dev_id = dev_id;
3585 	}
3586 
3587 	pos = os_strstr(cmd, "delay=");
3588 	if (pos) {
3589 		pos += 6;
3590 		search_delay = atoi(pos);
3591 	} else
3592 		search_delay = wpas_p2p_search_delay(wpa_s);
3593 
3594 	return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id,
3595 			     search_delay);
3596 }
3597 
3598 
p2p_ctrl_connect(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3599 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
3600 			    char *buf, size_t buflen)
3601 {
3602 	u8 addr[ETH_ALEN];
3603 	char *pos, *pos2;
3604 	char *pin = NULL;
3605 	enum p2p_wps_method wps_method;
3606 	int new_pin;
3607 	int ret;
3608 	int persistent_group, persistent_id = -1;
3609 	int join;
3610 	int auth;
3611 	int automatic;
3612 	int go_intent = -1;
3613 	int freq = 0;
3614 	int pd;
3615 	int ht40;
3616 
3617 	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
3618 	 * [persistent|persistent=<network id>]
3619 	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
3620 	 * [ht40] */
3621 
3622 	if (hwaddr_aton(cmd, addr))
3623 		return -1;
3624 
3625 	pos = cmd + 17;
3626 	if (*pos != ' ')
3627 		return -1;
3628 	pos++;
3629 
3630 	persistent_group = os_strstr(pos, " persistent") != NULL;
3631 	pos2 = os_strstr(pos, " persistent=");
3632 	if (pos2) {
3633 		struct wpa_ssid *ssid;
3634 		persistent_id = atoi(pos2 + 12);
3635 		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
3636 		if (ssid == NULL || ssid->disabled != 2 ||
3637 		    ssid->mode != WPAS_MODE_P2P_GO) {
3638 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3639 				   "SSID id=%d for persistent P2P group (GO)",
3640 				   persistent_id);
3641 			return -1;
3642 		}
3643 	}
3644 	join = os_strstr(pos, " join") != NULL;
3645 	auth = os_strstr(pos, " auth") != NULL;
3646 	automatic = os_strstr(pos, " auto") != NULL;
3647 	pd = os_strstr(pos, " provdisc") != NULL;
3648 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
3649 
3650 	pos2 = os_strstr(pos, " go_intent=");
3651 	if (pos2) {
3652 		pos2 += 11;
3653 		go_intent = atoi(pos2);
3654 		if (go_intent < 0 || go_intent > 15)
3655 			return -1;
3656 	}
3657 
3658 	pos2 = os_strstr(pos, " freq=");
3659 	if (pos2) {
3660 		pos2 += 6;
3661 		freq = atoi(pos2);
3662 		if (freq <= 0)
3663 			return -1;
3664 	}
3665 
3666 	if (os_strncmp(pos, "pin", 3) == 0) {
3667 		/* Request random PIN (to be displayed) and enable the PIN */
3668 		wps_method = WPS_PIN_DISPLAY;
3669 	} else if (os_strncmp(pos, "pbc", 3) == 0) {
3670 		wps_method = WPS_PBC;
3671 	} else {
3672 		pin = pos;
3673 		pos = os_strchr(pin, ' ');
3674 		wps_method = WPS_PIN_KEYPAD;
3675 		if (pos) {
3676 			*pos++ = '\0';
3677 			if (os_strncmp(pos, "display", 7) == 0)
3678 				wps_method = WPS_PIN_DISPLAY;
3679 		}
3680 		if (!wps_pin_str_valid(pin)) {
3681 			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
3682 			return 17;
3683 		}
3684 	}
3685 
3686 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
3687 				   persistent_group, automatic, join,
3688 				   auth, go_intent, freq, persistent_id, pd,
3689 				   ht40);
3690 	if (new_pin == -2) {
3691 		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
3692 		return 25;
3693 	}
3694 	if (new_pin == -3) {
3695 		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
3696 		return 25;
3697 	}
3698 	if (new_pin < 0)
3699 		return -1;
3700 	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
3701 		ret = os_snprintf(buf, buflen, "%08d", new_pin);
3702 		if (ret < 0 || (size_t) ret >= buflen)
3703 			return -1;
3704 		return ret;
3705 	}
3706 
3707 	os_memcpy(buf, "OK\n", 3);
3708 	return 3;
3709 }
3710 
3711 
p2p_ctrl_listen(struct wpa_supplicant * wpa_s,char * cmd)3712 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
3713 {
3714 	unsigned int timeout = atoi(cmd);
3715 	return wpas_p2p_listen(wpa_s, timeout);
3716 }
3717 
3718 
p2p_ctrl_prov_disc(struct wpa_supplicant * wpa_s,char * cmd)3719 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
3720 {
3721 	u8 addr[ETH_ALEN];
3722 	char *pos;
3723 	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
3724 
3725 	/* <addr> <config method> [join|auto] */
3726 
3727 	if (hwaddr_aton(cmd, addr))
3728 		return -1;
3729 
3730 	pos = cmd + 17;
3731 	if (*pos != ' ')
3732 		return -1;
3733 	pos++;
3734 
3735 	if (os_strstr(pos, " join") != NULL)
3736 		use = WPAS_P2P_PD_FOR_JOIN;
3737 	else if (os_strstr(pos, " auto") != NULL)
3738 		use = WPAS_P2P_PD_AUTO;
3739 
3740 	return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
3741 }
3742 
3743 
p2p_get_passphrase(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3744 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
3745 			      size_t buflen)
3746 {
3747 	struct wpa_ssid *ssid = wpa_s->current_ssid;
3748 
3749 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
3750 	    ssid->passphrase == NULL)
3751 		return -1;
3752 
3753 	os_strlcpy(buf, ssid->passphrase, buflen);
3754 	return os_strlen(buf);
3755 }
3756 
3757 
p2p_ctrl_serv_disc_req(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3758 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
3759 				  char *buf, size_t buflen)
3760 {
3761 	u64 ref;
3762 	int res;
3763 	u8 dst_buf[ETH_ALEN], *dst;
3764 	struct wpabuf *tlvs;
3765 	char *pos;
3766 	size_t len;
3767 
3768 	if (hwaddr_aton(cmd, dst_buf))
3769 		return -1;
3770 	dst = dst_buf;
3771 	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
3772 	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
3773 		dst = NULL;
3774 	pos = cmd + 17;
3775 	if (*pos != ' ')
3776 		return -1;
3777 	pos++;
3778 
3779 	if (os_strncmp(pos, "upnp ", 5) == 0) {
3780 		u8 version;
3781 		pos += 5;
3782 		if (hexstr2bin(pos, &version, 1) < 0)
3783 			return -1;
3784 		pos += 2;
3785 		if (*pos != ' ')
3786 			return -1;
3787 		pos++;
3788 		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
3789 #ifdef CONFIG_WIFI_DISPLAY
3790 	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
3791 		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
3792 #endif /* CONFIG_WIFI_DISPLAY */
3793 	} else {
3794 		len = os_strlen(pos);
3795 		if (len & 1)
3796 			return -1;
3797 		len /= 2;
3798 		tlvs = wpabuf_alloc(len);
3799 		if (tlvs == NULL)
3800 			return -1;
3801 		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
3802 			wpabuf_free(tlvs);
3803 			return -1;
3804 		}
3805 
3806 		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
3807 		wpabuf_free(tlvs);
3808 	}
3809 	if (ref == 0)
3810 		return -1;
3811 	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
3812 	if (res < 0 || (unsigned) res >= buflen)
3813 		return -1;
3814 	return res;
3815 }
3816 
3817 
p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant * wpa_s,char * cmd)3818 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
3819 					 char *cmd)
3820 {
3821 	long long unsigned val;
3822 	u64 req;
3823 	if (sscanf(cmd, "%llx", &val) != 1)
3824 		return -1;
3825 	req = val;
3826 	return wpas_p2p_sd_cancel_request(wpa_s, req);
3827 }
3828 
3829 
p2p_ctrl_serv_disc_resp(struct wpa_supplicant * wpa_s,char * cmd)3830 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
3831 {
3832 	int freq;
3833 	u8 dst[ETH_ALEN];
3834 	u8 dialog_token;
3835 	struct wpabuf *resp_tlvs;
3836 	char *pos, *pos2;
3837 	size_t len;
3838 
3839 	pos = os_strchr(cmd, ' ');
3840 	if (pos == NULL)
3841 		return -1;
3842 	*pos++ = '\0';
3843 	freq = atoi(cmd);
3844 	if (freq == 0)
3845 		return -1;
3846 
3847 	if (hwaddr_aton(pos, dst))
3848 		return -1;
3849 	pos += 17;
3850 	if (*pos != ' ')
3851 		return -1;
3852 	pos++;
3853 
3854 	pos2 = os_strchr(pos, ' ');
3855 	if (pos2 == NULL)
3856 		return -1;
3857 	*pos2++ = '\0';
3858 	dialog_token = atoi(pos);
3859 
3860 	len = os_strlen(pos2);
3861 	if (len & 1)
3862 		return -1;
3863 	len /= 2;
3864 	resp_tlvs = wpabuf_alloc(len);
3865 	if (resp_tlvs == NULL)
3866 		return -1;
3867 	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
3868 		wpabuf_free(resp_tlvs);
3869 		return -1;
3870 	}
3871 
3872 	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
3873 	wpabuf_free(resp_tlvs);
3874 	return 0;
3875 }
3876 
3877 
p2p_ctrl_serv_disc_external(struct wpa_supplicant * wpa_s,char * cmd)3878 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
3879 				       char *cmd)
3880 {
3881 	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
3882 		return -1;
3883 	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
3884 	return 0;
3885 }
3886 
3887 
p2p_ctrl_service_add_bonjour(struct wpa_supplicant * wpa_s,char * cmd)3888 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
3889 					char *cmd)
3890 {
3891 	char *pos;
3892 	size_t len;
3893 	struct wpabuf *query, *resp;
3894 
3895 	pos = os_strchr(cmd, ' ');
3896 	if (pos == NULL)
3897 		return -1;
3898 	*pos++ = '\0';
3899 
3900 	len = os_strlen(cmd);
3901 	if (len & 1)
3902 		return -1;
3903 	len /= 2;
3904 	query = wpabuf_alloc(len);
3905 	if (query == NULL)
3906 		return -1;
3907 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
3908 		wpabuf_free(query);
3909 		return -1;
3910 	}
3911 
3912 	len = os_strlen(pos);
3913 	if (len & 1) {
3914 		wpabuf_free(query);
3915 		return -1;
3916 	}
3917 	len /= 2;
3918 	resp = wpabuf_alloc(len);
3919 	if (resp == NULL) {
3920 		wpabuf_free(query);
3921 		return -1;
3922 	}
3923 	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
3924 		wpabuf_free(query);
3925 		wpabuf_free(resp);
3926 		return -1;
3927 	}
3928 
3929 	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
3930 		wpabuf_free(query);
3931 		wpabuf_free(resp);
3932 		return -1;
3933 	}
3934 	return 0;
3935 }
3936 
3937 
p2p_ctrl_service_add_upnp(struct wpa_supplicant * wpa_s,char * cmd)3938 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
3939 {
3940 	char *pos;
3941 	u8 version;
3942 
3943 	pos = os_strchr(cmd, ' ');
3944 	if (pos == NULL)
3945 		return -1;
3946 	*pos++ = '\0';
3947 
3948 	if (hexstr2bin(cmd, &version, 1) < 0)
3949 		return -1;
3950 
3951 	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
3952 }
3953 
3954 
p2p_ctrl_service_add(struct wpa_supplicant * wpa_s,char * cmd)3955 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
3956 {
3957 	char *pos;
3958 
3959 	pos = os_strchr(cmd, ' ');
3960 	if (pos == NULL)
3961 		return -1;
3962 	*pos++ = '\0';
3963 
3964 	if (os_strcmp(cmd, "bonjour") == 0)
3965 		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
3966 	if (os_strcmp(cmd, "upnp") == 0)
3967 		return p2p_ctrl_service_add_upnp(wpa_s, pos);
3968 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
3969 	return -1;
3970 }
3971 
3972 
p2p_ctrl_service_del_bonjour(struct wpa_supplicant * wpa_s,char * cmd)3973 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
3974 					char *cmd)
3975 {
3976 	size_t len;
3977 	struct wpabuf *query;
3978 	int ret;
3979 
3980 	len = os_strlen(cmd);
3981 	if (len & 1)
3982 		return -1;
3983 	len /= 2;
3984 	query = wpabuf_alloc(len);
3985 	if (query == NULL)
3986 		return -1;
3987 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
3988 		wpabuf_free(query);
3989 		return -1;
3990 	}
3991 
3992 	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
3993 	wpabuf_free(query);
3994 	return ret;
3995 }
3996 
3997 
p2p_ctrl_service_del_upnp(struct wpa_supplicant * wpa_s,char * cmd)3998 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
3999 {
4000 	char *pos;
4001 	u8 version;
4002 
4003 	pos = os_strchr(cmd, ' ');
4004 	if (pos == NULL)
4005 		return -1;
4006 	*pos++ = '\0';
4007 
4008 	if (hexstr2bin(cmd, &version, 1) < 0)
4009 		return -1;
4010 
4011 	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
4012 }
4013 
4014 
p2p_ctrl_service_del(struct wpa_supplicant * wpa_s,char * cmd)4015 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
4016 {
4017 	char *pos;
4018 
4019 	pos = os_strchr(cmd, ' ');
4020 	if (pos == NULL)
4021 		return -1;
4022 	*pos++ = '\0';
4023 
4024 	if (os_strcmp(cmd, "bonjour") == 0)
4025 		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
4026 	if (os_strcmp(cmd, "upnp") == 0)
4027 		return p2p_ctrl_service_del_upnp(wpa_s, pos);
4028 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4029 	return -1;
4030 }
4031 
4032 
p2p_ctrl_reject(struct wpa_supplicant * wpa_s,char * cmd)4033 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
4034 {
4035 	u8 addr[ETH_ALEN];
4036 
4037 	/* <addr> */
4038 
4039 	if (hwaddr_aton(cmd, addr))
4040 		return -1;
4041 
4042 	return wpas_p2p_reject(wpa_s, addr);
4043 }
4044 
4045 
p2p_ctrl_invite_persistent(struct wpa_supplicant * wpa_s,char * cmd)4046 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
4047 {
4048 	char *pos;
4049 	int id;
4050 	struct wpa_ssid *ssid;
4051 	u8 *_peer = NULL, peer[ETH_ALEN];
4052 	int freq = 0, pref_freq = 0;
4053 	int ht40;
4054 
4055 	id = atoi(cmd);
4056 	pos = os_strstr(cmd, " peer=");
4057 	if (pos) {
4058 		pos += 6;
4059 		if (hwaddr_aton(pos, peer))
4060 			return -1;
4061 		_peer = peer;
4062 	}
4063 	ssid = wpa_config_get_network(wpa_s->conf, id);
4064 	if (ssid == NULL || ssid->disabled != 2) {
4065 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4066 			   "for persistent P2P group",
4067 			   id);
4068 		return -1;
4069 	}
4070 
4071 	pos = os_strstr(cmd, " freq=");
4072 	if (pos) {
4073 		pos += 6;
4074 		freq = atoi(pos);
4075 		if (freq <= 0)
4076 			return -1;
4077 	}
4078 
4079 	pos = os_strstr(cmd, " pref=");
4080 	if (pos) {
4081 		pos += 6;
4082 		pref_freq = atoi(pos);
4083 		if (pref_freq <= 0)
4084 			return -1;
4085 	}
4086 
4087 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
4088 
4089 	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, pref_freq);
4090 }
4091 
4092 
p2p_ctrl_invite_group(struct wpa_supplicant * wpa_s,char * cmd)4093 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
4094 {
4095 	char *pos;
4096 	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
4097 
4098 	pos = os_strstr(cmd, " peer=");
4099 	if (!pos)
4100 		return -1;
4101 
4102 	*pos = '\0';
4103 	pos += 6;
4104 	if (hwaddr_aton(pos, peer)) {
4105 		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
4106 		return -1;
4107 	}
4108 
4109 	pos = os_strstr(pos, " go_dev_addr=");
4110 	if (pos) {
4111 		pos += 13;
4112 		if (hwaddr_aton(pos, go_dev_addr)) {
4113 			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
4114 				   pos);
4115 			return -1;
4116 		}
4117 		go_dev = go_dev_addr;
4118 	}
4119 
4120 	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
4121 }
4122 
4123 
p2p_ctrl_invite(struct wpa_supplicant * wpa_s,char * cmd)4124 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
4125 {
4126 	if (os_strncmp(cmd, "persistent=", 11) == 0)
4127 		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
4128 	if (os_strncmp(cmd, "group=", 6) == 0)
4129 		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
4130 
4131 	return -1;
4132 }
4133 
4134 
p2p_ctrl_group_add_persistent(struct wpa_supplicant * wpa_s,char * cmd,int freq,int ht40)4135 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
4136 					 char *cmd, int freq, int ht40)
4137 {
4138 	int id;
4139 	struct wpa_ssid *ssid;
4140 
4141 	id = atoi(cmd);
4142 	ssid = wpa_config_get_network(wpa_s->conf, id);
4143 	if (ssid == NULL || ssid->disabled != 2) {
4144 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4145 			   "for persistent P2P group",
4146 			   id);
4147 		return -1;
4148 	}
4149 
4150 	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40, NULL);
4151 }
4152 
4153 
p2p_ctrl_group_add(struct wpa_supplicant * wpa_s,char * cmd)4154 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
4155 {
4156 	int freq = 0, ht40;
4157 	char *pos;
4158 
4159 	pos = os_strstr(cmd, "freq=");
4160 	if (pos)
4161 		freq = atoi(pos + 5);
4162 
4163 	ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
4164 
4165 	if (os_strncmp(cmd, "persistent=", 11) == 0)
4166 		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
4167 						     ht40);
4168 	if (os_strcmp(cmd, "persistent") == 0 ||
4169 	    os_strncmp(cmd, "persistent ", 11) == 0)
4170 		return wpas_p2p_group_add(wpa_s, 1, freq, ht40);
4171 	if (os_strncmp(cmd, "freq=", 5) == 0)
4172 		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
4173 	if (ht40)
4174 		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
4175 
4176 	wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
4177 		   cmd);
4178 	return -1;
4179 }
4180 
4181 
p2p_ctrl_peer(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)4182 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
4183 			 char *buf, size_t buflen)
4184 {
4185 	u8 addr[ETH_ALEN], *addr_ptr;
4186 	int next, res;
4187 	const struct p2p_peer_info *info;
4188 	char *pos, *end;
4189 	char devtype[WPS_DEV_TYPE_BUFSIZE];
4190 	struct wpa_ssid *ssid;
4191 	size_t i;
4192 
4193 	if (!wpa_s->global->p2p)
4194 		return -1;
4195 
4196 	if (os_strcmp(cmd, "FIRST") == 0) {
4197 		addr_ptr = NULL;
4198 		next = 0;
4199 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
4200 		if (hwaddr_aton(cmd + 5, addr) < 0)
4201 			return -1;
4202 		addr_ptr = addr;
4203 		next = 1;
4204 	} else {
4205 		if (hwaddr_aton(cmd, addr) < 0)
4206 			return -1;
4207 		addr_ptr = addr;
4208 		next = 0;
4209 	}
4210 
4211 	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
4212 	if (info == NULL)
4213 		return -1;
4214 
4215 	pos = buf;
4216 	end = buf + buflen;
4217 
4218 	res = os_snprintf(pos, end - pos, MACSTR "\n"
4219 			  "pri_dev_type=%s\n"
4220 			  "device_name=%s\n"
4221 			  "manufacturer=%s\n"
4222 			  "model_name=%s\n"
4223 			  "model_number=%s\n"
4224 			  "serial_number=%s\n"
4225 			  "config_methods=0x%x\n"
4226 			  "dev_capab=0x%x\n"
4227 			  "group_capab=0x%x\n"
4228 			  "level=%d\n",
4229 			  MAC2STR(info->p2p_device_addr),
4230 			  wps_dev_type_bin2str(info->pri_dev_type,
4231 					       devtype, sizeof(devtype)),
4232 			  info->device_name,
4233 			  info->manufacturer,
4234 			  info->model_name,
4235 			  info->model_number,
4236 			  info->serial_number,
4237 			  info->config_methods,
4238 			  info->dev_capab,
4239 			  info->group_capab,
4240 			  info->level);
4241 	if (res < 0 || res >= end - pos)
4242 		return pos - buf;
4243 	pos += res;
4244 
4245 	for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
4246 	{
4247 		const u8 *t;
4248 		t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
4249 		res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
4250 				  wps_dev_type_bin2str(t, devtype,
4251 						       sizeof(devtype)));
4252 		if (res < 0 || res >= end - pos)
4253 			return pos - buf;
4254 		pos += res;
4255 	}
4256 
4257 	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
4258 	if (ssid) {
4259 		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
4260 		if (res < 0 || res >= end - pos)
4261 			return pos - buf;
4262 		pos += res;
4263 	}
4264 
4265 	res = p2p_get_peer_info_txt(info, pos, end - pos);
4266 	if (res < 0)
4267 		return pos - buf;
4268 	pos += res;
4269 
4270 	return pos - buf;
4271 }
4272 
4273 
p2p_ctrl_disallow_freq(struct wpa_supplicant * wpa_s,const char * param)4274 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
4275 				  const char *param)
4276 {
4277 	struct wpa_freq_range *freq = NULL, *n;
4278 	unsigned int count = 0, i;
4279 	const char *pos, *pos2, *pos3;
4280 
4281 	if (wpa_s->global->p2p == NULL)
4282 		return -1;
4283 
4284 	/*
4285 	 * param includes comma separated frequency range.
4286 	 * For example: 2412-2432,2462,5000-6000
4287 	 */
4288 	pos = param;
4289 	while (pos && pos[0]) {
4290 		n = os_realloc_array(freq, count + 1,
4291 				     sizeof(struct wpa_freq_range));
4292 		if (n == NULL) {
4293 			os_free(freq);
4294 			return -1;
4295 		}
4296 		freq = n;
4297 		freq[count].min = atoi(pos);
4298 		pos2 = os_strchr(pos, '-');
4299 		pos3 = os_strchr(pos, ',');
4300 		if (pos2 && (!pos3 || pos2 < pos3)) {
4301 			pos2++;
4302 			freq[count].max = atoi(pos2);
4303 		} else
4304 			freq[count].max = freq[count].min;
4305 		pos = pos3;
4306 		if (pos)
4307 			pos++;
4308 		count++;
4309 	}
4310 
4311 	for (i = 0; i < count; i++) {
4312 		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
4313 			   freq[i].min, freq[i].max);
4314 	}
4315 
4316 	os_free(wpa_s->global->p2p_disallow_freq);
4317 	wpa_s->global->p2p_disallow_freq = freq;
4318 	wpa_s->global->num_p2p_disallow_freq = count;
4319 	wpas_p2p_update_channel_list(wpa_s);
4320 	return 0;
4321 }
4322 
4323 
p2p_ctrl_set(struct wpa_supplicant * wpa_s,char * cmd)4324 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
4325 {
4326 	char *param;
4327 
4328 	if (wpa_s->global->p2p == NULL)
4329 		return -1;
4330 
4331 	param = os_strchr(cmd, ' ');
4332 	if (param == NULL)
4333 		return -1;
4334 	*param++ = '\0';
4335 
4336 	if (os_strcmp(cmd, "discoverability") == 0) {
4337 		p2p_set_client_discoverability(wpa_s->global->p2p,
4338 					       atoi(param));
4339 		return 0;
4340 	}
4341 
4342 	if (os_strcmp(cmd, "managed") == 0) {
4343 		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
4344 		return 0;
4345 	}
4346 
4347 	if (os_strcmp(cmd, "listen_channel") == 0) {
4348 		return p2p_set_listen_channel(wpa_s->global->p2p, 81,
4349 					      atoi(param));
4350 	}
4351 
4352 	if (os_strcmp(cmd, "ssid_postfix") == 0) {
4353 		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
4354 					    os_strlen(param));
4355 	}
4356 
4357 	if (os_strcmp(cmd, "noa") == 0) {
4358 		char *pos;
4359 		int count, start, duration;
4360 		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
4361 		count = atoi(param);
4362 		pos = os_strchr(param, ',');
4363 		if (pos == NULL)
4364 			return -1;
4365 		pos++;
4366 		start = atoi(pos);
4367 		pos = os_strchr(pos, ',');
4368 		if (pos == NULL)
4369 			return -1;
4370 		pos++;
4371 		duration = atoi(pos);
4372 		if (count < 0 || count > 255 || start < 0 || duration < 0)
4373 			return -1;
4374 		if (count == 0 && duration > 0)
4375 			return -1;
4376 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
4377 			   "start=%d duration=%d", count, start, duration);
4378 		return wpas_p2p_set_noa(wpa_s, count, start, duration);
4379 	}
4380 
4381 	if (os_strcmp(cmd, "ps") == 0)
4382 		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
4383 
4384 	if (os_strcmp(cmd, "oppps") == 0)
4385 		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
4386 
4387 	if (os_strcmp(cmd, "ctwindow") == 0)
4388 		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
4389 
4390 	if (os_strcmp(cmd, "disabled") == 0) {
4391 		wpa_s->global->p2p_disabled = atoi(param);
4392 		wpa_printf(MSG_DEBUG, "P2P functionality %s",
4393 			   wpa_s->global->p2p_disabled ?
4394 			   "disabled" : "enabled");
4395 		if (wpa_s->global->p2p_disabled) {
4396 			wpas_p2p_stop_find(wpa_s);
4397 			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4398 			p2p_flush(wpa_s->global->p2p);
4399 		}
4400 		return 0;
4401 	}
4402 
4403 	if (os_strcmp(cmd, "conc_pref") == 0) {
4404 		if (os_strcmp(param, "sta") == 0)
4405 			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
4406 		else if (os_strcmp(param, "p2p") == 0)
4407 			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
4408 		else {
4409 			wpa_printf(MSG_INFO, "Invalid conc_pref value");
4410 			return -1;
4411 		}
4412 		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
4413 			   "%s", param);
4414 		return 0;
4415 	}
4416 
4417 	if (os_strcmp(cmd, "force_long_sd") == 0) {
4418 		wpa_s->force_long_sd = atoi(param);
4419 		return 0;
4420 	}
4421 
4422 	if (os_strcmp(cmd, "peer_filter") == 0) {
4423 		u8 addr[ETH_ALEN];
4424 		if (hwaddr_aton(param, addr))
4425 			return -1;
4426 		p2p_set_peer_filter(wpa_s->global->p2p, addr);
4427 		return 0;
4428 	}
4429 
4430 	if (os_strcmp(cmd, "cross_connect") == 0)
4431 		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
4432 
4433 	if (os_strcmp(cmd, "go_apsd") == 0) {
4434 		if (os_strcmp(param, "disable") == 0)
4435 			wpa_s->set_ap_uapsd = 0;
4436 		else {
4437 			wpa_s->set_ap_uapsd = 1;
4438 			wpa_s->ap_uapsd = atoi(param);
4439 		}
4440 		return 0;
4441 	}
4442 
4443 	if (os_strcmp(cmd, "client_apsd") == 0) {
4444 		if (os_strcmp(param, "disable") == 0)
4445 			wpa_s->set_sta_uapsd = 0;
4446 		else {
4447 			int be, bk, vi, vo;
4448 			char *pos;
4449 			/* format: BE,BK,VI,VO;max SP Length */
4450 			be = atoi(param);
4451 			pos = os_strchr(param, ',');
4452 			if (pos == NULL)
4453 				return -1;
4454 			pos++;
4455 			bk = atoi(pos);
4456 			pos = os_strchr(pos, ',');
4457 			if (pos == NULL)
4458 				return -1;
4459 			pos++;
4460 			vi = atoi(pos);
4461 			pos = os_strchr(pos, ',');
4462 			if (pos == NULL)
4463 				return -1;
4464 			pos++;
4465 			vo = atoi(pos);
4466 			/* ignore max SP Length for now */
4467 
4468 			wpa_s->set_sta_uapsd = 1;
4469 			wpa_s->sta_uapsd = 0;
4470 			if (be)
4471 				wpa_s->sta_uapsd |= BIT(0);
4472 			if (bk)
4473 				wpa_s->sta_uapsd |= BIT(1);
4474 			if (vi)
4475 				wpa_s->sta_uapsd |= BIT(2);
4476 			if (vo)
4477 				wpa_s->sta_uapsd |= BIT(3);
4478 		}
4479 		return 0;
4480 	}
4481 
4482 	if (os_strcmp(cmd, "disallow_freq") == 0)
4483 		return p2p_ctrl_disallow_freq(wpa_s, param);
4484 
4485 	if (os_strcmp(cmd, "disc_int") == 0) {
4486 		int min_disc_int, max_disc_int, max_disc_tu;
4487 		char *pos;
4488 
4489 		pos = param;
4490 
4491 		min_disc_int = atoi(pos);
4492 		pos = os_strchr(pos, ' ');
4493 		if (pos == NULL)
4494 			return -1;
4495 		*pos++ = '\0';
4496 
4497 		max_disc_int = atoi(pos);
4498 		pos = os_strchr(pos, ' ');
4499 		if (pos == NULL)
4500 			return -1;
4501 		*pos++ = '\0';
4502 
4503 		max_disc_tu = atoi(pos);
4504 
4505 		return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
4506 					max_disc_int, max_disc_tu);
4507 	}
4508 
4509 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
4510 		   cmd);
4511 
4512 	return -1;
4513 }
4514 
4515 
p2p_ctrl_flush(struct wpa_supplicant * wpa_s)4516 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
4517 {
4518 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4519 	wpa_s->force_long_sd = 0;
4520 	if (wpa_s->global->p2p)
4521 		p2p_flush(wpa_s->global->p2p);
4522 }
4523 
4524 
p2p_ctrl_presence_req(struct wpa_supplicant * wpa_s,char * cmd)4525 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
4526 {
4527 	char *pos, *pos2;
4528 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
4529 
4530 	if (cmd[0]) {
4531 		pos = os_strchr(cmd, ' ');
4532 		if (pos == NULL)
4533 			return -1;
4534 		*pos++ = '\0';
4535 		dur1 = atoi(cmd);
4536 
4537 		pos2 = os_strchr(pos, ' ');
4538 		if (pos2)
4539 			*pos2++ = '\0';
4540 		int1 = atoi(pos);
4541 	} else
4542 		pos2 = NULL;
4543 
4544 	if (pos2) {
4545 		pos = os_strchr(pos2, ' ');
4546 		if (pos == NULL)
4547 			return -1;
4548 		*pos++ = '\0';
4549 		dur2 = atoi(pos2);
4550 		int2 = atoi(pos);
4551 	}
4552 
4553 	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
4554 }
4555 
4556 
p2p_ctrl_ext_listen(struct wpa_supplicant * wpa_s,char * cmd)4557 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
4558 {
4559 	char *pos;
4560 	unsigned int period = 0, interval = 0;
4561 
4562 	if (cmd[0]) {
4563 		pos = os_strchr(cmd, ' ');
4564 		if (pos == NULL)
4565 			return -1;
4566 		*pos++ = '\0';
4567 		period = atoi(cmd);
4568 		interval = atoi(pos);
4569 	}
4570 
4571 	return wpas_p2p_ext_listen(wpa_s, period, interval);
4572 }
4573 
4574 #endif /* CONFIG_P2P */
4575 
4576 
4577 #ifdef CONFIG_INTERWORKING
ctrl_interworking_connect(struct wpa_supplicant * wpa_s,char * dst)4578 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
4579 {
4580 	u8 bssid[ETH_ALEN];
4581 	struct wpa_bss *bss;
4582 
4583 	if (hwaddr_aton(dst, bssid)) {
4584 		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
4585 		return -1;
4586 	}
4587 
4588 	bss = wpa_bss_get_bssid(wpa_s, bssid);
4589 	if (bss == NULL) {
4590 		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
4591 			   MAC2STR(bssid));
4592 		return -1;
4593 	}
4594 
4595 	return interworking_connect(wpa_s, bss);
4596 }
4597 
4598 
get_anqp(struct wpa_supplicant * wpa_s,char * dst)4599 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
4600 {
4601 	u8 dst_addr[ETH_ALEN];
4602 	int used;
4603 	char *pos;
4604 #define MAX_ANQP_INFO_ID 100
4605 	u16 id[MAX_ANQP_INFO_ID];
4606 	size_t num_id = 0;
4607 
4608 	used = hwaddr_aton2(dst, dst_addr);
4609 	if (used < 0)
4610 		return -1;
4611 	pos = dst + used;
4612 	while (num_id < MAX_ANQP_INFO_ID) {
4613 		id[num_id] = atoi(pos);
4614 		if (id[num_id])
4615 			num_id++;
4616 		pos = os_strchr(pos + 1, ',');
4617 		if (pos == NULL)
4618 			break;
4619 		pos++;
4620 	}
4621 
4622 	if (num_id == 0)
4623 		return -1;
4624 
4625 	return anqp_send_req(wpa_s, dst_addr, id, num_id);
4626 }
4627 
4628 
gas_request(struct wpa_supplicant * wpa_s,char * cmd)4629 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
4630 {
4631 	u8 dst_addr[ETH_ALEN];
4632 	struct wpabuf *advproto, *query = NULL;
4633 	int used, ret = -1;
4634 	char *pos, *end;
4635 	size_t len;
4636 
4637 	used = hwaddr_aton2(cmd, dst_addr);
4638 	if (used < 0)
4639 		return -1;
4640 
4641 	pos = cmd + used;
4642 	while (*pos == ' ')
4643 		pos++;
4644 
4645 	/* Advertisement Protocol ID */
4646 	end = os_strchr(pos, ' ');
4647 	if (end)
4648 		len = end - pos;
4649 	else
4650 		len = os_strlen(pos);
4651 	if (len & 0x01)
4652 		return -1;
4653 	len /= 2;
4654 	if (len == 0)
4655 		return -1;
4656 	advproto = wpabuf_alloc(len);
4657 	if (advproto == NULL)
4658 		return -1;
4659 	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
4660 		goto fail;
4661 
4662 	if (end) {
4663 		/* Optional Query Request */
4664 		pos = end + 1;
4665 		while (*pos == ' ')
4666 			pos++;
4667 
4668 		len = os_strlen(pos);
4669 		if (len) {
4670 			if (len & 0x01)
4671 				goto fail;
4672 			len /= 2;
4673 			if (len == 0)
4674 				goto fail;
4675 			query = wpabuf_alloc(len);
4676 			if (query == NULL)
4677 				goto fail;
4678 			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
4679 				goto fail;
4680 		}
4681 	}
4682 
4683 	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
4684 
4685 fail:
4686 	wpabuf_free(advproto);
4687 	wpabuf_free(query);
4688 
4689 	return ret;
4690 }
4691 
4692 
gas_response_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)4693 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
4694 			    size_t buflen)
4695 {
4696 	u8 addr[ETH_ALEN];
4697 	int dialog_token;
4698 	int used;
4699 	char *pos;
4700 	size_t resp_len, start, requested_len;
4701 
4702 	if (!wpa_s->last_gas_resp)
4703 		return -1;
4704 
4705 	used = hwaddr_aton2(cmd, addr);
4706 	if (used < 0)
4707 		return -1;
4708 
4709 	pos = cmd + used;
4710 	while (*pos == ' ')
4711 		pos++;
4712 	dialog_token = atoi(pos);
4713 
4714 	if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 ||
4715 	    dialog_token != wpa_s->last_gas_dialog_token)
4716 		return -1;
4717 
4718 	resp_len = wpabuf_len(wpa_s->last_gas_resp);
4719 	start = 0;
4720 	requested_len = resp_len;
4721 
4722 	pos = os_strchr(pos, ' ');
4723 	if (pos) {
4724 		start = atoi(pos);
4725 		if (start > resp_len)
4726 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
4727 		pos = os_strchr(pos, ',');
4728 		if (pos == NULL)
4729 			return -1;
4730 		pos++;
4731 		requested_len = atoi(pos);
4732 		if (start + requested_len > resp_len)
4733 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
4734 	}
4735 
4736 	if (requested_len * 2 + 1 > buflen)
4737 		return os_snprintf(buf, buflen, "FAIL-Too long response");
4738 
4739 	return wpa_snprintf_hex(buf, buflen,
4740 				wpabuf_head_u8(wpa_s->last_gas_resp) + start,
4741 				requested_len);
4742 }
4743 #endif /* CONFIG_INTERWORKING */
4744 
4745 
4746 #ifdef CONFIG_HS20
4747 
get_hs20_anqp(struct wpa_supplicant * wpa_s,char * dst)4748 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
4749 {
4750 	u8 dst_addr[ETH_ALEN];
4751 	int used;
4752 	char *pos;
4753 	u32 subtypes = 0;
4754 
4755 	used = hwaddr_aton2(dst, dst_addr);
4756 	if (used < 0)
4757 		return -1;
4758 	pos = dst + used;
4759 	for (;;) {
4760 		int num = atoi(pos);
4761 		if (num <= 0 || num > 31)
4762 			return -1;
4763 		subtypes |= BIT(num);
4764 		pos = os_strchr(pos + 1, ',');
4765 		if (pos == NULL)
4766 			break;
4767 		pos++;
4768 	}
4769 
4770 	if (subtypes == 0)
4771 		return -1;
4772 
4773 	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
4774 }
4775 
4776 
hs20_nai_home_realm_list(struct wpa_supplicant * wpa_s,const u8 * addr,const char * realm)4777 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
4778 				    const u8 *addr, const char *realm)
4779 {
4780 	u8 *buf;
4781 	size_t rlen, len;
4782 	int ret;
4783 
4784 	rlen = os_strlen(realm);
4785 	len = 3 + rlen;
4786 	buf = os_malloc(len);
4787 	if (buf == NULL)
4788 		return -1;
4789 	buf[0] = 1; /* NAI Home Realm Count */
4790 	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
4791 	buf[2] = rlen;
4792 	os_memcpy(buf + 3, realm, rlen);
4793 
4794 	ret = hs20_anqp_send_req(wpa_s, addr,
4795 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
4796 				 buf, len);
4797 
4798 	os_free(buf);
4799 
4800 	return ret;
4801 }
4802 
4803 
hs20_get_nai_home_realm_list(struct wpa_supplicant * wpa_s,char * dst)4804 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
4805 					char *dst)
4806 {
4807 	struct wpa_cred *cred = wpa_s->conf->cred;
4808 	u8 dst_addr[ETH_ALEN];
4809 	int used;
4810 	u8 *buf;
4811 	size_t len;
4812 	int ret;
4813 
4814 	used = hwaddr_aton2(dst, dst_addr);
4815 	if (used < 0)
4816 		return -1;
4817 
4818 	while (dst[used] == ' ')
4819 		used++;
4820 	if (os_strncmp(dst + used, "realm=", 6) == 0)
4821 		return hs20_nai_home_realm_list(wpa_s, dst_addr,
4822 						dst + used + 6);
4823 
4824 	len = os_strlen(dst + used);
4825 
4826 	if (len == 0 && cred && cred->realm)
4827 		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
4828 
4829 	if (len % 1)
4830 		return -1;
4831 	len /= 2;
4832 	buf = os_malloc(len);
4833 	if (buf == NULL)
4834 		return -1;
4835 	if (hexstr2bin(dst + used, buf, len) < 0) {
4836 		os_free(buf);
4837 		return -1;
4838 	}
4839 
4840 	ret = hs20_anqp_send_req(wpa_s, dst_addr,
4841 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
4842 				 buf, len);
4843 	os_free(buf);
4844 
4845 	return ret;
4846 }
4847 
4848 #endif /* CONFIG_HS20 */
4849 
4850 
wpa_supplicant_ctrl_iface_sta_autoconnect(struct wpa_supplicant * wpa_s,char * cmd)4851 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
4852 	struct wpa_supplicant *wpa_s, char *cmd)
4853 {
4854 	wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
4855 	return 0;
4856 }
4857 
4858 
4859 #ifdef CONFIG_AUTOSCAN
4860 
wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant * wpa_s,char * cmd)4861 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
4862 					      char *cmd)
4863 {
4864 	enum wpa_states state = wpa_s->wpa_state;
4865 	char *new_params = NULL;
4866 
4867 	if (os_strlen(cmd) > 0) {
4868 		new_params = os_strdup(cmd);
4869 		if (new_params == NULL)
4870 			return -1;
4871 	}
4872 
4873 	os_free(wpa_s->conf->autoscan);
4874 	wpa_s->conf->autoscan = new_params;
4875 
4876 	if (wpa_s->conf->autoscan == NULL)
4877 		autoscan_deinit(wpa_s);
4878 	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
4879 		autoscan_init(wpa_s, 1);
4880 	else if (state == WPA_SCANNING)
4881 		wpa_supplicant_reinit_autoscan(wpa_s);
4882 
4883 	return 0;
4884 }
4885 
4886 #endif /* CONFIG_AUTOSCAN */
4887 
4888 
4889 #ifdef CONFIG_WNM
4890 
wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant * wpa_s,char * cmd)4891 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
4892 {
4893 	int enter;
4894 	int intval = 0;
4895 	char *pos;
4896 	int ret;
4897 	struct wpabuf *tfs_req = NULL;
4898 
4899 	if (os_strncmp(cmd, "enter", 5) == 0)
4900 		enter = 1;
4901 	else if (os_strncmp(cmd, "exit", 4) == 0)
4902 		enter = 0;
4903 	else
4904 		return -1;
4905 
4906 	pos = os_strstr(cmd, " interval=");
4907 	if (pos)
4908 		intval = atoi(pos + 10);
4909 
4910 	pos = os_strstr(cmd, " tfs_req=");
4911 	if (pos) {
4912 		char *end;
4913 		size_t len;
4914 		pos += 9;
4915 		end = os_strchr(pos, ' ');
4916 		if (end)
4917 			len = end - pos;
4918 		else
4919 			len = os_strlen(pos);
4920 		if (len & 1)
4921 			return -1;
4922 		len /= 2;
4923 		tfs_req = wpabuf_alloc(len);
4924 		if (tfs_req == NULL)
4925 			return -1;
4926 		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
4927 			wpabuf_free(tfs_req);
4928 			return -1;
4929 		}
4930 	}
4931 
4932 	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
4933 					   WNM_SLEEP_MODE_EXIT, intval,
4934 					   tfs_req);
4935 	wpabuf_free(tfs_req);
4936 
4937 	return ret;
4938 }
4939 
4940 #endif /* CONFIG_WNM */
4941 
4942 
wpa_supplicant_signal_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4943 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
4944 				      size_t buflen)
4945 {
4946 	struct wpa_signal_info si;
4947 	int ret;
4948 
4949 	ret = wpa_drv_signal_poll(wpa_s, &si);
4950 	if (ret)
4951 		return -1;
4952 
4953 	ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
4954 			  "NOISE=%d\nFREQUENCY=%u\n",
4955 			  si.current_signal, si.current_txrate / 1000,
4956 			  si.current_noise, si.frequency);
4957 	if (ret < 0 || (unsigned int) ret > buflen)
4958 		return -1;
4959 	return ret;
4960 }
4961 
4962 
wpa_supplicant_pktcnt_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4963 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
4964 				      size_t buflen)
4965 {
4966 	struct hostap_sta_driver_data sta;
4967 	int ret;
4968 
4969 	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
4970 	if (ret)
4971 		return -1;
4972 
4973 	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
4974 			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
4975 	if (ret < 0 || (size_t) ret > buflen)
4976 		return -1;
4977 	return ret;
4978 }
4979 
4980 
4981 #ifdef ANDROID
wpa_supplicant_driver_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)4982 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
4983 				     char *buf, size_t buflen)
4984 {
4985 	int ret;
4986 
4987 	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
4988 	if (ret == 0)
4989 		ret = sprintf(buf, "%s\n", "OK");
4990 	return ret;
4991 }
4992 #endif
4993 
4994 
wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant * wpa_s)4995 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
4996 {
4997 	wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
4998 
4999 #ifdef CONFIG_P2P
5000 	wpas_p2p_stop_find(wpa_s);
5001 	p2p_ctrl_flush(wpa_s);
5002 	wpas_p2p_group_remove(wpa_s, "*");
5003 #endif /* CONFIG_P2P */
5004 
5005 #ifdef CONFIG_WPS_TESTING
5006 	wps_version_number = 0x20;
5007 	wps_testing_dummy_cred = 0;
5008 #endif /* CONFIG_WPS_TESTING */
5009 #ifdef CONFIG_WPS
5010 	wpas_wps_cancel(wpa_s);
5011 #endif /* CONFIG_WPS */
5012 
5013 #ifdef CONFIG_TDLS_TESTING
5014 	extern unsigned int tdls_testing;
5015 	tdls_testing = 0;
5016 #endif /* CONFIG_TDLS_TESTING */
5017 #ifdef CONFIG_TDLS
5018 	wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
5019 	wpa_tdls_enable(wpa_s->wpa, 1);
5020 #endif /* CONFIG_TDLS */
5021 
5022 	wpa_s->no_keep_alive = 0;
5023 
5024 	os_free(wpa_s->disallow_aps_bssid);
5025 	wpa_s->disallow_aps_bssid = NULL;
5026 	wpa_s->disallow_aps_bssid_count = 0;
5027 	os_free(wpa_s->disallow_aps_ssid);
5028 	wpa_s->disallow_aps_ssid = NULL;
5029 	wpa_s->disallow_aps_ssid_count = 0;
5030 
5031 	wpa_s->set_sta_uapsd = 0;
5032 	wpa_s->sta_uapsd = 0;
5033 
5034 	wpa_drv_radio_disable(wpa_s, 0);
5035 
5036 	wpa_bss_flush(wpa_s);
5037 	wpa_blacklist_clear(wpa_s);
5038 	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
5039 	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
5040 }
5041 
5042 
wpa_supplicant_ctrl_iface_process(struct wpa_supplicant * wpa_s,char * buf,size_t * resp_len)5043 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
5044 					 char *buf, size_t *resp_len)
5045 {
5046 	char *reply;
5047 	const int reply_size = 4096;
5048 	int ctrl_rsp = 0;
5049 	int reply_len;
5050 
5051 	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
5052 	    os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
5053 	    os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
5054 	    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
5055 	    os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
5056 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
5057 				      (const u8 *) buf, os_strlen(buf));
5058 	} else {
5059 		int level = MSG_DEBUG;
5060 		if (os_strcmp(buf, "PING") == 0)
5061 			level = MSG_EXCESSIVE;
5062 		wpa_hexdump_ascii(level, "RX ctrl_iface",
5063 				  (const u8 *) buf, os_strlen(buf));
5064 		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
5065 	}
5066 
5067 	reply = os_malloc(reply_size);
5068 	if (reply == NULL) {
5069 		*resp_len = 1;
5070 		return NULL;
5071 	}
5072 
5073 	os_memcpy(reply, "OK\n", 3);
5074 	reply_len = 3;
5075 
5076 	if (os_strcmp(buf, "PING") == 0) {
5077 		os_memcpy(reply, "PONG\n", 5);
5078 		reply_len = 5;
5079 	} else if (os_strcmp(buf, "IFNAME") == 0) {
5080 		reply_len = os_strlen(wpa_s->ifname);
5081 		os_memcpy(reply, wpa_s->ifname, reply_len);
5082 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
5083 		if (wpa_debug_reopen_file() < 0)
5084 			reply_len = -1;
5085 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
5086 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
5087 	} else if (os_strcmp(buf, "MIB") == 0) {
5088 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
5089 		if (reply_len >= 0) {
5090 			int res;
5091 			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
5092 					       reply_size - reply_len);
5093 			if (res < 0)
5094 				reply_len = -1;
5095 			else
5096 				reply_len += res;
5097 		}
5098 	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
5099 		reply_len = wpa_supplicant_ctrl_iface_status(
5100 			wpa_s, buf + 6, reply, reply_size);
5101 	} else if (os_strcmp(buf, "PMKSA") == 0) {
5102 		reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
5103 						    reply_size);
5104 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
5105 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
5106 			reply_len = -1;
5107 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
5108 		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
5109 							  reply, reply_size);
5110 	} else if (os_strcmp(buf, "LOGON") == 0) {
5111 		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
5112 	} else if (os_strcmp(buf, "LOGOFF") == 0) {
5113 		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
5114 	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
5115 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5116 			reply_len = -1;
5117 		else
5118 			wpas_request_connection(wpa_s);
5119 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
5120 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5121 			reply_len = -1;
5122 		else if (wpa_s->disconnected)
5123 			wpas_request_connection(wpa_s);
5124 #ifdef IEEE8021X_EAPOL
5125 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
5126 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
5127 			reply_len = -1;
5128 #endif /* IEEE8021X_EAPOL */
5129 #ifdef CONFIG_PEERKEY
5130 	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
5131 		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
5132 			reply_len = -1;
5133 #endif /* CONFIG_PEERKEY */
5134 #ifdef CONFIG_IEEE80211R
5135 	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
5136 		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
5137 			reply_len = -1;
5138 #endif /* CONFIG_IEEE80211R */
5139 #ifdef CONFIG_WPS
5140 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
5141 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
5142 		if (res == -2) {
5143 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
5144 			reply_len = 17;
5145 		} else if (res)
5146 			reply_len = -1;
5147 	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
5148 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
5149 		if (res == -2) {
5150 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
5151 			reply_len = 17;
5152 		} else if (res)
5153 			reply_len = -1;
5154 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
5155 		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
5156 							      reply,
5157 							      reply_size);
5158 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
5159 		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
5160 			wpa_s, buf + 14, reply, reply_size);
5161 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
5162 		if (wpas_wps_cancel(wpa_s))
5163 			reply_len = -1;
5164 #ifdef CONFIG_WPS_NFC
5165 	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
5166 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
5167 			reply_len = -1;
5168 	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
5169 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
5170 			reply_len = -1;
5171 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
5172 		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
5173 			wpa_s, buf + 21, reply, reply_size);
5174 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
5175 		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
5176 			wpa_s, buf + 14, reply, reply_size);
5177 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
5178 		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
5179 							       buf + 17))
5180 			reply_len = -1;
5181 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
5182 		reply_len = wpas_ctrl_nfc_get_handover_req(
5183 			wpa_s, buf + 21, reply, reply_size);
5184 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
5185 		reply_len = wpas_ctrl_nfc_get_handover_sel(
5186 			wpa_s, buf + 21, reply, reply_size);
5187 	} else if (os_strncmp(buf, "NFC_RX_HANDOVER_REQ ", 20) == 0) {
5188 		reply_len = wpas_ctrl_nfc_rx_handover_req(
5189 			wpa_s, buf + 20, reply, reply_size);
5190 	} else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) {
5191 		if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20))
5192 			reply_len = -1;
5193 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
5194 		if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
5195 			reply_len = -1;
5196 #endif /* CONFIG_WPS_NFC */
5197 	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
5198 		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
5199 			reply_len = -1;
5200 #ifdef CONFIG_AP
5201 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
5202 		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
5203 			wpa_s, buf + 11, reply, reply_size);
5204 #endif /* CONFIG_AP */
5205 #ifdef CONFIG_WPS_ER
5206 	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
5207 		if (wpas_wps_er_start(wpa_s, NULL))
5208 			reply_len = -1;
5209 	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
5210 		if (wpas_wps_er_start(wpa_s, buf + 13))
5211 			reply_len = -1;
5212 	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
5213 		if (wpas_wps_er_stop(wpa_s))
5214 			reply_len = -1;
5215 	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
5216 		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
5217 			reply_len = -1;
5218 	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
5219 		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
5220 		if (ret == -2) {
5221 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
5222 			reply_len = 17;
5223 		} else if (ret == -3) {
5224 			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
5225 			reply_len = 18;
5226 		} else if (ret == -4) {
5227 			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
5228 			reply_len = 20;
5229 		} else if (ret)
5230 			reply_len = -1;
5231 	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
5232 		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
5233 			reply_len = -1;
5234 	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
5235 		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
5236 								buf + 18))
5237 			reply_len = -1;
5238 	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
5239 		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
5240 			reply_len = -1;
5241 #ifdef CONFIG_WPS_NFC
5242 	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
5243 		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
5244 			wpa_s, buf + 24, reply, reply_size);
5245 #endif /* CONFIG_WPS_NFC */
5246 #endif /* CONFIG_WPS_ER */
5247 #endif /* CONFIG_WPS */
5248 #ifdef CONFIG_IBSS_RSN
5249 	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
5250 		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
5251 			reply_len = -1;
5252 #endif /* CONFIG_IBSS_RSN */
5253 #ifdef CONFIG_P2P
5254 	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
5255 		if (p2p_ctrl_find(wpa_s, buf + 9))
5256 			reply_len = -1;
5257 	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
5258 		if (p2p_ctrl_find(wpa_s, ""))
5259 			reply_len = -1;
5260 	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
5261 		wpas_p2p_stop_find(wpa_s);
5262 	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
5263 		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
5264 					     reply_size);
5265 	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
5266 		if (p2p_ctrl_listen(wpa_s, buf + 11))
5267 			reply_len = -1;
5268 	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
5269 		if (p2p_ctrl_listen(wpa_s, ""))
5270 			reply_len = -1;
5271 	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
5272 		if (wpas_p2p_group_remove(wpa_s, buf + 17))
5273 			reply_len = -1;
5274 	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
5275 		if (wpas_p2p_group_add(wpa_s, 0, 0, 0))
5276 			reply_len = -1;
5277 	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
5278 		if (p2p_ctrl_group_add(wpa_s, buf + 14))
5279 			reply_len = -1;
5280 	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
5281 		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
5282 			reply_len = -1;
5283 	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
5284 		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
5285 	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
5286 		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
5287 						   reply_size);
5288 	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
5289 		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
5290 			reply_len = -1;
5291 	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
5292 		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
5293 			reply_len = -1;
5294 	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
5295 #ifdef ANDROID_P2P
5296 		wpas_p2p_sd_service_update(wpa_s, SRV_UPDATE);
5297 #else
5298 		wpas_p2p_sd_service_update(wpa_s);
5299 #endif
5300 	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
5301 		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
5302 			reply_len = -1;
5303 	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
5304 		wpas_p2p_service_flush(wpa_s);
5305 	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
5306 		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
5307 			reply_len = -1;
5308 	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
5309 		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
5310 			reply_len = -1;
5311 	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
5312 		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
5313 			reply_len = -1;
5314 	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
5315 		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
5316 			reply_len = -1;
5317 	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
5318 		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
5319 					      reply_size);
5320 	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
5321 		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
5322 			reply_len = -1;
5323 	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
5324 		p2p_ctrl_flush(wpa_s);
5325 	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
5326 		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
5327 			reply_len = -1;
5328 	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
5329 		if (wpas_p2p_cancel(wpa_s))
5330 			reply_len = -1;
5331 	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
5332 		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
5333 			reply_len = -1;
5334 	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
5335 		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
5336 			reply_len = -1;
5337 	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
5338 		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
5339 			reply_len = -1;
5340 	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
5341 		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
5342 			reply_len = -1;
5343 #endif /* CONFIG_P2P */
5344 #ifdef CONFIG_WIFI_DISPLAY
5345 	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
5346 		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
5347 			reply_len = -1;
5348 	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
5349 		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
5350 						     reply, reply_size);
5351 #endif /* CONFIG_WIFI_DISPLAY */
5352 #ifdef CONFIG_INTERWORKING
5353 	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
5354 		if (interworking_fetch_anqp(wpa_s) < 0)
5355 			reply_len = -1;
5356 	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
5357 		interworking_stop_fetch_anqp(wpa_s);
5358 	} else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) {
5359 		if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") !=
5360 					NULL) < 0)
5361 			reply_len = -1;
5362 	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
5363 		if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
5364 			reply_len = -1;
5365 	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
5366 		if (get_anqp(wpa_s, buf + 9) < 0)
5367 			reply_len = -1;
5368 	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
5369 		if (gas_request(wpa_s, buf + 12) < 0)
5370 			reply_len = -1;
5371 	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
5372 		reply_len = gas_response_get(wpa_s, buf + 17, reply,
5373 					     reply_size);
5374 #endif /* CONFIG_INTERWORKING */
5375 #ifdef CONFIG_HS20
5376 	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
5377 		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
5378 			reply_len = -1;
5379 	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
5380 		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
5381 			reply_len = -1;
5382 #endif /* CONFIG_HS20 */
5383 	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
5384 	{
5385 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
5386 			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
5387 			reply_len = -1;
5388 		else
5389 			ctrl_rsp = 1;
5390 	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
5391 		if (wpa_supplicant_reload_configuration(wpa_s))
5392 			reply_len = -1;
5393 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
5394 		wpa_supplicant_terminate_proc(wpa_s->global);
5395 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
5396 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
5397 			reply_len = -1;
5398 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
5399 		reply_len = wpa_supplicant_ctrl_iface_blacklist(
5400 			wpa_s, buf + 9, reply, reply_size);
5401 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
5402 		reply_len = wpa_supplicant_ctrl_iface_log_level(
5403 			wpa_s, buf + 9, reply, reply_size);
5404 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
5405 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
5406 			wpa_s, reply, reply_size);
5407 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
5408 #ifdef CONFIG_SME
5409 		wpa_s->sme.prev_bssid_set = 0;
5410 #endif /* CONFIG_SME */
5411 		wpa_s->reassociate = 0;
5412 		wpa_s->disconnected = 1;
5413 		wpa_supplicant_cancel_sched_scan(wpa_s);
5414 		wpa_supplicant_cancel_scan(wpa_s);
5415 		wpa_supplicant_deauthenticate(wpa_s,
5416 					      WLAN_REASON_DEAUTH_LEAVING);
5417 	} else if (os_strcmp(buf, "SCAN") == 0 ||
5418 		   os_strncmp(buf, "SCAN ", 5) == 0) {
5419 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5420 			reply_len = -1;
5421 		else {
5422 			if (os_strlen(buf) > 4 &&
5423 			    os_strncasecmp(buf + 5, "TYPE=ONLY", 9) == 0)
5424 				wpa_s->scan_res_handler = scan_only_handler;
5425 			if (!wpa_s->sched_scanning && !wpa_s->scanning &&
5426 			    ((wpa_s->wpa_state <= WPA_SCANNING) ||
5427 			     (wpa_s->wpa_state == WPA_COMPLETED))) {
5428 				wpa_s->normal_scans = 0;
5429 				wpa_s->scan_req = MANUAL_SCAN_REQ;
5430 				wpa_supplicant_req_scan(wpa_s, 0, 0);
5431 			} else if (wpa_s->sched_scanning) {
5432 				wpa_printf(MSG_DEBUG, "Stop ongoing "
5433 					   "sched_scan to allow requested "
5434 					   "full scan to proceed");
5435 				wpa_supplicant_cancel_sched_scan(wpa_s);
5436 				wpa_s->scan_req = MANUAL_SCAN_REQ;
5437 				wpa_supplicant_req_scan(wpa_s, 0, 0);
5438 			} else {
5439 				wpa_printf(MSG_DEBUG, "Ongoing scan action - "
5440 					   "reject new request");
5441 				reply_len = os_snprintf(reply, reply_size,
5442 							"FAIL-BUSY\n");
5443 			}
5444 		}
5445 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
5446 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
5447 			wpa_s, reply, reply_size);
5448 	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
5449 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
5450 			reply_len = -1;
5451 	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
5452 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
5453 			reply_len = -1;
5454 	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
5455 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
5456 			reply_len = -1;
5457 	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
5458 		reply_len = wpa_supplicant_ctrl_iface_add_network(
5459 			wpa_s, reply, reply_size);
5460 	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
5461 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
5462 			reply_len = -1;
5463 	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
5464 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
5465 			reply_len = -1;
5466 	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
5467 		reply_len = wpa_supplicant_ctrl_iface_get_network(
5468 			wpa_s, buf + 12, reply, reply_size);
5469 	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
5470 		reply_len = wpa_supplicant_ctrl_iface_list_creds(
5471 			wpa_s, reply, reply_size);
5472 	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
5473 		reply_len = wpa_supplicant_ctrl_iface_add_cred(
5474 			wpa_s, reply, reply_size);
5475 	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
5476 		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
5477 			reply_len = -1;
5478 	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
5479 		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
5480 			reply_len = -1;
5481 #ifndef CONFIG_NO_CONFIG_WRITE
5482 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
5483 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
5484 			reply_len = -1;
5485 #endif /* CONFIG_NO_CONFIG_WRITE */
5486 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
5487 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
5488 			wpa_s, buf + 15, reply, reply_size);
5489 	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
5490 		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
5491 			reply_len = -1;
5492 	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
5493 		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
5494 			reply_len = -1;
5495 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
5496 		reply_len = wpa_supplicant_global_iface_list(
5497 			wpa_s->global, reply, reply_size);
5498 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
5499 		reply_len = wpa_supplicant_global_iface_interfaces(
5500 			wpa_s->global, reply, reply_size);
5501 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
5502 		reply_len = wpa_supplicant_ctrl_iface_bss(
5503 			wpa_s, buf + 4, reply, reply_size);
5504 #ifdef CONFIG_AP
5505 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
5506 		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
5507 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
5508 		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
5509 					      reply_size);
5510 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
5511 		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
5512 						   reply_size);
5513 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
5514 		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
5515 			reply_len = -1;
5516 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
5517 		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
5518 			reply_len = -1;
5519 #endif /* CONFIG_AP */
5520 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
5521 		wpas_notify_suspend(wpa_s->global);
5522 	} else if (os_strcmp(buf, "RESUME") == 0) {
5523 		wpas_notify_resume(wpa_s->global);
5524 	} else if (os_strcmp(buf, "DROP_SA") == 0) {
5525 		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
5526 	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
5527 		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
5528 			reply_len = -1;
5529 	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
5530 		if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
5531 			reply_len = -1;
5532 	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
5533 		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
5534 			reply_len = -1;
5535 	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
5536 		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
5537 							       buf + 17))
5538 			reply_len = -1;
5539 	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
5540 		if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10))
5541 			reply_len = -1;
5542 #ifdef CONFIG_TDLS
5543 	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
5544 		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
5545 			reply_len = -1;
5546 	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
5547 		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
5548 			reply_len = -1;
5549 	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
5550 		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
5551 			reply_len = -1;
5552 #endif /* CONFIG_TDLS */
5553 	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
5554 		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
5555 						       reply_size);
5556 	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
5557 		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
5558 						       reply_size);
5559 #ifdef CONFIG_AUTOSCAN
5560 	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
5561 		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
5562 			reply_len = -1;
5563 #endif /* CONFIG_AUTOSCAN */
5564 #ifdef ANDROID
5565 	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
5566 		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
5567 						      reply_size);
5568 #endif
5569 	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
5570 		pmksa_cache_clear_current(wpa_s->wpa);
5571 		eapol_sm_request_reauth(wpa_s->eapol);
5572 #ifdef CONFIG_WNM
5573 	} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
5574 		if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
5575 			reply_len = -1;
5576 #endif /* CONFIG_WNM */
5577 	} else if (os_strcmp(buf, "FLUSH") == 0) {
5578 		wpa_supplicant_ctrl_iface_flush(wpa_s);
5579 	} else {
5580 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
5581 		reply_len = 16;
5582 	}
5583 
5584 	if (reply_len < 0) {
5585 		os_memcpy(reply, "FAIL\n", 5);
5586 		reply_len = 5;
5587 	}
5588 
5589 	if (ctrl_rsp)
5590 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
5591 
5592 	*resp_len = reply_len;
5593 	return reply;
5594 }
5595 
5596 
wpa_supplicant_global_iface_add(struct wpa_global * global,char * cmd)5597 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
5598 					   char *cmd)
5599 {
5600 	struct wpa_interface iface;
5601 	char *pos;
5602 
5603 	/*
5604 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
5605 	 * TAB<bridge_ifname>
5606 	 */
5607 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
5608 
5609 	os_memset(&iface, 0, sizeof(iface));
5610 
5611 	do {
5612 		iface.ifname = pos = cmd;
5613 		pos = os_strchr(pos, '\t');
5614 		if (pos)
5615 			*pos++ = '\0';
5616 		if (iface.ifname[0] == '\0')
5617 			return -1;
5618 		if (pos == NULL)
5619 			break;
5620 
5621 		iface.confname = pos;
5622 		pos = os_strchr(pos, '\t');
5623 		if (pos)
5624 			*pos++ = '\0';
5625 		if (iface.confname[0] == '\0')
5626 			iface.confname = NULL;
5627 		if (pos == NULL)
5628 			break;
5629 
5630 		iface.driver = pos;
5631 		pos = os_strchr(pos, '\t');
5632 		if (pos)
5633 			*pos++ = '\0';
5634 		if (iface.driver[0] == '\0')
5635 			iface.driver = NULL;
5636 		if (pos == NULL)
5637 			break;
5638 
5639 		iface.ctrl_interface = pos;
5640 		pos = os_strchr(pos, '\t');
5641 		if (pos)
5642 			*pos++ = '\0';
5643 		if (iface.ctrl_interface[0] == '\0')
5644 			iface.ctrl_interface = NULL;
5645 		if (pos == NULL)
5646 			break;
5647 
5648 		iface.driver_param = pos;
5649 		pos = os_strchr(pos, '\t');
5650 		if (pos)
5651 			*pos++ = '\0';
5652 		if (iface.driver_param[0] == '\0')
5653 			iface.driver_param = NULL;
5654 		if (pos == NULL)
5655 			break;
5656 
5657 		iface.bridge_ifname = pos;
5658 		pos = os_strchr(pos, '\t');
5659 		if (pos)
5660 			*pos++ = '\0';
5661 		if (iface.bridge_ifname[0] == '\0')
5662 			iface.bridge_ifname = NULL;
5663 		if (pos == NULL)
5664 			break;
5665 	} while (0);
5666 
5667 	if (wpa_supplicant_get_iface(global, iface.ifname))
5668 		return -1;
5669 
5670 	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
5671 }
5672 
5673 
wpa_supplicant_global_iface_remove(struct wpa_global * global,char * cmd)5674 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
5675 					      char *cmd)
5676 {
5677 	struct wpa_supplicant *wpa_s;
5678 
5679 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
5680 
5681 	wpa_s = wpa_supplicant_get_iface(global, cmd);
5682 	if (wpa_s == NULL)
5683 		return -1;
5684 	return wpa_supplicant_remove_iface(global, wpa_s, 0);
5685 }
5686 
5687 
wpa_free_iface_info(struct wpa_interface_info * iface)5688 static void wpa_free_iface_info(struct wpa_interface_info *iface)
5689 {
5690 	struct wpa_interface_info *prev;
5691 
5692 	while (iface) {
5693 		prev = iface;
5694 		iface = iface->next;
5695 
5696 		os_free(prev->ifname);
5697 		os_free(prev->desc);
5698 		os_free(prev);
5699 	}
5700 }
5701 
5702 
wpa_supplicant_global_iface_list(struct wpa_global * global,char * buf,int len)5703 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
5704 					    char *buf, int len)
5705 {
5706 	int i, res;
5707 	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
5708 	char *pos, *end;
5709 
5710 	for (i = 0; wpa_drivers[i]; i++) {
5711 		struct wpa_driver_ops *drv = wpa_drivers[i];
5712 		if (drv->get_interfaces == NULL)
5713 			continue;
5714 		tmp = drv->get_interfaces(global->drv_priv[i]);
5715 		if (tmp == NULL)
5716 			continue;
5717 
5718 		if (last == NULL)
5719 			iface = last = tmp;
5720 		else
5721 			last->next = tmp;
5722 		while (last->next)
5723 			last = last->next;
5724 	}
5725 
5726 	pos = buf;
5727 	end = buf + len;
5728 	for (tmp = iface; tmp; tmp = tmp->next) {
5729 		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
5730 				  tmp->drv_name, tmp->ifname,
5731 				  tmp->desc ? tmp->desc : "");
5732 		if (res < 0 || res >= end - pos) {
5733 			*pos = '\0';
5734 			break;
5735 		}
5736 		pos += res;
5737 	}
5738 
5739 	wpa_free_iface_info(iface);
5740 
5741 	return pos - buf;
5742 }
5743 
5744 
wpa_supplicant_global_iface_interfaces(struct wpa_global * global,char * buf,int len)5745 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
5746 						  char *buf, int len)
5747 {
5748 	int res;
5749 	char *pos, *end;
5750 	struct wpa_supplicant *wpa_s;
5751 
5752 	wpa_s = global->ifaces;
5753 	pos = buf;
5754 	end = buf + len;
5755 
5756 	while (wpa_s) {
5757 		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
5758 		if (res < 0 || res >= end - pos) {
5759 			*pos = '\0';
5760 			break;
5761 		}
5762 		pos += res;
5763 		wpa_s = wpa_s->next;
5764 	}
5765 	return pos - buf;
5766 }
5767 
5768 
wpa_supplicant_global_ctrl_iface_process(struct wpa_global * global,char * buf,size_t * resp_len)5769 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
5770 						char *buf, size_t *resp_len)
5771 {
5772 	char *reply;
5773 	const int reply_size = 2048;
5774 	int reply_len;
5775 	int level = MSG_DEBUG;
5776 
5777 	if (os_strcmp(buf, "PING") == 0)
5778 		level = MSG_EXCESSIVE;
5779 	wpa_hexdump_ascii(level, "RX global ctrl_iface",
5780 			  (const u8 *) buf, os_strlen(buf));
5781 
5782 	reply = os_malloc(reply_size);
5783 	if (reply == NULL) {
5784 		*resp_len = 1;
5785 		return NULL;
5786 	}
5787 
5788 	os_memcpy(reply, "OK\n", 3);
5789 	reply_len = 3;
5790 
5791 	if (os_strcmp(buf, "PING") == 0) {
5792 		os_memcpy(reply, "PONG\n", 5);
5793 		reply_len = 5;
5794 	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
5795 		if (wpa_supplicant_global_iface_add(global, buf + 14))
5796 			reply_len = -1;
5797 	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
5798 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
5799 			reply_len = -1;
5800 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
5801 		reply_len = wpa_supplicant_global_iface_list(
5802 			global, reply, reply_size);
5803 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
5804 		reply_len = wpa_supplicant_global_iface_interfaces(
5805 			global, reply, reply_size);
5806 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
5807 		wpa_supplicant_terminate_proc(global);
5808 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
5809 		wpas_notify_suspend(global);
5810 	} else if (os_strcmp(buf, "RESUME") == 0) {
5811 		wpas_notify_resume(global);
5812 	} else {
5813 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
5814 		reply_len = 16;
5815 	}
5816 
5817 	if (reply_len < 0) {
5818 		os_memcpy(reply, "FAIL\n", 5);
5819 		reply_len = 5;
5820 	}
5821 
5822 	*resp_len = reply_len;
5823 	return reply;
5824 }
5825