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