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