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_blacklist(
    428 		struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
    429 {
    430 	u8 bssid[ETH_ALEN];
    431 	struct wpa_blacklist *e;
    432 	char *pos, *end;
    433 	int ret;
    434 
    435 	/* cmd: "BLACKLIST [<BSSID>]" */
    436 	if (*cmd == '\0') {
    437 		pos = buf;
    438 		end = buf + buflen;
    439 
    440 		e = wpa_s->blacklist;
    441 		while (e) {
    442 			ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid));
    443 			if (ret < 0 || ret >= end - pos)
    444 				return pos - buf;
    445 			pos += ret;
    446 			e = e->next;
    447 		}
    448 		return pos - buf;
    449 	}
    450 
    451 	++cmd;
    452 	if (os_strncmp(cmd, "clear", 5) == 0) {
    453 		wpa_blacklist_clear(wpa_s);
    454 		os_memcpy(buf, "OK\n", 3);
    455 		return 3;
    456 	}
    457 
    458 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
    459 	if (hwaddr_aton(cmd, bssid)) {
    460 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd);
    461 		return -1;
    462 	}
    463 
    464 	/*
    465 	 * Add the BSSID twice, so its count will be 2, causing it to be
    466 	 * skipped when processing scan results.
    467 	 */
    468 	ret = wpa_blacklist_add(wpa_s, bssid);
    469 	if (ret != 0)
    470 		return -1;
    471 	ret = wpa_blacklist_add(wpa_s, bssid);
    472 	if (ret != 0)
    473 		return -1;
    474 	os_memcpy(buf, "OK\n", 3);
    475 	return 3;
    476 }
    477 
    478 
    479 extern int wpa_debug_level;
    480 extern int wpa_debug_timestamp;
    481 static int wpa_supplicant_ctrl_iface_log_level(
    482 		struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
    483 {
    484 	char *pos, *end, *stamp;
    485 	int ret;
    486 
    487 	if (cmd == NULL) {
    488 		return -1;
    489 	}
    490 
    491 	/* cmd: "LOG_LEVEL [<level>]" */
    492 	if (*cmd == '\0') {
    493 		pos = buf;
    494 		end = buf + buflen;
    495 		ret = os_snprintf(pos, end-pos, "Current level: %d\n"
    496 			"{0-MSGDUMP, 1-DEBUG, 2-INFO, 3-WARNING, 4-ERROR}\n"
    497 			"Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp);
    498 		if (ret < 0 || ret >= end - pos)
    499 			ret = 0;
    500 
    501 		return ret;
    502 	}
    503 
    504 	while (*cmd == ' ') {
    505 		cmd++;
    506 	}
    507 
    508 	stamp = os_strchr(cmd, ' ');
    509 	if (stamp) {
    510 		*stamp++ = '\0';
    511 		while (*stamp == ' ') {
    512 			stamp++;
    513 		}
    514 	}
    515 
    516 	if (cmd && os_strlen(cmd)) {
    517 		wpa_debug_level = atoi(cmd);
    518 	}
    519 
    520 	if (stamp && os_strlen(stamp)) {
    521 		wpa_debug_timestamp = atoi(stamp);
    522 	}
    523 
    524 	os_memcpy(buf, "OK\n", 3);
    525 	return 3;
    526 }
    527 #endif
    528 
    529 static int wpa_supplicant_ctrl_iface_list_networks(
    530 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    531 {
    532 	char *pos, *end;
    533 	struct wpa_ssid *ssid;
    534 	int ret;
    535 
    536 	pos = buf;
    537 	end = buf + buflen;
    538 	ret = os_snprintf(pos, end - pos,
    539 			  "network id / ssid / bssid / flags\n");
    540 	if (ret < 0 || ret >= end - pos)
    541 		return pos - buf;
    542 	pos += ret;
    543 
    544 	ssid = wpa_s->conf->ssid;
    545 	while (ssid) {
    546 		ret = os_snprintf(pos, end - pos, "%d\t%s",
    547 				  ssid->id,
    548 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
    549 		if (ret < 0 || ret >= end - pos)
    550 			return pos - buf;
    551 		pos += ret;
    552 		if (ssid->bssid_set) {
    553 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
    554 					  MAC2STR(ssid->bssid));
    555 		} else {
    556 			ret = os_snprintf(pos, end - pos, "\tany");
    557 		}
    558 		if (ret < 0 || ret >= end - pos)
    559 			return pos - buf;
    560 		pos += ret;
    561 		ret = os_snprintf(pos, end - pos, "\t%s%s",
    562 				  ssid == wpa_s->current_ssid ?
    563 				  "[CURRENT]" : "",
    564 				  ssid->disabled ? "[DISABLED]" : "");
    565 		if (ret < 0 || ret >= end - pos)
    566 			return pos - buf;
    567 		pos += ret;
    568 		ret = os_snprintf(pos, end - pos, "\n");
    569 		if (ret < 0 || ret >= end - pos)
    570 			return pos - buf;
    571 		pos += ret;
    572 
    573 		ssid = ssid->next;
    574 	}
    575 
    576 	return pos - buf;
    577 }
    578 
    579 
    580 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
    581 {
    582 	int first = 1, ret;
    583 	ret = os_snprintf(pos, end - pos, "-");
    584 	if (ret < 0 || ret >= end - pos)
    585 		return pos;
    586 	pos += ret;
    587 	if (cipher & WPA_CIPHER_NONE) {
    588 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
    589 		if (ret < 0 || ret >= end - pos)
    590 			return pos;
    591 		pos += ret;
    592 		first = 0;
    593 	}
    594 	if (cipher & WPA_CIPHER_WEP40) {
    595 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
    596 		if (ret < 0 || ret >= end - pos)
    597 			return pos;
    598 		pos += ret;
    599 		first = 0;
    600 	}
    601 	if (cipher & WPA_CIPHER_WEP104) {
    602 		ret = os_snprintf(pos, end - pos, "%sWEP104",
    603 				  first ? "" : "+");
    604 		if (ret < 0 || ret >= end - pos)
    605 			return pos;
    606 		pos += ret;
    607 		first = 0;
    608 	}
    609 	if (cipher & WPA_CIPHER_TKIP) {
    610 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
    611 		if (ret < 0 || ret >= end - pos)
    612 			return pos;
    613 		pos += ret;
    614 		first = 0;
    615 	}
    616 	if (cipher & WPA_CIPHER_CCMP) {
    617 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
    618 		if (ret < 0 || ret >= end - pos)
    619 			return pos;
    620 		pos += ret;
    621 		first = 0;
    622 	}
    623 	return pos;
    624 }
    625 
    626 
    627 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
    628 				    const u8 *ie, size_t ie_len)
    629 {
    630 	struct wpa_ie_data data;
    631 	int first, ret;
    632 
    633 	ret = os_snprintf(pos, end - pos, "[%s-", proto);
    634 	if (ret < 0 || ret >= end - pos)
    635 		return pos;
    636 	pos += ret;
    637 
    638 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
    639 		ret = os_snprintf(pos, end - pos, "?]");
    640 		if (ret < 0 || ret >= end - pos)
    641 			return pos;
    642 		pos += ret;
    643 		return pos;
    644 	}
    645 
    646 	first = 1;
    647 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    648 		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
    649 		if (ret < 0 || ret >= end - pos)
    650 			return pos;
    651 		pos += ret;
    652 		first = 0;
    653 	}
    654 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
    655 		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
    656 		if (ret < 0 || ret >= end - pos)
    657 			return pos;
    658 		pos += ret;
    659 		first = 0;
    660 	}
    661 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
    662 		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
    663 		if (ret < 0 || ret >= end - pos)
    664 			return pos;
    665 		pos += ret;
    666 		first = 0;
    667 	}
    668 #ifdef CONFIG_IEEE80211R
    669 	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    670 		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
    671 				  first ? "" : "+");
    672 		if (ret < 0 || ret >= end - pos)
    673 			return pos;
    674 		pos += ret;
    675 		first = 0;
    676 	}
    677 	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    678 		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
    679 				  first ? "" : "+");
    680 		if (ret < 0 || ret >= end - pos)
    681 			return pos;
    682 		pos += ret;
    683 		first = 0;
    684 	}
    685 #endif /* CONFIG_IEEE80211R */
    686 #ifdef CONFIG_IEEE80211W
    687 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    688 		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
    689 				  first ? "" : "+");
    690 		if (ret < 0 || ret >= end - pos)
    691 			return pos;
    692 		pos += ret;
    693 		first = 0;
    694 	}
    695 	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    696 		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
    697 				  first ? "" : "+");
    698 		if (ret < 0 || ret >= end - pos)
    699 			return pos;
    700 		pos += ret;
    701 		first = 0;
    702 	}
    703 #endif /* CONFIG_IEEE80211W */
    704 
    705 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
    706 
    707 	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
    708 		ret = os_snprintf(pos, end - pos, "-preauth");
    709 		if (ret < 0 || ret >= end - pos)
    710 			return pos;
    711 		pos += ret;
    712 	}
    713 
    714 	ret = os_snprintf(pos, end - pos, "]");
    715 	if (ret < 0 || ret >= end - pos)
    716 		return pos;
    717 	pos += ret;
    718 
    719 	return pos;
    720 }
    721 
    722 static char * wpa_supplicant_wps_ie_txt(char *pos, char *end,
    723 					const struct wpa_scan_res *res)
    724 {
    725 #ifdef CONFIG_WPS
    726 	struct wpabuf *wps_ie;
    727 	int ret;
    728 	const char *txt;
    729 
    730 	wps_ie = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
    731 	if (wps_ie == NULL)
    732 		return pos;
    733 
    734 	if (wps_is_selected_pbc_registrar(wps_ie))
    735 		txt = "[WPS-PBC]";
    736 	else if (wps_is_selected_pin_registrar(wps_ie))
    737 		txt = "[WPS-PIN]";
    738 	else
    739 		txt = "[WPS]";
    740 
    741 	ret = os_snprintf(pos, end - pos, "%s", txt);
    742 	if (ret >= 0 && ret < end - pos)
    743 		pos += ret;
    744 	wpabuf_free(wps_ie);
    745 #endif /* CONFIG_WPS */
    746 
    747 	return pos;
    748 }
    749 
    750 
    751 /* Format one result on one text line into a buffer. */
    752 static int wpa_supplicant_ctrl_iface_scan_result(
    753 	const struct wpa_scan_res *res, char *buf, size_t buflen)
    754 {
    755 	char *pos, *end;
    756 	int ret;
    757 	const u8 *ie, *ie2;
    758 
    759 	pos = buf;
    760 	end = buf + buflen;
    761 
    762 	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
    763 			  MAC2STR(res->bssid), res->freq, res->level);
    764 	if (ret < 0 || ret >= end - pos)
    765 		return -1;
    766 	pos += ret;
    767 	ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
    768 	if (ie)
    769 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
    770 	ie2 = wpa_scan_get_ie(res, WLAN_EID_RSN);
    771 	if (ie2)
    772 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
    773 	pos = wpa_supplicant_wps_ie_txt(pos, end, res);
    774 	if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) {
    775 		ret = os_snprintf(pos, end - pos, "[WEP]");
    776 		if (ret < 0 || ret >= end - pos)
    777 			return -1;
    778 		pos += ret;
    779 	}
    780 	if (res->caps & IEEE80211_CAP_IBSS) {
    781 		ret = os_snprintf(pos, end - pos, "[IBSS]");
    782 		if (ret < 0 || ret >= end - pos)
    783 			return -1;
    784 		pos += ret;
    785 	}
    786     /* Just to make the fields line up nicely when printed */
    787 	if (!ie && !ie2) {
    788 		ret = os_snprintf(pos, end - pos, "\t");
    789 		if (ret < 0 || ret >= end - pos)
    790 			return -1;
    791 		pos += ret;
    792 	}
    793 	ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
    794 	ret = os_snprintf(pos, end - pos, "\t%s",
    795 			  ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
    796 	if (ret < 0 || ret >= end - pos)
    797 		return -1;
    798 	pos += ret;
    799 
    800 	ret = os_snprintf(pos, end - pos, "\n");
    801 	if (ret < 0 || ret >= end - pos)
    802 		return -1;
    803 	pos += ret;
    804 
    805 	return pos - buf;
    806 }
    807 
    808 
    809 static int wpa_supplicant_ctrl_iface_scan_results(
    810 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    811 {
    812 	char *pos, *end;
    813 	struct wpa_scan_res *res;
    814 	int ret;
    815 	size_t i;
    816 
    817 	if (wpa_s->scan_res == NULL &&
    818 	    wpa_supplicant_get_scan_results(wpa_s) < 0)
    819 		return 0;
    820 	if (wpa_s->scan_res == NULL)
    821 		return 0;
    822 
    823 	pos = buf;
    824 	end = buf + buflen;
    825 	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
    826 			  "flags / ssid\n");
    827 	if (ret < 0 || ret >= end - pos)
    828 		return pos - buf;
    829 	pos += ret;
    830 
    831 	for (i = 0; i < wpa_s->scan_res->num; i++) {
    832 		res = wpa_s->scan_res->res[i];
    833 		ret = wpa_supplicant_ctrl_iface_scan_result(res, pos,
    834 							    end - pos);
    835 		if (ret < 0 || ret >= end - pos)
    836 			return pos - buf;
    837 		pos += ret;
    838 	}
    839 
    840 	return pos - buf;
    841 }
    842 
    843 
    844 static int wpa_supplicant_ctrl_iface_select_network(
    845 	struct wpa_supplicant *wpa_s, char *cmd)
    846 {
    847 	int id;
    848 	struct wpa_ssid *ssid;
    849 
    850 	/* cmd: "<network id>" or "any" */
    851 	if (os_strcmp(cmd, "any") == 0) {
    852 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
    853 		ssid = wpa_s->conf->ssid;
    854 		while (ssid) {
    855 			ssid->disabled = 0;
    856 			ssid = ssid->next;
    857 		}
    858 		wpa_s->reassociate = 1;
    859 		wpa_supplicant_req_scan(wpa_s, 0, 0);
    860 		return 0;
    861 	}
    862 
    863 	id = atoi(cmd);
    864 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
    865 
    866 	ssid = wpa_config_get_network(wpa_s->conf, id);
    867 	if (ssid == NULL) {
    868 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    869 			   "id=%d", id);
    870 		return -1;
    871 	}
    872 
    873 	if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
    874 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
    875 
    876 	/* Mark all other networks disabled and trigger reassociation */
    877 	ssid = wpa_s->conf->ssid;
    878 	while (ssid) {
    879 		ssid->disabled = id != ssid->id;
    880 		ssid = ssid->next;
    881 	}
    882 	wpa_s->reassociate = 1;
    883 	wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
    884 	wpa_supplicant_req_scan(wpa_s, 0, 0);
    885 
    886 	return 0;
    887 }
    888 
    889 
    890 static int wpa_supplicant_ctrl_iface_enable_network(
    891 	struct wpa_supplicant *wpa_s, char *cmd)
    892 {
    893 	int id;
    894 	struct wpa_ssid *ssid;
    895 
    896 	/* cmd: "<network id>" or "all" */
    897 	if (os_strcmp(cmd, "all") == 0) {
    898 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
    899 		ssid = wpa_s->conf->ssid;
    900 		while (ssid) {
    901 			if (ssid == wpa_s->current_ssid && ssid->disabled)
    902 				wpa_s->reassociate = 1;
    903 			ssid->disabled = 0;
    904 			ssid = ssid->next;
    905 		}
    906 		if (wpa_s->reassociate)
    907 #ifdef ANDROID
    908 			wpa_supplicant_req_scan(wpa_s, 2, 0);
    909 #else
    910 			wpa_supplicant_req_scan(wpa_s, 0, 0);
    911 #endif
    912 		return 0;
    913 	}
    914 
    915 	id = atoi(cmd);
    916 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
    917 
    918 	ssid = wpa_config_get_network(wpa_s->conf, id);
    919 	if (ssid == NULL) {
    920 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    921 			   "id=%d", id);
    922 		return -1;
    923 	}
    924 
    925 	if (wpa_s->current_ssid == NULL && ssid->disabled) {
    926 		/*
    927 		 * Try to reassociate since there is no current configuration
    928 		 * and a new network was made available. */
    929 		wpa_s->reassociate = 1;
    930 #ifdef ANDROID
    931 		wpa_supplicant_req_scan(wpa_s, 2, 0);
    932 #else
    933 		wpa_supplicant_req_scan(wpa_s, 0, 0);
    934 #endif
    935 	}
    936 	ssid->disabled = 0;
    937 
    938 	return 0;
    939 }
    940 
    941 
    942 static int wpa_supplicant_ctrl_iface_disable_network(
    943 	struct wpa_supplicant *wpa_s, char *cmd)
    944 {
    945 	int id;
    946 	struct wpa_ssid *ssid;
    947 
    948 	/* cmd: "<network id>" or "all" */
    949 	if (os_strcmp(cmd, "all") == 0) {
    950 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
    951 		ssid = wpa_s->conf->ssid;
    952 		while (ssid) {
    953 			ssid->disabled = 1;
    954 			ssid = ssid->next;
    955 		}
    956 		if (wpa_s->current_ssid)
    957 			wpa_supplicant_disassociate(wpa_s,
    958 				                    WLAN_REASON_DEAUTH_LEAVING);
    959 		return 0;
    960 	}
    961 
    962 	id = atoi(cmd);
    963 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
    964 
    965 	ssid = wpa_config_get_network(wpa_s->conf, id);
    966 	if (ssid == NULL) {
    967 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    968 			   "id=%d", id);
    969 		return -1;
    970 	}
    971 
    972 #ifdef ANDROID
    973 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
    974 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not disable WPS network "
    975 			   "id=%d", id);
    976 		return -1;
    977 	}
    978 #endif
    979 
    980 	if (ssid == wpa_s->current_ssid)
    981 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
    982 	ssid->disabled = 1;
    983 
    984 	return 0;
    985 }
    986 
    987 
    988 static int wpa_supplicant_ctrl_iface_add_network(
    989 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    990 {
    991 	struct wpa_ssid *ssid;
    992 	int ret;
    993 
    994 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
    995 
    996 	ssid = wpa_config_add_network(wpa_s->conf);
    997 	if (ssid == NULL)
    998 		return -1;
    999 	ssid->disabled = 1;
   1000 	wpa_config_set_network_defaults(ssid);
   1001 
   1002 	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
   1003 	if (ret < 0 || (size_t) ret >= buflen)
   1004 		return -1;
   1005 	return ret;
   1006 }
   1007 
   1008 
   1009 static int wpa_supplicant_ctrl_iface_remove_network(
   1010 	struct wpa_supplicant *wpa_s, char *cmd)
   1011 {
   1012 	int id;
   1013 	struct wpa_ssid *ssid;
   1014 
   1015 	/* cmd: "<network id>" or "all" */
   1016 	if (os_strcmp(cmd, "all") == 0) {
   1017 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
   1018 		ssid = wpa_s->conf->ssid;
   1019 		while (ssid) {
   1020 			id = ssid->id;
   1021 			ssid = ssid->next;
   1022 			wpa_config_remove_network(wpa_s->conf, id);
   1023 		}
   1024 		if (wpa_s->current_ssid) {
   1025 			eapol_sm_invalidate_cached_session(wpa_s->eapol);
   1026 			wpa_supplicant_disassociate(wpa_s,
   1027 				                    WLAN_REASON_DEAUTH_LEAVING);
   1028 		}
   1029 		return 0;
   1030 	}
   1031 
   1032 	id = atoi(cmd);
   1033 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
   1034 
   1035 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1036 	if (ssid == NULL ||
   1037 	    wpa_config_remove_network(wpa_s->conf, id) < 0) {
   1038 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   1039 			   "id=%d", id);
   1040 		return -1;
   1041 	}
   1042 
   1043 	if (ssid == wpa_s->current_ssid) {
   1044 		/*
   1045 		 * Invalidate the EAP session cache if the current network is
   1046 		 * removed.
   1047 		 */
   1048 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
   1049 
   1050 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
   1051 	}
   1052 
   1053 	return 0;
   1054 }
   1055 
   1056 
   1057 static int wpa_supplicant_ctrl_iface_set_network(
   1058 	struct wpa_supplicant *wpa_s, char *cmd)
   1059 {
   1060 	int id;
   1061 	struct wpa_ssid *ssid;
   1062 	char *name, *value;
   1063 
   1064 	/* cmd: "<network id> <variable name> <value>" */
   1065 	name = os_strchr(cmd, ' ');
   1066 	if (name == NULL)
   1067 		return -1;
   1068 	*name++ = '\0';
   1069 
   1070 	value = os_strchr(name, ' ');
   1071 	if (value == NULL)
   1072 		return -1;
   1073 	*value++ = '\0';
   1074 
   1075 	id = atoi(cmd);
   1076 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
   1077 		   id, name);
   1078 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
   1079 			      (u8 *) value, os_strlen(value));
   1080 
   1081 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1082 	if (ssid == NULL) {
   1083 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   1084 			   "id=%d", id);
   1085 		return -1;
   1086 	}
   1087 
   1088 	if (wpa_config_set(ssid, name, value, 0) < 0) {
   1089 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
   1090 			   "variable '%s'", name);
   1091 		return -1;
   1092 	} else {
   1093 		if (os_strcmp(name, "priority") == 0) {
   1094 			wpa_config_update_prio_list(wpa_s->conf);
   1095 		}
   1096 	}
   1097 
   1098 	if (wpa_s->current_ssid == ssid) {
   1099 		/*
   1100 		 * Invalidate the EAP session cache if anything in the current
   1101 		 * configuration changes.
   1102 		 */
   1103 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
   1104 	}
   1105 
   1106 	if ((os_strcmp(name, "psk") == 0 &&
   1107 	     value[0] == '"' && ssid->ssid_len) ||
   1108 	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
   1109 		wpa_config_update_psk(ssid);
   1110 
   1111 	return 0;
   1112 }
   1113 
   1114 
   1115 static int wpa_supplicant_ctrl_iface_get_network(
   1116 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
   1117 {
   1118 	int id;
   1119 	size_t res;
   1120 	struct wpa_ssid *ssid;
   1121 	char *name, *value;
   1122 
   1123 	/* cmd: "<network id> <variable name>" */
   1124 	name = os_strchr(cmd, ' ');
   1125 	if (name == NULL || buflen == 0)
   1126 		return -1;
   1127 	*name++ = '\0';
   1128 
   1129 	id = atoi(cmd);
   1130 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
   1131 		   id, name);
   1132 
   1133 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1134 	if (ssid == NULL) {
   1135 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   1136 			   "id=%d", id);
   1137 		return -1;
   1138 	}
   1139 
   1140 	value = wpa_config_get_no_key(ssid, name);
   1141 	if (value == NULL) {
   1142 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
   1143 			   "variable '%s'", name);
   1144 		return -1;
   1145 	}
   1146 
   1147 	res = os_strlcpy(buf, value, buflen);
   1148 	if (res >= buflen) {
   1149 		os_free(value);
   1150 		return -1;
   1151 	}
   1152 
   1153 	os_free(value);
   1154 
   1155 	return res;
   1156 }
   1157 
   1158 
   1159 #ifndef CONFIG_NO_CONFIG_WRITE
   1160 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
   1161 {
   1162 	int ret;
   1163 
   1164 	if (!wpa_s->conf->update_config) {
   1165 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
   1166 			   "to update configuration (update_config=0)");
   1167 		return -1;
   1168 	}
   1169 
   1170 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
   1171 	if (ret) {
   1172 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
   1173 			   "update configuration");
   1174 	} else {
   1175 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
   1176 			   " updated");
   1177 	}
   1178 
   1179 	return ret;
   1180 }
   1181 #endif /* CONFIG_NO_CONFIG_WRITE */
   1182 
   1183 
   1184 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
   1185 					      struct wpa_driver_capa *capa,
   1186 					      char *buf, size_t buflen)
   1187 {
   1188 	int ret, first = 1;
   1189 	char *pos, *end;
   1190 	size_t len;
   1191 
   1192 	pos = buf;
   1193 	end = pos + buflen;
   1194 
   1195 	if (res < 0) {
   1196 		if (strict)
   1197 			return 0;
   1198 		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
   1199 		if (len >= buflen)
   1200 			return -1;
   1201 		return len;
   1202 	}
   1203 
   1204 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
   1205 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
   1206 		if (ret < 0 || ret >= end - pos)
   1207 			return pos - buf;
   1208 		pos += ret;
   1209 		first = 0;
   1210 	}
   1211 
   1212 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
   1213 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
   1214 		if (ret < 0 || ret >= end - pos)
   1215 			return pos - buf;
   1216 		pos += ret;
   1217 		first = 0;
   1218 	}
   1219 
   1220 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
   1221 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
   1222 		if (ret < 0 || ret >= end - pos)
   1223 			return pos - buf;
   1224 		pos += ret;
   1225 		first = 0;
   1226 	}
   1227 
   1228 	return pos - buf;
   1229 }
   1230 
   1231 
   1232 static int ctrl_iface_get_capability_group(int res, char *strict,
   1233 					   struct wpa_driver_capa *capa,
   1234 					   char *buf, size_t buflen)
   1235 {
   1236 	int ret, first = 1;
   1237 	char *pos, *end;
   1238 	size_t len;
   1239 
   1240 	pos = buf;
   1241 	end = pos + buflen;
   1242 
   1243 	if (res < 0) {
   1244 		if (strict)
   1245 			return 0;
   1246 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
   1247 		if (len >= buflen)
   1248 			return -1;
   1249 		return len;
   1250 	}
   1251 
   1252 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
   1253 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
   1254 		if (ret < 0 || ret >= end - pos)
   1255 			return pos - buf;
   1256 		pos += ret;
   1257 		first = 0;
   1258 	}
   1259 
   1260 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
   1261 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
   1262 		if (ret < 0 || ret >= end - pos)
   1263 			return pos - buf;
   1264 		pos += ret;
   1265 		first = 0;
   1266 	}
   1267 
   1268 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
   1269 		ret = os_snprintf(pos, end - pos, "%sWEP104",
   1270 				  first ? "" : " ");
   1271 		if (ret < 0 || ret >= end - pos)
   1272 			return pos - buf;
   1273 		pos += ret;
   1274 		first = 0;
   1275 	}
   1276 
   1277 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
   1278 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
   1279 		if (ret < 0 || ret >= end - pos)
   1280 			return pos - buf;
   1281 		pos += ret;
   1282 		first = 0;
   1283 	}
   1284 
   1285 	return pos - buf;
   1286 }
   1287 
   1288 
   1289 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
   1290 					      struct wpa_driver_capa *capa,
   1291 					      char *buf, size_t buflen)
   1292 {
   1293 	int ret;
   1294 	char *pos, *end;
   1295 	size_t len;
   1296 
   1297 	pos = buf;
   1298 	end = pos + buflen;
   1299 
   1300 	if (res < 0) {
   1301 		if (strict)
   1302 			return 0;
   1303 		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
   1304 				 "NONE", buflen);
   1305 		if (len >= buflen)
   1306 			return -1;
   1307 		return len;
   1308 	}
   1309 
   1310 	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
   1311 	if (ret < 0 || ret >= end - pos)
   1312 		return pos - buf;
   1313 	pos += ret;
   1314 
   1315 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   1316 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
   1317 		ret = os_snprintf(pos, end - pos, " WPA-EAP");
   1318 		if (ret < 0 || ret >= end - pos)
   1319 			return pos - buf;
   1320 		pos += ret;
   1321 	}
   1322 
   1323 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
   1324 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   1325 		ret = os_snprintf(pos, end - pos, " WPA-PSK");
   1326 		if (ret < 0 || ret >= end - pos)
   1327 			return pos - buf;
   1328 		pos += ret;
   1329 	}
   1330 
   1331 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
   1332 		ret = os_snprintf(pos, end - pos, " WPA-NONE");
   1333 		if (ret < 0 || ret >= end - pos)
   1334 			return pos - buf;
   1335 		pos += ret;
   1336 	}
   1337 
   1338 	return pos - buf;
   1339 }
   1340 
   1341 
   1342 static int ctrl_iface_get_capability_proto(int res, char *strict,
   1343 					   struct wpa_driver_capa *capa,
   1344 					   char *buf, size_t buflen)
   1345 {
   1346 	int ret, first = 1;
   1347 	char *pos, *end;
   1348 	size_t len;
   1349 
   1350 	pos = buf;
   1351 	end = pos + buflen;
   1352 
   1353 	if (res < 0) {
   1354 		if (strict)
   1355 			return 0;
   1356 		len = os_strlcpy(buf, "RSN WPA", buflen);
   1357 		if (len >= buflen)
   1358 			return -1;
   1359 		return len;
   1360 	}
   1361 
   1362 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
   1363 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   1364 		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
   1365 		if (ret < 0 || ret >= end - pos)
   1366 			return pos - buf;
   1367 		pos += ret;
   1368 		first = 0;
   1369 	}
   1370 
   1371 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   1372 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
   1373 		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
   1374 		if (ret < 0 || ret >= end - pos)
   1375 			return pos - buf;
   1376 		pos += ret;
   1377 		first = 0;
   1378 	}
   1379 
   1380 	return pos - buf;
   1381 }
   1382 
   1383 
   1384 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
   1385 					      struct wpa_driver_capa *capa,
   1386 					      char *buf, size_t buflen)
   1387 {
   1388 	int ret, first = 1;
   1389 	char *pos, *end;
   1390 	size_t len;
   1391 
   1392 	pos = buf;
   1393 	end = pos + buflen;
   1394 
   1395 	if (res < 0) {
   1396 		if (strict)
   1397 			return 0;
   1398 		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
   1399 		if (len >= buflen)
   1400 			return -1;
   1401 		return len;
   1402 	}
   1403 
   1404 	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
   1405 		ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
   1406 		if (ret < 0 || ret >= end - pos)
   1407 			return pos - buf;
   1408 		pos += ret;
   1409 		first = 0;
   1410 	}
   1411 
   1412 	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
   1413 		ret = os_snprintf(pos, end - pos, "%sSHARED",
   1414 				  first ? "" : " ");
   1415 		if (ret < 0 || ret >= end - pos)
   1416 			return pos - buf;
   1417 		pos += ret;
   1418 		first = 0;
   1419 	}
   1420 
   1421 	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
   1422 		ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
   1423 		if (ret < 0 || ret >= end - pos)
   1424 			return pos - buf;
   1425 		pos += ret;
   1426 		first = 0;
   1427 	}
   1428 
   1429 	return pos - buf;
   1430 }
   1431 
   1432 
   1433 static int wpa_supplicant_ctrl_iface_get_capability(
   1434 	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
   1435 	size_t buflen)
   1436 {
   1437 	struct wpa_driver_capa capa;
   1438 	int res;
   1439 	char *strict;
   1440 	char field[30];
   1441 	size_t len;
   1442 
   1443 	/* Determine whether or not strict checking was requested */
   1444 	len = os_strlcpy(field, _field, sizeof(field));
   1445 	if (len >= sizeof(field))
   1446 		return -1;
   1447 	strict = os_strchr(field, ' ');
   1448 	if (strict != NULL) {
   1449 		*strict++ = '\0';
   1450 		if (os_strcmp(strict, "strict") != 0)
   1451 			return -1;
   1452 	}
   1453 
   1454 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
   1455 		field, strict ? strict : "");
   1456 
   1457 	if (os_strcmp(field, "eap") == 0) {
   1458 		return eap_get_names(buf, buflen);
   1459 	}
   1460 
   1461 	res = wpa_drv_get_capa(wpa_s, &capa);
   1462 
   1463 	if (os_strcmp(field, "pairwise") == 0)
   1464 		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
   1465 							  buf, buflen);
   1466 
   1467 	if (os_strcmp(field, "group") == 0)
   1468 		return ctrl_iface_get_capability_group(res, strict, &capa,
   1469 						       buf, buflen);
   1470 
   1471 	if (os_strcmp(field, "key_mgmt") == 0)
   1472 		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
   1473 							  buf, buflen);
   1474 
   1475 	if (os_strcmp(field, "proto") == 0)
   1476 		return ctrl_iface_get_capability_proto(res, strict, &capa,
   1477 						       buf, buflen);
   1478 
   1479 	if (os_strcmp(field, "auth_alg") == 0)
   1480 		return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
   1481 							  buf, buflen);
   1482 
   1483 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
   1484 		   field);
   1485 
   1486 	return -1;
   1487 }
   1488 
   1489 
   1490 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
   1491 					 const char *cmd, char *buf,
   1492 					 size_t buflen)
   1493 {
   1494 	u8 bssid[ETH_ALEN];
   1495 	size_t i;
   1496 	struct wpa_scan_results *results;
   1497 	struct wpa_scan_res *bss;
   1498 	int ret;
   1499 	char *pos, *end;
   1500 	const u8 *ie, *ie2;
   1501 
   1502 	if (wpa_s->scan_res == NULL &&
   1503 	    wpa_supplicant_get_scan_results(wpa_s) < 0)
   1504 		return 0;
   1505 
   1506 	results = wpa_s->scan_res;
   1507 	if (results == NULL)
   1508 		return 0;
   1509 
   1510 	if (hwaddr_aton(cmd, bssid) == 0) {
   1511 		for (i = 0; i < results->num; i++) {
   1512 			if (os_memcmp(bssid, results->res[i]->bssid, ETH_ALEN)
   1513 			    == 0)
   1514 				break;
   1515 		}
   1516 	} else
   1517 		i = atoi(cmd);
   1518 
   1519 	if (i >= results->num || results->res[i] == NULL)
   1520 		return 0; /* no match found */
   1521 
   1522 	bss = results->res[i];
   1523 	pos = buf;
   1524 	end = buf + buflen;
   1525 	ret = os_snprintf(pos, end - pos,
   1526 			  "bssid=" MACSTR "\n"
   1527 			  "freq=%d\n"
   1528 			  "beacon_int=%d\n"
   1529 			  "capabilities=0x%04x\n"
   1530 			  "qual=%d\n"
   1531 			  "noise=%d\n"
   1532 			  "level=%d\n"
   1533 			  "tsf=%016llu\n"
   1534 			  "ie=",
   1535 			  MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
   1536 			  bss->caps, bss->qual, bss->noise, bss->level,
   1537 			  (unsigned long long) bss->tsf);
   1538 	if (ret < 0 || ret >= end - pos)
   1539 		return pos - buf;
   1540 	pos += ret;
   1541 
   1542 	ie = (const u8 *) (bss + 1);
   1543 	for (i = 0; i < bss->ie_len; i++) {
   1544 		ret = os_snprintf(pos, end - pos, "%02x", *ie++);
   1545 		if (ret < 0 || ret >= end - pos)
   1546 			return pos - buf;
   1547 		pos += ret;
   1548 	}
   1549 
   1550 	ret = os_snprintf(pos, end - pos, "\n");
   1551 	if (ret < 0 || ret >= end - pos)
   1552 		return pos - buf;
   1553 	pos += ret;
   1554 
   1555 	ret = os_snprintf(pos, end - pos, "flags=");
   1556 	if (ret < 0 || ret >= end - pos)
   1557 		return pos - buf;
   1558 	pos += ret;
   1559 
   1560 	ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
   1561 	if (ie)
   1562 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
   1563 	ie2 = wpa_scan_get_ie(bss, WLAN_EID_RSN);
   1564 	if (ie2)
   1565 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
   1566 	pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
   1567 	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
   1568 		ret = os_snprintf(pos, end - pos, "[WEP]");
   1569 		if (ret < 0 || ret >= end - pos)
   1570 			return pos - buf;
   1571 		pos += ret;
   1572 	}
   1573 	if (bss->caps & IEEE80211_CAP_IBSS) {
   1574 		ret = os_snprintf(pos, end - pos, "[IBSS]");
   1575 		if (ret < 0 || ret >= end - pos)
   1576 			return pos - buf;
   1577 		pos += ret;
   1578 	}
   1579 
   1580 	ret = os_snprintf(pos, end - pos, "\n");
   1581 	if (ret < 0 || ret >= end - pos)
   1582 		return pos - buf;
   1583 	pos += ret;
   1584 
   1585 	ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
   1586 	ret = os_snprintf(pos, end - pos, "ssid=%s\n",
   1587 			  ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
   1588 	if (ret < 0 || ret >= end - pos)
   1589 		return pos - buf;
   1590 	pos += ret;
   1591 
   1592 	return pos - buf;
   1593 }
   1594 
   1595 
   1596 static int wpa_supplicant_ctrl_iface_ap_scan(
   1597 	struct wpa_supplicant *wpa_s, char *cmd)
   1598 {
   1599 	int ap_scan = atoi(cmd);
   1600 
   1601 	if (ap_scan < 0 || ap_scan > 2)
   1602 		return -1;
   1603 #ifdef ANDROID
   1604 	if ((ap_scan == 2) && (wpa_s->wpa_state != WPA_COMPLETED)) {
   1605 		wpa_printf(MSG_DEBUG, "ap_scan = %d", wpa_s->conf->ap_scan);
   1606 		return 0;
   1607 	}
   1608 	wpa_printf(MSG_DEBUG, "ap_scan = %d", ap_scan);
   1609 #endif
   1610 	wpa_s->conf->ap_scan = ap_scan;
   1611 	return 0;
   1612 }
   1613 
   1614 #ifdef ANDROID
   1615 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s,
   1616                                      char *cmd, char *buf, size_t buflen)
   1617 {
   1618     int ret;
   1619 
   1620     ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
   1621     if( ret == 0 ) {
   1622         ret = sprintf(buf, "%s\n", "OK");
   1623     }
   1624     return( ret );
   1625 }
   1626 #endif
   1627 
   1628 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
   1629 					 char *buf, size_t *resp_len)
   1630 {
   1631 	char *reply;
   1632 	const int reply_size = 4096;
   1633 	int ctrl_rsp = 0;
   1634 	int reply_len;
   1635 
   1636 	wpa_printf(MSG_DEBUG, "CMD: %s", buf);
   1637 
   1638 	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
   1639 	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
   1640 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
   1641 				      (const u8 *) buf, os_strlen(buf));
   1642 	} else {
   1643 		if (os_strcmp(buf, "PING") != 0) {
   1644 		    wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
   1645 				  (const u8 *) buf, os_strlen(buf));
   1646 		}
   1647 	}
   1648 
   1649 	reply = os_malloc(reply_size);
   1650 	if (reply == NULL) {
   1651 		*resp_len = 1;
   1652 		return NULL;
   1653 	}
   1654 
   1655 	os_memcpy(reply, "OK\n", 3);
   1656 	reply_len = 3;
   1657 
   1658 	if (os_strcmp(buf, "PING") == 0) {
   1659 		os_memcpy(reply, "PONG\n", 5);
   1660 		reply_len = 5;
   1661 	} else if (os_strcmp(buf, "MIB") == 0) {
   1662 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
   1663 		if (reply_len >= 0) {
   1664 			int res;
   1665 			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
   1666 					       reply_size - reply_len);
   1667 			if (res < 0)
   1668 				reply_len = -1;
   1669 			else
   1670 				reply_len += res;
   1671 		}
   1672 	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
   1673 		reply_len = wpa_supplicant_ctrl_iface_status(
   1674 			wpa_s, buf + 6, reply, reply_size);
   1675 	} else if (os_strcmp(buf, "PMKSA") == 0) {
   1676 		reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
   1677 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
   1678 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
   1679 			reply_len = -1;
   1680 	} else if (os_strcmp(buf, "LOGON") == 0) {
   1681 		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
   1682 	} else if (os_strcmp(buf, "LOGOFF") == 0) {
   1683 		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
   1684 	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
   1685 		wpa_s->disconnected = 0;
   1686 		wpa_s->reassociate = 1;
   1687 		wpa_supplicant_req_scan(wpa_s, 0, 0);
   1688 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
   1689 		if (wpa_s->disconnected) {
   1690 			wpa_s->disconnected = 0;
   1691 			wpa_s->reassociate = 1;
   1692 			wpa_supplicant_req_scan(wpa_s, 0, 0);
   1693 		}
   1694 #ifdef IEEE8021X_EAPOL
   1695 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
   1696 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
   1697 			reply_len = -1;
   1698 #endif /* IEEE8021X_EAPOL */
   1699 #ifdef CONFIG_PEERKEY
   1700 	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
   1701 		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
   1702 			reply_len = -1;
   1703 #endif /* CONFIG_PEERKEY */
   1704 #ifdef CONFIG_IEEE80211R
   1705 	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
   1706 		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
   1707 			reply_len = -1;
   1708 #endif /* CONFIG_IEEE80211R */
   1709 #ifdef CONFIG_WPS
   1710 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
   1711 		if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
   1712 			reply_len = -1;
   1713 	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
   1714 		if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
   1715 			reply_len = -1;
   1716 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
   1717 		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
   1718 							      reply,
   1719 							      reply_size);
   1720 	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
   1721 		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
   1722 			reply_len = -1;
   1723 #endif /* CONFIG_WPS */
   1724 	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
   1725 	{
   1726 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
   1727 			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
   1728 			reply_len = -1;
   1729 		else
   1730 			ctrl_rsp = 1;
   1731 	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
   1732 		if (wpa_supplicant_reload_configuration(wpa_s))
   1733 			reply_len = -1;
   1734 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   1735 		eloop_terminate();
   1736 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
   1737 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
   1738 			reply_len = -1;
   1739 #ifdef ANDROID
   1740 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
   1741 		reply_len = wpa_supplicant_ctrl_iface_blacklist(
   1742 				wpa_s, buf + 9, reply, reply_size);
   1743 		if (os_strlen(buf) > 10 && reply_len == 0) {
   1744 			struct wpa_blacklist *bl = wpa_s->blacklist;
   1745 			if (os_strncmp(buf+10, "clear", 5) == 0 ||
   1746 			    (bl != NULL && os_memcmp(bl->bssid, wpa_s->bssid, ETH_ALEN) == 0)) {
   1747 				wpa_s->disconnected = 0;
   1748 				wpa_s->reassociate = 1;
   1749 				wpa_supplicant_req_scan(wpa_s, 0, 0);
   1750 			}
   1751 		}
   1752 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
   1753 		reply_len = wpa_supplicant_ctrl_iface_log_level(
   1754 				wpa_s, buf + 9, reply, reply_size);
   1755 #endif
   1756 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
   1757 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
   1758 			wpa_s, reply, reply_size);
   1759 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
   1760 		wpa_s->reassociate = 0;
   1761 		wpa_s->disconnected = 1;
   1762 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
   1763 	} else if (os_strcmp(buf, "SCAN") == 0) {
   1764 #ifdef ANDROID
   1765 		if (!wpa_s->scanning && ((wpa_s->wpa_state <= WPA_SCANNING) ||
   1766 			(wpa_s->wpa_state >= WPA_COMPLETED))) {
   1767 #endif
   1768 			wpa_s->scan_req = 2;
   1769 			wpa_supplicant_req_scan(wpa_s, 0, 0);
   1770 #ifdef ANDROID
   1771 		} else {
   1772 			wpa_printf(MSG_ERROR, "Ongoing Scan action...");
   1773 #endif
   1774 		}
   1775 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
   1776 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
   1777 			wpa_s, reply, reply_size);
   1778 	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
   1779 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
   1780 			reply_len = -1;
   1781 	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
   1782 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
   1783 			reply_len = -1;
   1784 	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
   1785 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
   1786 			reply_len = -1;
   1787 	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
   1788 		reply_len = wpa_supplicant_ctrl_iface_add_network(
   1789 			wpa_s, reply, reply_size);
   1790 	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
   1791 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
   1792 			reply_len = -1;
   1793 	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
   1794 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
   1795 			reply_len = -1;
   1796 	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
   1797 		reply_len = wpa_supplicant_ctrl_iface_get_network(
   1798 			wpa_s, buf + 12, reply, reply_size);
   1799 #ifndef CONFIG_NO_CONFIG_WRITE
   1800 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
   1801 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
   1802 			reply_len = -1;
   1803 #endif /* CONFIG_NO_CONFIG_WRITE */
   1804 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
   1805 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
   1806 			wpa_s, buf + 15, reply, reply_size);
   1807 	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
   1808 		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
   1809 			reply_len = -1;
   1810 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
   1811 		reply_len = wpa_supplicant_global_iface_list(
   1812 			wpa_s->global, reply, reply_size);
   1813 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
   1814 		reply_len = wpa_supplicant_global_iface_interfaces(
   1815 			wpa_s->global, reply, reply_size);
   1816 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
   1817 		reply_len = wpa_supplicant_ctrl_iface_bss(
   1818 			wpa_s, buf + 4, reply, reply_size);
   1819 #ifdef ANDROID
   1820     } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
   1821         reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, reply_size);
   1822 #endif
   1823 	} else {
   1824 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   1825 		reply_len = 16;
   1826 	}
   1827 
   1828 	if (reply_len < 0) {
   1829 		os_memcpy(reply, "FAIL\n", 5);
   1830 		reply_len = 5;
   1831 	}
   1832 
   1833 	if (ctrl_rsp)
   1834 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
   1835 
   1836 	*resp_len = reply_len;
   1837 	return reply;
   1838 }
   1839 
   1840 
   1841 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
   1842 					   char *cmd)
   1843 {
   1844 	struct wpa_interface iface;
   1845 	char *pos;
   1846 
   1847 	/*
   1848 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
   1849 	 * TAB<bridge_ifname>
   1850 	 */
   1851 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
   1852 
   1853 	os_memset(&iface, 0, sizeof(iface));
   1854 
   1855 	do {
   1856 		iface.ifname = pos = cmd;
   1857 		pos = os_strchr(pos, '\t');
   1858 		if (pos)
   1859 			*pos++ = '\0';
   1860 		if (iface.ifname[0] == '\0')
   1861 			return -1;
   1862 		if (pos == NULL)
   1863 			break;
   1864 
   1865 		iface.confname = pos;
   1866 		pos = os_strchr(pos, '\t');
   1867 		if (pos)
   1868 			*pos++ = '\0';
   1869 		if (iface.confname[0] == '\0')
   1870 			iface.confname = NULL;
   1871 		if (pos == NULL)
   1872 			break;
   1873 
   1874 		iface.driver = pos;
   1875 		pos = os_strchr(pos, '\t');
   1876 		if (pos)
   1877 			*pos++ = '\0';
   1878 		if (iface.driver[0] == '\0')
   1879 			iface.driver = NULL;
   1880 		if (pos == NULL)
   1881 			break;
   1882 
   1883 		iface.ctrl_interface = pos;
   1884 		pos = os_strchr(pos, '\t');
   1885 		if (pos)
   1886 			*pos++ = '\0';
   1887 		if (iface.ctrl_interface[0] == '\0')
   1888 			iface.ctrl_interface = NULL;
   1889 		if (pos == NULL)
   1890 			break;
   1891 
   1892 		iface.driver_param = pos;
   1893 		pos = os_strchr(pos, '\t');
   1894 		if (pos)
   1895 			*pos++ = '\0';
   1896 		if (iface.driver_param[0] == '\0')
   1897 			iface.driver_param = NULL;
   1898 		if (pos == NULL)
   1899 			break;
   1900 
   1901 		iface.bridge_ifname = pos;
   1902 		pos = os_strchr(pos, '\t');
   1903 		if (pos)
   1904 			*pos++ = '\0';
   1905 		if (iface.bridge_ifname[0] == '\0')
   1906 			iface.bridge_ifname = NULL;
   1907 		if (pos == NULL)
   1908 			break;
   1909 	} while (0);
   1910 
   1911 	if (wpa_supplicant_get_iface(global, iface.ifname))
   1912 		return -1;
   1913 
   1914 	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
   1915 }
   1916 
   1917 
   1918 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
   1919 					      char *cmd)
   1920 {
   1921 	struct wpa_supplicant *wpa_s;
   1922 
   1923 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
   1924 
   1925 	wpa_s = wpa_supplicant_get_iface(global, cmd);
   1926 	if (wpa_s == NULL)
   1927 		return -1;
   1928 	return wpa_supplicant_remove_iface(global, wpa_s);
   1929 }
   1930 
   1931 
   1932 static void wpa_free_iface_info(struct wpa_interface_info *iface)
   1933 {
   1934 	struct wpa_interface_info *prev;
   1935 
   1936 	while (iface) {
   1937 		prev = iface;
   1938 		iface = iface->next;
   1939 
   1940 		os_free(prev->ifname);
   1941 		os_free(prev->desc);
   1942 		os_free(prev);
   1943 	}
   1944 }
   1945 
   1946 
   1947 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
   1948 					    char *buf, int len)
   1949 {
   1950 	int i, res;
   1951 	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
   1952 	char *pos, *end;
   1953 
   1954 	for (i = 0; wpa_supplicant_drivers[i]; i++) {
   1955 		struct wpa_driver_ops *drv = wpa_supplicant_drivers[i];
   1956 		if (drv->get_interfaces == NULL)
   1957 			continue;
   1958 		tmp = drv->get_interfaces(global->drv_priv);
   1959 		if (tmp == NULL)
   1960 			continue;
   1961 
   1962 		if (last == NULL)
   1963 			iface = last = tmp;
   1964 		else
   1965 			last->next = tmp;
   1966 		while (last->next)
   1967 			last = last->next;
   1968 	}
   1969 
   1970 	pos = buf;
   1971 	end = buf + len;
   1972 	for (tmp = iface; tmp; tmp = tmp->next) {
   1973 		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
   1974 				  tmp->drv_name, tmp->ifname,
   1975 				  tmp->desc ? tmp->desc : "");
   1976 		if (res < 0 || res >= end - pos) {
   1977 			*pos = '\0';
   1978 			break;
   1979 		}
   1980 		pos += res;
   1981 	}
   1982 
   1983 	wpa_free_iface_info(iface);
   1984 
   1985 	return pos - buf;
   1986 }
   1987 
   1988 
   1989 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
   1990 						  char *buf, int len)
   1991 {
   1992 	int res;
   1993 	char *pos, *end;
   1994 	struct wpa_supplicant *wpa_s;
   1995 
   1996 	wpa_s = global->ifaces;
   1997 	pos = buf;
   1998 	end = buf + len;
   1999 
   2000 	while (wpa_s) {
   2001 		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
   2002 		if (res < 0 || res >= end - pos) {
   2003 			*pos = '\0';
   2004 			break;
   2005 		}
   2006 		pos += res;
   2007 		wpa_s = wpa_s->next;
   2008 	}
   2009 	return pos - buf;
   2010 }
   2011 
   2012 
   2013 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
   2014 						char *buf, size_t *resp_len)
   2015 {
   2016 	char *reply;
   2017 	const int reply_size = 4096;
   2018 	int reply_len;
   2019 
   2020     if (os_strcmp(buf, "PING") != 0) {
   2021 	    wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
   2022 			  (const u8 *) buf, os_strlen(buf));
   2023     }
   2024 
   2025 	reply = os_malloc(reply_size);
   2026 	if (reply == NULL) {
   2027 		*resp_len = 1;
   2028 		return NULL;
   2029 	}
   2030 
   2031 	os_memcpy(reply, "OK\n", 3);
   2032 	reply_len = 3;
   2033 
   2034 	if (os_strcmp(buf, "PING") == 0) {
   2035 		os_memcpy(reply, "PONG\n", 5);
   2036 		reply_len = 5;
   2037 	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
   2038 		if (wpa_supplicant_global_iface_add(global, buf + 14))
   2039 			reply_len = -1;
   2040 	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
   2041 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
   2042 			reply_len = -1;
   2043 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
   2044 		reply_len = wpa_supplicant_global_iface_list(
   2045 			global, reply, reply_size);
   2046 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
   2047 		reply_len = wpa_supplicant_global_iface_interfaces(
   2048 			global, reply, reply_size);
   2049 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   2050 		eloop_terminate();
   2051 	} else {
   2052 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   2053 		reply_len = 16;
   2054 	}
   2055 
   2056 	if (reply_len < 0) {
   2057 		os_memcpy(reply, "FAIL\n", 5);
   2058 		reply_len = 5;
   2059 	}
   2060 
   2061 	*resp_len = reply_len;
   2062 	return reply;
   2063 }
   2064