• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "eloop.h"
19 #include "wpa.h"
20 #include "config.h"
21 #include "eapol_supp/eapol_supp_sm.h"
22 #include "wpa_supplicant_i.h"
23 #include "blacklist.h"
24 #include "ctrl_iface.h"
25 #include "l2_packet/l2_packet.h"
26 #include "preauth.h"
27 #include "pmksa_cache.h"
28 #include "wpa_ctrl.h"
29 #include "eap_peer/eap.h"
30 #include "ieee802_11_defs.h"
31 #include "wps_supplicant.h"
32 #include "wps/wps.h"
33 
34 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
35 					    char *buf, int len);
36 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
37 						  char *buf, int len);
38 
39 
wpa_supplicant_ctrl_iface_set(struct wpa_supplicant * wpa_s,char * cmd)40 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
41 					 char *cmd)
42 {
43 	char *value;
44 	int ret = 0;
45 
46 	value = os_strchr(cmd, ' ');
47 	if (value == NULL)
48 		return -1;
49 	*value++ = '\0';
50 
51 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
52 	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
53 		eapol_sm_configure(wpa_s->eapol,
54 				   atoi(value), -1, -1, -1);
55 	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
56 		eapol_sm_configure(wpa_s->eapol,
57 				   -1, atoi(value), -1, -1);
58 	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
59 		eapol_sm_configure(wpa_s->eapol,
60 				   -1, -1, atoi(value), -1);
61 	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
62 		eapol_sm_configure(wpa_s->eapol,
63 				   -1, -1, -1, atoi(value));
64 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
65 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
66 				     atoi(value)))
67 			ret = -1;
68 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
69 		   0) {
70 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
71 				     atoi(value)))
72 			ret = -1;
73 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
74 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
75 			ret = -1;
76 	} else
77 		ret = -1;
78 
79 	return ret;
80 }
81 
82 
83 #ifdef IEEE8021X_EAPOL
wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant * wpa_s,char * addr)84 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
85 					     char *addr)
86 {
87 	u8 bssid[ETH_ALEN];
88 	struct wpa_ssid *ssid = wpa_s->current_ssid;
89 
90 	if (hwaddr_aton(addr, bssid)) {
91 		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
92 			   "'%s'", addr);
93 		return -1;
94 	}
95 
96 	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
97 	rsn_preauth_deinit(wpa_s->wpa);
98 	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
99 		return -1;
100 
101 	return 0;
102 }
103 #endif /* IEEE8021X_EAPOL */
104 
105 
106 #ifdef CONFIG_PEERKEY
107 /* MLME-STKSTART.request(peer) */
wpa_supplicant_ctrl_iface_stkstart(struct wpa_supplicant * wpa_s,char * addr)108 static int wpa_supplicant_ctrl_iface_stkstart(
109 	struct wpa_supplicant *wpa_s, char *addr)
110 {
111 	u8 peer[ETH_ALEN];
112 
113 	if (hwaddr_aton(addr, peer)) {
114 		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
115 			   "address '%s'", peer);
116 		return -1;
117 	}
118 
119 	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
120 		   MAC2STR(peer));
121 
122 	return wpa_sm_stkstart(wpa_s->wpa, peer);
123 }
124 #endif /* CONFIG_PEERKEY */
125 
126 
127 #ifdef CONFIG_IEEE80211R
wpa_supplicant_ctrl_iface_ft_ds(struct wpa_supplicant * wpa_s,char * addr)128 static int wpa_supplicant_ctrl_iface_ft_ds(
129 	struct wpa_supplicant *wpa_s, char *addr)
130 {
131 	u8 target_ap[ETH_ALEN];
132 
133 	if (hwaddr_aton(addr, target_ap)) {
134 		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
135 			   "address '%s'", target_ap);
136 		return -1;
137 	}
138 
139 	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
140 
141 	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap);
142 }
143 #endif /* CONFIG_IEEE80211R */
144 
145 
146 #ifdef CONFIG_WPS
wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant * wpa_s,char * cmd)147 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
148 					     char *cmd)
149 {
150 	u8 bssid[ETH_ALEN];
151 
152 	if (cmd == NULL || os_strcmp(cmd, "any") == 0)
153 		return wpas_wps_start_pbc(wpa_s, NULL);
154 
155 	if (hwaddr_aton(cmd, bssid)) {
156 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
157 			   cmd);
158 		return -1;
159 	}
160 
161 	return wpas_wps_start_pbc(wpa_s, bssid);
162 }
163 
164 
wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)165 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
166 					     char *cmd, char *buf,
167 					     size_t buflen)
168 {
169 	u8 bssid[ETH_ALEN], *_bssid = bssid;
170 	char *pin;
171 	int ret;
172 
173 	pin = os_strchr(cmd, ' ');
174 	if (pin)
175 		*pin++ = '\0';
176 
177 	if (os_strcmp(cmd, "any") == 0)
178 		_bssid = NULL;
179 	else if (hwaddr_aton(cmd, bssid)) {
180 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
181 			   cmd);
182 		return -1;
183 	}
184 
185 	if (pin) {
186 		ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
187 		if (ret < 0)
188 			return -1;
189 		ret = os_snprintf(buf, buflen, "%s", pin);
190 		if (ret < 0 || (size_t) ret >= buflen)
191 			return -1;
192 		return ret;
193 	}
194 
195 	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL);
196 	if (ret < 0)
197 		return -1;
198 
199 	/* Return the generated PIN */
200 	ret = os_snprintf(buf, buflen, "%08d", ret);
201 	if (ret < 0 || (size_t) ret >= buflen)
202 		return -1;
203 	return ret;
204 }
205 
206 
wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant * wpa_s,char * cmd)207 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
208 					     char *cmd)
209 {
210 	u8 bssid[ETH_ALEN], *_bssid = bssid;
211 	char *pin;
212 
213 	pin = os_strchr(cmd, ' ');
214 	if (pin == NULL)
215 		return -1;
216 	*pin++ = '\0';
217 
218 	if (os_strcmp(cmd, "any") == 0)
219 		_bssid = NULL;
220 	else if (hwaddr_aton(cmd, bssid)) {
221 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
222 			   cmd);
223 		return -1;
224 	}
225 
226 	return wpas_wps_start_reg(wpa_s, _bssid, pin);
227 }
228 #endif /* CONFIG_WPS */
229 
230 
wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant * wpa_s,char * rsp)231 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
232 					      char *rsp)
233 {
234 #ifdef IEEE8021X_EAPOL
235 	char *pos, *id_pos;
236 	int id;
237 	struct wpa_ssid *ssid;
238 	struct eap_peer_config *eap;
239 
240 	pos = os_strchr(rsp, '-');
241 	if (pos == NULL)
242 		return -1;
243 	*pos++ = '\0';
244 	id_pos = pos;
245 	pos = os_strchr(pos, ':');
246 	if (pos == NULL)
247 		return -1;
248 	*pos++ = '\0';
249 	id = atoi(id_pos);
250 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
251 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
252 			      (u8 *) pos, os_strlen(pos));
253 
254 	ssid = wpa_config_get_network(wpa_s->conf, id);
255 	if (ssid == NULL) {
256 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
257 			   "to update", id);
258 		return -1;
259 	}
260 	eap = &ssid->eap;
261 
262 	if (os_strcmp(rsp, "IDENTITY") == 0) {
263 		os_free(eap->identity);
264 		eap->identity = (u8 *) os_strdup(pos);
265 		eap->identity_len = os_strlen(pos);
266 		eap->pending_req_identity = 0;
267 		if (ssid == wpa_s->current_ssid)
268 			wpa_s->reassociate = 1;
269 	} else if (os_strcmp(rsp, "PASSWORD") == 0) {
270 		os_free(eap->password);
271 		eap->password = (u8 *) os_strdup(pos);
272 		eap->password_len = os_strlen(pos);
273 		eap->pending_req_password = 0;
274 		if (ssid == wpa_s->current_ssid)
275 			wpa_s->reassociate = 1;
276 	} else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
277 		os_free(eap->new_password);
278 		eap->new_password = (u8 *) os_strdup(pos);
279 		eap->new_password_len = os_strlen(pos);
280 		eap->pending_req_new_password = 0;
281 		if (ssid == wpa_s->current_ssid)
282 			wpa_s->reassociate = 1;
283 	} else if (os_strcmp(rsp, "PIN") == 0) {
284 		os_free(eap->pin);
285 		eap->pin = os_strdup(pos);
286 		eap->pending_req_pin = 0;
287 		if (ssid == wpa_s->current_ssid)
288 			wpa_s->reassociate = 1;
289 	} else if (os_strcmp(rsp, "OTP") == 0) {
290 		os_free(eap->otp);
291 		eap->otp = (u8 *) os_strdup(pos);
292 		eap->otp_len = os_strlen(pos);
293 		os_free(eap->pending_req_otp);
294 		eap->pending_req_otp = NULL;
295 		eap->pending_req_otp_len = 0;
296 	} else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
297 		os_free(eap->private_key_passwd);
298 		eap->private_key_passwd = (u8 *) os_strdup(pos);
299 		eap->pending_req_passphrase = 0;
300 		if (ssid == wpa_s->current_ssid)
301 			wpa_s->reassociate = 1;
302 	} else {
303 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
304 		return -1;
305 	}
306 
307 	return 0;
308 #else /* IEEE8021X_EAPOL */
309 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
310 	return -1;
311 #endif /* IEEE8021X_EAPOL */
312 }
313 
314 
wpa_supplicant_ctrl_iface_status(struct wpa_supplicant * wpa_s,const char * params,char * buf,size_t buflen)315 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
316 					    const char *params,
317 					    char *buf, size_t buflen)
318 {
319 	char *pos, *end, tmp[30];
320 	int res, verbose, ret;
321 
322 	verbose = os_strcmp(params, "-VERBOSE") == 0;
323 	pos = buf;
324 	end = buf + buflen;
325 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
326 		struct wpa_ssid *ssid = wpa_s->current_ssid;
327 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
328 				  MAC2STR(wpa_s->bssid));
329 		if (ret < 0 || ret >= end - pos)
330 			return pos - buf;
331 		pos += ret;
332 		if (ssid) {
333 			u8 *_ssid = ssid->ssid;
334 			size_t ssid_len = ssid->ssid_len;
335 			u8 ssid_buf[MAX_SSID_LEN];
336 			if (ssid_len == 0) {
337 				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
338 				if (_res < 0)
339 					ssid_len = 0;
340 				else
341 					ssid_len = _res;
342 				_ssid = ssid_buf;
343 			}
344 			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
345 					  wpa_ssid_txt(_ssid, ssid_len),
346 					  ssid->id);
347 			if (ret < 0 || ret >= end - pos)
348 				return pos - buf;
349 			pos += ret;
350 
351 			if (ssid->id_str) {
352 				ret = os_snprintf(pos, end - pos,
353 						  "id_str=%s\n",
354 						  ssid->id_str);
355 				if (ret < 0 || ret >= end - pos)
356 					return pos - buf;
357 				pos += ret;
358 			}
359 		}
360 
361 		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
362 	}
363 	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
364 			  wpa_supplicant_state_txt(wpa_s->wpa_state));
365 	if (ret < 0 || ret >= end - pos)
366 		return pos - buf;
367 	pos += ret;
368 
369 	if (wpa_s->l2 &&
370 	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
371 		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
372 		if (ret < 0 || ret >= end - pos)
373 			return pos - buf;
374 		pos += ret;
375 	}
376 
377 	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
378 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
379 		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
380 					  verbose);
381 		if (res >= 0)
382 			pos += res;
383 	}
384 
385 	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
386 	if (res >= 0)
387 		pos += res;
388 
389 	return pos - buf;
390 }
391 
392 
wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant * wpa_s,char * cmd)393 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
394 					   char *cmd)
395 {
396 	char *pos;
397 	int id;
398 	struct wpa_ssid *ssid;
399 	u8 bssid[ETH_ALEN];
400 
401 	/* cmd: "<network id> <BSSID>" */
402 	pos = os_strchr(cmd, ' ');
403 	if (pos == NULL)
404 		return -1;
405 	*pos++ = '\0';
406 	id = atoi(cmd);
407 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
408 	if (hwaddr_aton(pos, bssid)) {
409 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
410 		return -1;
411 	}
412 
413 	ssid = wpa_config_get_network(wpa_s->conf, id);
414 	if (ssid == NULL) {
415 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
416 			   "to update", id);
417 		return -1;
418 	}
419 
420 	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
421 	ssid->bssid_set = !is_zero_ether_addr(bssid);
422 
423 	return 0;
424 }
425 
426 #ifdef ANDROID
wpa_supplicant_ctrl_iface_scan_interval(struct wpa_supplicant * wpa_s,char * cmd)427 static int wpa_supplicant_ctrl_iface_scan_interval(
428 	struct wpa_supplicant *wpa_s, char *cmd)
429 {
430 	int scan_int = atoi(cmd);
431 	if (scan_int < 0)
432 		return -1;
433 	wpa_s->scan_interval = scan_int;
434 	return 0;
435 }
436 
437 
wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)438 static int wpa_supplicant_ctrl_iface_blacklist(
439 		struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
440 {
441 	u8 bssid[ETH_ALEN];
442 	struct wpa_blacklist *e;
443 	char *pos, *end;
444 	int ret;
445 
446 	/* cmd: "BLACKLIST [<BSSID>]" */
447 	if (*cmd == '\0') {
448 		pos = buf;
449 		end = buf + buflen;
450 
451 		e = wpa_s->blacklist;
452 		while (e) {
453 			ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid));
454 			if (ret < 0 || ret >= end - pos)
455 				return pos - buf;
456 			pos += ret;
457 			e = e->next;
458 		}
459 		return pos - buf;
460 	}
461 
462 	++cmd;
463 	if (os_strncmp(cmd, "clear", 5) == 0) {
464 		wpa_blacklist_clear(wpa_s);
465 		os_memcpy(buf, "OK\n", 3);
466 		return 3;
467 	}
468 
469 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
470 	if (hwaddr_aton(cmd, bssid)) {
471 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd);
472 		return -1;
473 	}
474 
475 	/*
476 	 * Add the BSSID twice, so its count will be 2, causing it to be
477 	 * skipped when processing scan results.
478 	 */
479 	ret = wpa_blacklist_add(wpa_s, bssid);
480 	if (ret != 0)
481 		return -1;
482 	ret = wpa_blacklist_add(wpa_s, bssid);
483 	if (ret != 0)
484 		return -1;
485 	os_memcpy(buf, "OK\n", 3);
486 	return 3;
487 }
488 
489 
490 extern int wpa_debug_level;
491 extern int wpa_debug_timestamp;
wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)492 static int wpa_supplicant_ctrl_iface_log_level(
493 		struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
494 {
495 	char *pos, *end, *stamp;
496 	int ret;
497 
498 	if (cmd == NULL) {
499 		return -1;
500 	}
501 
502 	/* cmd: "LOG_LEVEL [<level>]" */
503 	if (*cmd == '\0') {
504 		pos = buf;
505 		end = buf + buflen;
506 		ret = os_snprintf(pos, end-pos, "Current level: %d\n"
507 			"{0-MSGDUMP, 1-DEBUG, 2-INFO, 3-WARNING, 4-ERROR}\n"
508 			"Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp);
509 		if (ret < 0 || ret >= end - pos)
510 			ret = 0;
511 
512 		return ret;
513 	}
514 
515 	while (*cmd == ' ') {
516 		cmd++;
517 	}
518 
519 	stamp = os_strchr(cmd, ' ');
520 	if (stamp) {
521 		*stamp++ = '\0';
522 		while (*stamp == ' ') {
523 			stamp++;
524 		}
525 	}
526 
527 	if (cmd && os_strlen(cmd)) {
528 		wpa_debug_level = atoi(cmd);
529 	}
530 
531 	if (stamp && os_strlen(stamp)) {
532 		wpa_debug_timestamp = atoi(stamp);
533 	}
534 
535 	os_memcpy(buf, "OK\n", 3);
536 	return 3;
537 }
538 #endif
539 
wpa_supplicant_ctrl_iface_list_networks(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)540 static int wpa_supplicant_ctrl_iface_list_networks(
541 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
542 {
543 	char *pos, *end;
544 	struct wpa_ssid *ssid;
545 	int ret;
546 
547 	pos = buf;
548 	end = buf + buflen;
549 	ret = os_snprintf(pos, end - pos,
550 			  "network id / ssid / bssid / flags\n");
551 	if (ret < 0 || ret >= end - pos)
552 		return pos - buf;
553 	pos += ret;
554 
555 	ssid = wpa_s->conf->ssid;
556 	while (ssid) {
557 		ret = os_snprintf(pos, end - pos, "%d\t%s",
558 				  ssid->id,
559 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
560 		if (ret < 0 || ret >= end - pos)
561 			return pos - buf;
562 		pos += ret;
563 		if (ssid->bssid_set) {
564 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
565 					  MAC2STR(ssid->bssid));
566 		} else {
567 			ret = os_snprintf(pos, end - pos, "\tany");
568 		}
569 		if (ret < 0 || ret >= end - pos)
570 			return pos - buf;
571 		pos += ret;
572 		ret = os_snprintf(pos, end - pos, "\t%s%s",
573 				  ssid == wpa_s->current_ssid ?
574 				  "[CURRENT]" : "",
575 				  ssid->disabled ? "[DISABLED]" : "");
576 		if (ret < 0 || ret >= end - pos)
577 			return pos - buf;
578 		pos += ret;
579 		ret = os_snprintf(pos, end - pos, "\n");
580 		if (ret < 0 || ret >= end - pos)
581 			return pos - buf;
582 		pos += ret;
583 
584 		ssid = ssid->next;
585 	}
586 
587 	return pos - buf;
588 }
589 
590 
wpa_supplicant_cipher_txt(char * pos,char * end,int cipher)591 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
592 {
593 	int first = 1, ret;
594 	ret = os_snprintf(pos, end - pos, "-");
595 	if (ret < 0 || ret >= end - pos)
596 		return pos;
597 	pos += ret;
598 	if (cipher & WPA_CIPHER_NONE) {
599 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
600 		if (ret < 0 || ret >= end - pos)
601 			return pos;
602 		pos += ret;
603 		first = 0;
604 	}
605 	if (cipher & WPA_CIPHER_WEP40) {
606 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
607 		if (ret < 0 || ret >= end - pos)
608 			return pos;
609 		pos += ret;
610 		first = 0;
611 	}
612 	if (cipher & WPA_CIPHER_WEP104) {
613 		ret = os_snprintf(pos, end - pos, "%sWEP104",
614 				  first ? "" : "+");
615 		if (ret < 0 || ret >= end - pos)
616 			return pos;
617 		pos += ret;
618 		first = 0;
619 	}
620 	if (cipher & WPA_CIPHER_TKIP) {
621 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
622 		if (ret < 0 || ret >= end - pos)
623 			return pos;
624 		pos += ret;
625 		first = 0;
626 	}
627 	if (cipher & WPA_CIPHER_CCMP) {
628 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
629 		if (ret < 0 || ret >= end - pos)
630 			return pos;
631 		pos += ret;
632 		first = 0;
633 	}
634 	return pos;
635 }
636 
637 
wpa_supplicant_ie_txt(char * pos,char * end,const char * proto,const u8 * ie,size_t ie_len)638 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
639 				    const u8 *ie, size_t ie_len)
640 {
641 	struct wpa_ie_data data;
642 	int first, ret;
643 
644 	ret = os_snprintf(pos, end - pos, "[%s-", proto);
645 	if (ret < 0 || ret >= end - pos)
646 		return pos;
647 	pos += ret;
648 
649 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
650 		ret = os_snprintf(pos, end - pos, "?]");
651 		if (ret < 0 || ret >= end - pos)
652 			return pos;
653 		pos += ret;
654 		return pos;
655 	}
656 
657 	first = 1;
658 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
659 		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
660 		if (ret < 0 || ret >= end - pos)
661 			return pos;
662 		pos += ret;
663 		first = 0;
664 	}
665 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
666 		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
667 		if (ret < 0 || ret >= end - pos)
668 			return pos;
669 		pos += ret;
670 		first = 0;
671 	}
672 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
673 		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
674 		if (ret < 0 || ret >= end - pos)
675 			return pos;
676 		pos += ret;
677 		first = 0;
678 	}
679 #ifdef CONFIG_IEEE80211R
680 	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
681 		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
682 				  first ? "" : "+");
683 		if (ret < 0 || ret >= end - pos)
684 			return pos;
685 		pos += ret;
686 		first = 0;
687 	}
688 	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
689 		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
690 				  first ? "" : "+");
691 		if (ret < 0 || ret >= end - pos)
692 			return pos;
693 		pos += ret;
694 		first = 0;
695 	}
696 #endif /* CONFIG_IEEE80211R */
697 #ifdef CONFIG_IEEE80211W
698 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
699 		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
700 				  first ? "" : "+");
701 		if (ret < 0 || ret >= end - pos)
702 			return pos;
703 		pos += ret;
704 		first = 0;
705 	}
706 	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
707 		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
708 				  first ? "" : "+");
709 		if (ret < 0 || ret >= end - pos)
710 			return pos;
711 		pos += ret;
712 		first = 0;
713 	}
714 #endif /* CONFIG_IEEE80211W */
715 
716 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
717 
718 	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
719 		ret = os_snprintf(pos, end - pos, "-preauth");
720 		if (ret < 0 || ret >= end - pos)
721 			return pos;
722 		pos += ret;
723 	}
724 
725 	ret = os_snprintf(pos, end - pos, "]");
726 	if (ret < 0 || ret >= end - pos)
727 		return pos;
728 	pos += ret;
729 
730 	return pos;
731 }
732 
wpa_supplicant_wps_ie_txt(char * pos,char * end,const struct wpa_scan_res * res)733 static char * wpa_supplicant_wps_ie_txt(char *pos, char *end,
734 					const struct wpa_scan_res *res)
735 {
736 #ifdef CONFIG_WPS
737 	struct wpabuf *wps_ie;
738 	int ret;
739 	const char *txt;
740 
741 	wps_ie = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
742 	if (wps_ie == NULL)
743 		return pos;
744 
745 	if (wps_is_selected_pbc_registrar(wps_ie))
746 		txt = "[WPS-PBC]";
747 	else if (wps_is_selected_pin_registrar(wps_ie))
748 		txt = "[WPS-PIN]";
749 	else
750 		txt = "[WPS]";
751 
752 	ret = os_snprintf(pos, end - pos, "%s", txt);
753 	if (ret >= 0 && ret < end - pos)
754 		pos += ret;
755 	wpabuf_free(wps_ie);
756 #endif /* CONFIG_WPS */
757 
758 	return pos;
759 }
760 
761 
762 /* Format one result on one text line into a buffer. */
wpa_supplicant_ctrl_iface_scan_result(const struct wpa_scan_res * res,char * buf,size_t buflen)763 static int wpa_supplicant_ctrl_iface_scan_result(
764 	const struct wpa_scan_res *res, char *buf, size_t buflen)
765 {
766 	char *pos, *end;
767 	int ret;
768 	const u8 *ie, *ie2;
769 
770 	pos = buf;
771 	end = buf + buflen;
772 
773 	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
774 			  MAC2STR(res->bssid), res->freq, res->level);
775 	if (ret < 0 || ret >= end - pos)
776 		return -1;
777 	pos += ret;
778 	ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
779 	if (ie)
780 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
781 	ie2 = wpa_scan_get_ie(res, WLAN_EID_RSN);
782 	if (ie2)
783 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
784 	pos = wpa_supplicant_wps_ie_txt(pos, end, res);
785 	if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) {
786 		ret = os_snprintf(pos, end - pos, "[WEP]");
787 		if (ret < 0 || ret >= end - pos)
788 			return -1;
789 		pos += ret;
790 	}
791 	if (res->caps & IEEE80211_CAP_IBSS) {
792 		ret = os_snprintf(pos, end - pos, "[IBSS]");
793 		if (ret < 0 || ret >= end - pos)
794 			return -1;
795 		pos += ret;
796 	}
797     /* Just to make the fields line up nicely when printed */
798 	if (!ie && !ie2) {
799 		ret = os_snprintf(pos, end - pos, "\t");
800 		if (ret < 0 || ret >= end - pos)
801 			return -1;
802 		pos += ret;
803 	}
804 	ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
805 	ret = os_snprintf(pos, end - pos, "\t%s",
806 			  ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
807 	if (ret < 0 || ret >= end - pos)
808 		return -1;
809 	pos += ret;
810 
811 	ret = os_snprintf(pos, end - pos, "\n");
812 	if (ret < 0 || ret >= end - pos)
813 		return -1;
814 	pos += ret;
815 
816 	return pos - buf;
817 }
818 
819 
wpa_supplicant_ctrl_iface_scan_results(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)820 static int wpa_supplicant_ctrl_iface_scan_results(
821 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
822 {
823 	char *pos, *end;
824 	struct wpa_scan_res *res;
825 	int ret;
826 	size_t i;
827 
828 	if (wpa_s->scan_res == NULL &&
829 	    wpa_supplicant_get_scan_results(wpa_s) < 0)
830 		return 0;
831 	if (wpa_s->scan_res == NULL)
832 		return 0;
833 
834 	pos = buf;
835 	end = buf + buflen;
836 	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
837 			  "flags / ssid\n");
838 	if (ret < 0 || ret >= end - pos)
839 		return pos - buf;
840 	pos += ret;
841 
842 	for (i = 0; i < wpa_s->scan_res->num; i++) {
843 		res = wpa_s->scan_res->res[i];
844 		ret = wpa_supplicant_ctrl_iface_scan_result(res, pos,
845 							    end - pos);
846 		if (ret < 0 || ret >= end - pos)
847 			return pos - buf;
848 		pos += ret;
849 	}
850 
851 	return pos - buf;
852 }
853 
854 
wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant * wpa_s,char * cmd)855 static int wpa_supplicant_ctrl_iface_select_network(
856 	struct wpa_supplicant *wpa_s, char *cmd)
857 {
858 	int id;
859 	struct wpa_ssid *ssid;
860 
861 	/* cmd: "<network id>" or "any" */
862 	if (os_strcmp(cmd, "any") == 0) {
863 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
864 		ssid = wpa_s->conf->ssid;
865 		while (ssid) {
866 			ssid->disabled = 0;
867 			ssid = ssid->next;
868 		}
869 		wpa_s->reassociate = 1;
870 		wpa_supplicant_req_scan(wpa_s, 0, 0);
871 		return 0;
872 	}
873 
874 	id = atoi(cmd);
875 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
876 
877 	ssid = wpa_config_get_network(wpa_s->conf, id);
878 	if (ssid == NULL) {
879 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
880 			   "id=%d", id);
881 		return -1;
882 	}
883 
884 	if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
885 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
886 
887 	/* Mark all other networks disabled and trigger reassociation */
888 	ssid = wpa_s->conf->ssid;
889 	while (ssid) {
890 		ssid->disabled = id != ssid->id;
891 		ssid = ssid->next;
892 	}
893 	wpa_s->reassociate = 1;
894 	wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
895 	wpa_supplicant_req_scan(wpa_s, 0, 0);
896 
897 	return 0;
898 }
899 
900 
wpa_supplicant_ctrl_iface_enable_network(struct wpa_supplicant * wpa_s,char * cmd)901 static int wpa_supplicant_ctrl_iface_enable_network(
902 	struct wpa_supplicant *wpa_s, char *cmd)
903 {
904 	int id;
905 	struct wpa_ssid *ssid;
906 
907 	/* cmd: "<network id>" or "all" */
908 	if (os_strcmp(cmd, "all") == 0) {
909 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
910 		ssid = wpa_s->conf->ssid;
911 		while (ssid) {
912 			if (ssid == wpa_s->current_ssid && ssid->disabled)
913 				wpa_s->reassociate = 1;
914 			ssid->disabled = 0;
915 			ssid = ssid->next;
916 		}
917 		if (wpa_s->reassociate)
918 #ifdef ANDROID
919 			wpa_supplicant_req_scan(wpa_s, 2, 0);
920 #else
921 			wpa_supplicant_req_scan(wpa_s, 0, 0);
922 #endif
923 		return 0;
924 	}
925 
926 	id = atoi(cmd);
927 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
928 
929 	ssid = wpa_config_get_network(wpa_s->conf, id);
930 	if (ssid == NULL) {
931 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
932 			   "id=%d", id);
933 		return -1;
934 	}
935 
936 	if (wpa_s->current_ssid == NULL && ssid->disabled) {
937 		/*
938 		 * Try to reassociate since there is no current configuration
939 		 * and a new network was made available. */
940 		wpa_s->reassociate = 1;
941 #ifdef ANDROID
942 		wpa_supplicant_req_scan(wpa_s, 2, 0);
943 #else
944 		wpa_supplicant_req_scan(wpa_s, 0, 0);
945 #endif
946 	}
947 	ssid->disabled = 0;
948 
949 	return 0;
950 }
951 
952 
wpa_supplicant_ctrl_iface_disable_network(struct wpa_supplicant * wpa_s,char * cmd)953 static int wpa_supplicant_ctrl_iface_disable_network(
954 	struct wpa_supplicant *wpa_s, char *cmd)
955 {
956 	int id;
957 	struct wpa_ssid *ssid;
958 
959 	/* cmd: "<network id>" or "all" */
960 	if (os_strcmp(cmd, "all") == 0) {
961 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
962 		ssid = wpa_s->conf->ssid;
963 		while (ssid) {
964 			ssid->disabled = 1;
965 			ssid = ssid->next;
966 		}
967 		if (wpa_s->current_ssid)
968 			wpa_supplicant_disassociate(wpa_s,
969 				                    WLAN_REASON_DEAUTH_LEAVING);
970 		return 0;
971 	}
972 
973 	id = atoi(cmd);
974 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
975 
976 	ssid = wpa_config_get_network(wpa_s->conf, id);
977 	if (ssid == NULL) {
978 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
979 			   "id=%d", id);
980 		return -1;
981 	}
982 
983 #ifdef ANDROID
984 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
985 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not disable WPS network "
986 			   "id=%d", id);
987 		return -1;
988 	}
989 #endif
990 
991 	if (ssid == wpa_s->current_ssid)
992 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
993 	ssid->disabled = 1;
994 
995 	return 0;
996 }
997 
998 
wpa_supplicant_ctrl_iface_add_network(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)999 static int wpa_supplicant_ctrl_iface_add_network(
1000 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1001 {
1002 	struct wpa_ssid *ssid;
1003 	int ret;
1004 
1005 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1006 
1007 	ssid = wpa_config_add_network(wpa_s->conf);
1008 	if (ssid == NULL)
1009 		return -1;
1010 	ssid->disabled = 1;
1011 	wpa_config_set_network_defaults(ssid);
1012 
1013 	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1014 	if (ret < 0 || (size_t) ret >= buflen)
1015 		return -1;
1016 	return ret;
1017 }
1018 
1019 
wpa_supplicant_ctrl_iface_remove_network(struct wpa_supplicant * wpa_s,char * cmd)1020 static int wpa_supplicant_ctrl_iface_remove_network(
1021 	struct wpa_supplicant *wpa_s, char *cmd)
1022 {
1023 	int id;
1024 	struct wpa_ssid *ssid;
1025 
1026 	/* cmd: "<network id>" or "all" */
1027 	if (os_strcmp(cmd, "all") == 0) {
1028 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1029 		ssid = wpa_s->conf->ssid;
1030 		while (ssid) {
1031 			id = ssid->id;
1032 			ssid = ssid->next;
1033 			wpa_config_remove_network(wpa_s->conf, id);
1034 		}
1035 		if (wpa_s->current_ssid) {
1036 			eapol_sm_invalidate_cached_session(wpa_s->eapol);
1037 			wpa_supplicant_disassociate(wpa_s,
1038 				                    WLAN_REASON_DEAUTH_LEAVING);
1039 		}
1040 		return 0;
1041 	}
1042 
1043 	id = atoi(cmd);
1044 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1045 
1046 	ssid = wpa_config_get_network(wpa_s->conf, id);
1047 	if (ssid == NULL ||
1048 	    wpa_config_remove_network(wpa_s->conf, id) < 0) {
1049 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1050 			   "id=%d", id);
1051 		return -1;
1052 	}
1053 
1054 	if (ssid == wpa_s->current_ssid) {
1055 		/*
1056 		 * Invalidate the EAP session cache if the current network is
1057 		 * removed.
1058 		 */
1059 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1060 
1061 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1062 	}
1063 
1064 	return 0;
1065 }
1066 
1067 
wpa_supplicant_ctrl_iface_set_network(struct wpa_supplicant * wpa_s,char * cmd)1068 static int wpa_supplicant_ctrl_iface_set_network(
1069 	struct wpa_supplicant *wpa_s, char *cmd)
1070 {
1071 	int id;
1072 	struct wpa_ssid *ssid;
1073 	char *name, *value;
1074 
1075 	/* cmd: "<network id> <variable name> <value>" */
1076 	name = os_strchr(cmd, ' ');
1077 	if (name == NULL)
1078 		return -1;
1079 	*name++ = '\0';
1080 
1081 	value = os_strchr(name, ' ');
1082 	if (value == NULL)
1083 		return -1;
1084 	*value++ = '\0';
1085 
1086 	id = atoi(cmd);
1087 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1088 		   id, name);
1089 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1090 			      (u8 *) value, os_strlen(value));
1091 
1092 	ssid = wpa_config_get_network(wpa_s->conf, id);
1093 	if (ssid == NULL) {
1094 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1095 			   "id=%d", id);
1096 		return -1;
1097 	}
1098 
1099 	if (wpa_config_set(ssid, name, value, 0) < 0) {
1100 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1101 			   "variable '%s'", name);
1102 		return -1;
1103 	} else {
1104 		if (os_strcmp(name, "priority") == 0) {
1105 			wpa_config_update_prio_list(wpa_s->conf);
1106 		}
1107 	}
1108 
1109 	if (wpa_s->current_ssid == ssid) {
1110 		/*
1111 		 * Invalidate the EAP session cache if anything in the current
1112 		 * configuration changes.
1113 		 */
1114 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1115 	}
1116 
1117 	if ((os_strcmp(name, "psk") == 0 &&
1118 	     value[0] == '"' && ssid->ssid_len) ||
1119 	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1120 		wpa_config_update_psk(ssid);
1121 
1122 	return 0;
1123 }
1124 
1125 
wpa_supplicant_ctrl_iface_get_network(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1126 static int wpa_supplicant_ctrl_iface_get_network(
1127 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1128 {
1129 	int id;
1130 	size_t res;
1131 	struct wpa_ssid *ssid;
1132 	char *name, *value;
1133 
1134 	/* cmd: "<network id> <variable name>" */
1135 	name = os_strchr(cmd, ' ');
1136 	if (name == NULL || buflen == 0)
1137 		return -1;
1138 	*name++ = '\0';
1139 
1140 	id = atoi(cmd);
1141 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1142 		   id, name);
1143 
1144 	ssid = wpa_config_get_network(wpa_s->conf, id);
1145 	if (ssid == NULL) {
1146 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1147 			   "id=%d", id);
1148 		return -1;
1149 	}
1150 
1151 	value = wpa_config_get_no_key(ssid, name);
1152 	if (value == NULL) {
1153 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1154 			   "variable '%s'", name);
1155 		return -1;
1156 	}
1157 
1158 	res = os_strlcpy(buf, value, buflen);
1159 	if (res >= buflen) {
1160 		os_free(value);
1161 		return -1;
1162 	}
1163 
1164 	os_free(value);
1165 
1166 	return res;
1167 }
1168 
1169 
1170 #ifndef CONFIG_NO_CONFIG_WRITE
wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant * wpa_s)1171 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1172 {
1173 	int ret;
1174 
1175 	if (!wpa_s->conf->update_config) {
1176 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1177 			   "to update configuration (update_config=0)");
1178 		return -1;
1179 	}
1180 
1181 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1182 	if (ret) {
1183 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1184 			   "update configuration");
1185 	} else {
1186 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1187 			   " updated");
1188 	}
1189 
1190 	return ret;
1191 }
1192 #endif /* CONFIG_NO_CONFIG_WRITE */
1193 
1194 
ctrl_iface_get_capability_pairwise(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1195 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1196 					      struct wpa_driver_capa *capa,
1197 					      char *buf, size_t buflen)
1198 {
1199 	int ret, first = 1;
1200 	char *pos, *end;
1201 	size_t len;
1202 
1203 	pos = buf;
1204 	end = pos + buflen;
1205 
1206 	if (res < 0) {
1207 		if (strict)
1208 			return 0;
1209 		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1210 		if (len >= buflen)
1211 			return -1;
1212 		return len;
1213 	}
1214 
1215 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1216 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1217 		if (ret < 0 || ret >= end - pos)
1218 			return pos - buf;
1219 		pos += ret;
1220 		first = 0;
1221 	}
1222 
1223 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1224 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1225 		if (ret < 0 || ret >= end - pos)
1226 			return pos - buf;
1227 		pos += ret;
1228 		first = 0;
1229 	}
1230 
1231 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1232 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1233 		if (ret < 0 || ret >= end - pos)
1234 			return pos - buf;
1235 		pos += ret;
1236 		first = 0;
1237 	}
1238 
1239 	return pos - buf;
1240 }
1241 
1242 
ctrl_iface_get_capability_group(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1243 static int ctrl_iface_get_capability_group(int res, char *strict,
1244 					   struct wpa_driver_capa *capa,
1245 					   char *buf, size_t buflen)
1246 {
1247 	int ret, first = 1;
1248 	char *pos, *end;
1249 	size_t len;
1250 
1251 	pos = buf;
1252 	end = pos + buflen;
1253 
1254 	if (res < 0) {
1255 		if (strict)
1256 			return 0;
1257 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1258 		if (len >= buflen)
1259 			return -1;
1260 		return len;
1261 	}
1262 
1263 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1264 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1265 		if (ret < 0 || ret >= end - pos)
1266 			return pos - buf;
1267 		pos += ret;
1268 		first = 0;
1269 	}
1270 
1271 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1272 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1273 		if (ret < 0 || ret >= end - pos)
1274 			return pos - buf;
1275 		pos += ret;
1276 		first = 0;
1277 	}
1278 
1279 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1280 		ret = os_snprintf(pos, end - pos, "%sWEP104",
1281 				  first ? "" : " ");
1282 		if (ret < 0 || ret >= end - pos)
1283 			return pos - buf;
1284 		pos += ret;
1285 		first = 0;
1286 	}
1287 
1288 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1289 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1290 		if (ret < 0 || ret >= end - pos)
1291 			return pos - buf;
1292 		pos += ret;
1293 		first = 0;
1294 	}
1295 
1296 	return pos - buf;
1297 }
1298 
1299 
ctrl_iface_get_capability_key_mgmt(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1300 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1301 					      struct wpa_driver_capa *capa,
1302 					      char *buf, size_t buflen)
1303 {
1304 	int ret;
1305 	char *pos, *end;
1306 	size_t len;
1307 
1308 	pos = buf;
1309 	end = pos + buflen;
1310 
1311 	if (res < 0) {
1312 		if (strict)
1313 			return 0;
1314 		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1315 				 "NONE", buflen);
1316 		if (len >= buflen)
1317 			return -1;
1318 		return len;
1319 	}
1320 
1321 	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1322 	if (ret < 0 || ret >= end - pos)
1323 		return pos - buf;
1324 	pos += ret;
1325 
1326 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1327 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1328 		ret = os_snprintf(pos, end - pos, " WPA-EAP");
1329 		if (ret < 0 || ret >= end - pos)
1330 			return pos - buf;
1331 		pos += ret;
1332 	}
1333 
1334 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1335 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1336 		ret = os_snprintf(pos, end - pos, " WPA-PSK");
1337 		if (ret < 0 || ret >= end - pos)
1338 			return pos - buf;
1339 		pos += ret;
1340 	}
1341 
1342 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1343 		ret = os_snprintf(pos, end - pos, " WPA-NONE");
1344 		if (ret < 0 || ret >= end - pos)
1345 			return pos - buf;
1346 		pos += ret;
1347 	}
1348 
1349 	return pos - buf;
1350 }
1351 
1352 
ctrl_iface_get_capability_proto(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1353 static int ctrl_iface_get_capability_proto(int res, char *strict,
1354 					   struct wpa_driver_capa *capa,
1355 					   char *buf, size_t buflen)
1356 {
1357 	int ret, first = 1;
1358 	char *pos, *end;
1359 	size_t len;
1360 
1361 	pos = buf;
1362 	end = pos + buflen;
1363 
1364 	if (res < 0) {
1365 		if (strict)
1366 			return 0;
1367 		len = os_strlcpy(buf, "RSN WPA", buflen);
1368 		if (len >= buflen)
1369 			return -1;
1370 		return len;
1371 	}
1372 
1373 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1374 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1375 		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1376 		if (ret < 0 || ret >= end - pos)
1377 			return pos - buf;
1378 		pos += ret;
1379 		first = 0;
1380 	}
1381 
1382 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1383 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1384 		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1385 		if (ret < 0 || ret >= end - pos)
1386 			return pos - buf;
1387 		pos += ret;
1388 		first = 0;
1389 	}
1390 
1391 	return pos - buf;
1392 }
1393 
1394 
ctrl_iface_get_capability_auth_alg(int res,char * strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)1395 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1396 					      struct wpa_driver_capa *capa,
1397 					      char *buf, size_t buflen)
1398 {
1399 	int ret, first = 1;
1400 	char *pos, *end;
1401 	size_t len;
1402 
1403 	pos = buf;
1404 	end = pos + buflen;
1405 
1406 	if (res < 0) {
1407 		if (strict)
1408 			return 0;
1409 		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1410 		if (len >= buflen)
1411 			return -1;
1412 		return len;
1413 	}
1414 
1415 	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1416 		ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1417 		if (ret < 0 || ret >= end - pos)
1418 			return pos - buf;
1419 		pos += ret;
1420 		first = 0;
1421 	}
1422 
1423 	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1424 		ret = os_snprintf(pos, end - pos, "%sSHARED",
1425 				  first ? "" : " ");
1426 		if (ret < 0 || ret >= end - pos)
1427 			return pos - buf;
1428 		pos += ret;
1429 		first = 0;
1430 	}
1431 
1432 	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1433 		ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1434 		if (ret < 0 || ret >= end - pos)
1435 			return pos - buf;
1436 		pos += ret;
1437 		first = 0;
1438 	}
1439 
1440 	return pos - buf;
1441 }
1442 
1443 
wpa_supplicant_ctrl_iface_get_capability(struct wpa_supplicant * wpa_s,const char * _field,char * buf,size_t buflen)1444 static int wpa_supplicant_ctrl_iface_get_capability(
1445 	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1446 	size_t buflen)
1447 {
1448 	struct wpa_driver_capa capa;
1449 	int res;
1450 	char *strict;
1451 	char field[30];
1452 	size_t len;
1453 
1454 	/* Determine whether or not strict checking was requested */
1455 	len = os_strlcpy(field, _field, sizeof(field));
1456 	if (len >= sizeof(field))
1457 		return -1;
1458 	strict = os_strchr(field, ' ');
1459 	if (strict != NULL) {
1460 		*strict++ = '\0';
1461 		if (os_strcmp(strict, "strict") != 0)
1462 			return -1;
1463 	}
1464 
1465 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1466 		field, strict ? strict : "");
1467 
1468 	if (os_strcmp(field, "eap") == 0) {
1469 		return eap_get_names(buf, buflen);
1470 	}
1471 
1472 	res = wpa_drv_get_capa(wpa_s, &capa);
1473 
1474 	if (os_strcmp(field, "pairwise") == 0)
1475 		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1476 							  buf, buflen);
1477 
1478 	if (os_strcmp(field, "group") == 0)
1479 		return ctrl_iface_get_capability_group(res, strict, &capa,
1480 						       buf, buflen);
1481 
1482 	if (os_strcmp(field, "key_mgmt") == 0)
1483 		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1484 							  buf, buflen);
1485 
1486 	if (os_strcmp(field, "proto") == 0)
1487 		return ctrl_iface_get_capability_proto(res, strict, &capa,
1488 						       buf, buflen);
1489 
1490 	if (os_strcmp(field, "auth_alg") == 0)
1491 		return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1492 							  buf, buflen);
1493 
1494 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1495 		   field);
1496 
1497 	return -1;
1498 }
1499 
1500 
wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)1501 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
1502 					 const char *cmd, char *buf,
1503 					 size_t buflen)
1504 {
1505 	u8 bssid[ETH_ALEN];
1506 	size_t i;
1507 	struct wpa_scan_results *results;
1508 	struct wpa_scan_res *bss;
1509 	int ret;
1510 	char *pos, *end;
1511 	const u8 *ie, *ie2;
1512 
1513 	if (wpa_s->scan_res == NULL &&
1514 	    wpa_supplicant_get_scan_results(wpa_s) < 0)
1515 		return 0;
1516 
1517 	results = wpa_s->scan_res;
1518 	if (results == NULL)
1519 		return 0;
1520 
1521 	if (hwaddr_aton(cmd, bssid) == 0) {
1522 		for (i = 0; i < results->num; i++) {
1523 			if (os_memcmp(bssid, results->res[i]->bssid, ETH_ALEN)
1524 			    == 0)
1525 				break;
1526 		}
1527 	} else
1528 		i = atoi(cmd);
1529 
1530 	if (i >= results->num || results->res[i] == NULL)
1531 		return 0; /* no match found */
1532 
1533 	bss = results->res[i];
1534 	pos = buf;
1535 	end = buf + buflen;
1536 	ret = os_snprintf(pos, end - pos,
1537 			  "bssid=" MACSTR "\n"
1538 			  "freq=%d\n"
1539 			  "beacon_int=%d\n"
1540 			  "capabilities=0x%04x\n"
1541 			  "qual=%d\n"
1542 			  "noise=%d\n"
1543 			  "level=%d\n"
1544 			  "tsf=%016llu\n"
1545 			  "ie=",
1546 			  MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
1547 			  bss->caps, bss->qual, bss->noise, bss->level,
1548 			  (unsigned long long) bss->tsf);
1549 	if (ret < 0 || ret >= end - pos)
1550 		return pos - buf;
1551 	pos += ret;
1552 
1553 	ie = (const u8 *) (bss + 1);
1554 	for (i = 0; i < bss->ie_len; i++) {
1555 		ret = os_snprintf(pos, end - pos, "%02x", *ie++);
1556 		if (ret < 0 || ret >= end - pos)
1557 			return pos - buf;
1558 		pos += ret;
1559 	}
1560 
1561 	ret = os_snprintf(pos, end - pos, "\n");
1562 	if (ret < 0 || ret >= end - pos)
1563 		return pos - buf;
1564 	pos += ret;
1565 
1566 	ret = os_snprintf(pos, end - pos, "flags=");
1567 	if (ret < 0 || ret >= end - pos)
1568 		return pos - buf;
1569 	pos += ret;
1570 
1571 	ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1572 	if (ie)
1573 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1574 	ie2 = wpa_scan_get_ie(bss, WLAN_EID_RSN);
1575 	if (ie2)
1576 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1577 	pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
1578 	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1579 		ret = os_snprintf(pos, end - pos, "[WEP]");
1580 		if (ret < 0 || ret >= end - pos)
1581 			return pos - buf;
1582 		pos += ret;
1583 	}
1584 	if (bss->caps & IEEE80211_CAP_IBSS) {
1585 		ret = os_snprintf(pos, end - pos, "[IBSS]");
1586 		if (ret < 0 || ret >= end - pos)
1587 			return pos - buf;
1588 		pos += ret;
1589 	}
1590 
1591 	ret = os_snprintf(pos, end - pos, "\n");
1592 	if (ret < 0 || ret >= end - pos)
1593 		return pos - buf;
1594 	pos += ret;
1595 
1596 	ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
1597 	ret = os_snprintf(pos, end - pos, "ssid=%s\n",
1598 			  ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
1599 	if (ret < 0 || ret >= end - pos)
1600 		return pos - buf;
1601 	pos += ret;
1602 
1603 	return pos - buf;
1604 }
1605 
1606 
wpa_supplicant_ctrl_iface_ap_scan(struct wpa_supplicant * wpa_s,char * cmd)1607 static int wpa_supplicant_ctrl_iface_ap_scan(
1608 	struct wpa_supplicant *wpa_s, char *cmd)
1609 {
1610 	int ap_scan = atoi(cmd);
1611 
1612 	if (ap_scan < 0 || ap_scan > 2)
1613 		return -1;
1614 #ifdef ANDROID
1615 	if ((ap_scan == 2) && (wpa_s->wpa_state != WPA_COMPLETED)) {
1616 		wpa_printf(MSG_DEBUG, "ap_scan = %d", wpa_s->conf->ap_scan);
1617 		return 0;
1618 	}
1619 	wpa_printf(MSG_DEBUG, "ap_scan = %d", ap_scan);
1620 #endif
1621 	wpa_s->conf->ap_scan = ap_scan;
1622 	return 0;
1623 }
1624 
1625 #ifdef ANDROID
wpa_supplicant_driver_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1626 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s,
1627                                      char *cmd, char *buf, size_t buflen)
1628 {
1629     int ret;
1630 
1631     ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
1632     if( ret == 0 ) {
1633         ret = sprintf(buf, "%s\n", "OK");
1634     }
1635     return( ret );
1636 }
1637 #endif
1638 
wpa_supplicant_ctrl_iface_process(struct wpa_supplicant * wpa_s,char * buf,size_t * resp_len)1639 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
1640 					 char *buf, size_t *resp_len)
1641 {
1642 	char *reply;
1643 	const int reply_size = 4096;
1644 	int ctrl_rsp = 0;
1645 	int reply_len;
1646 
1647 	wpa_printf(MSG_DEBUG, "CMD = %s", buf);
1648 
1649 	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
1650 	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1651 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
1652 				      (const u8 *) buf, os_strlen(buf));
1653 	} else {
1654 		if (os_strcmp(buf, "PING") != 0) {
1655 		    wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
1656 				  (const u8 *) buf, os_strlen(buf));
1657 		}
1658 	}
1659 
1660 	reply = os_malloc(reply_size);
1661 	if (reply == NULL) {
1662 		*resp_len = 1;
1663 		return NULL;
1664 	}
1665 
1666 	os_memcpy(reply, "OK\n", 3);
1667 	reply_len = 3;
1668 
1669 	if (os_strcmp(buf, "PING") == 0) {
1670 		os_memcpy(reply, "PONG\n", 5);
1671 		reply_len = 5;
1672 	} else if (os_strcmp(buf, "MIB") == 0) {
1673 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
1674 		if (reply_len >= 0) {
1675 			int res;
1676 			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
1677 					       reply_size - reply_len);
1678 			if (res < 0)
1679 				reply_len = -1;
1680 			else
1681 				reply_len += res;
1682 		}
1683 	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
1684 		reply_len = wpa_supplicant_ctrl_iface_status(
1685 			wpa_s, buf + 6, reply, reply_size);
1686 	} else if (os_strcmp(buf, "PMKSA") == 0) {
1687 		reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
1688 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
1689 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
1690 			reply_len = -1;
1691 	} else if (os_strcmp(buf, "LOGON") == 0) {
1692 		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
1693 	} else if (os_strcmp(buf, "LOGOFF") == 0) {
1694 		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
1695 	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
1696 		wpa_s->disconnected = 0;
1697 		wpa_s->reassociate = 1;
1698 		wpa_supplicant_req_scan(wpa_s, 0, 0);
1699 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
1700 		if (wpa_s->disconnected) {
1701 			wpa_s->disconnected = 0;
1702 			wpa_s->reassociate = 1;
1703 			wpa_supplicant_req_scan(wpa_s, 0, 0);
1704 		}
1705 #ifdef IEEE8021X_EAPOL
1706 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
1707 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
1708 			reply_len = -1;
1709 #endif /* IEEE8021X_EAPOL */
1710 #ifdef CONFIG_PEERKEY
1711 	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
1712 		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
1713 			reply_len = -1;
1714 #endif /* CONFIG_PEERKEY */
1715 #ifdef CONFIG_IEEE80211R
1716 	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
1717 		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
1718 			reply_len = -1;
1719 #endif /* CONFIG_IEEE80211R */
1720 #ifdef CONFIG_WPS
1721 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
1722 		if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
1723 			reply_len = -1;
1724 	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
1725 		if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
1726 			reply_len = -1;
1727 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
1728 		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
1729 							      reply,
1730 							      reply_size);
1731 	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
1732 		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
1733 			reply_len = -1;
1734 #endif /* CONFIG_WPS */
1735 	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
1736 	{
1737 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
1738 			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
1739 			reply_len = -1;
1740 		else
1741 			ctrl_rsp = 1;
1742 	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
1743 		if (wpa_supplicant_reload_configuration(wpa_s))
1744 			reply_len = -1;
1745 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
1746 		eloop_terminate();
1747 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
1748 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
1749 			reply_len = -1;
1750 #ifdef ANDROID
1751 	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
1752 		reply_len = wpa_supplicant_ctrl_iface_scan_interval(
1753 				wpa_s, buf + 14);
1754 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
1755 		reply_len = wpa_supplicant_ctrl_iface_blacklist(
1756 				wpa_s, buf + 9, reply, reply_size);
1757 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
1758 		reply_len = wpa_supplicant_ctrl_iface_log_level(
1759 				wpa_s, buf + 9, reply, reply_size);
1760 #endif
1761 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
1762 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
1763 			wpa_s, reply, reply_size);
1764 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
1765 		wpa_s->reassociate = 0;
1766 		wpa_s->disconnected = 1;
1767 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1768 	} else if (os_strcmp(buf, "SCAN") == 0) {
1769 #ifdef ANDROID
1770 		if (!wpa_s->scanning && ((wpa_s->wpa_state <= WPA_SCANNING) ||
1771 			(wpa_s->wpa_state >= WPA_COMPLETED))) {
1772 #endif
1773 			wpa_s->scan_req = 2;
1774 			wpa_supplicant_req_scan(wpa_s, 0, 0);
1775 #ifdef ANDROID
1776 		} else {
1777 			wpa_printf(MSG_ERROR, "Ongoing Scan action...");
1778 #endif
1779 		}
1780 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
1781 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
1782 			wpa_s, reply, reply_size);
1783 	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
1784 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
1785 			reply_len = -1;
1786 	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
1787 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
1788 			reply_len = -1;
1789 	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
1790 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
1791 			reply_len = -1;
1792 	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
1793 		reply_len = wpa_supplicant_ctrl_iface_add_network(
1794 			wpa_s, reply, reply_size);
1795 	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
1796 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
1797 			reply_len = -1;
1798 	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1799 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
1800 			reply_len = -1;
1801 	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
1802 		reply_len = wpa_supplicant_ctrl_iface_get_network(
1803 			wpa_s, buf + 12, reply, reply_size);
1804 #ifndef CONFIG_NO_CONFIG_WRITE
1805 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
1806 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
1807 			reply_len = -1;
1808 #endif /* CONFIG_NO_CONFIG_WRITE */
1809 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
1810 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
1811 			wpa_s, buf + 15, reply, reply_size);
1812 	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
1813 		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
1814 			reply_len = -1;
1815 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
1816 		reply_len = wpa_supplicant_global_iface_list(
1817 			wpa_s->global, reply, reply_size);
1818 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
1819 		reply_len = wpa_supplicant_global_iface_interfaces(
1820 			wpa_s->global, reply, reply_size);
1821 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
1822 		reply_len = wpa_supplicant_ctrl_iface_bss(
1823 			wpa_s, buf + 4, reply, reply_size);
1824 #ifdef ANDROID
1825     } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
1826         reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, reply_size);
1827 #endif
1828 	} else {
1829 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1830 		reply_len = 16;
1831 	}
1832 
1833 	if (reply_len < 0) {
1834 		os_memcpy(reply, "FAIL\n", 5);
1835 		reply_len = 5;
1836 	}
1837 
1838 	if (ctrl_rsp)
1839 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
1840 
1841 	*resp_len = reply_len;
1842 	return reply;
1843 }
1844 
1845 
wpa_supplicant_global_iface_add(struct wpa_global * global,char * cmd)1846 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
1847 					   char *cmd)
1848 {
1849 	struct wpa_interface iface;
1850 	char *pos;
1851 
1852 	/*
1853 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
1854 	 * TAB<bridge_ifname>
1855 	 */
1856 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
1857 
1858 	os_memset(&iface, 0, sizeof(iface));
1859 
1860 	do {
1861 		iface.ifname = pos = cmd;
1862 		pos = os_strchr(pos, '\t');
1863 		if (pos)
1864 			*pos++ = '\0';
1865 		if (iface.ifname[0] == '\0')
1866 			return -1;
1867 		if (pos == NULL)
1868 			break;
1869 
1870 		iface.confname = pos;
1871 		pos = os_strchr(pos, '\t');
1872 		if (pos)
1873 			*pos++ = '\0';
1874 		if (iface.confname[0] == '\0')
1875 			iface.confname = NULL;
1876 		if (pos == NULL)
1877 			break;
1878 
1879 		iface.driver = pos;
1880 		pos = os_strchr(pos, '\t');
1881 		if (pos)
1882 			*pos++ = '\0';
1883 		if (iface.driver[0] == '\0')
1884 			iface.driver = NULL;
1885 		if (pos == NULL)
1886 			break;
1887 
1888 		iface.ctrl_interface = pos;
1889 		pos = os_strchr(pos, '\t');
1890 		if (pos)
1891 			*pos++ = '\0';
1892 		if (iface.ctrl_interface[0] == '\0')
1893 			iface.ctrl_interface = NULL;
1894 		if (pos == NULL)
1895 			break;
1896 
1897 		iface.driver_param = pos;
1898 		pos = os_strchr(pos, '\t');
1899 		if (pos)
1900 			*pos++ = '\0';
1901 		if (iface.driver_param[0] == '\0')
1902 			iface.driver_param = NULL;
1903 		if (pos == NULL)
1904 			break;
1905 
1906 		iface.bridge_ifname = pos;
1907 		pos = os_strchr(pos, '\t');
1908 		if (pos)
1909 			*pos++ = '\0';
1910 		if (iface.bridge_ifname[0] == '\0')
1911 			iface.bridge_ifname = NULL;
1912 		if (pos == NULL)
1913 			break;
1914 	} while (0);
1915 
1916 	if (wpa_supplicant_get_iface(global, iface.ifname))
1917 		return -1;
1918 
1919 	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
1920 }
1921 
1922 
wpa_supplicant_global_iface_remove(struct wpa_global * global,char * cmd)1923 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
1924 					      char *cmd)
1925 {
1926 	struct wpa_supplicant *wpa_s;
1927 
1928 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
1929 
1930 	wpa_s = wpa_supplicant_get_iface(global, cmd);
1931 	if (wpa_s == NULL)
1932 		return -1;
1933 	return wpa_supplicant_remove_iface(global, wpa_s);
1934 }
1935 
1936 
wpa_free_iface_info(struct wpa_interface_info * iface)1937 static void wpa_free_iface_info(struct wpa_interface_info *iface)
1938 {
1939 	struct wpa_interface_info *prev;
1940 
1941 	while (iface) {
1942 		prev = iface;
1943 		iface = iface->next;
1944 
1945 		os_free(prev->ifname);
1946 		os_free(prev->desc);
1947 		os_free(prev);
1948 	}
1949 }
1950 
1951 
wpa_supplicant_global_iface_list(struct wpa_global * global,char * buf,int len)1952 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
1953 					    char *buf, int len)
1954 {
1955 	int i, res;
1956 	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
1957 	char *pos, *end;
1958 
1959 	for (i = 0; wpa_supplicant_drivers[i]; i++) {
1960 		struct wpa_driver_ops *drv = wpa_supplicant_drivers[i];
1961 		if (drv->get_interfaces == NULL)
1962 			continue;
1963 		tmp = drv->get_interfaces(global->drv_priv);
1964 		if (tmp == NULL)
1965 			continue;
1966 
1967 		if (last == NULL)
1968 			iface = last = tmp;
1969 		else
1970 			last->next = tmp;
1971 		while (last->next)
1972 			last = last->next;
1973 	}
1974 
1975 	pos = buf;
1976 	end = buf + len;
1977 	for (tmp = iface; tmp; tmp = tmp->next) {
1978 		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
1979 				  tmp->drv_name, tmp->ifname,
1980 				  tmp->desc ? tmp->desc : "");
1981 		if (res < 0 || res >= end - pos) {
1982 			*pos = '\0';
1983 			break;
1984 		}
1985 		pos += res;
1986 	}
1987 
1988 	wpa_free_iface_info(iface);
1989 
1990 	return pos - buf;
1991 }
1992 
1993 
wpa_supplicant_global_iface_interfaces(struct wpa_global * global,char * buf,int len)1994 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
1995 						  char *buf, int len)
1996 {
1997 	int res;
1998 	char *pos, *end;
1999 	struct wpa_supplicant *wpa_s;
2000 
2001 	wpa_s = global->ifaces;
2002 	pos = buf;
2003 	end = buf + len;
2004 
2005 	while (wpa_s) {
2006 		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
2007 		if (res < 0 || res >= end - pos) {
2008 			*pos = '\0';
2009 			break;
2010 		}
2011 		pos += res;
2012 		wpa_s = wpa_s->next;
2013 	}
2014 	return pos - buf;
2015 }
2016 
2017 
wpa_supplicant_global_ctrl_iface_process(struct wpa_global * global,char * buf,size_t * resp_len)2018 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
2019 						char *buf, size_t *resp_len)
2020 {
2021 	char *reply;
2022 	const int reply_size = 4096;
2023 	int reply_len;
2024 
2025     if (os_strcmp(buf, "PING") != 0) {
2026 	    wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
2027 			  (const u8 *) buf, os_strlen(buf));
2028     }
2029 
2030 	reply = os_malloc(reply_size);
2031 	if (reply == NULL) {
2032 		*resp_len = 1;
2033 		return NULL;
2034 	}
2035 
2036 	os_memcpy(reply, "OK\n", 3);
2037 	reply_len = 3;
2038 
2039 	if (os_strcmp(buf, "PING") == 0) {
2040 		os_memcpy(reply, "PONG\n", 5);
2041 		reply_len = 5;
2042 	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
2043 		if (wpa_supplicant_global_iface_add(global, buf + 14))
2044 			reply_len = -1;
2045 	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
2046 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
2047 			reply_len = -1;
2048 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
2049 		reply_len = wpa_supplicant_global_iface_list(
2050 			global, reply, reply_size);
2051 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
2052 		reply_len = wpa_supplicant_global_iface_interfaces(
2053 			global, reply, reply_size);
2054 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
2055 		eloop_terminate();
2056 	} else {
2057 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2058 		reply_len = 16;
2059 	}
2060 
2061 	if (reply_len < 0) {
2062 		os_memcpy(reply, "FAIL\n", 5);
2063 		reply_len = 5;
2064 	}
2065 
2066 	*resp_len = reply_len;
2067 	return reply;
2068 }
2069