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