Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * WPA Supplicant / Control interface (shared code for all backends)
      3  * Copyright (c) 2004-2012, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "utils/includes.h"
     10 
     11 #include "utils/common.h"
     12 #include "utils/eloop.h"
     13 #include "common/version.h"
     14 #include "common/ieee802_11_defs.h"
     15 #include "common/ieee802_11_common.h"
     16 #include "common/wpa_ctrl.h"
     17 #include "eap_peer/eap.h"
     18 #include "eapol_supp/eapol_supp_sm.h"
     19 #include "rsn_supp/wpa.h"
     20 #include "rsn_supp/preauth.h"
     21 #include "rsn_supp/pmksa_cache.h"
     22 #include "l2_packet/l2_packet.h"
     23 #include "wps/wps.h"
     24 #include "config.h"
     25 #include "wpa_supplicant_i.h"
     26 #include "driver_i.h"
     27 #include "wps_supplicant.h"
     28 #include "ibss_rsn.h"
     29 #include "ap.h"
     30 #include "p2p_supplicant.h"
     31 #include "p2p/p2p.h"
     32 #include "hs20_supplicant.h"
     33 #include "wifi_display.h"
     34 #include "notify.h"
     35 #include "bss.h"
     36 #include "scan.h"
     37 #include "ctrl_iface.h"
     38 #include "interworking.h"
     39 #include "blacklist.h"
     40 #include "wpas_glue.h"
     41 #include "autoscan.h"
     42 
     43 extern struct wpa_driver_ops *wpa_drivers[];
     44 
     45 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
     46 					    char *buf, int len);
     47 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
     48 						  char *buf, int len);
     49 
     50 
     51 static int pno_start(struct wpa_supplicant *wpa_s)
     52 {
     53 	int ret;
     54 	size_t i, num_ssid;
     55 	struct wpa_ssid *ssid;
     56 	struct wpa_driver_scan_params params;
     57 
     58 	if (wpa_s->pno)
     59 		return 0;
     60 
     61 	os_memset(&params, 0, sizeof(params));
     62 
     63 	num_ssid = 0;
     64 	ssid = wpa_s->conf->ssid;
     65 	while (ssid) {
     66 		if (!wpas_network_disabled(wpa_s, ssid))
     67 			num_ssid++;
     68 		ssid = ssid->next;
     69 	}
     70 	if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
     71 		wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
     72 			   "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
     73 		num_ssid = WPAS_MAX_SCAN_SSIDS;
     74 	}
     75 
     76 	if (num_ssid == 0) {
     77 		wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
     78 		return -1;
     79 	}
     80 
     81 	params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
     82 					num_ssid);
     83 	if (params.filter_ssids == NULL)
     84 		return -1;
     85 	i = 0;
     86 	ssid = wpa_s->conf->ssid;
     87 	while (ssid) {
     88 		if (!wpas_network_disabled(wpa_s, ssid)) {
     89 			params.ssids[i].ssid = ssid->ssid;
     90 			params.ssids[i].ssid_len = ssid->ssid_len;
     91 			params.num_ssids++;
     92 			os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
     93 				  ssid->ssid_len);
     94 			params.filter_ssids[i].ssid_len = ssid->ssid_len;
     95 			params.num_filter_ssids++;
     96 			i++;
     97 			if (i == num_ssid)
     98 				break;
     99 		}
    100 		ssid = ssid->next;
    101 	}
    102 
    103 	if (wpa_s->conf->filter_rssi)
    104 		params.filter_rssi = wpa_s->conf->filter_rssi;
    105 
    106 	ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
    107 	os_free(params.filter_ssids);
    108 	if (ret == 0)
    109 		wpa_s->pno = 1;
    110 	return ret;
    111 }
    112 
    113 
    114 static int pno_stop(struct wpa_supplicant *wpa_s)
    115 {
    116 	if (wpa_s->pno) {
    117 		wpa_s->pno = 0;
    118 		return wpa_drv_stop_sched_scan(wpa_s);
    119 	}
    120 	return 0;
    121 }
    122 
    123 
    124 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
    125 {
    126 	char *pos;
    127 	u8 addr[ETH_ALEN], *filter = NULL, *n;
    128 	size_t count = 0;
    129 
    130 	pos = val;
    131 	while (pos) {
    132 		if (*pos == '\0')
    133 			break;
    134 		if (hwaddr_aton(pos, addr)) {
    135 			os_free(filter);
    136 			return -1;
    137 		}
    138 		n = os_realloc_array(filter, count + 1, ETH_ALEN);
    139 		if (n == NULL) {
    140 			os_free(filter);
    141 			return -1;
    142 		}
    143 		filter = n;
    144 		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
    145 		count++;
    146 
    147 		pos = os_strchr(pos, ' ');
    148 		if (pos)
    149 			pos++;
    150 	}
    151 
    152 	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
    153 	os_free(wpa_s->bssid_filter);
    154 	wpa_s->bssid_filter = filter;
    155 	wpa_s->bssid_filter_count = count;
    156 
    157 	return 0;
    158 }
    159 
    160 
    161 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
    162 					 char *cmd)
    163 {
    164 	char *value;
    165 	int ret = 0;
    166 
    167 	value = os_strchr(cmd, ' ');
    168 	if (value == NULL)
    169 		return -1;
    170 	*value++ = '\0';
    171 
    172 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    173 	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
    174 		eapol_sm_configure(wpa_s->eapol,
    175 				   atoi(value), -1, -1, -1);
    176 	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
    177 		eapol_sm_configure(wpa_s->eapol,
    178 				   -1, atoi(value), -1, -1);
    179 	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
    180 		eapol_sm_configure(wpa_s->eapol,
    181 				   -1, -1, atoi(value), -1);
    182 	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
    183 		eapol_sm_configure(wpa_s->eapol,
    184 				   -1, -1, -1, atoi(value));
    185 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
    186 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
    187 				     atoi(value)))
    188 			ret = -1;
    189 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
    190 		   0) {
    191 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
    192 				     atoi(value)))
    193 			ret = -1;
    194 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
    195 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
    196 			ret = -1;
    197 	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
    198 		wpa_s->wps_fragment_size = atoi(value);
    199 #ifdef CONFIG_WPS_TESTING
    200 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
    201 		long int val;
    202 		val = strtol(value, NULL, 0);
    203 		if (val < 0 || val > 0xff) {
    204 			ret = -1;
    205 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
    206 				   "wps_version_number %ld", val);
    207 		} else {
    208 			wps_version_number = val;
    209 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
    210 				   "version %u.%u",
    211 				   (wps_version_number & 0xf0) >> 4,
    212 				   wps_version_number & 0x0f);
    213 		}
    214 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
    215 		wps_testing_dummy_cred = atoi(value);
    216 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
    217 			   wps_testing_dummy_cred);
    218 #endif /* CONFIG_WPS_TESTING */
    219 	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
    220 		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
    221 			ret = -1;
    222 #ifdef CONFIG_TDLS_TESTING
    223 	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
    224 		extern unsigned int tdls_testing;
    225 		tdls_testing = strtol(value, NULL, 0);
    226 		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
    227 #endif /* CONFIG_TDLS_TESTING */
    228 #ifdef CONFIG_TDLS
    229 	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
    230 		int disabled = atoi(value);
    231 		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
    232 		if (disabled) {
    233 			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
    234 				ret = -1;
    235 		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
    236 			ret = -1;
    237 		wpa_tdls_enable(wpa_s->wpa, !disabled);
    238 #endif /* CONFIG_TDLS */
    239 	} else if (os_strcasecmp(cmd, "pno") == 0) {
    240 		if (atoi(value))
    241 			ret = pno_start(wpa_s);
    242 		else
    243 			ret = pno_stop(wpa_s);
    244 	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
    245 		int disabled = atoi(value);
    246 		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
    247 			ret = -1;
    248 		else if (disabled)
    249 			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
    250 	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
    251 		if (os_strcmp(value, "disable") == 0)
    252 			wpa_s->set_sta_uapsd = 0;
    253 		else {
    254 			int be, bk, vi, vo;
    255 			char *pos;
    256 			/* format: BE,BK,VI,VO;max SP Length */
    257 			be = atoi(value);
    258 			pos = os_strchr(value, ',');
    259 			if (pos == NULL)
    260 				return -1;
    261 			pos++;
    262 			bk = atoi(pos);
    263 			pos = os_strchr(pos, ',');
    264 			if (pos == NULL)
    265 				return -1;
    266 			pos++;
    267 			vi = atoi(pos);
    268 			pos = os_strchr(pos, ',');
    269 			if (pos == NULL)
    270 				return -1;
    271 			pos++;
    272 			vo = atoi(pos);
    273 			/* ignore max SP Length for now */
    274 
    275 			wpa_s->set_sta_uapsd = 1;
    276 			wpa_s->sta_uapsd = 0;
    277 			if (be)
    278 				wpa_s->sta_uapsd |= BIT(0);
    279 			if (bk)
    280 				wpa_s->sta_uapsd |= BIT(1);
    281 			if (vi)
    282 				wpa_s->sta_uapsd |= BIT(2);
    283 			if (vo)
    284 				wpa_s->sta_uapsd |= BIT(3);
    285 		}
    286 	} else if (os_strcasecmp(cmd, "ps") == 0) {
    287 		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
    288 #ifdef CONFIG_WIFI_DISPLAY
    289 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
    290 		wifi_display_enable(wpa_s->global, !!atoi(value));
    291 #endif /* CONFIG_WIFI_DISPLAY */
    292 	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
    293 		ret = set_bssid_filter(wpa_s, value);
    294 	} else {
    295 		value[-1] = '=';
    296 		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
    297 		if (ret == 0)
    298 			wpa_supplicant_update_config(wpa_s);
    299 	}
    300 
    301 	return ret;
    302 }
    303 
    304 
    305 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
    306 					 char *cmd, char *buf, size_t buflen)
    307 {
    308 	int res = -1;
    309 
    310 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
    311 
    312 	if (os_strcmp(cmd, "version") == 0) {
    313 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
    314 	} else if (os_strcasecmp(cmd, "country") == 0) {
    315 		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
    316 			res = os_snprintf(buf, buflen, "%c%c",
    317 					  wpa_s->conf->country[0],
    318 					  wpa_s->conf->country[1]);
    319 #ifdef CONFIG_WIFI_DISPLAY
    320 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
    321 		res = os_snprintf(buf, buflen, "%d",
    322 				  wpa_s->global->wifi_display);
    323 		if (res < 0 || (unsigned int) res >= buflen)
    324 			return -1;
    325 		return res;
    326 #endif /* CONFIG_WIFI_DISPLAY */
    327 	}
    328 
    329 	if (res < 0 || (unsigned int) res >= buflen)
    330 		return -1;
    331 	return res;
    332 }
    333 
    334 
    335 #ifdef IEEE8021X_EAPOL
    336 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
    337 					     char *addr)
    338 {
    339 	u8 bssid[ETH_ALEN];
    340 	struct wpa_ssid *ssid = wpa_s->current_ssid;
    341 
    342 	if (hwaddr_aton(addr, bssid)) {
    343 		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
    344 			   "'%s'", addr);
    345 		return -1;
    346 	}
    347 
    348 	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
    349 	rsn_preauth_deinit(wpa_s->wpa);
    350 	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
    351 		return -1;
    352 
    353 	return 0;
    354 }
    355 #endif /* IEEE8021X_EAPOL */
    356 
    357 
    358 #ifdef CONFIG_PEERKEY
    359 /* MLME-STKSTART.request(peer) */
    360 static int wpa_supplicant_ctrl_iface_stkstart(
    361 	struct wpa_supplicant *wpa_s, char *addr)
    362 {
    363 	u8 peer[ETH_ALEN];
    364 
    365 	if (hwaddr_aton(addr, peer)) {
    366 		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
    367 			   "address '%s'", addr);
    368 		return -1;
    369 	}
    370 
    371 	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
    372 		   MAC2STR(peer));
    373 
    374 	return wpa_sm_stkstart(wpa_s->wpa, peer);
    375 }
    376 #endif /* CONFIG_PEERKEY */
    377 
    378 
    379 #ifdef CONFIG_TDLS
    380 
    381 static int wpa_supplicant_ctrl_iface_tdls_discover(
    382 	struct wpa_supplicant *wpa_s, char *addr)
    383 {
    384 	u8 peer[ETH_ALEN];
    385 	int ret;
    386 
    387 	if (hwaddr_aton(addr, peer)) {
    388 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
    389 			   "address '%s'", addr);
    390 		return -1;
    391 	}
    392 
    393 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
    394 		   MAC2STR(peer));
    395 
    396 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
    397 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
    398 	else
    399 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
    400 
    401 	return ret;
    402 }
    403 
    404 
    405 static int wpa_supplicant_ctrl_iface_tdls_setup(
    406 	struct wpa_supplicant *wpa_s, char *addr)
    407 {
    408 	u8 peer[ETH_ALEN];
    409 	int ret;
    410 
    411 	if (hwaddr_aton(addr, peer)) {
    412 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
    413 			   "address '%s'", addr);
    414 		return -1;
    415 	}
    416 
    417 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
    418 		   MAC2STR(peer));
    419 
    420 	ret = wpa_tdls_reneg(wpa_s->wpa, peer);
    421 	if (ret) {
    422 		if (wpa_tdls_is_external_setup(wpa_s->wpa))
    423 			ret = wpa_tdls_start(wpa_s->wpa, peer);
    424 		else
    425 			ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
    426 	}
    427 
    428 	return ret;
    429 }
    430 
    431 
    432 static int wpa_supplicant_ctrl_iface_tdls_teardown(
    433 	struct wpa_supplicant *wpa_s, char *addr)
    434 {
    435 	u8 peer[ETH_ALEN];
    436 
    437 	if (hwaddr_aton(addr, peer)) {
    438 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
    439 			   "address '%s'", addr);
    440 		return -1;
    441 	}
    442 
    443 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
    444 		   MAC2STR(peer));
    445 
    446 	return wpa_tdls_teardown_link(wpa_s->wpa, peer,
    447 				      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
    448 }
    449 
    450 #endif /* CONFIG_TDLS */
    451 
    452 
    453 #ifdef CONFIG_IEEE80211R
    454 static int wpa_supplicant_ctrl_iface_ft_ds(
    455 	struct wpa_supplicant *wpa_s, char *addr)
    456 {
    457 	u8 target_ap[ETH_ALEN];
    458 	struct wpa_bss *bss;
    459 	const u8 *mdie;
    460 
    461 	if (hwaddr_aton(addr, target_ap)) {
    462 		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
    463 			   "address '%s'", addr);
    464 		return -1;
    465 	}
    466 
    467 	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
    468 
    469 	bss = wpa_bss_get_bssid(wpa_s, target_ap);
    470 	if (bss)
    471 		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
    472 	else
    473 		mdie = NULL;
    474 
    475 	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
    476 }
    477 #endif /* CONFIG_IEEE80211R */
    478 
    479 
    480 #ifdef CONFIG_WPS
    481 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
    482 					     char *cmd)
    483 {
    484 	u8 bssid[ETH_ALEN], *_bssid = bssid;
    485 #ifdef CONFIG_P2P
    486 	u8 p2p_dev_addr[ETH_ALEN];
    487 #endif /* CONFIG_P2P */
    488 #ifdef CONFIG_AP
    489 	u8 *_p2p_dev_addr = NULL;
    490 #endif /* CONFIG_AP */
    491 
    492 	if (cmd == NULL || os_strcmp(cmd, "any") == 0 || cmd[0] == '\0') {
    493 		_bssid = NULL;
    494 #ifdef CONFIG_P2P
    495 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
    496 		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
    497 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
    498 				   "P2P Device Address '%s'",
    499 				   cmd + 13);
    500 			return -1;
    501 		}
    502 		_p2p_dev_addr = p2p_dev_addr;
    503 #endif /* CONFIG_P2P */
    504 	} else if (hwaddr_aton(cmd, bssid)) {
    505 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
    506 			   cmd);
    507 		return -1;
    508 	}
    509 
    510 #ifdef CONFIG_AP
    511 	if (wpa_s->ap_iface)
    512 		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
    513 #endif /* CONFIG_AP */
    514 
    515 	return wpas_wps_start_pbc(wpa_s, _bssid, 0);
    516 }
    517 
    518 
    519 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
    520 					     char *cmd, char *buf,
    521 					     size_t buflen)
    522 {
    523 	u8 bssid[ETH_ALEN], *_bssid = bssid;
    524 	char *pin;
    525 	int ret;
    526 
    527 	pin = os_strchr(cmd, ' ');
    528 	if (pin)
    529 		*pin++ = '\0';
    530 
    531 	if (os_strcmp(cmd, "any") == 0)
    532 		_bssid = NULL;
    533 	else if (os_strcmp(cmd, "get") == 0) {
    534 		ret = wps_generate_pin();
    535 		goto done;
    536 	} else if (hwaddr_aton(cmd, bssid)) {
    537 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
    538 			   cmd);
    539 		return -1;
    540 	}
    541 
    542 #ifdef CONFIG_AP
    543 	if (wpa_s->ap_iface)
    544 		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
    545 						 buf, buflen);
    546 #endif /* CONFIG_AP */
    547 
    548 	if (pin) {
    549 		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
    550 					 DEV_PW_DEFAULT);
    551 		if (ret < 0)
    552 			return -1;
    553 		ret = os_snprintf(buf, buflen, "%s", pin);
    554 		if (ret < 0 || (size_t) ret >= buflen)
    555 			return -1;
    556 		return ret;
    557 	}
    558 
    559 	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
    560 	if (ret < 0)
    561 		return -1;
    562 
    563 done:
    564 	/* Return the generated PIN */
    565 	ret = os_snprintf(buf, buflen, "%08d", ret);
    566 	if (ret < 0 || (size_t) ret >= buflen)
    567 		return -1;
    568 	return ret;
    569 }
    570 
    571 
    572 static int wpa_supplicant_ctrl_iface_wps_check_pin(
    573 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
    574 {
    575 	char pin[9];
    576 	size_t len;
    577 	char *pos;
    578 	int ret;
    579 
    580 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
    581 			      (u8 *) cmd, os_strlen(cmd));
    582 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
    583 		if (*pos < '0' || *pos > '9')
    584 			continue;
    585 		pin[len++] = *pos;
    586 		if (len == 9) {
    587 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
    588 			return -1;
    589 		}
    590 	}
    591 	if (len != 4 && len != 8) {
    592 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
    593 		return -1;
    594 	}
    595 	pin[len] = '\0';
    596 
    597 	if (len == 8) {
    598 		unsigned int pin_val;
    599 		pin_val = atoi(pin);
    600 		if (!wps_pin_valid(pin_val)) {
    601 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
    602 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
    603 			if (ret < 0 || (size_t) ret >= buflen)
    604 				return -1;
    605 			return ret;
    606 		}
    607 	}
    608 
    609 	ret = os_snprintf(buf, buflen, "%s", pin);
    610 	if (ret < 0 || (size_t) ret >= buflen)
    611 		return -1;
    612 
    613 	return ret;
    614 }
    615 
    616 
    617 #ifdef CONFIG_WPS_OOB
    618 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
    619 					     char *cmd)
    620 {
    621 	char *path, *method, *name;
    622 
    623 	path = os_strchr(cmd, ' ');
    624 	if (path == NULL)
    625 		return -1;
    626 	*path++ = '\0';
    627 
    628 	method = os_strchr(path, ' ');
    629 	if (method == NULL)
    630 		return -1;
    631 	*method++ = '\0';
    632 
    633 	name = os_strchr(method, ' ');
    634 	if (name != NULL)
    635 		*name++ = '\0';
    636 
    637 	return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
    638 }
    639 #endif /* CONFIG_WPS_OOB */
    640 
    641 
    642 #ifdef CONFIG_WPS_NFC
    643 
    644 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
    645 					     char *cmd)
    646 {
    647 	u8 bssid[ETH_ALEN], *_bssid = bssid;
    648 
    649 	if (cmd == NULL || cmd[0] == '\0')
    650 		_bssid = NULL;
    651 	else if (hwaddr_aton(cmd, bssid))
    652 		return -1;
    653 
    654 	return wpas_wps_start_nfc(wpa_s, _bssid);
    655 }
    656 
    657 
    658 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
    659 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
    660 {
    661 	int ndef;
    662 	struct wpabuf *buf;
    663 	int res;
    664 
    665 	if (os_strcmp(cmd, "WPS") == 0)
    666 		ndef = 0;
    667 	else if (os_strcmp(cmd, "NDEF") == 0)
    668 		ndef = 1;
    669 	else
    670 		return -1;
    671 
    672 	buf = wpas_wps_nfc_token(wpa_s, ndef);
    673 	if (buf == NULL)
    674 		return -1;
    675 
    676 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    677 					 wpabuf_len(buf));
    678 	reply[res++] = '\n';
    679 	reply[res] = '\0';
    680 
    681 	wpabuf_free(buf);
    682 
    683 	return res;
    684 }
    685 
    686 
    687 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
    688 	struct wpa_supplicant *wpa_s, char *pos)
    689 {
    690 	size_t len;
    691 	struct wpabuf *buf;
    692 	int ret;
    693 
    694 	len = os_strlen(pos);
    695 	if (len & 0x01)
    696 		return -1;
    697 	len /= 2;
    698 
    699 	buf = wpabuf_alloc(len);
    700 	if (buf == NULL)
    701 		return -1;
    702 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
    703 		wpabuf_free(buf);
    704 		return -1;
    705 	}
    706 
    707 	ret = wpas_wps_nfc_tag_read(wpa_s, buf);
    708 	wpabuf_free(buf);
    709 
    710 	return ret;
    711 }
    712 
    713 #endif /* CONFIG_WPS_NFC */
    714 
    715 
    716 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
    717 					     char *cmd)
    718 {
    719 	u8 bssid[ETH_ALEN];
    720 	char *pin;
    721 	char *new_ssid;
    722 	char *new_auth;
    723 	char *new_encr;
    724 	char *new_key;
    725 	struct wps_new_ap_settings ap;
    726 
    727 	pin = os_strchr(cmd, ' ');
    728 	if (pin == NULL)
    729 		return -1;
    730 	*pin++ = '\0';
    731 
    732 	if (hwaddr_aton(cmd, bssid)) {
    733 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
    734 			   cmd);
    735 		return -1;
    736 	}
    737 
    738 	new_ssid = os_strchr(pin, ' ');
    739 	if (new_ssid == NULL)
    740 		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
    741 	*new_ssid++ = '\0';
    742 
    743 	new_auth = os_strchr(new_ssid, ' ');
    744 	if (new_auth == NULL)
    745 		return -1;
    746 	*new_auth++ = '\0';
    747 
    748 	new_encr = os_strchr(new_auth, ' ');
    749 	if (new_encr == NULL)
    750 		return -1;
    751 	*new_encr++ = '\0';
    752 
    753 	new_key = os_strchr(new_encr, ' ');
    754 	if (new_key == NULL)
    755 		return -1;
    756 	*new_key++ = '\0';
    757 
    758 	os_memset(&ap, 0, sizeof(ap));
    759 	ap.ssid_hex = new_ssid;
    760 	ap.auth = new_auth;
    761 	ap.encr = new_encr;
    762 	ap.key_hex = new_key;
    763 	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
    764 }
    765 
    766 
    767 #ifdef CONFIG_AP
    768 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
    769 						char *cmd, char *buf,
    770 						size_t buflen)
    771 {
    772 	int timeout = 300;
    773 	char *pos;
    774 	const char *pin_txt;
    775 
    776 	if (!wpa_s->ap_iface)
    777 		return -1;
    778 
    779 	pos = os_strchr(cmd, ' ');
    780 	if (pos)
    781 		*pos++ = '\0';
    782 
    783 	if (os_strcmp(cmd, "disable") == 0) {
    784 		wpas_wps_ap_pin_disable(wpa_s);
    785 		return os_snprintf(buf, buflen, "OK\n");
    786 	}
    787 
    788 	if (os_strcmp(cmd, "random") == 0) {
    789 		if (pos)
    790 			timeout = atoi(pos);
    791 		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
    792 		if (pin_txt == NULL)
    793 			return -1;
    794 		return os_snprintf(buf, buflen, "%s", pin_txt);
    795 	}
    796 
    797 	if (os_strcmp(cmd, "get") == 0) {
    798 		pin_txt = wpas_wps_ap_pin_get(wpa_s);
    799 		if (pin_txt == NULL)
    800 			return -1;
    801 		return os_snprintf(buf, buflen, "%s", pin_txt);
    802 	}
    803 
    804 	if (os_strcmp(cmd, "set") == 0) {
    805 		char *pin;
    806 		if (pos == NULL)
    807 			return -1;
    808 		pin = pos;
    809 		pos = os_strchr(pos, ' ');
    810 		if (pos) {
    811 			*pos++ = '\0';
    812 			timeout = atoi(pos);
    813 		}
    814 		if (os_strlen(pin) > buflen)
    815 			return -1;
    816 		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
    817 			return -1;
    818 		return os_snprintf(buf, buflen, "%s", pin);
    819 	}
    820 
    821 	return -1;
    822 }
    823 #endif /* CONFIG_AP */
    824 
    825 
    826 #ifdef CONFIG_WPS_ER
    827 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
    828 						char *cmd)
    829 {
    830 	char *uuid = cmd, *pin, *pos;
    831 	u8 addr_buf[ETH_ALEN], *addr = NULL;
    832 	pin = os_strchr(uuid, ' ');
    833 	if (pin == NULL)
    834 		return -1;
    835 	*pin++ = '\0';
    836 	pos = os_strchr(pin, ' ');
    837 	if (pos) {
    838 		*pos++ = '\0';
    839 		if (hwaddr_aton(pos, addr_buf) == 0)
    840 			addr = addr_buf;
    841 	}
    842 	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
    843 }
    844 
    845 
    846 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
    847 						  char *cmd)
    848 {
    849 	char *uuid = cmd, *pin;
    850 	pin = os_strchr(uuid, ' ');
    851 	if (pin == NULL)
    852 		return -1;
    853 	*pin++ = '\0';
    854 	return wpas_wps_er_learn(wpa_s, uuid, pin);
    855 }
    856 
    857 
    858 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
    859 	struct wpa_supplicant *wpa_s, char *cmd)
    860 {
    861 	char *uuid = cmd, *id;
    862 	id = os_strchr(uuid, ' ');
    863 	if (id == NULL)
    864 		return -1;
    865 	*id++ = '\0';
    866 	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
    867 }
    868 
    869 
    870 static int wpa_supplicant_ctrl_iface_wps_er_config(
    871 	struct wpa_supplicant *wpa_s, char *cmd)
    872 {
    873 	char *pin;
    874 	char *new_ssid;
    875 	char *new_auth;
    876 	char *new_encr;
    877 	char *new_key;
    878 	struct wps_new_ap_settings ap;
    879 
    880 	pin = os_strchr(cmd, ' ');
    881 	if (pin == NULL)
    882 		return -1;
    883 	*pin++ = '\0';
    884 
    885 	new_ssid = os_strchr(pin, ' ');
    886 	if (new_ssid == NULL)
    887 		return -1;
    888 	*new_ssid++ = '\0';
    889 
    890 	new_auth = os_strchr(new_ssid, ' ');
    891 	if (new_auth == NULL)
    892 		return -1;
    893 	*new_auth++ = '\0';
    894 
    895 	new_encr = os_strchr(new_auth, ' ');
    896 	if (new_encr == NULL)
    897 		return -1;
    898 	*new_encr++ = '\0';
    899 
    900 	new_key = os_strchr(new_encr, ' ');
    901 	if (new_key == NULL)
    902 		return -1;
    903 	*new_key++ = '\0';
    904 
    905 	os_memset(&ap, 0, sizeof(ap));
    906 	ap.ssid_hex = new_ssid;
    907 	ap.auth = new_auth;
    908 	ap.encr = new_encr;
    909 	ap.key_hex = new_key;
    910 	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
    911 }
    912 
    913 
    914 #ifdef CONFIG_WPS_NFC
    915 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
    916 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
    917 {
    918 	int ndef;
    919 	struct wpabuf *buf;
    920 	int res;
    921 	char *uuid;
    922 
    923 	uuid = os_strchr(cmd, ' ');
    924 	if (uuid == NULL)
    925 		return -1;
    926 	*uuid++ = '\0';
    927 
    928 	if (os_strcmp(cmd, "WPS") == 0)
    929 		ndef = 0;
    930 	else if (os_strcmp(cmd, "NDEF") == 0)
    931 		ndef = 1;
    932 	else
    933 		return -1;
    934 
    935 	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
    936 	if (buf == NULL)
    937 		return -1;
    938 
    939 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    940 					 wpabuf_len(buf));
    941 	reply[res++] = '\n';
    942 	reply[res] = '\0';
    943 
    944 	wpabuf_free(buf);
    945 
    946 	return res;
    947 }
    948 #endif /* CONFIG_WPS_NFC */
    949 #endif /* CONFIG_WPS_ER */
    950 
    951 #endif /* CONFIG_WPS */
    952 
    953 
    954 #ifdef CONFIG_IBSS_RSN
    955 static int wpa_supplicant_ctrl_iface_ibss_rsn(
    956 	struct wpa_supplicant *wpa_s, char *addr)
    957 {
    958 	u8 peer[ETH_ALEN];
    959 
    960 	if (hwaddr_aton(addr, peer)) {
    961 		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
    962 			   "address '%s'", addr);
    963 		return -1;
    964 	}
    965 
    966 	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
    967 		   MAC2STR(peer));
    968 
    969 	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
    970 }
    971 #endif /* CONFIG_IBSS_RSN */
    972 
    973 
    974 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
    975 					      char *rsp)
    976 {
    977 #ifdef IEEE8021X_EAPOL
    978 	char *pos, *id_pos;
    979 	int id;
    980 	struct wpa_ssid *ssid;
    981 
    982 	pos = os_strchr(rsp, '-');
    983 	if (pos == NULL)
    984 		return -1;
    985 	*pos++ = '\0';
    986 	id_pos = pos;
    987 	pos = os_strchr(pos, ':');
    988 	if (pos == NULL)
    989 		return -1;
    990 	*pos++ = '\0';
    991 	id = atoi(id_pos);
    992 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
    993 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
    994 			      (u8 *) pos, os_strlen(pos));
    995 
    996 	ssid = wpa_config_get_network(wpa_s->conf, id);
    997 	if (ssid == NULL) {
    998 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    999 			   "to update", id);
   1000 		return -1;
   1001 	}
   1002 
   1003 	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
   1004 							 pos);
   1005 #else /* IEEE8021X_EAPOL */
   1006 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
   1007 	return -1;
   1008 #endif /* IEEE8021X_EAPOL */
   1009 }
   1010 
   1011 
   1012 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
   1013 					    const char *params,
   1014 					    char *buf, size_t buflen)
   1015 {
   1016 	char *pos, *end, tmp[30];
   1017 	int res, verbose, wps, ret;
   1018 
   1019 	verbose = os_strcmp(params, "-VERBOSE") == 0;
   1020 	wps = os_strcmp(params, "-WPS") == 0;
   1021 	pos = buf;
   1022 	end = buf + buflen;
   1023 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
   1024 		struct wpa_ssid *ssid = wpa_s->current_ssid;
   1025 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
   1026 				  MAC2STR(wpa_s->bssid));
   1027 		if (ret < 0 || ret >= end - pos)
   1028 			return pos - buf;
   1029 		pos += ret;
   1030 		if (ssid) {
   1031 			u8 *_ssid = ssid->ssid;
   1032 			size_t ssid_len = ssid->ssid_len;
   1033 			u8 ssid_buf[MAX_SSID_LEN];
   1034 			if (ssid_len == 0) {
   1035 				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
   1036 				if (_res < 0)
   1037 					ssid_len = 0;
   1038 				else
   1039 					ssid_len = _res;
   1040 				_ssid = ssid_buf;
   1041 			}
   1042 			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
   1043 					  wpa_ssid_txt(_ssid, ssid_len),
   1044 					  ssid->id);
   1045 			if (ret < 0 || ret >= end - pos)
   1046 				return pos - buf;
   1047 			pos += ret;
   1048 
   1049 			if (wps && ssid->passphrase &&
   1050 			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
   1051 			    (ssid->mode == WPAS_MODE_AP ||
   1052 			     ssid->mode == WPAS_MODE_P2P_GO)) {
   1053 				ret = os_snprintf(pos, end - pos,
   1054 						  "passphrase=%s\n",
   1055 						  ssid->passphrase);
   1056 				if (ret < 0 || ret >= end - pos)
   1057 					return pos - buf;
   1058 				pos += ret;
   1059 			}
   1060 			if (ssid->id_str) {
   1061 				ret = os_snprintf(pos, end - pos,
   1062 						  "id_str=%s\n",
   1063 						  ssid->id_str);
   1064 				if (ret < 0 || ret >= end - pos)
   1065 					return pos - buf;
   1066 				pos += ret;
   1067 			}
   1068 
   1069 			switch (ssid->mode) {
   1070 			case WPAS_MODE_INFRA:
   1071 				ret = os_snprintf(pos, end - pos,
   1072 						  "mode=station\n");
   1073 				break;
   1074 			case WPAS_MODE_IBSS:
   1075 				ret = os_snprintf(pos, end - pos,
   1076 						  "mode=IBSS\n");
   1077 				break;
   1078 			case WPAS_MODE_AP:
   1079 				ret = os_snprintf(pos, end - pos,
   1080 						  "mode=AP\n");
   1081 				break;
   1082 			case WPAS_MODE_P2P_GO:
   1083 				ret = os_snprintf(pos, end - pos,
   1084 						  "mode=P2P GO\n");
   1085 				break;
   1086 			case WPAS_MODE_P2P_GROUP_FORMATION:
   1087 				ret = os_snprintf(pos, end - pos,
   1088 						  "mode=P2P GO - group "
   1089 						  "formation\n");
   1090 				break;
   1091 			default:
   1092 				ret = 0;
   1093 				break;
   1094 			}
   1095 			if (ret < 0 || ret >= end - pos)
   1096 				return pos - buf;
   1097 			pos += ret;
   1098 		}
   1099 
   1100 #ifdef CONFIG_AP
   1101 		if (wpa_s->ap_iface) {
   1102 			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
   1103 							    end - pos,
   1104 							    verbose);
   1105 		} else
   1106 #endif /* CONFIG_AP */
   1107 		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
   1108 	}
   1109 	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
   1110 			  wpa_supplicant_state_txt(wpa_s->wpa_state));
   1111 	if (ret < 0 || ret >= end - pos)
   1112 		return pos - buf;
   1113 	pos += ret;
   1114 
   1115 	if (wpa_s->l2 &&
   1116 	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
   1117 		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
   1118 		if (ret < 0 || ret >= end - pos)
   1119 			return pos - buf;
   1120 		pos += ret;
   1121 	}
   1122 
   1123 #ifdef CONFIG_P2P
   1124 	if (wpa_s->global->p2p) {
   1125 		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
   1126 				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
   1127 		if (ret < 0 || ret >= end - pos)
   1128 			return pos - buf;
   1129 		pos += ret;
   1130 	}
   1131 #endif /* CONFIG_P2P */
   1132 
   1133 	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
   1134 			  MAC2STR(wpa_s->own_addr));
   1135 	if (ret < 0 || ret >= end - pos)
   1136 		return pos - buf;
   1137 	pos += ret;
   1138 
   1139 #ifdef CONFIG_HS20
   1140 	if (wpa_s->current_bss &&
   1141 	    wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) &&
   1142 	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
   1143 	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
   1144 		ret = os_snprintf(pos, end - pos, "hs20=1\n");
   1145 		if (ret < 0 || ret >= end - pos)
   1146 			return pos - buf;
   1147 		pos += ret;
   1148 	}
   1149 #endif /* CONFIG_HS20 */
   1150 
   1151 	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
   1152 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
   1153 		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
   1154 					  verbose);
   1155 		if (res >= 0)
   1156 			pos += res;
   1157 	}
   1158 
   1159 	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
   1160 	if (res >= 0)
   1161 		pos += res;
   1162 
   1163 #ifdef ANDROID
   1164 	wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
   1165 		     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
   1166 		     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
   1167 		     wpa_s->wpa_state,
   1168 		     MAC2STR(wpa_s->bssid),
   1169 		     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
   1170 		     wpa_ssid_txt(wpa_s->current_ssid->ssid,
   1171 		     wpa_s->current_ssid->ssid_len) : "");
   1172 	if (wpa_s->wpa_state == WPA_COMPLETED) {
   1173 		struct wpa_ssid *ssid = wpa_s->current_ssid;
   1174 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- connection to "
   1175 			MACSTR " completed %s [id=%d id_str=%s]",
   1176 			MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ?
   1177 			"(reauth)" : "(auth)",
   1178 			ssid ? ssid->id : -1,
   1179 			ssid && ssid->id_str ? ssid->id_str : "");
   1180 	}
   1181 #endif /* ANDROID */
   1182 
   1183 	return pos - buf;
   1184 }
   1185 
   1186 
   1187 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
   1188 					   char *cmd)
   1189 {
   1190 	char *pos;
   1191 	int id;
   1192 	struct wpa_ssid *ssid;
   1193 	u8 bssid[ETH_ALEN];
   1194 
   1195 	/* cmd: "<network id> <BSSID>" */
   1196 	pos = os_strchr(cmd, ' ');
   1197 	if (pos == NULL)
   1198 		return -1;
   1199 	*pos++ = '\0';
   1200 	id = atoi(cmd);
   1201 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
   1202 	if (hwaddr_aton(pos, bssid)) {
   1203 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
   1204 		return -1;
   1205 	}
   1206 
   1207 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1208 	if (ssid == NULL) {
   1209 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
   1210 			   "to update", id);
   1211 		return -1;
   1212 	}
   1213 
   1214 	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
   1215 	ssid->bssid_set = !is_zero_ether_addr(bssid);
   1216 
   1217 	return 0;
   1218 }
   1219 
   1220 
   1221 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
   1222 					       char *cmd, char *buf,
   1223 					       size_t buflen)
   1224 {
   1225 	u8 bssid[ETH_ALEN];
   1226 	struct wpa_blacklist *e;
   1227 	char *pos, *end;
   1228 	int ret;
   1229 
   1230 	/* cmd: "BLACKLIST [<BSSID>]" */
   1231 	if (*cmd == '\0') {
   1232 		pos = buf;
   1233 		end = buf + buflen;
   1234 		e = wpa_s->blacklist;
   1235 		while (e) {
   1236 			ret = os_snprintf(pos, end - pos, MACSTR "\n",
   1237 					  MAC2STR(e->bssid));
   1238 			if (ret < 0 || ret >= end - pos)
   1239 				return pos - buf;
   1240 			pos += ret;
   1241 			e = e->next;
   1242 		}
   1243 		return pos - buf;
   1244 	}
   1245 
   1246 	cmd++;
   1247 	if (os_strncmp(cmd, "clear", 5) == 0) {
   1248 		wpa_blacklist_clear(wpa_s);
   1249 		os_memcpy(buf, "OK\n", 3);
   1250 		return 3;
   1251 	}
   1252 
   1253 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
   1254 	if (hwaddr_aton(cmd, bssid)) {
   1255 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
   1256 		return -1;
   1257 	}
   1258 
   1259 	/*
   1260 	 * Add the BSSID twice, so its count will be 2, causing it to be
   1261 	 * skipped when processing scan results.
   1262 	 */
   1263 	ret = wpa_blacklist_add(wpa_s, bssid);
   1264 	if (ret != 0)
   1265 		return -1;
   1266 	ret = wpa_blacklist_add(wpa_s, bssid);
   1267 	if (ret != 0)
   1268 		return -1;
   1269 	os_memcpy(buf, "OK\n", 3);
   1270 	return 3;
   1271 }
   1272 
   1273 
   1274 extern int wpa_debug_level;
   1275 extern int wpa_debug_timestamp;
   1276 
   1277 static const char * debug_level_str(int level)
   1278 {
   1279 	switch (level) {
   1280 	case MSG_EXCESSIVE:
   1281 		return "EXCESSIVE";
   1282 	case MSG_MSGDUMP:
   1283 		return "MSGDUMP";
   1284 	case MSG_DEBUG:
   1285 		return "DEBUG";
   1286 	case MSG_INFO:
   1287 		return "INFO";
   1288 	case MSG_WARNING:
   1289 		return "WARNING";
   1290 	case MSG_ERROR:
   1291 		return "ERROR";
   1292 	default:
   1293 		return "?";
   1294 	}
   1295 }
   1296 
   1297 
   1298 static int str_to_debug_level(const char *s)
   1299 {
   1300 	if (os_strcasecmp(s, "EXCESSIVE") == 0)
   1301 		return MSG_EXCESSIVE;
   1302 	if (os_strcasecmp(s, "MSGDUMP") == 0)
   1303 		return MSG_MSGDUMP;
   1304 	if (os_strcasecmp(s, "DEBUG") == 0)
   1305 		return MSG_DEBUG;
   1306 	if (os_strcasecmp(s, "INFO") == 0)
   1307 		return MSG_INFO;
   1308 	if (os_strcasecmp(s, "WARNING") == 0)
   1309 		return MSG_WARNING;
   1310 	if (os_strcasecmp(s, "ERROR") == 0)
   1311 		return MSG_ERROR;
   1312 	return -1;
   1313 }
   1314 
   1315 
   1316 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
   1317 					       char *cmd, char *buf,
   1318 					       size_t buflen)
   1319 {
   1320 	char *pos, *end, *stamp;
   1321 	int ret;
   1322 
   1323 	if (cmd == NULL) {
   1324 		return -1;
   1325 	}
   1326 
   1327 	/* cmd: "LOG_LEVEL [<level>]" */
   1328 	if (*cmd == '\0') {
   1329 		pos = buf;
   1330 		end = buf + buflen;
   1331 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
   1332 				  "Timestamp: %d\n",
   1333 				  debug_level_str(wpa_debug_level),
   1334 				  wpa_debug_timestamp);
   1335 		if (ret < 0 || ret >= end - pos)
   1336 			ret = 0;
   1337 
   1338 		return ret;
   1339 	}
   1340 
   1341 	while (*cmd == ' ')
   1342 		cmd++;
   1343 
   1344 	stamp = os_strchr(cmd, ' ');
   1345 	if (stamp) {
   1346 		*stamp++ = '\0';
   1347 		while (*stamp == ' ') {
   1348 			stamp++;
   1349 		}
   1350 	}
   1351 
   1352 	if (cmd && os_strlen(cmd)) {
   1353 		int level = str_to_debug_level(cmd);
   1354 		if (level < 0)
   1355 			return -1;
   1356 		wpa_debug_level = level;
   1357 	}
   1358 
   1359 	if (stamp && os_strlen(stamp))
   1360 		wpa_debug_timestamp = atoi(stamp);
   1361 
   1362 	os_memcpy(buf, "OK\n", 3);
   1363 	return 3;
   1364 }
   1365 
   1366 
   1367 static int wpa_supplicant_ctrl_iface_list_networks(
   1368 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
   1369 {
   1370 	char *pos, *end;
   1371 	struct wpa_ssid *ssid;
   1372 	int ret;
   1373 
   1374 	pos = buf;
   1375 	end = buf + buflen;
   1376 	ret = os_snprintf(pos, end - pos,
   1377 			  "network id / ssid / bssid / flags\n");
   1378 	if (ret < 0 || ret >= end - pos)
   1379 		return pos - buf;
   1380 	pos += ret;
   1381 
   1382 	ssid = wpa_s->conf->ssid;
   1383 	while (ssid) {
   1384 		ret = os_snprintf(pos, end - pos, "%d\t%s",
   1385 				  ssid->id,
   1386 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
   1387 		if (ret < 0 || ret >= end - pos)
   1388 			return pos - buf;
   1389 		pos += ret;
   1390 		if (ssid->bssid_set) {
   1391 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
   1392 					  MAC2STR(ssid->bssid));
   1393 		} else {
   1394 			ret = os_snprintf(pos, end - pos, "\tany");
   1395 		}
   1396 		if (ret < 0 || ret >= end - pos)
   1397 			return pos - buf;
   1398 		pos += ret;
   1399 		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
   1400 				  ssid == wpa_s->current_ssid ?
   1401 				  "[CURRENT]" : "",
   1402 				  ssid->disabled ? "[DISABLED]" : "",
   1403 				  ssid->disabled_until.sec ?
   1404 				  "[TEMP-DISABLED]" : "",
   1405 				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
   1406 				  "");
   1407 		if (ret < 0 || ret >= end - pos)
   1408 			return pos - buf;
   1409 		pos += ret;
   1410 		ret = os_snprintf(pos, end - pos, "\n");
   1411 		if (ret < 0 || ret >= end - pos)
   1412 			return pos - buf;
   1413 		pos += ret;
   1414 
   1415 		ssid = ssid->next;
   1416 	}
   1417 
   1418 	return pos - buf;
   1419 }
   1420 
   1421 
   1422 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
   1423 {
   1424 	int first = 1, ret;
   1425 	ret = os_snprintf(pos, end - pos, "-");
   1426 	if (ret < 0 || ret >= end - pos)
   1427 		return pos;
   1428 	pos += ret;
   1429 	if (cipher & WPA_CIPHER_NONE) {
   1430 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
   1431 		if (ret < 0 || ret >= end - pos)
   1432 			return pos;
   1433 		pos += ret;
   1434 		first = 0;
   1435 	}
   1436 	if (cipher & WPA_CIPHER_WEP40) {
   1437 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
   1438 		if (ret < 0 || ret >= end - pos)
   1439 			return pos;
   1440 		pos += ret;
   1441 		first = 0;
   1442 	}
   1443 	if (cipher & WPA_CIPHER_WEP104) {
   1444 		ret = os_snprintf(pos, end - pos, "%sWEP104",
   1445 				  first ? "" : "+");
   1446 		if (ret < 0 || ret >= end - pos)
   1447 			return pos;
   1448 		pos += ret;
   1449 		first = 0;
   1450 	}
   1451 	if (cipher & WPA_CIPHER_TKIP) {
   1452 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
   1453 		if (ret < 0 || ret >= end - pos)
   1454 			return pos;
   1455 		pos += ret;
   1456 		first = 0;
   1457 	}
   1458 	if (cipher & WPA_CIPHER_CCMP) {
   1459 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
   1460 		if (ret < 0 || ret >= end - pos)
   1461 			return pos;
   1462 		pos += ret;
   1463 		first = 0;
   1464 	}
   1465 	if (cipher & WPA_CIPHER_GCMP) {
   1466 		ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : "+");
   1467 		if (ret < 0 || ret >= end - pos)
   1468 			return pos;
   1469 		pos += ret;
   1470 		first = 0;
   1471 	}
   1472 	return pos;
   1473 }
   1474 
   1475 
   1476 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
   1477 				    const u8 *ie, size_t ie_len)
   1478 {
   1479 	struct wpa_ie_data data;
   1480 	int first, ret;
   1481 
   1482 	ret = os_snprintf(pos, end - pos, "[%s-", proto);
   1483 	if (ret < 0 || ret >= end - pos)
   1484 		return pos;
   1485 	pos += ret;
   1486 
   1487 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
   1488 		ret = os_snprintf(pos, end - pos, "?]");
   1489 		if (ret < 0 || ret >= end - pos)
   1490 			return pos;
   1491 		pos += ret;
   1492 		return pos;
   1493 	}
   1494 
   1495 	first = 1;
   1496 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
   1497 		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
   1498 		if (ret < 0 || ret >= end - pos)
   1499 			return pos;
   1500 		pos += ret;
   1501 		first = 0;
   1502 	}
   1503 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
   1504 		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
   1505 		if (ret < 0 || ret >= end - pos)
   1506 			return pos;
   1507 		pos += ret;
   1508 		first = 0;
   1509 	}
   1510 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
   1511 		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
   1512 		if (ret < 0 || ret >= end - pos)
   1513 			return pos;
   1514 		pos += ret;
   1515 		first = 0;
   1516 	}
   1517 #ifdef CONFIG_IEEE80211R
   1518 	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
   1519 		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
   1520 				  first ? "" : "+");
   1521 		if (ret < 0 || ret >= end - pos)
   1522 			return pos;
   1523 		pos += ret;
   1524 		first = 0;
   1525 	}
   1526 	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
   1527 		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
   1528 				  first ? "" : "+");
   1529 		if (ret < 0 || ret >= end - pos)
   1530 			return pos;
   1531 		pos += ret;
   1532 		first = 0;
   1533 	}
   1534 #endif /* CONFIG_IEEE80211R */
   1535 #ifdef CONFIG_IEEE80211W
   1536 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
   1537 		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
   1538 				  first ? "" : "+");
   1539 		if (ret < 0 || ret >= end - pos)
   1540 			return pos;
   1541 		pos += ret;
   1542 		first = 0;
   1543 	}
   1544 	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
   1545 		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
   1546 				  first ? "" : "+");
   1547 		if (ret < 0 || ret >= end - pos)
   1548 			return pos;
   1549 		pos += ret;
   1550 		first = 0;
   1551 	}
   1552 #endif /* CONFIG_IEEE80211W */
   1553 
   1554 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
   1555 
   1556 	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
   1557 		ret = os_snprintf(pos, end - pos, "-preauth");
   1558 		if (ret < 0 || ret >= end - pos)
   1559 			return pos;
   1560 		pos += ret;
   1561 	}
   1562 
   1563 	ret = os_snprintf(pos, end - pos, "]");
   1564 	if (ret < 0 || ret >= end - pos)
   1565 		return pos;
   1566 	pos += ret;
   1567 
   1568 	return pos;
   1569 }
   1570 
   1571 
   1572 #ifdef CONFIG_WPS
   1573 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
   1574 					    char *pos, char *end,
   1575 					    struct wpabuf *wps_ie)
   1576 {
   1577 	int ret;
   1578 	const char *txt;
   1579 
   1580 	if (wps_ie == NULL)
   1581 		return pos;
   1582 	if (wps_is_selected_pbc_registrar(wps_ie))
   1583 		txt = "[WPS-PBC]";
   1584 #ifdef CONFIG_WPS2
   1585 	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
   1586 		txt = "[WPS-AUTH]";
   1587 #endif /* CONFIG_WPS2 */
   1588 	else if (wps_is_selected_pin_registrar(wps_ie))
   1589 		txt = "[WPS-PIN]";
   1590 	else
   1591 		txt = "[WPS]";
   1592 
   1593 	ret = os_snprintf(pos, end - pos, "%s", txt);
   1594 	if (ret >= 0 && ret < end - pos)
   1595 		pos += ret;
   1596 	wpabuf_free(wps_ie);
   1597 	return pos;
   1598 }
   1599 #endif /* CONFIG_WPS */
   1600 
   1601 
   1602 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
   1603 					char *pos, char *end,
   1604 					const struct wpa_bss *bss)
   1605 {
   1606 #ifdef CONFIG_WPS
   1607 	struct wpabuf *wps_ie;
   1608 	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
   1609 	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
   1610 #else /* CONFIG_WPS */
   1611 	return pos;
   1612 #endif /* CONFIG_WPS */
   1613 }
   1614 
   1615 
   1616 /* Format one result on one text line into a buffer. */
   1617 static int wpa_supplicant_ctrl_iface_scan_result(
   1618 	struct wpa_supplicant *wpa_s,
   1619 	const struct wpa_bss *bss, char *buf, size_t buflen)
   1620 {
   1621 	char *pos, *end;
   1622 	int ret;
   1623 	const u8 *ie, *ie2, *p2p;
   1624 
   1625 	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
   1626 	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
   1627 	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
   1628 	    0)
   1629 		return 0; /* Do not show P2P listen discovery results here */
   1630 
   1631 	pos = buf;
   1632 	end = buf + buflen;
   1633 
   1634 	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
   1635 			  MAC2STR(bss->bssid), bss->freq, bss->level);
   1636 	if (ret < 0 || ret >= end - pos)
   1637 		return -1;
   1638 	pos += ret;
   1639 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
   1640 	if (ie)
   1641 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
   1642 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
   1643 	if (ie2)
   1644 		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
   1645 	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
   1646 	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
   1647 		ret = os_snprintf(pos, end - pos, "[WEP]");
   1648 		if (ret < 0 || ret >= end - pos)
   1649 			return -1;
   1650 		pos += ret;
   1651 	}
   1652 	if (bss->caps & IEEE80211_CAP_IBSS) {
   1653 		ret = os_snprintf(pos, end - pos, "[IBSS]");
   1654 		if (ret < 0 || ret >= end - pos)
   1655 			return -1;
   1656 		pos += ret;
   1657 	}
   1658 	if (bss->caps & IEEE80211_CAP_ESS) {
   1659 		ret = os_snprintf(pos, end - pos, "[ESS]");
   1660 		if (ret < 0 || ret >= end - pos)
   1661 			return -1;
   1662 		pos += ret;
   1663 	}
   1664 	if (p2p) {
   1665 		ret = os_snprintf(pos, end - pos, "[P2P]");
   1666 		if (ret < 0 || ret >= end - pos)
   1667 			return -1;
   1668 		pos += ret;
   1669 	}
   1670 #ifdef CONFIG_HS20
   1671 	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
   1672 		ret = os_snprintf(pos, end - pos, "[HS20]");
   1673 		if (ret < 0 || ret >= end - pos)
   1674 			return -1;
   1675 		pos += ret;
   1676 	}
   1677 #endif /* CONFIG_HS20 */
   1678 
   1679 	ret = os_snprintf(pos, end - pos, "\t%s",
   1680 			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
   1681 	if (ret < 0 || ret >= end - pos)
   1682 		return -1;
   1683 	pos += ret;
   1684 
   1685 	ret = os_snprintf(pos, end - pos, "\n");
   1686 	if (ret < 0 || ret >= end - pos)
   1687 		return -1;
   1688 	pos += ret;
   1689 
   1690 	return pos - buf;
   1691 }
   1692 
   1693 
   1694 static int wpa_supplicant_ctrl_iface_scan_results(
   1695 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
   1696 {
   1697 	char *pos, *end;
   1698 	struct wpa_bss *bss;
   1699 	int ret;
   1700 
   1701 	pos = buf;
   1702 	end = buf + buflen;
   1703 	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
   1704 			  "flags / ssid\n");
   1705 	if (ret < 0 || ret >= end - pos)
   1706 		return pos - buf;
   1707 	pos += ret;
   1708 
   1709 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
   1710 		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
   1711 							    end - pos);
   1712 		if (ret < 0 || ret >= end - pos)
   1713 			return pos - buf;
   1714 		pos += ret;
   1715 	}
   1716 
   1717 	return pos - buf;
   1718 }
   1719 
   1720 
   1721 static int wpa_supplicant_ctrl_iface_select_network(
   1722 	struct wpa_supplicant *wpa_s, char *cmd)
   1723 {
   1724 	int id;
   1725 	struct wpa_ssid *ssid;
   1726 
   1727 	/* cmd: "<network id>" or "any" */
   1728 	if (os_strcmp(cmd, "any") == 0) {
   1729 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
   1730 		ssid = NULL;
   1731 	} else {
   1732 		id = atoi(cmd);
   1733 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
   1734 
   1735 		ssid = wpa_config_get_network(wpa_s->conf, id);
   1736 		if (ssid == NULL) {
   1737 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   1738 				   "network id=%d", id);
   1739 			return -1;
   1740 		}
   1741 		if (ssid->disabled == 2) {
   1742 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
   1743 				   "SELECT_NETWORK with persistent P2P group");
   1744 			return -1;
   1745 		}
   1746 	}
   1747 
   1748 	wpa_supplicant_select_network(wpa_s, ssid);
   1749 
   1750 	return 0;
   1751 }
   1752 
   1753 
   1754 static int wpa_supplicant_ctrl_iface_enable_network(
   1755 	struct wpa_supplicant *wpa_s, char *cmd)
   1756 {
   1757 	int id;
   1758 	struct wpa_ssid *ssid;
   1759 
   1760 	/* cmd: "<network id>" or "all" */
   1761 	if (os_strcmp(cmd, "all") == 0) {
   1762 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
   1763 		ssid = NULL;
   1764 	} else {
   1765 		id = atoi(cmd);
   1766 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
   1767 
   1768 		ssid = wpa_config_get_network(wpa_s->conf, id);
   1769 		if (ssid == NULL) {
   1770 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   1771 				   "network id=%d", id);
   1772 			return -1;
   1773 		}
   1774 		if (ssid->disabled == 2) {
   1775 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
   1776 				   "ENABLE_NETWORK with persistent P2P group");
   1777 			return -1;
   1778 		}
   1779 
   1780 		if (os_strstr(cmd, " no-connect")) {
   1781 			ssid->disabled = 0;
   1782 			return 0;
   1783 		}
   1784 	}
   1785 	wpa_supplicant_enable_network(wpa_s, ssid);
   1786 
   1787 	return 0;
   1788 }
   1789 
   1790 
   1791 static int wpa_supplicant_ctrl_iface_disable_network(
   1792 	struct wpa_supplicant *wpa_s, char *cmd)
   1793 {
   1794 	int id;
   1795 	struct wpa_ssid *ssid;
   1796 
   1797 	/* cmd: "<network id>" or "all" */
   1798 	if (os_strcmp(cmd, "all") == 0) {
   1799 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
   1800 		ssid = NULL;
   1801 	} else {
   1802 		id = atoi(cmd);
   1803 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
   1804 
   1805 		ssid = wpa_config_get_network(wpa_s->conf, id);
   1806 		if (ssid == NULL) {
   1807 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   1808 				   "network id=%d", id);
   1809 			return -1;
   1810 		}
   1811 		if (ssid->disabled == 2) {
   1812 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
   1813 				   "DISABLE_NETWORK with persistent P2P "
   1814 				   "group");
   1815 			return -1;
   1816 		}
   1817 	}
   1818 	wpa_supplicant_disable_network(wpa_s, ssid);
   1819 
   1820 	return 0;
   1821 }
   1822 
   1823 
   1824 static int wpa_supplicant_ctrl_iface_add_network(
   1825 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
   1826 {
   1827 	struct wpa_ssid *ssid;
   1828 	int ret;
   1829 
   1830 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
   1831 
   1832 	ssid = wpa_config_add_network(wpa_s->conf);
   1833 	if (ssid == NULL)
   1834 		return -1;
   1835 
   1836 	wpas_notify_network_added(wpa_s, ssid);
   1837 
   1838 	ssid->disabled = 1;
   1839 	wpa_config_set_network_defaults(ssid);
   1840 
   1841 	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
   1842 	if (ret < 0 || (size_t) ret >= buflen)
   1843 		return -1;
   1844 	return ret;
   1845 }
   1846 
   1847 
   1848 static int wpa_supplicant_ctrl_iface_remove_network(
   1849 	struct wpa_supplicant *wpa_s, char *cmd)
   1850 {
   1851 	int id;
   1852 	struct wpa_ssid *ssid;
   1853 
   1854 	/* cmd: "<network id>" or "all" */
   1855 	if (os_strcmp(cmd, "all") == 0) {
   1856 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
   1857 		ssid = wpa_s->conf->ssid;
   1858 		while (ssid) {
   1859 			struct wpa_ssid *remove_ssid = ssid;
   1860 			id = ssid->id;
   1861 			ssid = ssid->next;
   1862 			wpas_notify_network_removed(wpa_s, remove_ssid);
   1863 			wpa_config_remove_network(wpa_s->conf, id);
   1864 		}
   1865 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
   1866 		if (wpa_s->current_ssid) {
   1867 #ifdef CONFIG_SME
   1868 			wpa_s->sme.prev_bssid_set = 0;
   1869 #endif /* CONFIG_SME */
   1870 			wpa_sm_set_config(wpa_s->wpa, NULL);
   1871 			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
   1872 			wpa_supplicant_disassociate(wpa_s,
   1873 				                    WLAN_REASON_DEAUTH_LEAVING);
   1874 		}
   1875 		return 0;
   1876 	}
   1877 
   1878 	id = atoi(cmd);
   1879 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
   1880 
   1881 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1882 	if (ssid)
   1883 		wpas_notify_network_removed(wpa_s, ssid);
   1884 	if (ssid == NULL) {
   1885 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   1886 			   "id=%d", id);
   1887 		return -1;
   1888 	}
   1889 
   1890 	if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
   1891 #ifdef CONFIG_SME
   1892 		wpa_s->sme.prev_bssid_set = 0;
   1893 #endif /* CONFIG_SME */
   1894 		/*
   1895 		 * Invalidate the EAP session cache if the current or
   1896 		 * previously used network is removed.
   1897 		 */
   1898 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
   1899 	}
   1900 
   1901 	if (ssid == wpa_s->current_ssid) {
   1902 		wpa_sm_set_config(wpa_s->wpa, NULL);
   1903 		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
   1904 
   1905 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
   1906 	}
   1907 
   1908 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
   1909 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
   1910 			   "network id=%d", id);
   1911 		return -1;
   1912 	}
   1913 
   1914 	return 0;
   1915 }
   1916 
   1917 
   1918 static int wpa_supplicant_ctrl_iface_set_network(
   1919 	struct wpa_supplicant *wpa_s, char *cmd)
   1920 {
   1921 	int id;
   1922 	struct wpa_ssid *ssid;
   1923 	char *name, *value;
   1924 
   1925 	/* cmd: "<network id> <variable name> <value>" */
   1926 	name = os_strchr(cmd, ' ');
   1927 	if (name == NULL)
   1928 		return -1;
   1929 	*name++ = '\0';
   1930 
   1931 	value = os_strchr(name, ' ');
   1932 	if (value == NULL)
   1933 		return -1;
   1934 	*value++ = '\0';
   1935 
   1936 	id = atoi(cmd);
   1937 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
   1938 		   id, name);
   1939 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
   1940 			      (u8 *) value, os_strlen(value));
   1941 
   1942 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1943 	if (ssid == NULL) {
   1944 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   1945 			   "id=%d", id);
   1946 		return -1;
   1947 	}
   1948 
   1949 	if (wpa_config_set(ssid, name, value, 0) < 0) {
   1950 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
   1951 			   "variable '%s'", name);
   1952 		return -1;
   1953 	}
   1954 
   1955 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
   1956 
   1957 	if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
   1958 		/*
   1959 		 * Invalidate the EAP session cache if anything in the current
   1960 		 * or previously used configuration changes.
   1961 		 */
   1962 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
   1963 	}
   1964 
   1965 	if ((os_strcmp(name, "psk") == 0 &&
   1966 	     value[0] == '"' && ssid->ssid_len) ||
   1967 	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
   1968 		wpa_config_update_psk(ssid);
   1969 	else if (os_strcmp(name, "priority") == 0)
   1970 		wpa_config_update_prio_list(wpa_s->conf);
   1971 
   1972 	return 0;
   1973 }
   1974 
   1975 
   1976 static int wpa_supplicant_ctrl_iface_get_network(
   1977 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
   1978 {
   1979 	int id;
   1980 	size_t res;
   1981 	struct wpa_ssid *ssid;
   1982 	char *name, *value;
   1983 
   1984 	/* cmd: "<network id> <variable name>" */
   1985 	name = os_strchr(cmd, ' ');
   1986 	if (name == NULL || buflen == 0)
   1987 		return -1;
   1988 	*name++ = '\0';
   1989 
   1990 	id = atoi(cmd);
   1991 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
   1992 		   id, name);
   1993 
   1994 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1995 	if (ssid == NULL) {
   1996 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   1997 			   "id=%d", id);
   1998 		return -1;
   1999 	}
   2000 
   2001 	value = wpa_config_get_no_key(ssid, name);
   2002 	if (value == NULL) {
   2003 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
   2004 			   "variable '%s'", name);
   2005 		return -1;
   2006 	}
   2007 
   2008 	res = os_strlcpy(buf, value, buflen);
   2009 	if (res >= buflen) {
   2010 		os_free(value);
   2011 		return -1;
   2012 	}
   2013 
   2014 	os_free(value);
   2015 
   2016 	return res;
   2017 }
   2018 
   2019 
   2020 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
   2021 						char *buf, size_t buflen)
   2022 {
   2023 	char *pos, *end;
   2024 	struct wpa_cred *cred;
   2025 	int ret;
   2026 
   2027 	pos = buf;
   2028 	end = buf + buflen;
   2029 	ret = os_snprintf(pos, end - pos,
   2030 			  "cred id / realm / username / domain / imsi\n");
   2031 	if (ret < 0 || ret >= end - pos)
   2032 		return pos - buf;
   2033 	pos += ret;
   2034 
   2035 	cred = wpa_s->conf->cred;
   2036 	while (cred) {
   2037 		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
   2038 				  cred->id, cred->realm ? cred->realm : "",
   2039 				  cred->username ? cred->username : "",
   2040 				  cred->domain ? cred->domain : "",
   2041 				  cred->imsi ? cred->imsi : "");
   2042 		if (ret < 0 || ret >= end - pos)
   2043 			return pos - buf;
   2044 		pos += ret;
   2045 
   2046 		cred = cred->next;
   2047 	}
   2048 
   2049 	return pos - buf;
   2050 }
   2051 
   2052 
   2053 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
   2054 					      char *buf, size_t buflen)
   2055 {
   2056 	struct wpa_cred *cred;
   2057 	int ret;
   2058 
   2059 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
   2060 
   2061 	cred = wpa_config_add_cred(wpa_s->conf);
   2062 	if (cred == NULL)
   2063 		return -1;
   2064 
   2065 	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
   2066 	if (ret < 0 || (size_t) ret >= buflen)
   2067 		return -1;
   2068 	return ret;
   2069 }
   2070 
   2071 
   2072 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
   2073 						 char *cmd)
   2074 {
   2075 	int id;
   2076 	struct wpa_cred *cred;
   2077 
   2078 	/* cmd: "<cred id>" or "all" */
   2079 	if (os_strcmp(cmd, "all") == 0) {
   2080 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
   2081 		cred = wpa_s->conf->cred;
   2082 		while (cred) {
   2083 			id = cred->id;
   2084 			cred = cred->next;
   2085 			wpa_config_remove_cred(wpa_s->conf, id);
   2086 		}
   2087 		return 0;
   2088 	}
   2089 
   2090 	id = atoi(cmd);
   2091 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
   2092 
   2093 	cred = wpa_config_get_cred(wpa_s->conf, id);
   2094 	if (cred == NULL ||
   2095 	    wpa_config_remove_cred(wpa_s->conf, id) < 0) {
   2096 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
   2097 			   id);
   2098 		return -1;
   2099 	}
   2100 
   2101 	return 0;
   2102 }
   2103 
   2104 
   2105 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
   2106 					      char *cmd)
   2107 {
   2108 	int id;
   2109 	struct wpa_cred *cred;
   2110 	char *name, *value;
   2111 
   2112 	/* cmd: "<cred id> <variable name> <value>" */
   2113 	name = os_strchr(cmd, ' ');
   2114 	if (name == NULL)
   2115 		return -1;
   2116 	*name++ = '\0';
   2117 
   2118 	value = os_strchr(name, ' ');
   2119 	if (value == NULL)
   2120 		return -1;
   2121 	*value++ = '\0';
   2122 
   2123 	id = atoi(cmd);
   2124 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
   2125 		   id, name);
   2126 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
   2127 			      (u8 *) value, os_strlen(value));
   2128 
   2129 	cred = wpa_config_get_cred(wpa_s->conf, id);
   2130 	if (cred == NULL) {
   2131 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
   2132 			   id);
   2133 		return -1;
   2134 	}
   2135 
   2136 	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
   2137 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
   2138 			   "variable '%s'", name);
   2139 		return -1;
   2140 	}
   2141 
   2142 	return 0;
   2143 }
   2144 
   2145 
   2146 #ifndef CONFIG_NO_CONFIG_WRITE
   2147 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
   2148 {
   2149 	int ret;
   2150 
   2151 	if (!wpa_s->conf->update_config) {
   2152 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
   2153 			   "to update configuration (update_config=0)");
   2154 		return -1;
   2155 	}
   2156 
   2157 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
   2158 	if (ret) {
   2159 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
   2160 			   "update configuration");
   2161 	} else {
   2162 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
   2163 			   " updated");
   2164 	}
   2165 
   2166 	return ret;
   2167 }
   2168 #endif /* CONFIG_NO_CONFIG_WRITE */
   2169 
   2170 
   2171 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
   2172 					      struct wpa_driver_capa *capa,
   2173 					      char *buf, size_t buflen)
   2174 {
   2175 	int ret, first = 1;
   2176 	char *pos, *end;
   2177 	size_t len;
   2178 
   2179 	pos = buf;
   2180 	end = pos + buflen;
   2181 
   2182 	if (res < 0) {
   2183 		if (strict)
   2184 			return 0;
   2185 		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
   2186 		if (len >= buflen)
   2187 			return -1;
   2188 		return len;
   2189 	}
   2190 
   2191 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
   2192 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
   2193 		if (ret < 0 || ret >= end - pos)
   2194 			return pos - buf;
   2195 		pos += ret;
   2196 		first = 0;
   2197 	}
   2198 
   2199 	if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
   2200 		ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
   2201 		if (ret < 0 || ret >= end - pos)
   2202 			return pos - buf;
   2203 		pos += ret;
   2204 		first = 0;
   2205 	}
   2206 
   2207 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
   2208 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
   2209 		if (ret < 0 || ret >= end - pos)
   2210 			return pos - buf;
   2211 		pos += ret;
   2212 		first = 0;
   2213 	}
   2214 
   2215 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
   2216 		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
   2217 		if (ret < 0 || ret >= end - pos)
   2218 			return pos - buf;
   2219 		pos += ret;
   2220 		first = 0;
   2221 	}
   2222 
   2223 	return pos - buf;
   2224 }
   2225 
   2226 
   2227 static int ctrl_iface_get_capability_group(int res, char *strict,
   2228 					   struct wpa_driver_capa *capa,
   2229 					   char *buf, size_t buflen)
   2230 {
   2231 	int ret, first = 1;
   2232 	char *pos, *end;
   2233 	size_t len;
   2234 
   2235 	pos = buf;
   2236 	end = pos + buflen;
   2237 
   2238 	if (res < 0) {
   2239 		if (strict)
   2240 			return 0;
   2241 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
   2242 		if (len >= buflen)
   2243 			return -1;
   2244 		return len;
   2245 	}
   2246 
   2247 	if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
   2248 		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
   2249 		if (ret < 0 || ret >= end - pos)
   2250 			return pos - buf;
   2251 		pos += ret;
   2252 		first = 0;
   2253 	}
   2254 
   2255 	if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
   2256 		ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
   2257 		if (ret < 0 || ret >= end - pos)
   2258 			return pos - buf;
   2259 		pos += ret;
   2260 		first = 0;
   2261 	}
   2262 
   2263 	if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
   2264 		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
   2265 		if (ret < 0 || ret >= end - pos)
   2266 			return pos - buf;
   2267 		pos += ret;
   2268 		first = 0;
   2269 	}
   2270 
   2271 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
   2272 		ret = os_snprintf(pos, end - pos, "%sWEP104",
   2273 				  first ? "" : " ");
   2274 		if (ret < 0 || ret >= end - pos)
   2275 			return pos - buf;
   2276 		pos += ret;
   2277 		first = 0;
   2278 	}
   2279 
   2280 	if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
   2281 		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
   2282 		if (ret < 0 || ret >= end - pos)
   2283 			return pos - buf;
   2284 		pos += ret;
   2285 		first = 0;
   2286 	}
   2287 
   2288 	return pos - buf;
   2289 }
   2290 
   2291 
   2292 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
   2293 					      struct wpa_driver_capa *capa,
   2294 					      char *buf, size_t buflen)
   2295 {
   2296 	int ret;
   2297 	char *pos, *end;
   2298 	size_t len;
   2299 
   2300 	pos = buf;
   2301 	end = pos + buflen;
   2302 
   2303 	if (res < 0) {
   2304 		if (strict)
   2305 			return 0;
   2306 		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
   2307 				 "NONE", buflen);
   2308 		if (len >= buflen)
   2309 			return -1;
   2310 		return len;
   2311 	}
   2312 
   2313 	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
   2314 	if (ret < 0 || ret >= end - pos)
   2315 		return pos - buf;
   2316 	pos += ret;
   2317 
   2318 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   2319 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
   2320 		ret = os_snprintf(pos, end - pos, " WPA-EAP");
   2321 		if (ret < 0 || ret >= end - pos)
   2322 			return pos - buf;
   2323 		pos += ret;
   2324 	}
   2325 
   2326 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
   2327 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   2328 		ret = os_snprintf(pos, end - pos, " WPA-PSK");
   2329 		if (ret < 0 || ret >= end - pos)
   2330 			return pos - buf;
   2331 		pos += ret;
   2332 	}
   2333 
   2334 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
   2335 		ret = os_snprintf(pos, end - pos, " WPA-NONE");
   2336 		if (ret < 0 || ret >= end - pos)
   2337 			return pos - buf;
   2338 		pos += ret;
   2339 	}
   2340 
   2341 	return pos - buf;
   2342 }
   2343 
   2344 
   2345 static int ctrl_iface_get_capability_proto(int res, char *strict,
   2346 					   struct wpa_driver_capa *capa,
   2347 					   char *buf, size_t buflen)
   2348 {
   2349 	int ret, first = 1;
   2350 	char *pos, *end;
   2351 	size_t len;
   2352 
   2353 	pos = buf;
   2354 	end = pos + buflen;
   2355 
   2356 	if (res < 0) {
   2357 		if (strict)
   2358 			return 0;
   2359 		len = os_strlcpy(buf, "RSN WPA", buflen);
   2360 		if (len >= buflen)
   2361 			return -1;
   2362 		return len;
   2363 	}
   2364 
   2365 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
   2366 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   2367 		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
   2368 		if (ret < 0 || ret >= end - pos)
   2369 			return pos - buf;
   2370 		pos += ret;
   2371 		first = 0;
   2372 	}
   2373 
   2374 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   2375 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
   2376 		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
   2377 		if (ret < 0 || ret >= end - pos)
   2378 			return pos - buf;
   2379 		pos += ret;
   2380 		first = 0;
   2381 	}
   2382 
   2383 	return pos - buf;
   2384 }
   2385 
   2386 
   2387 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
   2388 					      struct wpa_driver_capa *capa,
   2389 					      char *buf, size_t buflen)
   2390 {
   2391 	int ret, first = 1;
   2392 	char *pos, *end;
   2393 	size_t len;
   2394 
   2395 	pos = buf;
   2396 	end = pos + buflen;
   2397 
   2398 	if (res < 0) {
   2399 		if (strict)
   2400 			return 0;
   2401 		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
   2402 		if (len >= buflen)
   2403 			return -1;
   2404 		return len;
   2405 	}
   2406 
   2407 	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
   2408 		ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
   2409 		if (ret < 0 || ret >= end - pos)
   2410 			return pos - buf;
   2411 		pos += ret;
   2412 		first = 0;
   2413 	}
   2414 
   2415 	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
   2416 		ret = os_snprintf(pos, end - pos, "%sSHARED",
   2417 				  first ? "" : " ");
   2418 		if (ret < 0 || ret >= end - pos)
   2419 			return pos - buf;
   2420 		pos += ret;
   2421 		first = 0;
   2422 	}
   2423 
   2424 	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
   2425 		ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
   2426 		if (ret < 0 || ret >= end - pos)
   2427 			return pos - buf;
   2428 		pos += ret;
   2429 		first = 0;
   2430 	}
   2431 
   2432 	return pos - buf;
   2433 }
   2434 
   2435 
   2436 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
   2437 					      char *buf, size_t buflen)
   2438 {
   2439 	struct hostapd_channel_data *chnl;
   2440 	int ret, i, j;
   2441 	char *pos, *end, *hmode;
   2442 
   2443 	pos = buf;
   2444 	end = pos + buflen;
   2445 
   2446 	for (j = 0; j < wpa_s->hw.num_modes; j++) {
   2447 		switch (wpa_s->hw.modes[j].mode) {
   2448 		case HOSTAPD_MODE_IEEE80211B:
   2449 			hmode = "B";
   2450 			break;
   2451 		case HOSTAPD_MODE_IEEE80211G:
   2452 			hmode = "G";
   2453 			break;
   2454 		case HOSTAPD_MODE_IEEE80211A:
   2455 			hmode = "A";
   2456 			break;
   2457 		default:
   2458 			continue;
   2459 		}
   2460 		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
   2461 		if (ret < 0 || ret >= end - pos)
   2462 			return pos - buf;
   2463 		pos += ret;
   2464 		chnl = wpa_s->hw.modes[j].channels;
   2465 		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
   2466 			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
   2467 				continue;
   2468 			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
   2469 			if (ret < 0 || ret >= end - pos)
   2470 				return pos - buf;
   2471 			pos += ret;
   2472 		}
   2473 		ret = os_snprintf(pos, end - pos, "\n");
   2474 		if (ret < 0 || ret >= end - pos)
   2475 			return pos - buf;
   2476 		pos += ret;
   2477 	}
   2478 
   2479 	return pos - buf;
   2480 }
   2481 
   2482 
   2483 static int wpa_supplicant_ctrl_iface_get_capability(
   2484 	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
   2485 	size_t buflen)
   2486 {
   2487 	struct wpa_driver_capa capa;
   2488 	int res;
   2489 	char *strict;
   2490 	char field[30];
   2491 	size_t len;
   2492 
   2493 	/* Determine whether or not strict checking was requested */
   2494 	len = os_strlcpy(field, _field, sizeof(field));
   2495 	if (len >= sizeof(field))
   2496 		return -1;
   2497 	strict = os_strchr(field, ' ');
   2498 	if (strict != NULL) {
   2499 		*strict++ = '\0';
   2500 		if (os_strcmp(strict, "strict") != 0)
   2501 			return -1;
   2502 	}
   2503 
   2504 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
   2505 		field, strict ? strict : "");
   2506 
   2507 	if (os_strcmp(field, "eap") == 0) {
   2508 		return eap_get_names(buf, buflen);
   2509 	}
   2510 
   2511 	res = wpa_drv_get_capa(wpa_s, &capa);
   2512 
   2513 	if (os_strcmp(field, "pairwise") == 0)
   2514 		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
   2515 							  buf, buflen);
   2516 
   2517 	if (os_strcmp(field, "group") == 0)
   2518 		return ctrl_iface_get_capability_group(res, strict, &capa,
   2519 						       buf, buflen);
   2520 
   2521 	if (os_strcmp(field, "key_mgmt") == 0)
   2522 		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
   2523 							  buf, buflen);
   2524 
   2525 	if (os_strcmp(field, "proto") == 0)
   2526 		return ctrl_iface_get_capability_proto(res, strict, &capa,
   2527 						       buf, buflen);
   2528 
   2529 	if (os_strcmp(field, "auth_alg") == 0)
   2530 		return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
   2531 							  buf, buflen);
   2532 
   2533 	if (os_strcmp(field, "channels") == 0)
   2534 		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
   2535 
   2536 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
   2537 		   field);
   2538 
   2539 	return -1;
   2540 }
   2541 
   2542 
   2543 #ifdef CONFIG_INTERWORKING
   2544 static char * anqp_add_hex(char *pos, char *end, const char *title,
   2545 			   struct wpabuf *data)
   2546 {
   2547 	char *start = pos;
   2548 	size_t i;
   2549 	int ret;
   2550 	const u8 *d;
   2551 
   2552 	if (data == NULL)
   2553 		return start;
   2554 
   2555 	ret = os_snprintf(pos, end - pos, "%s=", title);
   2556 	if (ret < 0 || ret >= end - pos)
   2557 		return start;
   2558 	pos += ret;
   2559 
   2560 	d = wpabuf_head_u8(data);
   2561 	for (i = 0; i < wpabuf_len(data); i++) {
   2562 		ret = os_snprintf(pos, end - pos, "%02x", *d++);
   2563 		if (ret < 0 || ret >= end - pos)
   2564 			return start;
   2565 		pos += ret;
   2566 	}
   2567 
   2568 	ret = os_snprintf(pos, end - pos, "\n");
   2569 	if (ret < 0 || ret >= end - pos)
   2570 		return start;
   2571 	pos += ret;
   2572 
   2573 	return pos;
   2574 }
   2575 #endif /* CONFIG_INTERWORKING */
   2576 
   2577 
   2578 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
   2579 			  unsigned long mask, char *buf, size_t buflen)
   2580 {
   2581 	size_t i;
   2582 	int ret;
   2583 	char *pos, *end;
   2584 	const u8 *ie, *ie2;
   2585 
   2586 	pos = buf;
   2587 	end = buf + buflen;
   2588 
   2589 	if (mask & WPA_BSS_MASK_ID) {
   2590 		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
   2591 		if (ret < 0 || ret >= end - pos)
   2592 			return 0;
   2593 		pos += ret;
   2594 	}
   2595 
   2596 	if (mask & WPA_BSS_MASK_BSSID) {
   2597 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
   2598 				  MAC2STR(bss->bssid));
   2599 		if (ret < 0 || ret >= end - pos)
   2600 			return 0;
   2601 		pos += ret;
   2602 	}
   2603 
   2604 	if (mask & WPA_BSS_MASK_FREQ) {
   2605 		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
   2606 		if (ret < 0 || ret >= end - pos)
   2607 			return 0;
   2608 		pos += ret;
   2609 	}
   2610 
   2611 	if (mask & WPA_BSS_MASK_BEACON_INT) {
   2612 		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
   2613 				  bss->beacon_int);
   2614 		if (ret < 0 || ret >= end - pos)
   2615 			return 0;
   2616 		pos += ret;
   2617 	}
   2618 
   2619 	if (mask & WPA_BSS_MASK_CAPABILITIES) {
   2620 		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
   2621 				  bss->caps);
   2622 		if (ret < 0 || ret >= end - pos)
   2623 			return 0;
   2624 		pos += ret;
   2625 	}
   2626 
   2627 	if (mask & WPA_BSS_MASK_QUAL) {
   2628 		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
   2629 		if (ret < 0 || ret >= end - pos)
   2630 			return 0;
   2631 		pos += ret;
   2632 	}
   2633 
   2634 	if (mask & WPA_BSS_MASK_NOISE) {
   2635 		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
   2636 		if (ret < 0 || ret >= end - pos)
   2637 			return 0;
   2638 		pos += ret;
   2639 	}
   2640 
   2641 	if (mask & WPA_BSS_MASK_LEVEL) {
   2642 		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
   2643 		if (ret < 0 || ret >= end - pos)
   2644 			return 0;
   2645 		pos += ret;
   2646 	}
   2647 
   2648 	if (mask & WPA_BSS_MASK_TSF) {
   2649 		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
   2650 				  (unsigned long long) bss->tsf);
   2651 		if (ret < 0 || ret >= end - pos)
   2652 			return 0;
   2653 		pos += ret;
   2654 	}
   2655 
   2656 	if (mask & WPA_BSS_MASK_AGE) {
   2657 		struct os_time now;
   2658 
   2659 		os_get_time(&now);
   2660 		ret = os_snprintf(pos, end - pos, "age=%d\n",
   2661 				  (int) (now.sec - bss->last_update.sec));
   2662 		if (ret < 0 || ret >= end - pos)
   2663 			return 0;
   2664 		pos += ret;
   2665 	}
   2666 
   2667 	if (mask & WPA_BSS_MASK_IE) {
   2668 		ret = os_snprintf(pos, end - pos, "ie=");
   2669 		if (ret < 0 || ret >= end - pos)
   2670 			return 0;
   2671 		pos += ret;
   2672 
   2673 		ie = (const u8 *) (bss + 1);
   2674 		for (i = 0; i < bss->ie_len; i++) {
   2675 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
   2676 			if (ret < 0 || ret >= end - pos)
   2677 				return 0;
   2678 			pos += ret;
   2679 		}
   2680 
   2681 		ret = os_snprintf(pos, end - pos, "\n");
   2682 		if (ret < 0 || ret >= end - pos)
   2683 			return 0;
   2684 		pos += ret;
   2685 	}
   2686 
   2687 	if (mask & WPA_BSS_MASK_FLAGS) {
   2688 		ret = os_snprintf(pos, end - pos, "flags=");
   2689 		if (ret < 0 || ret >= end - pos)
   2690 			return 0;
   2691 		pos += ret;
   2692 
   2693 		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
   2694 		if (ie)
   2695 			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
   2696 						    2 + ie[1]);
   2697 		ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
   2698 		if (ie2)
   2699 			pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
   2700 						    2 + ie2[1]);
   2701 		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
   2702 		if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
   2703 			ret = os_snprintf(pos, end - pos, "[WEP]");
   2704 			if (ret < 0 || ret >= end - pos)
   2705 				return 0;
   2706 			pos += ret;
   2707 		}
   2708 		if (bss->caps & IEEE80211_CAP_IBSS) {
   2709 			ret = os_snprintf(pos, end - pos, "[IBSS]");
   2710 			if (ret < 0 || ret >= end - pos)
   2711 				return 0;
   2712 			pos += ret;
   2713 		}
   2714 		if (bss->caps & IEEE80211_CAP_ESS) {
   2715 			ret = os_snprintf(pos, end - pos, "[ESS]");
   2716 			if (ret < 0 || ret >= end - pos)
   2717 				return 0;
   2718 			pos += ret;
   2719 		}
   2720 		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
   2721 			ret = os_snprintf(pos, end - pos, "[P2P]");
   2722 			if (ret < 0 || ret >= end - pos)
   2723 				return 0;
   2724 			pos += ret;
   2725 		}
   2726 #ifdef CONFIG_HS20
   2727 		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
   2728 			ret = os_snprintf(pos, end - pos, "[HS20]");
   2729 			if (ret < 0 || ret >= end - pos)
   2730 				return -1;
   2731 			pos += ret;
   2732 		}
   2733 #endif /* CONFIG_HS20 */
   2734 
   2735 		ret = os_snprintf(pos, end - pos, "\n");
   2736 		if (ret < 0 || ret >= end - pos)
   2737 			return 0;
   2738 		pos += ret;
   2739 	}
   2740 
   2741 	if (mask & WPA_BSS_MASK_SSID) {
   2742 		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
   2743 				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
   2744 		if (ret < 0 || ret >= end - pos)
   2745 			return 0;
   2746 		pos += ret;
   2747 	}
   2748 
   2749 #ifdef CONFIG_WPS
   2750 	if (mask & WPA_BSS_MASK_WPS_SCAN) {
   2751 		ie = (const u8 *) (bss + 1);
   2752 		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
   2753 		if (ret < 0 || ret >= end - pos)
   2754 			return 0;
   2755 		pos += ret;
   2756 	}
   2757 #endif /* CONFIG_WPS */
   2758 
   2759 #ifdef CONFIG_P2P
   2760 	if (mask & WPA_BSS_MASK_P2P_SCAN) {
   2761 		ie = (const u8 *) (bss + 1);
   2762 		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
   2763 		if (ret < 0 || ret >= end - pos)
   2764 			return 0;
   2765 		pos += ret;
   2766 	}
   2767 #endif /* CONFIG_P2P */
   2768 
   2769 #ifdef CONFIG_WIFI_DISPLAY
   2770 	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
   2771 		struct wpabuf *wfd;
   2772 		ie = (const u8 *) (bss + 1);
   2773 		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
   2774 						  WFD_IE_VENDOR_TYPE);
   2775 		if (wfd) {
   2776 			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
   2777 			if (ret < 0 || ret >= end - pos)
   2778 				return pos - buf;
   2779 			pos += ret;
   2780 
   2781 			pos += wpa_snprintf_hex(pos, end - pos,
   2782 						wpabuf_head(wfd),
   2783 						wpabuf_len(wfd));
   2784 			wpabuf_free(wfd);
   2785 
   2786 			ret = os_snprintf(pos, end - pos, "\n");
   2787 			if (ret < 0 || ret >= end - pos)
   2788 				return pos - buf;
   2789 			pos += ret;
   2790 		}
   2791 	}
   2792 #endif /* CONFIG_WIFI_DISPLAY */
   2793 
   2794 #ifdef CONFIG_INTERWORKING
   2795 	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
   2796 		struct wpa_bss_anqp *anqp = bss->anqp;
   2797 		pos = anqp_add_hex(pos, end, "anqp_venue_name",
   2798 				   anqp->venue_name);
   2799 		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
   2800 				   anqp->network_auth_type);
   2801 		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
   2802 				   anqp->roaming_consortium);
   2803 		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
   2804 				   anqp->ip_addr_type_availability);
   2805 		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
   2806 				   anqp->nai_realm);
   2807 		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
   2808 		pos = anqp_add_hex(pos, end, "anqp_domain_name",
   2809 				   anqp->domain_name);
   2810 #ifdef CONFIG_HS20
   2811 		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
   2812 				   anqp->hs20_operator_friendly_name);
   2813 		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
   2814 				   anqp->hs20_wan_metrics);
   2815 		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
   2816 				   anqp->hs20_connection_capability);
   2817 #endif /* CONFIG_HS20 */
   2818 	}
   2819 #endif /* CONFIG_INTERWORKING */
   2820 
   2821 #ifdef ANDROID
   2822 	ret = os_snprintf(pos, end - pos, "====\n");
   2823 	if (ret < 0 || ret >= end - pos)
   2824 		return 0;
   2825 	pos += ret;
   2826 #endif
   2827 
   2828 	return pos - buf;
   2829 }
   2830 
   2831 
   2832 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
   2833 					 const char *cmd, char *buf,
   2834 					 size_t buflen)
   2835 {
   2836 	u8 bssid[ETH_ALEN];
   2837 	size_t i;
   2838 	struct wpa_bss *bss;
   2839 	struct wpa_bss *bsslast = NULL;
   2840 	struct dl_list *next;
   2841 	int ret = 0;
   2842 	int len;
   2843 	char *ctmp;
   2844 	unsigned long mask = WPA_BSS_MASK_ALL;
   2845 
   2846 	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
   2847 		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
   2848 			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
   2849 					    list_id);
   2850 			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
   2851 					       list_id);
   2852 		} else { /* N1-N2 */
   2853 			unsigned int id1, id2;
   2854 
   2855 			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
   2856 				wpa_printf(MSG_INFO, "Wrong BSS range "
   2857 					   "format");
   2858 				return 0;
   2859 			}
   2860 
   2861 			id1 = atoi(cmd + 6);
   2862 			bss = wpa_bss_get_id(wpa_s, id1);
   2863 			id2 = atoi(ctmp + 1);
   2864 			if (id2 == 0)
   2865 				bsslast = dl_list_last(&wpa_s->bss_id,
   2866 						       struct wpa_bss,
   2867 						       list_id);
   2868 			else {
   2869 				bsslast = wpa_bss_get_id(wpa_s, id2);
   2870 				if (bsslast == NULL && bss && id2 > id1) {
   2871 					struct wpa_bss *tmp = bss;
   2872 					for (;;) {
   2873 						next = tmp->list_id.next;
   2874 						if (next == &wpa_s->bss_id)
   2875 							break;
   2876 						tmp = dl_list_entry(
   2877 							next, struct wpa_bss,
   2878 							list_id);
   2879 						if (tmp->id > id2)
   2880 							break;
   2881 						bsslast = tmp;
   2882 					}
   2883 				}
   2884 			}
   2885 		}
   2886 	} else if (os_strcmp(cmd, "FIRST") == 0)
   2887 		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
   2888 	else if (os_strncmp(cmd, "ID-", 3) == 0) {
   2889 		i = atoi(cmd + 3);
   2890 		bss = wpa_bss_get_id(wpa_s, i);
   2891 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
   2892 		i = atoi(cmd + 5);
   2893 		bss = wpa_bss_get_id(wpa_s, i);
   2894 		if (bss) {
   2895 			next = bss->list_id.next;
   2896 			if (next == &wpa_s->bss_id)
   2897 				bss = NULL;
   2898 			else
   2899 				bss = dl_list_entry(next, struct wpa_bss,
   2900 						    list_id);
   2901 		}
   2902 #ifdef CONFIG_P2P
   2903 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
   2904 		if (hwaddr_aton(cmd + 13, bssid) == 0)
   2905 			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
   2906 		else
   2907 			bss = NULL;
   2908 #endif /* CONFIG_P2P */
   2909 	} else if (hwaddr_aton(cmd, bssid) == 0)
   2910 		bss = wpa_bss_get_bssid(wpa_s, bssid);
   2911 	else {
   2912 		struct wpa_bss *tmp;
   2913 		i = atoi(cmd);
   2914 		bss = NULL;
   2915 		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
   2916 		{
   2917 			if (i-- == 0) {
   2918 				bss = tmp;
   2919 				break;
   2920 			}
   2921 		}
   2922 	}
   2923 
   2924 	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
   2925 		mask = strtoul(ctmp + 5, NULL, 0x10);
   2926 		if (mask == 0)
   2927 			mask = WPA_BSS_MASK_ALL;
   2928 	}
   2929 
   2930 	if (bss == NULL)
   2931 		return 0;
   2932 
   2933 	if (bsslast == NULL)
   2934 		bsslast = bss;
   2935 	do {
   2936 		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
   2937 		ret += len;
   2938 		buf += len;
   2939 		buflen -= len;
   2940 		if (bss == bsslast)
   2941 			break;
   2942 		next = bss->list_id.next;
   2943 		if (next == &wpa_s->bss_id)
   2944 			break;
   2945 		bss = dl_list_entry(next, struct wpa_bss, list_id);
   2946 	} while (bss && len);
   2947 
   2948 	return ret;
   2949 }
   2950 
   2951 
   2952 static int wpa_supplicant_ctrl_iface_ap_scan(
   2953 	struct wpa_supplicant *wpa_s, char *cmd)
   2954 {
   2955 	int ap_scan = atoi(cmd);
   2956 	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
   2957 }
   2958 
   2959 
   2960 static int wpa_supplicant_ctrl_iface_scan_interval(
   2961 	struct wpa_supplicant *wpa_s, char *cmd)
   2962 {
   2963 	int scan_int = atoi(cmd);
   2964 	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
   2965 }
   2966 
   2967 
   2968 static int wpa_supplicant_ctrl_iface_bss_expire_age(
   2969 	struct wpa_supplicant *wpa_s, char *cmd)
   2970 {
   2971 	int expire_age = atoi(cmd);
   2972 	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
   2973 }
   2974 
   2975 
   2976 static int wpa_supplicant_ctrl_iface_bss_expire_count(
   2977 	struct wpa_supplicant *wpa_s, char *cmd)
   2978 {
   2979 	int expire_count = atoi(cmd);
   2980 	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
   2981 }
   2982 
   2983 
   2984 static int wpa_supplicant_ctrl_iface_bss_flush(
   2985 	struct wpa_supplicant *wpa_s, char *cmd)
   2986 {
   2987 	int flush_age = atoi(cmd);
   2988 
   2989 	if (flush_age == 0)
   2990 		wpa_bss_flush(wpa_s);
   2991 	else
   2992 		wpa_bss_flush_by_age(wpa_s, flush_age);
   2993 	return 0;
   2994 }
   2995 
   2996 
   2997 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
   2998 {
   2999 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
   3000 	/* MLME-DELETEKEYS.request */
   3001 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
   3002 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
   3003 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
   3004 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
   3005 #ifdef CONFIG_IEEE80211W
   3006 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
   3007 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
   3008 #endif /* CONFIG_IEEE80211W */
   3009 
   3010 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
   3011 			0);
   3012 	/* MLME-SETPROTECTION.request(None) */
   3013 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
   3014 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
   3015 				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
   3016 	wpa_sm_drop_sa(wpa_s->wpa);
   3017 }
   3018 
   3019 
   3020 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
   3021 					  char *addr)
   3022 {
   3023 #ifdef CONFIG_NO_SCAN_PROCESSING
   3024 	return -1;
   3025 #else /* CONFIG_NO_SCAN_PROCESSING */
   3026 	u8 bssid[ETH_ALEN];
   3027 	struct wpa_bss *bss;
   3028 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   3029 
   3030 	if (hwaddr_aton(addr, bssid)) {
   3031 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
   3032 			   "address '%s'", addr);
   3033 		return -1;
   3034 	}
   3035 
   3036 	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
   3037 
   3038 	bss = wpa_bss_get_bssid(wpa_s, bssid);
   3039 	if (!bss) {
   3040 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
   3041 			   "from BSS table");
   3042 		return -1;
   3043 	}
   3044 
   3045 	/*
   3046 	 * TODO: Find best network configuration block from configuration to
   3047 	 * allow roaming to other networks
   3048 	 */
   3049 
   3050 	if (!ssid) {
   3051 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
   3052 			   "configuration known for the target AP");
   3053 		return -1;
   3054 	}
   3055 
   3056 	wpa_s->reassociate = 1;
   3057 	wpa_supplicant_connect(wpa_s, bss, ssid);
   3058 
   3059 	return 0;
   3060 #endif /* CONFIG_NO_SCAN_PROCESSING */
   3061 }
   3062 
   3063 
   3064 #ifdef CONFIG_P2P
   3065 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
   3066 {
   3067 	unsigned int timeout = atoi(cmd);
   3068 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
   3069 	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
   3070 	char *pos;
   3071 	unsigned int search_delay;
   3072 
   3073 	if (os_strstr(cmd, "type=social"))
   3074 		type = P2P_FIND_ONLY_SOCIAL;
   3075 	else if (os_strstr(cmd, "type=progressive"))
   3076 		type = P2P_FIND_PROGRESSIVE;
   3077 
   3078 	pos = os_strstr(cmd, "dev_id=");
   3079 	if (pos) {
   3080 		pos += 7;
   3081 		if (hwaddr_aton(pos, dev_id))
   3082 			return -1;
   3083 		_dev_id = dev_id;
   3084 	}
   3085 
   3086 	pos = os_strstr(cmd, "delay=");
   3087 	if (pos) {
   3088 		pos += 6;
   3089 		search_delay = atoi(pos);
   3090 	} else
   3091 		search_delay = wpas_p2p_search_delay(wpa_s);
   3092 
   3093 	return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id,
   3094 			     search_delay);
   3095 }
   3096 
   3097 
   3098 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
   3099 			    char *buf, size_t buflen)
   3100 {
   3101 	u8 addr[ETH_ALEN];
   3102 	char *pos, *pos2;
   3103 	char *pin = NULL;
   3104 	enum p2p_wps_method wps_method;
   3105 	int new_pin;
   3106 	int ret;
   3107 	int persistent_group, persistent_id = -1;
   3108 	int join;
   3109 	int auth;
   3110 	int automatic;
   3111 	int go_intent = -1;
   3112 	int freq = 0;
   3113 	int pd;
   3114 	int ht40;
   3115 
   3116 	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
   3117 	 * [persistent|persistent=<network id>]
   3118 	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
   3119 	 * [ht40] */
   3120 
   3121 	if (hwaddr_aton(cmd, addr))
   3122 		return -1;
   3123 
   3124 	pos = cmd + 17;
   3125 	if (*pos != ' ')
   3126 		return -1;
   3127 	pos++;
   3128 
   3129 	persistent_group = os_strstr(pos, " persistent") != NULL;
   3130 	pos2 = os_strstr(pos, " persistent=");
   3131 	if (pos2) {
   3132 		struct wpa_ssid *ssid;
   3133 		persistent_id = atoi(pos2 + 12);
   3134 		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
   3135 		if (ssid == NULL || ssid->disabled != 2 ||
   3136 		    ssid->mode != WPAS_MODE_P2P_GO) {
   3137 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   3138 				   "SSID id=%d for persistent P2P group (GO)",
   3139 				   persistent_id);
   3140 			return -1;
   3141 		}
   3142 	}
   3143 	join = os_strstr(pos, " join") != NULL;
   3144 	auth = os_strstr(pos, " auth") != NULL;
   3145 	automatic = os_strstr(pos, " auto") != NULL;
   3146 	pd = os_strstr(pos, " provdisc") != NULL;
   3147 	ht40 = os_strstr(pos, " ht40") != NULL;
   3148 
   3149 	pos2 = os_strstr(pos, " go_intent=");
   3150 	if (pos2) {
   3151 		pos2 += 11;
   3152 		go_intent = atoi(pos2);
   3153 		if (go_intent < 0 || go_intent > 15)
   3154 			return -1;
   3155 	}
   3156 
   3157 	pos2 = os_strstr(pos, " freq=");
   3158 	if (pos2) {
   3159 		pos2 += 6;
   3160 		freq = atoi(pos2);
   3161 		if (freq <= 0)
   3162 			return -1;
   3163 	}
   3164 
   3165 	if (os_strncmp(pos, "pin", 3) == 0) {
   3166 		/* Request random PIN (to be displayed) and enable the PIN */
   3167 		wps_method = WPS_PIN_DISPLAY;
   3168 	} else if (os_strncmp(pos, "pbc", 3) == 0) {
   3169 		wps_method = WPS_PBC;
   3170 	} else {
   3171 		pin = pos;
   3172 		pos = os_strchr(pin, ' ');
   3173 		wps_method = WPS_PIN_KEYPAD;
   3174 		if (pos) {
   3175 			*pos++ = '\0';
   3176 			if (os_strncmp(pos, "display", 7) == 0)
   3177 				wps_method = WPS_PIN_DISPLAY;
   3178 		}
   3179 		if (!wps_pin_str_valid(pin)) {
   3180 			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
   3181 			return 17;
   3182 		}
   3183 	}
   3184 
   3185 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
   3186 				   persistent_group, automatic, join,
   3187 				   auth, go_intent, freq, persistent_id, pd,
   3188 				   ht40);
   3189 	if (new_pin == -2) {
   3190 		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
   3191 		return 25;
   3192 	}
   3193 	if (new_pin == -3) {
   3194 		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
   3195 		return 25;
   3196 	}
   3197 	if (new_pin < 0)
   3198 		return -1;
   3199 	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
   3200 		ret = os_snprintf(buf, buflen, "%08d", new_pin);
   3201 		if (ret < 0 || (size_t) ret >= buflen)
   3202 			return -1;
   3203 		return ret;
   3204 	}
   3205 
   3206 	os_memcpy(buf, "OK\n", 3);
   3207 	return 3;
   3208 }
   3209 
   3210 
   3211 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
   3212 {
   3213 	unsigned int timeout = atoi(cmd);
   3214 	return wpas_p2p_listen(wpa_s, timeout);
   3215 }
   3216 
   3217 
   3218 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
   3219 {
   3220 	u8 addr[ETH_ALEN];
   3221 	char *pos;
   3222 	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
   3223 
   3224 	/* <addr> <config method> [join|auto] */
   3225 
   3226 	if (hwaddr_aton(cmd, addr))
   3227 		return -1;
   3228 
   3229 	pos = cmd + 17;
   3230 	if (*pos != ' ')
   3231 		return -1;
   3232 	pos++;
   3233 
   3234 	if (os_strstr(pos, " join") != NULL)
   3235 		use = WPAS_P2P_PD_FOR_JOIN;
   3236 	else if (os_strstr(pos, " auto") != NULL)
   3237 		use = WPAS_P2P_PD_AUTO;
   3238 
   3239 	return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
   3240 }
   3241 
   3242 
   3243 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
   3244 			      size_t buflen)
   3245 {
   3246 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   3247 
   3248 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
   3249 	    ssid->passphrase == NULL)
   3250 		return -1;
   3251 
   3252 	os_strlcpy(buf, ssid->passphrase, buflen);
   3253 	return os_strlen(buf);
   3254 }
   3255 
   3256 
   3257 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
   3258 				  char *buf, size_t buflen)
   3259 {
   3260 	u64 ref;
   3261 	int res;
   3262 	u8 dst_buf[ETH_ALEN], *dst;
   3263 	struct wpabuf *tlvs;
   3264 	char *pos;
   3265 	size_t len;
   3266 
   3267 	if (hwaddr_aton(cmd, dst_buf))
   3268 		return -1;
   3269 	dst = dst_buf;
   3270 	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
   3271 	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
   3272 		dst = NULL;
   3273 	pos = cmd + 17;
   3274 	if (*pos != ' ')
   3275 		return -1;
   3276 	pos++;
   3277 
   3278 	if (os_strncmp(pos, "upnp ", 5) == 0) {
   3279 		u8 version;
   3280 		pos += 5;
   3281 		if (hexstr2bin(pos, &version, 1) < 0)
   3282 			return -1;
   3283 		pos += 2;
   3284 		if (*pos != ' ')
   3285 			return -1;
   3286 		pos++;
   3287 		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
   3288 #ifdef CONFIG_WIFI_DISPLAY
   3289 	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
   3290 		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
   3291 #endif /* CONFIG_WIFI_DISPLAY */
   3292 	} else {
   3293 		len = os_strlen(pos);
   3294 		if (len & 1)
   3295 			return -1;
   3296 		len /= 2;
   3297 		tlvs = wpabuf_alloc(len);
   3298 		if (tlvs == NULL)
   3299 			return -1;
   3300 		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
   3301 			wpabuf_free(tlvs);
   3302 			return -1;
   3303 		}
   3304 
   3305 		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
   3306 		wpabuf_free(tlvs);
   3307 	}
   3308 	if (ref == 0)
   3309 		return -1;
   3310 	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
   3311 	if (res < 0 || (unsigned) res >= buflen)
   3312 		return -1;
   3313 	return res;
   3314 }
   3315 
   3316 
   3317 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
   3318 					 char *cmd)
   3319 {
   3320 	long long unsigned val;
   3321 	u64 req;
   3322 	if (sscanf(cmd, "%llx", &val) != 1)
   3323 		return -1;
   3324 	req = val;
   3325 	return wpas_p2p_sd_cancel_request(wpa_s, req);
   3326 }
   3327 
   3328 
   3329 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
   3330 {
   3331 	int freq;
   3332 	u8 dst[ETH_ALEN];
   3333 	u8 dialog_token;
   3334 	struct wpabuf *resp_tlvs;
   3335 	char *pos, *pos2;
   3336 	size_t len;
   3337 
   3338 	pos = os_strchr(cmd, ' ');
   3339 	if (pos == NULL)
   3340 		return -1;
   3341 	*pos++ = '\0';
   3342 	freq = atoi(cmd);
   3343 	if (freq == 0)
   3344 		return -1;
   3345 
   3346 	if (hwaddr_aton(pos, dst))
   3347 		return -1;
   3348 	pos += 17;
   3349 	if (*pos != ' ')
   3350 		return -1;
   3351 	pos++;
   3352 
   3353 	pos2 = os_strchr(pos, ' ');
   3354 	if (pos2 == NULL)
   3355 		return -1;
   3356 	*pos2++ = '\0';
   3357 	dialog_token = atoi(pos);
   3358 
   3359 	len = os_strlen(pos2);
   3360 	if (len & 1)
   3361 		return -1;
   3362 	len /= 2;
   3363 	resp_tlvs = wpabuf_alloc(len);
   3364 	if (resp_tlvs == NULL)
   3365 		return -1;
   3366 	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
   3367 		wpabuf_free(resp_tlvs);
   3368 		return -1;
   3369 	}
   3370 
   3371 	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
   3372 	wpabuf_free(resp_tlvs);
   3373 	return 0;
   3374 }
   3375 
   3376 
   3377 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
   3378 				       char *cmd)
   3379 {
   3380 	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
   3381 		return -1;
   3382 	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
   3383 	return 0;
   3384 }
   3385 
   3386 
   3387 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
   3388 					char *cmd)
   3389 {
   3390 	char *pos;
   3391 	size_t len;
   3392 	struct wpabuf *query, *resp;
   3393 
   3394 	pos = os_strchr(cmd, ' ');
   3395 	if (pos == NULL)
   3396 		return -1;
   3397 	*pos++ = '\0';
   3398 
   3399 	len = os_strlen(cmd);
   3400 	if (len & 1)
   3401 		return -1;
   3402 	len /= 2;
   3403 	query = wpabuf_alloc(len);
   3404 	if (query == NULL)
   3405 		return -1;
   3406 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
   3407 		wpabuf_free(query);
   3408 		return -1;
   3409 	}
   3410 
   3411 	len = os_strlen(pos);
   3412 	if (len & 1) {
   3413 		wpabuf_free(query);
   3414 		return -1;
   3415 	}
   3416 	len /= 2;
   3417 	resp = wpabuf_alloc(len);
   3418 	if (resp == NULL) {
   3419 		wpabuf_free(query);
   3420 		return -1;
   3421 	}
   3422 	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
   3423 		wpabuf_free(query);
   3424 		wpabuf_free(resp);
   3425 		return -1;
   3426 	}
   3427 
   3428 	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
   3429 		wpabuf_free(query);
   3430 		wpabuf_free(resp);
   3431 		return -1;
   3432 	}
   3433 	return 0;
   3434 }
   3435 
   3436 
   3437 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
   3438 {
   3439 	char *pos;
   3440 	u8 version;
   3441 
   3442 	pos = os_strchr(cmd, ' ');
   3443 	if (pos == NULL)
   3444 		return -1;
   3445 	*pos++ = '\0';
   3446 
   3447 	if (hexstr2bin(cmd, &version, 1) < 0)
   3448 		return -1;
   3449 
   3450 	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
   3451 }
   3452 
   3453 
   3454 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
   3455 {
   3456 	char *pos;
   3457 
   3458 	pos = os_strchr(cmd, ' ');
   3459 	if (pos == NULL)
   3460 		return -1;
   3461 	*pos++ = '\0';
   3462 
   3463 	if (os_strcmp(cmd, "bonjour") == 0)
   3464 		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
   3465 	if (os_strcmp(cmd, "upnp") == 0)
   3466 		return p2p_ctrl_service_add_upnp(wpa_s, pos);
   3467 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
   3468 	return -1;
   3469 }
   3470 
   3471 
   3472 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
   3473 					char *cmd)
   3474 {
   3475 	size_t len;
   3476 	struct wpabuf *query;
   3477 	int ret;
   3478 
   3479 	len = os_strlen(cmd);
   3480 	if (len & 1)
   3481 		return -1;
   3482 	len /= 2;
   3483 	query = wpabuf_alloc(len);
   3484 	if (query == NULL)
   3485 		return -1;
   3486 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
   3487 		wpabuf_free(query);
   3488 		return -1;
   3489 	}
   3490 
   3491 	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
   3492 	wpabuf_free(query);
   3493 	return ret;
   3494 }
   3495 
   3496 
   3497 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
   3498 {
   3499 	char *pos;
   3500 	u8 version;
   3501 
   3502 	pos = os_strchr(cmd, ' ');
   3503 	if (pos == NULL)
   3504 		return -1;
   3505 	*pos++ = '\0';
   3506 
   3507 	if (hexstr2bin(cmd, &version, 1) < 0)
   3508 		return -1;
   3509 
   3510 	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
   3511 }
   3512 
   3513 
   3514 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
   3515 {
   3516 	char *pos;
   3517 
   3518 	pos = os_strchr(cmd, ' ');
   3519 	if (pos == NULL)
   3520 		return -1;
   3521 	*pos++ = '\0';
   3522 
   3523 	if (os_strcmp(cmd, "bonjour") == 0)
   3524 		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
   3525 	if (os_strcmp(cmd, "upnp") == 0)
   3526 		return p2p_ctrl_service_del_upnp(wpa_s, pos);
   3527 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
   3528 	return -1;
   3529 }
   3530 
   3531 
   3532 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
   3533 {
   3534 	u8 addr[ETH_ALEN];
   3535 
   3536 	/* <addr> */
   3537 
   3538 	if (hwaddr_aton(cmd, addr))
   3539 		return -1;
   3540 
   3541 	return wpas_p2p_reject(wpa_s, addr);
   3542 }
   3543 
   3544 
   3545 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
   3546 {
   3547 	char *pos;
   3548 	int id;
   3549 	struct wpa_ssid *ssid;
   3550 	u8 *_peer = NULL, peer[ETH_ALEN];
   3551 	int freq = 0;
   3552 	int ht40;
   3553 
   3554 	id = atoi(cmd);
   3555 	pos = os_strstr(cmd, " peer=");
   3556 	if (pos) {
   3557 		pos += 6;
   3558 		if (hwaddr_aton(pos, peer))
   3559 			return -1;
   3560 		_peer = peer;
   3561 	}
   3562 	ssid = wpa_config_get_network(wpa_s->conf, id);
   3563 	if (ssid == NULL || ssid->disabled != 2) {
   3564 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
   3565 			   "for persistent P2P group",
   3566 			   id);
   3567 		return -1;
   3568 	}
   3569 
   3570 	pos = os_strstr(cmd, " freq=");
   3571 	if (pos) {
   3572 		pos += 6;
   3573 		freq = atoi(pos);
   3574 		if (freq <= 0)
   3575 			return -1;
   3576 	}
   3577 
   3578 	ht40 = os_strstr(cmd, " ht40") != NULL;
   3579 
   3580 	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40);
   3581 }
   3582 
   3583 
   3584 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
   3585 {
   3586 	char *pos;
   3587 	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
   3588 
   3589 	pos = os_strstr(cmd, " peer=");
   3590 	if (!pos)
   3591 		return -1;
   3592 
   3593 	*pos = '\0';
   3594 	pos += 6;
   3595 	if (hwaddr_aton(pos, peer)) {
   3596 		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
   3597 		return -1;
   3598 	}
   3599 
   3600 	pos = os_strstr(pos, " go_dev_addr=");
   3601 	if (pos) {
   3602 		pos += 13;
   3603 		if (hwaddr_aton(pos, go_dev_addr)) {
   3604 			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
   3605 				   pos);
   3606 			return -1;
   3607 		}
   3608 		go_dev = go_dev_addr;
   3609 	}
   3610 
   3611 	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
   3612 }
   3613 
   3614 
   3615 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
   3616 {
   3617 	if (os_strncmp(cmd, "persistent=", 11) == 0)
   3618 		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
   3619 	if (os_strncmp(cmd, "group=", 6) == 0)
   3620 		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
   3621 
   3622 	return -1;
   3623 }
   3624 
   3625 
   3626 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
   3627 					 char *cmd, int freq, int ht40)
   3628 {
   3629 	int id;
   3630 	struct wpa_ssid *ssid;
   3631 
   3632 	id = atoi(cmd);
   3633 	ssid = wpa_config_get_network(wpa_s->conf, id);
   3634 	if (ssid == NULL || ssid->disabled != 2) {
   3635 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
   3636 			   "for persistent P2P group",
   3637 			   id);
   3638 		return -1;
   3639 	}
   3640 
   3641 	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40);
   3642 }
   3643 
   3644 
   3645 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
   3646 {
   3647 	int freq = 0, ht40;
   3648 	char *pos;
   3649 
   3650 	pos = os_strstr(cmd, "freq=");
   3651 	if (pos)
   3652 		freq = atoi(pos + 5);
   3653 
   3654 	ht40 = os_strstr(cmd, "ht40") != NULL;
   3655 
   3656 	if (os_strncmp(cmd, "persistent=", 11) == 0)
   3657 		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
   3658 						     ht40);
   3659 	if (os_strcmp(cmd, "persistent") == 0 ||
   3660 	    os_strncmp(cmd, "persistent ", 11) == 0)
   3661 		return wpas_p2p_group_add(wpa_s, 1, freq, ht40);
   3662 	if (os_strncmp(cmd, "freq=", 5) == 0)
   3663 		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
   3664 	if (ht40)
   3665 		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
   3666 
   3667 	wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
   3668 		   cmd);
   3669 	return -1;
   3670 }
   3671 
   3672 
   3673 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
   3674 			 char *buf, size_t buflen)
   3675 {
   3676 	u8 addr[ETH_ALEN], *addr_ptr;
   3677 	int next, res;
   3678 	const struct p2p_peer_info *info;
   3679 	char *pos, *end;
   3680 	char devtype[WPS_DEV_TYPE_BUFSIZE];
   3681 	struct wpa_ssid *ssid;
   3682 
   3683 	if (!wpa_s->global->p2p)
   3684 		return -1;
   3685 
   3686 	if (os_strcmp(cmd, "FIRST") == 0) {
   3687 		addr_ptr = NULL;
   3688 		next = 0;
   3689 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
   3690 		if (hwaddr_aton(cmd + 5, addr) < 0)
   3691 			return -1;
   3692 		addr_ptr = addr;
   3693 		next = 1;
   3694 	} else {
   3695 		if (hwaddr_aton(cmd, addr) < 0)
   3696 			return -1;
   3697 		addr_ptr = addr;
   3698 		next = 0;
   3699 	}
   3700 
   3701 	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
   3702 	if (info == NULL)
   3703 		return -1;
   3704 
   3705 	pos = buf;
   3706 	end = buf + buflen;
   3707 
   3708 	res = os_snprintf(pos, end - pos, MACSTR "\n"
   3709 			  "pri_dev_type=%s\n"
   3710 			  "device_name=%s\n"
   3711 			  "manufacturer=%s\n"
   3712 			  "model_name=%s\n"
   3713 			  "model_number=%s\n"
   3714 			  "serial_number=%s\n"
   3715 			  "config_methods=0x%x\n"
   3716 			  "dev_capab=0x%x\n"
   3717 			  "group_capab=0x%x\n"
   3718 			  "level=%d\n",
   3719 			  MAC2STR(info->p2p_device_addr),
   3720 			  wps_dev_type_bin2str(info->pri_dev_type,
   3721 					       devtype, sizeof(devtype)),
   3722 			  info->device_name,
   3723 			  info->manufacturer,
   3724 			  info->model_name,
   3725 			  info->model_number,
   3726 			  info->serial_number,
   3727 			  info->config_methods,
   3728 			  info->dev_capab,
   3729 			  info->group_capab,
   3730 			  info->level);
   3731 	if (res < 0 || res >= end - pos)
   3732 		return pos - buf;
   3733 	pos += res;
   3734 
   3735 	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
   3736 	if (ssid) {
   3737 		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
   3738 		if (res < 0 || res >= end - pos)
   3739 			return pos - buf;
   3740 		pos += res;
   3741 	}
   3742 
   3743 	res = p2p_get_peer_info_txt(info, pos, end - pos);
   3744 	if (res < 0)
   3745 		return pos - buf;
   3746 	pos += res;
   3747 
   3748 	return pos - buf;
   3749 }
   3750 
   3751 
   3752 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
   3753 				  const char *param)
   3754 {
   3755 	struct wpa_freq_range *freq = NULL, *n;
   3756 	unsigned int count = 0, i;
   3757 	const char *pos, *pos2, *pos3;
   3758 
   3759 	if (wpa_s->global->p2p == NULL)
   3760 		return -1;
   3761 
   3762 	/*
   3763 	 * param includes comma separated frequency range.
   3764 	 * For example: 2412-2432,2462,5000-6000
   3765 	 */
   3766 	pos = param;
   3767 	while (pos && pos[0]) {
   3768 		n = os_realloc_array(freq, count + 1,
   3769 				     sizeof(struct wpa_freq_range));
   3770 		if (n == NULL) {
   3771 			os_free(freq);
   3772 			return -1;
   3773 		}
   3774 		freq = n;
   3775 		freq[count].min = atoi(pos);
   3776 		pos2 = os_strchr(pos, '-');
   3777 		pos3 = os_strchr(pos, ',');
   3778 		if (pos2 && (!pos3 || pos2 < pos3)) {
   3779 			pos2++;
   3780 			freq[count].max = atoi(pos2);
   3781 		} else
   3782 			freq[count].max = freq[count].min;
   3783 		pos = pos3;
   3784 		if (pos)
   3785 			pos++;
   3786 		count++;
   3787 	}
   3788 
   3789 	for (i = 0; i < count; i++) {
   3790 		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
   3791 			   freq[i].min, freq[i].max);
   3792 	}
   3793 
   3794 	os_free(wpa_s->global->p2p_disallow_freq);
   3795 	wpa_s->global->p2p_disallow_freq = freq;
   3796 	wpa_s->global->num_p2p_disallow_freq = count;
   3797 	wpas_p2p_update_channel_list(wpa_s);
   3798 	return 0;
   3799 }
   3800 
   3801 
   3802 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
   3803 {
   3804 	char *param;
   3805 
   3806 	if (wpa_s->global->p2p == NULL)
   3807 		return -1;
   3808 
   3809 	param = os_strchr(cmd, ' ');
   3810 	if (param == NULL)
   3811 		return -1;
   3812 	*param++ = '\0';
   3813 
   3814 	if (os_strcmp(cmd, "discoverability") == 0) {
   3815 		p2p_set_client_discoverability(wpa_s->global->p2p,
   3816 					       atoi(param));
   3817 		return 0;
   3818 	}
   3819 
   3820 	if (os_strcmp(cmd, "managed") == 0) {
   3821 		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
   3822 		return 0;
   3823 	}
   3824 
   3825 	if (os_strcmp(cmd, "listen_channel") == 0) {
   3826 		return p2p_set_listen_channel(wpa_s->global->p2p, 81,
   3827 					      atoi(param));
   3828 	}
   3829 
   3830 	if (os_strcmp(cmd, "ssid_postfix") == 0) {
   3831 		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
   3832 					    os_strlen(param));
   3833 	}
   3834 
   3835 	if (os_strcmp(cmd, "noa") == 0) {
   3836 		char *pos;
   3837 		int count, start, duration;
   3838 		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
   3839 		count = atoi(param);
   3840 		pos = os_strchr(param, ',');
   3841 		if (pos == NULL)
   3842 			return -1;
   3843 		pos++;
   3844 		start = atoi(pos);
   3845 		pos = os_strchr(pos, ',');
   3846 		if (pos == NULL)
   3847 			return -1;
   3848 		pos++;
   3849 		duration = atoi(pos);
   3850 		if (count < 0 || count > 255 || start < 0 || duration < 0)
   3851 			return -1;
   3852 		if (count == 0 && duration > 0)
   3853 			return -1;
   3854 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
   3855 			   "start=%d duration=%d", count, start, duration);
   3856 		return wpas_p2p_set_noa(wpa_s, count, start, duration);
   3857 	}
   3858 
   3859 	if (os_strcmp(cmd, "ps") == 0)
   3860 		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
   3861 
   3862 	if (os_strcmp(cmd, "oppps") == 0)
   3863 		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
   3864 
   3865 	if (os_strcmp(cmd, "ctwindow") == 0)
   3866 		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
   3867 
   3868 	if (os_strcmp(cmd, "disabled") == 0) {
   3869 		wpa_s->global->p2p_disabled = atoi(param);
   3870 		wpa_printf(MSG_DEBUG, "P2P functionality %s",
   3871 			   wpa_s->global->p2p_disabled ?
   3872 			   "disabled" : "enabled");
   3873 		if (wpa_s->global->p2p_disabled) {
   3874 			wpas_p2p_stop_find(wpa_s);
   3875 			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
   3876 			p2p_flush(wpa_s->global->p2p);
   3877 		}
   3878 		return 0;
   3879 	}
   3880 
   3881 	if (os_strcmp(cmd, "conc_pref") == 0) {
   3882 		if (os_strcmp(param, "sta") == 0)
   3883 			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
   3884 		else if (os_strcmp(param, "p2p") == 0)
   3885 			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
   3886 		else {
   3887 			wpa_printf(MSG_INFO, "Invalid conc_pref value");
   3888 			return -1;
   3889 		}
   3890 		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
   3891 			   "%s", param);
   3892 		return 0;
   3893 	}
   3894 
   3895 	if (os_strcmp(cmd, "force_long_sd") == 0) {
   3896 		wpa_s->force_long_sd = atoi(param);
   3897 		return 0;
   3898 	}
   3899 
   3900 	if (os_strcmp(cmd, "peer_filter") == 0) {
   3901 		u8 addr[ETH_ALEN];
   3902 		if (hwaddr_aton(param, addr))
   3903 			return -1;
   3904 		p2p_set_peer_filter(wpa_s->global->p2p, addr);
   3905 		return 0;
   3906 	}
   3907 
   3908 	if (os_strcmp(cmd, "cross_connect") == 0)
   3909 		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
   3910 
   3911 	if (os_strcmp(cmd, "go_apsd") == 0) {
   3912 		if (os_strcmp(param, "disable") == 0)
   3913 			wpa_s->set_ap_uapsd = 0;
   3914 		else {
   3915 			wpa_s->set_ap_uapsd = 1;
   3916 			wpa_s->ap_uapsd = atoi(param);
   3917 		}
   3918 		return 0;
   3919 	}
   3920 
   3921 	if (os_strcmp(cmd, "client_apsd") == 0) {
   3922 		if (os_strcmp(param, "disable") == 0)
   3923 			wpa_s->set_sta_uapsd = 0;
   3924 		else {
   3925 			int be, bk, vi, vo;
   3926 			char *pos;
   3927 			/* format: BE,BK,VI,VO;max SP Length */
   3928 			be = atoi(param);
   3929 			pos = os_strchr(param, ',');
   3930 			if (pos == NULL)
   3931 				return -1;
   3932 			pos++;
   3933 			bk = atoi(pos);
   3934 			pos = os_strchr(pos, ',');
   3935 			if (pos == NULL)
   3936 				return -1;
   3937 			pos++;
   3938 			vi = atoi(pos);
   3939 			pos = os_strchr(pos, ',');
   3940 			if (pos == NULL)
   3941 				return -1;
   3942 			pos++;
   3943 			vo = atoi(pos);
   3944 			/* ignore max SP Length for now */
   3945 
   3946 			wpa_s->set_sta_uapsd = 1;
   3947 			wpa_s->sta_uapsd = 0;
   3948 			if (be)
   3949 				wpa_s->sta_uapsd |= BIT(0);
   3950 			if (bk)
   3951 				wpa_s->sta_uapsd |= BIT(1);
   3952 			if (vi)
   3953 				wpa_s->sta_uapsd |= BIT(2);
   3954 			if (vo)
   3955 				wpa_s->sta_uapsd |= BIT(3);
   3956 		}
   3957 		return 0;
   3958 	}
   3959 
   3960 	if (os_strcmp(cmd, "disallow_freq") == 0)
   3961 		return p2p_ctrl_disallow_freq(wpa_s, param);
   3962 
   3963 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
   3964 		   cmd);
   3965 
   3966 	return -1;
   3967 }
   3968 
   3969 
   3970 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
   3971 {
   3972 	char *pos, *pos2;
   3973 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
   3974 
   3975 	if (cmd[0]) {
   3976 		pos = os_strchr(cmd, ' ');
   3977 		if (pos == NULL)
   3978 			return -1;
   3979 		*pos++ = '\0';
   3980 		dur1 = atoi(cmd);
   3981 
   3982 		pos2 = os_strchr(pos, ' ');
   3983 		if (pos2)
   3984 			*pos2++ = '\0';
   3985 		int1 = atoi(pos);
   3986 	} else
   3987 		pos2 = NULL;
   3988 
   3989 	if (pos2) {
   3990 		pos = os_strchr(pos2, ' ');
   3991 		if (pos == NULL)
   3992 			return -1;
   3993 		*pos++ = '\0';
   3994 		dur2 = atoi(pos2);
   3995 		int2 = atoi(pos);
   3996 	}
   3997 
   3998 	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
   3999 }
   4000 
   4001 
   4002 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
   4003 {
   4004 	char *pos;
   4005 	unsigned int period = 0, interval = 0;
   4006 
   4007 	if (cmd[0]) {
   4008 		pos = os_strchr(cmd, ' ');
   4009 		if (pos == NULL)
   4010 			return -1;
   4011 		*pos++ = '\0';
   4012 		period = atoi(cmd);
   4013 		interval = atoi(pos);
   4014 	}
   4015 
   4016 	return wpas_p2p_ext_listen(wpa_s, period, interval);
   4017 }
   4018 
   4019 #endif /* CONFIG_P2P */
   4020 
   4021 
   4022 #ifdef CONFIG_INTERWORKING
   4023 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
   4024 {
   4025 	u8 bssid[ETH_ALEN];
   4026 	struct wpa_bss *bss;
   4027 
   4028 	if (hwaddr_aton(dst, bssid)) {
   4029 		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
   4030 		return -1;
   4031 	}
   4032 
   4033 	bss = wpa_bss_get_bssid(wpa_s, bssid);
   4034 	if (bss == NULL) {
   4035 		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
   4036 			   MAC2STR(bssid));
   4037 		return -1;
   4038 	}
   4039 
   4040 	return interworking_connect(wpa_s, bss);
   4041 }
   4042 
   4043 
   4044 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
   4045 {
   4046 	u8 dst_addr[ETH_ALEN];
   4047 	int used;
   4048 	char *pos;
   4049 #define MAX_ANQP_INFO_ID 100
   4050 	u16 id[MAX_ANQP_INFO_ID];
   4051 	size_t num_id = 0;
   4052 
   4053 	used = hwaddr_aton2(dst, dst_addr);
   4054 	if (used < 0)
   4055 		return -1;
   4056 	pos = dst + used;
   4057 	while (num_id < MAX_ANQP_INFO_ID) {
   4058 		id[num_id] = atoi(pos);
   4059 		if (id[num_id])
   4060 			num_id++;
   4061 		pos = os_strchr(pos + 1, ',');
   4062 		if (pos == NULL)
   4063 			break;
   4064 		pos++;
   4065 	}
   4066 
   4067 	if (num_id == 0)
   4068 		return -1;
   4069 
   4070 	return anqp_send_req(wpa_s, dst_addr, id, num_id);
   4071 }
   4072 
   4073 
   4074 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
   4075 {
   4076 	u8 dst_addr[ETH_ALEN];
   4077 	struct wpabuf *advproto, *query = NULL;
   4078 	int used, ret = -1;
   4079 	char *pos, *end;
   4080 	size_t len;
   4081 
   4082 	used = hwaddr_aton2(cmd, dst_addr);
   4083 	if (used < 0)
   4084 		return -1;
   4085 
   4086 	pos = cmd + used;
   4087 	while (*pos == ' ')
   4088 		pos++;
   4089 
   4090 	/* Advertisement Protocol ID */
   4091 	end = os_strchr(pos, ' ');
   4092 	if (end)
   4093 		len = end - pos;
   4094 	else
   4095 		len = os_strlen(pos);
   4096 	if (len & 0x01)
   4097 		return -1;
   4098 	len /= 2;
   4099 	if (len == 0)
   4100 		return -1;
   4101 	advproto = wpabuf_alloc(len);
   4102 	if (advproto == NULL)
   4103 		return -1;
   4104 	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
   4105 		goto fail;
   4106 
   4107 	if (end) {
   4108 		/* Optional Query Request */
   4109 		pos = end + 1;
   4110 		while (*pos == ' ')
   4111 			pos++;
   4112 
   4113 		len = os_strlen(pos);
   4114 		if (len) {
   4115 			if (len & 0x01)
   4116 				goto fail;
   4117 			len /= 2;
   4118 			if (len == 0)
   4119 				goto fail;
   4120 			query = wpabuf_alloc(len);
   4121 			if (query == NULL)
   4122 				goto fail;
   4123 			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
   4124 				goto fail;
   4125 		}
   4126 	}
   4127 
   4128 	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
   4129 
   4130 fail:
   4131 	wpabuf_free(advproto);
   4132 	wpabuf_free(query);
   4133 
   4134 	return ret;
   4135 }
   4136 
   4137 
   4138 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
   4139 			    size_t buflen)
   4140 {
   4141 	u8 addr[ETH_ALEN];
   4142 	int dialog_token;
   4143 	int used;
   4144 	char *pos;
   4145 	size_t resp_len, start, requested_len;
   4146 
   4147 	if (!wpa_s->last_gas_resp)
   4148 		return -1;
   4149 
   4150 	used = hwaddr_aton2(cmd, addr);
   4151 	if (used < 0)
   4152 		return -1;
   4153 
   4154 	pos = cmd + used;
   4155 	while (*pos == ' ')
   4156 		pos++;
   4157 	dialog_token = atoi(pos);
   4158 
   4159 	if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 ||
   4160 	    dialog_token != wpa_s->last_gas_dialog_token)
   4161 		return -1;
   4162 
   4163 	resp_len = wpabuf_len(wpa_s->last_gas_resp);
   4164 	start = 0;
   4165 	requested_len = resp_len;
   4166 
   4167 	pos = os_strchr(pos, ' ');
   4168 	if (pos) {
   4169 		start = atoi(pos);
   4170 		if (start > resp_len)
   4171 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
   4172 		pos = os_strchr(pos, ',');
   4173 		if (pos == NULL)
   4174 			return -1;
   4175 		pos++;
   4176 		requested_len = atoi(pos);
   4177 		if (start + requested_len > resp_len)
   4178 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
   4179 	}
   4180 
   4181 	if (requested_len * 2 + 1 > buflen)
   4182 		return os_snprintf(buf, buflen, "FAIL-Too long response");
   4183 
   4184 	return wpa_snprintf_hex(buf, buflen,
   4185 				wpabuf_head_u8(wpa_s->last_gas_resp) + start,
   4186 				requested_len);
   4187 }
   4188 #endif /* CONFIG_INTERWORKING */
   4189 
   4190 
   4191 #ifdef CONFIG_HS20
   4192 
   4193 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
   4194 {
   4195 	u8 dst_addr[ETH_ALEN];
   4196 	int used;
   4197 	char *pos;
   4198 	u32 subtypes = 0;
   4199 
   4200 	used = hwaddr_aton2(dst, dst_addr);
   4201 	if (used < 0)
   4202 		return -1;
   4203 	pos = dst + used;
   4204 	for (;;) {
   4205 		int num = atoi(pos);
   4206 		if (num <= 0 || num > 31)
   4207 			return -1;
   4208 		subtypes |= BIT(num);
   4209 		pos = os_strchr(pos + 1, ',');
   4210 		if (pos == NULL)
   4211 			break;
   4212 		pos++;
   4213 	}
   4214 
   4215 	if (subtypes == 0)
   4216 		return -1;
   4217 
   4218 	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
   4219 }
   4220 
   4221 
   4222 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
   4223 				    const u8 *addr, const char *realm)
   4224 {
   4225 	u8 *buf;
   4226 	size_t rlen, len;
   4227 	int ret;
   4228 
   4229 	rlen = os_strlen(realm);
   4230 	len = 3 + rlen;
   4231 	buf = os_malloc(len);
   4232 	if (buf == NULL)
   4233 		return -1;
   4234 	buf[0] = 1; /* NAI Home Realm Count */
   4235 	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
   4236 	buf[2] = rlen;
   4237 	os_memcpy(buf + 3, realm, rlen);
   4238 
   4239 	ret = hs20_anqp_send_req(wpa_s, addr,
   4240 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
   4241 				 buf, len);
   4242 
   4243 	os_free(buf);
   4244 
   4245 	return ret;
   4246 }
   4247 
   4248 
   4249 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
   4250 					char *dst)
   4251 {
   4252 	struct wpa_cred *cred = wpa_s->conf->cred;
   4253 	u8 dst_addr[ETH_ALEN];
   4254 	int used;
   4255 	u8 *buf;
   4256 	size_t len;
   4257 	int ret;
   4258 
   4259 	used = hwaddr_aton2(dst, dst_addr);
   4260 	if (used < 0)
   4261 		return -1;
   4262 
   4263 	while (dst[used] == ' ')
   4264 		used++;
   4265 	if (os_strncmp(dst + used, "realm=", 6) == 0)
   4266 		return hs20_nai_home_realm_list(wpa_s, dst_addr,
   4267 						dst + used + 6);
   4268 
   4269 	len = os_strlen(dst + used);
   4270 
   4271 	if (len == 0 && cred && cred->realm)
   4272 		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
   4273 
   4274 	if (len % 1)
   4275 		return -1;
   4276 	len /= 2;
   4277 	buf = os_malloc(len);
   4278 	if (buf == NULL)
   4279 		return -1;
   4280 	if (hexstr2bin(dst + used, buf, len) < 0) {
   4281 		os_free(buf);
   4282 		return -1;
   4283 	}
   4284 
   4285 	ret = hs20_anqp_send_req(wpa_s, dst_addr,
   4286 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
   4287 				 buf, len);
   4288 	os_free(buf);
   4289 
   4290 	return ret;
   4291 }
   4292 
   4293 #endif /* CONFIG_HS20 */
   4294 
   4295 
   4296 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
   4297 	struct wpa_supplicant *wpa_s, char *cmd)
   4298 {
   4299 	wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
   4300 	return 0;
   4301 }
   4302 
   4303 
   4304 #ifdef CONFIG_AUTOSCAN
   4305 
   4306 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
   4307 					      char *cmd)
   4308 {
   4309 	enum wpa_states state = wpa_s->wpa_state;
   4310 	char *new_params = NULL;
   4311 
   4312 	if (os_strlen(cmd) > 0) {
   4313 		new_params = os_strdup(cmd);
   4314 		if (new_params == NULL)
   4315 			return -1;
   4316 	}
   4317 
   4318 	os_free(wpa_s->conf->autoscan);
   4319 	wpa_s->conf->autoscan = new_params;
   4320 
   4321 	if (wpa_s->conf->autoscan == NULL)
   4322 		autoscan_deinit(wpa_s);
   4323 	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
   4324 		autoscan_init(wpa_s, 1);
   4325 	else if (state == WPA_SCANNING)
   4326 		wpa_supplicant_reinit_autoscan(wpa_s);
   4327 
   4328 	return 0;
   4329 }
   4330 
   4331 #endif /* CONFIG_AUTOSCAN */
   4332 
   4333 
   4334 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
   4335 				      size_t buflen)
   4336 {
   4337 	struct wpa_signal_info si;
   4338 	int ret;
   4339 
   4340 	ret = wpa_drv_signal_poll(wpa_s, &si);
   4341 	if (ret)
   4342 		return -1;
   4343 
   4344 	ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
   4345 			  "NOISE=%d\nFREQUENCY=%u\n",
   4346 			  si.current_signal, si.current_txrate / 1000,
   4347 			  si.current_noise, si.frequency);
   4348 	if (ret < 0 || (unsigned int) ret > buflen)
   4349 		return -1;
   4350 	return ret;
   4351 }
   4352 
   4353 
   4354 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
   4355 				      size_t buflen)
   4356 {
   4357 	struct hostap_sta_driver_data sta;
   4358 	int ret;
   4359 
   4360 	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
   4361 	if (ret)
   4362 		return -1;
   4363 
   4364 	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
   4365 			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
   4366 	if (ret < 0 || (size_t) ret > buflen)
   4367 		return -1;
   4368 	return ret;
   4369 }
   4370 
   4371 
   4372 #ifdef ANDROID
   4373 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
   4374 				     char *buf, size_t buflen)
   4375 {
   4376 	int ret;
   4377 
   4378 	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
   4379 	if (ret == 0)
   4380 		ret = sprintf(buf, "%s\n", "OK");
   4381 	return ret;
   4382 }
   4383 #endif
   4384 
   4385 
   4386 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
   4387 					 char *buf, size_t *resp_len)
   4388 {
   4389 	char *reply;
   4390 	const int reply_size = 4096;
   4391 	int ctrl_rsp = 0;
   4392 	int reply_len;
   4393 
   4394 	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
   4395 	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
   4396 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
   4397 				      (const u8 *) buf, os_strlen(buf));
   4398 	} else {
   4399 		int level = MSG_DEBUG;
   4400 		if (os_strcmp(buf, "PING") == 0)
   4401 			level = MSG_EXCESSIVE;
   4402 		wpa_hexdump_ascii(level, "RX ctrl_iface",
   4403 				  (const u8 *) buf, os_strlen(buf));
   4404 		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
   4405 	}
   4406 
   4407 	reply = os_malloc(reply_size);
   4408 	if (reply == NULL) {
   4409 		*resp_len = 1;
   4410 		return NULL;
   4411 	}
   4412 
   4413 	os_memcpy(reply, "OK\n", 3);
   4414 	reply_len = 3;
   4415 
   4416 	if (os_strcmp(buf, "PING") == 0) {
   4417 		os_memcpy(reply, "PONG\n", 5);
   4418 		reply_len = 5;
   4419 	} else if (os_strcmp(buf, "IFNAME") == 0) {
   4420 		reply_len = os_strlen(wpa_s->ifname);
   4421 		os_memcpy(reply, wpa_s->ifname, reply_len);
   4422 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
   4423 		if (wpa_debug_reopen_file() < 0)
   4424 			reply_len = -1;
   4425 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
   4426 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
   4427 	} else if (os_strcmp(buf, "MIB") == 0) {
   4428 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
   4429 		if (reply_len >= 0) {
   4430 			int res;
   4431 			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
   4432 					       reply_size - reply_len);
   4433 			if (res < 0)
   4434 				reply_len = -1;
   4435 			else
   4436 				reply_len += res;
   4437 		}
   4438 	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
   4439 		reply_len = wpa_supplicant_ctrl_iface_status(
   4440 			wpa_s, buf + 6, reply, reply_size);
   4441 	} else if (os_strcmp(buf, "PMKSA") == 0) {
   4442 		reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
   4443 						    reply_size);
   4444 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
   4445 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
   4446 			reply_len = -1;
   4447 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
   4448 		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
   4449 							  reply, reply_size);
   4450 	} else if (os_strcmp(buf, "LOGON") == 0) {
   4451 		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
   4452 	} else if (os_strcmp(buf, "LOGOFF") == 0) {
   4453 		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
   4454 	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
   4455 		wpa_s->normal_scans = 0;
   4456 		wpa_supplicant_reinit_autoscan(wpa_s);
   4457 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
   4458 			reply_len = -1;
   4459 		else {
   4460 			wpa_s->disconnected = 0;
   4461 			wpa_s->reassociate = 1;
   4462 			wpa_supplicant_req_scan(wpa_s, 0, 0);
   4463 		}
   4464 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
   4465 		wpa_s->normal_scans = 0;
   4466 		wpa_supplicant_reinit_autoscan(wpa_s);
   4467 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
   4468 			reply_len = -1;
   4469 		else if (wpa_s->disconnected) {
   4470 			wpa_s->disconnected = 0;
   4471 			wpa_s->reassociate = 1;
   4472 			wpa_supplicant_req_scan(wpa_s, 0, 0);
   4473 		}
   4474 #ifdef IEEE8021X_EAPOL
   4475 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
   4476 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
   4477 			reply_len = -1;
   4478 #endif /* IEEE8021X_EAPOL */
   4479 #ifdef CONFIG_PEERKEY
   4480 	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
   4481 		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
   4482 			reply_len = -1;
   4483 #endif /* CONFIG_PEERKEY */
   4484 #ifdef CONFIG_IEEE80211R
   4485 	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
   4486 		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
   4487 			reply_len = -1;
   4488 #endif /* CONFIG_IEEE80211R */
   4489 #ifdef CONFIG_WPS
   4490 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
   4491 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
   4492 		if (res == -2) {
   4493 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
   4494 			reply_len = 17;
   4495 		} else if (res)
   4496 			reply_len = -1;
   4497 	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
   4498 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
   4499 		if (res == -2) {
   4500 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
   4501 			reply_len = 17;
   4502 		} else if (res)
   4503 			reply_len = -1;
   4504 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
   4505 		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
   4506 							      reply,
   4507 							      reply_size);
   4508 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
   4509 		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
   4510 			wpa_s, buf + 14, reply, reply_size);
   4511 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
   4512 		if (wpas_wps_cancel(wpa_s))
   4513 			reply_len = -1;
   4514 #ifdef CONFIG_WPS_OOB
   4515 	} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
   4516 		if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
   4517 			reply_len = -1;
   4518 #endif /* CONFIG_WPS_OOB */
   4519 #ifdef CONFIG_WPS_NFC
   4520 	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
   4521 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
   4522 			reply_len = -1;
   4523 	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
   4524 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
   4525 			reply_len = -1;
   4526 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
   4527 		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
   4528 			wpa_s, buf + 14, reply, reply_size);
   4529 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
   4530 		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
   4531 							       buf + 17))
   4532 			reply_len = -1;
   4533 #endif /* CONFIG_WPS_NFC */
   4534 	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
   4535 		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
   4536 			reply_len = -1;
   4537 #ifdef CONFIG_AP
   4538 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
   4539 		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
   4540 			wpa_s, buf + 11, reply, reply_size);
   4541 #endif /* CONFIG_AP */
   4542 #ifdef CONFIG_WPS_ER
   4543 	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
   4544 		if (wpas_wps_er_start(wpa_s, NULL))
   4545 			reply_len = -1;
   4546 	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
   4547 		if (wpas_wps_er_start(wpa_s, buf + 13))
   4548 			reply_len = -1;
   4549 	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
   4550 		if (wpas_wps_er_stop(wpa_s))
   4551 			reply_len = -1;
   4552 	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
   4553 		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
   4554 			reply_len = -1;
   4555 	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
   4556 		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
   4557 		if (ret == -2) {
   4558 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
   4559 			reply_len = 17;
   4560 		} else if (ret == -3) {
   4561 			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
   4562 			reply_len = 18;
   4563 		} else if (ret == -4) {
   4564 			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
   4565 			reply_len = 20;
   4566 		} else if (ret)
   4567 			reply_len = -1;
   4568 	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
   4569 		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
   4570 			reply_len = -1;
   4571 	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
   4572 		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
   4573 								buf + 18))
   4574 			reply_len = -1;
   4575 	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
   4576 		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
   4577 			reply_len = -1;
   4578 #ifdef CONFIG_WPS_NFC
   4579 	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
   4580 		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
   4581 			wpa_s, buf + 24, reply, reply_size);
   4582 #endif /* CONFIG_WPS_NFC */
   4583 #endif /* CONFIG_WPS_ER */
   4584 #endif /* CONFIG_WPS */
   4585 #ifdef CONFIG_IBSS_RSN
   4586 	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
   4587 		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
   4588 			reply_len = -1;
   4589 #endif /* CONFIG_IBSS_RSN */
   4590 #ifdef CONFIG_P2P
   4591 	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
   4592 		if (p2p_ctrl_find(wpa_s, buf + 9))
   4593 			reply_len = -1;
   4594 	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
   4595 		if (p2p_ctrl_find(wpa_s, ""))
   4596 			reply_len = -1;
   4597 	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
   4598 		wpas_p2p_stop_find(wpa_s);
   4599 	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
   4600 		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
   4601 					     reply_size);
   4602 	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
   4603 		if (p2p_ctrl_listen(wpa_s, buf + 11))
   4604 			reply_len = -1;
   4605 	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
   4606 		if (p2p_ctrl_listen(wpa_s, ""))
   4607 			reply_len = -1;
   4608 	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
   4609 		if (wpas_p2p_group_remove(wpa_s, buf + 17))
   4610 			reply_len = -1;
   4611 	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
   4612 		if (wpas_p2p_group_add(wpa_s, 0, 0, 0))
   4613 			reply_len = -1;
   4614 	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
   4615 		if (p2p_ctrl_group_add(wpa_s, buf + 14))
   4616 			reply_len = -1;
   4617 	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
   4618 		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
   4619 			reply_len = -1;
   4620 	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
   4621 		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
   4622 	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
   4623 		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
   4624 						   reply_size);
   4625 	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
   4626 		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
   4627 			reply_len = -1;
   4628 	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
   4629 		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
   4630 			reply_len = -1;
   4631 	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
   4632 #ifdef ANDROID_P2P
   4633 		wpas_p2p_sd_service_update(wpa_s, SRV_UPDATE);
   4634 #else
   4635 		wpas_p2p_sd_service_update(wpa_s);
   4636 #endif
   4637 	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
   4638 		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
   4639 			reply_len = -1;
   4640 	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
   4641 		wpas_p2p_service_flush(wpa_s);
   4642 	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
   4643 		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
   4644 			reply_len = -1;
   4645 	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
   4646 		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
   4647 			reply_len = -1;
   4648 	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
   4649 		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
   4650 			reply_len = -1;
   4651 	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
   4652 		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
   4653 			reply_len = -1;
   4654 	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
   4655 		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
   4656 					      reply_size);
   4657 	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
   4658 		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
   4659 			reply_len = -1;
   4660 	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
   4661 		os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
   4662 		wpa_s->force_long_sd = 0;
   4663 		if (wpa_s->global->p2p)
   4664 			p2p_flush(wpa_s->global->p2p);
   4665 	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
   4666 		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
   4667 			reply_len = -1;
   4668 	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
   4669 		if (wpas_p2p_cancel(wpa_s))
   4670 			reply_len = -1;
   4671 	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
   4672 		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
   4673 			reply_len = -1;
   4674 	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
   4675 		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
   4676 			reply_len = -1;
   4677 	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
   4678 		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
   4679 			reply_len = -1;
   4680 	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
   4681 		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
   4682 			reply_len = -1;
   4683 #endif /* CONFIG_P2P */
   4684 #ifdef CONFIG_WIFI_DISPLAY
   4685 	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
   4686 		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
   4687 			reply_len = -1;
   4688 	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
   4689 		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
   4690 						     reply, reply_size);
   4691 #endif /* CONFIG_WIFI_DISPLAY */
   4692 #ifdef CONFIG_INTERWORKING
   4693 	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
   4694 		if (interworking_fetch_anqp(wpa_s) < 0)
   4695 			reply_len = -1;
   4696 	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
   4697 		interworking_stop_fetch_anqp(wpa_s);
   4698 	} else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) {
   4699 		if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") !=
   4700 					NULL) < 0)
   4701 			reply_len = -1;
   4702 	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
   4703 		if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
   4704 			reply_len = -1;
   4705 	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
   4706 		if (get_anqp(wpa_s, buf + 9) < 0)
   4707 			reply_len = -1;
   4708 	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
   4709 		if (gas_request(wpa_s, buf + 12) < 0)
   4710 			reply_len = -1;
   4711 	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
   4712 		reply_len = gas_response_get(wpa_s, buf + 17, reply,
   4713 					     reply_size);
   4714 #endif /* CONFIG_INTERWORKING */
   4715 #ifdef CONFIG_HS20
   4716 	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
   4717 		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
   4718 			reply_len = -1;
   4719 	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
   4720 		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
   4721 			reply_len = -1;
   4722 #endif /* CONFIG_HS20 */
   4723 	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
   4724 	{
   4725 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
   4726 			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
   4727 			reply_len = -1;
   4728 		else
   4729 			ctrl_rsp = 1;
   4730 	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
   4731 		if (wpa_supplicant_reload_configuration(wpa_s))
   4732 			reply_len = -1;
   4733 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   4734 		wpa_supplicant_terminate_proc(wpa_s->global);
   4735 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
   4736 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
   4737 			reply_len = -1;
   4738 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
   4739 		reply_len = wpa_supplicant_ctrl_iface_blacklist(
   4740 			wpa_s, buf + 9, reply, reply_size);
   4741 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
   4742 		reply_len = wpa_supplicant_ctrl_iface_log_level(
   4743 			wpa_s, buf + 9, reply, reply_size);
   4744 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
   4745 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
   4746 			wpa_s, reply, reply_size);
   4747 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
   4748 #ifdef CONFIG_SME
   4749 		wpa_s->sme.prev_bssid_set = 0;
   4750 #endif /* CONFIG_SME */
   4751 		wpa_s->reassociate = 0;
   4752 		wpa_s->disconnected = 1;
   4753 		wpa_supplicant_cancel_sched_scan(wpa_s);
   4754 		wpa_supplicant_cancel_scan(wpa_s);
   4755 		wpa_supplicant_deauthenticate(wpa_s,
   4756 					      WLAN_REASON_DEAUTH_LEAVING);
   4757 	} else if (os_strcmp(buf, "SCAN") == 0) {
   4758 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
   4759 			reply_len = -1;
   4760 		else {
   4761 			if (!wpa_s->scanning &&
   4762 			    ((wpa_s->wpa_state <= WPA_SCANNING) ||
   4763 			     (wpa_s->wpa_state == WPA_COMPLETED))) {
   4764 				wpa_s->normal_scans = 0;
   4765 				wpa_s->scan_req = 2;
   4766 				wpa_supplicant_req_scan(wpa_s, 0, 0);
   4767 			} else if (wpa_s->sched_scanning) {
   4768 				wpa_printf(MSG_DEBUG, "Stop ongoing "
   4769 					   "sched_scan to allow requested "
   4770 					   "full scan to proceed");
   4771 				wpa_supplicant_cancel_sched_scan(wpa_s);
   4772 				wpa_s->scan_req = 2;
   4773 				wpa_supplicant_req_scan(wpa_s, 0, 0);
   4774 			} else {
   4775 				wpa_printf(MSG_DEBUG, "Ongoing scan action - "
   4776 					   "reject new request");
   4777 				reply_len = os_snprintf(reply, reply_size,
   4778 							"FAIL-BUSY\n");
   4779 			}
   4780 		}
   4781 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
   4782 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
   4783 			wpa_s, reply, reply_size);
   4784 	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
   4785 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
   4786 			reply_len = -1;
   4787 	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
   4788 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
   4789 			reply_len = -1;
   4790 	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
   4791 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
   4792 			reply_len = -1;
   4793 	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
   4794 		reply_len = wpa_supplicant_ctrl_iface_add_network(
   4795 			wpa_s, reply, reply_size);
   4796 	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
   4797 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
   4798 			reply_len = -1;
   4799 	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
   4800 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
   4801 			reply_len = -1;
   4802 	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
   4803 		reply_len = wpa_supplicant_ctrl_iface_get_network(
   4804 			wpa_s, buf + 12, reply, reply_size);
   4805 	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
   4806 		reply_len = wpa_supplicant_ctrl_iface_list_creds(
   4807 			wpa_s, reply, reply_size);
   4808 	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
   4809 		reply_len = wpa_supplicant_ctrl_iface_add_cred(
   4810 			wpa_s, reply, reply_size);
   4811 	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
   4812 		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
   4813 			reply_len = -1;
   4814 	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
   4815 		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
   4816 			reply_len = -1;
   4817 #ifndef CONFIG_NO_CONFIG_WRITE
   4818 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
   4819 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
   4820 			reply_len = -1;
   4821 #endif /* CONFIG_NO_CONFIG_WRITE */
   4822 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
   4823 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
   4824 			wpa_s, buf + 15, reply, reply_size);
   4825 	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
   4826 		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
   4827 			reply_len = -1;
   4828 	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
   4829 		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
   4830 			reply_len = -1;
   4831 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
   4832 		reply_len = wpa_supplicant_global_iface_list(
   4833 			wpa_s->global, reply, reply_size);
   4834 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
   4835 		reply_len = wpa_supplicant_global_iface_interfaces(
   4836 			wpa_s->global, reply, reply_size);
   4837 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
   4838 		reply_len = wpa_supplicant_ctrl_iface_bss(
   4839 			wpa_s, buf + 4, reply, reply_size);
   4840 #ifdef CONFIG_AP
   4841 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
   4842 		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
   4843 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
   4844 		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
   4845 					      reply_size);
   4846 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
   4847 		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
   4848 						   reply_size);
   4849 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
   4850 		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
   4851 			reply_len = -1;
   4852 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
   4853 		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
   4854 			reply_len = -1;
   4855 #endif /* CONFIG_AP */
   4856 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
   4857 		wpas_notify_suspend(wpa_s->global);
   4858 	} else if (os_strcmp(buf, "RESUME") == 0) {
   4859 		wpas_notify_resume(wpa_s->global);
   4860 	} else if (os_strcmp(buf, "DROP_SA") == 0) {
   4861 		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
   4862 	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
   4863 		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
   4864 			reply_len = -1;
   4865 	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
   4866 		if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
   4867 			reply_len = -1;
   4868 	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
   4869 		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
   4870 			reply_len = -1;
   4871 	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
   4872 		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
   4873 							       buf + 17))
   4874 			reply_len = -1;
   4875 	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
   4876 		if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10))
   4877 			reply_len = -1;
   4878 #ifdef CONFIG_TDLS
   4879 	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
   4880 		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
   4881 			reply_len = -1;
   4882 	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
   4883 		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
   4884 			reply_len = -1;
   4885 	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
   4886 		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
   4887 			reply_len = -1;
   4888 #endif /* CONFIG_TDLS */
   4889 	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
   4890 		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
   4891 						       reply_size);
   4892 	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
   4893 		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
   4894 						       reply_size);
   4895 #ifdef CONFIG_AUTOSCAN
   4896 	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
   4897 		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
   4898 			reply_len = -1;
   4899 #endif /* CONFIG_AUTOSCAN */
   4900 #ifdef ANDROID
   4901 	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
   4902 		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
   4903 						      reply_size);
   4904 #endif
   4905 	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
   4906 		eapol_sm_request_reauth(wpa_s->eapol);
   4907 	} else {
   4908 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   4909 		reply_len = 16;
   4910 	}
   4911 
   4912 	if (reply_len < 0) {
   4913 		os_memcpy(reply, "FAIL\n", 5);
   4914 		reply_len = 5;
   4915 	}
   4916 
   4917 	if (ctrl_rsp)
   4918 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
   4919 
   4920 	*resp_len = reply_len;
   4921 	return reply;
   4922 }
   4923 
   4924 
   4925 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
   4926 					   char *cmd)
   4927 {
   4928 	struct wpa_interface iface;
   4929 	char *pos;
   4930 
   4931 	/*
   4932 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
   4933 	 * TAB<bridge_ifname>
   4934 	 */
   4935 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
   4936 
   4937 	os_memset(&iface, 0, sizeof(iface));
   4938 
   4939 	do {
   4940 		iface.ifname = pos = cmd;
   4941 		pos = os_strchr(pos, '\t');
   4942 		if (pos)
   4943 			*pos++ = '\0';
   4944 		if (iface.ifname[0] == '\0')
   4945 			return -1;
   4946 		if (pos == NULL)
   4947 			break;
   4948 
   4949 		iface.confname = pos;
   4950 		pos = os_strchr(pos, '\t');
   4951 		if (pos)
   4952 			*pos++ = '\0';
   4953 		if (iface.confname[0] == '\0')
   4954 			iface.confname = NULL;
   4955 		if (pos == NULL)
   4956 			break;
   4957 
   4958 		iface.driver = pos;
   4959 		pos = os_strchr(pos, '\t');
   4960 		if (pos)
   4961 			*pos++ = '\0';
   4962 		if (iface.driver[0] == '\0')
   4963 			iface.driver = NULL;
   4964 		if (pos == NULL)
   4965 			break;
   4966 
   4967 		iface.ctrl_interface = pos;
   4968 		pos = os_strchr(pos, '\t');
   4969 		if (pos)
   4970 			*pos++ = '\0';
   4971 		if (iface.ctrl_interface[0] == '\0')
   4972 			iface.ctrl_interface = NULL;
   4973 		if (pos == NULL)
   4974 			break;
   4975 
   4976 		iface.driver_param = pos;
   4977 		pos = os_strchr(pos, '\t');
   4978 		if (pos)
   4979 			*pos++ = '\0';
   4980 		if (iface.driver_param[0] == '\0')
   4981 			iface.driver_param = NULL;
   4982 		if (pos == NULL)
   4983 			break;
   4984 
   4985 		iface.bridge_ifname = pos;
   4986 		pos = os_strchr(pos, '\t');
   4987 		if (pos)
   4988 			*pos++ = '\0';
   4989 		if (iface.bridge_ifname[0] == '\0')
   4990 			iface.bridge_ifname = NULL;
   4991 		if (pos == NULL)
   4992 			break;
   4993 	} while (0);
   4994 
   4995 	if (wpa_supplicant_get_iface(global, iface.ifname))
   4996 		return -1;
   4997 
   4998 	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
   4999 }
   5000 
   5001 
   5002 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
   5003 					      char *cmd)
   5004 {
   5005 	struct wpa_supplicant *wpa_s;
   5006 
   5007 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
   5008 
   5009 	wpa_s = wpa_supplicant_get_iface(global, cmd);
   5010 	if (wpa_s == NULL)
   5011 		return -1;
   5012 	return wpa_supplicant_remove_iface(global, wpa_s, 0);
   5013 }
   5014 
   5015 
   5016 static void wpa_free_iface_info(struct wpa_interface_info *iface)
   5017 {
   5018 	struct wpa_interface_info *prev;
   5019 
   5020 	while (iface) {
   5021 		prev = iface;
   5022 		iface = iface->next;
   5023 
   5024 		os_free(prev->ifname);
   5025 		os_free(prev->desc);
   5026 		os_free(prev);
   5027 	}
   5028 }
   5029 
   5030 
   5031 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
   5032 					    char *buf, int len)
   5033 {
   5034 	int i, res;
   5035 	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
   5036 	char *pos, *end;
   5037 
   5038 	for (i = 0; wpa_drivers[i]; i++) {
   5039 		struct wpa_driver_ops *drv = wpa_drivers[i];
   5040 		if (drv->get_interfaces == NULL)
   5041 			continue;
   5042 		tmp = drv->get_interfaces(global->drv_priv[i]);
   5043 		if (tmp == NULL)
   5044 			continue;
   5045 
   5046 		if (last == NULL)
   5047 			iface = last = tmp;
   5048 		else
   5049 			last->next = tmp;
   5050 		while (last->next)
   5051 			last = last->next;
   5052 	}
   5053 
   5054 	pos = buf;
   5055 	end = buf + len;
   5056 	for (tmp = iface; tmp; tmp = tmp->next) {
   5057 		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
   5058 				  tmp->drv_name, tmp->ifname,
   5059 				  tmp->desc ? tmp->desc : "");
   5060 		if (res < 0 || res >= end - pos) {
   5061 			*pos = '\0';
   5062 			break;
   5063 		}
   5064 		pos += res;
   5065 	}
   5066 
   5067 	wpa_free_iface_info(iface);
   5068 
   5069 	return pos - buf;
   5070 }
   5071 
   5072 
   5073 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
   5074 						  char *buf, int len)
   5075 {
   5076 	int res;
   5077 	char *pos, *end;
   5078 	struct wpa_supplicant *wpa_s;
   5079 
   5080 	wpa_s = global->ifaces;
   5081 	pos = buf;
   5082 	end = buf + len;
   5083 
   5084 	while (wpa_s) {
   5085 		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
   5086 		if (res < 0 || res >= end - pos) {
   5087 			*pos = '\0';
   5088 			break;
   5089 		}
   5090 		pos += res;
   5091 		wpa_s = wpa_s->next;
   5092 	}
   5093 	return pos - buf;
   5094 }
   5095 
   5096 
   5097 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
   5098 						char *buf, size_t *resp_len)
   5099 {
   5100 	char *reply;
   5101 	const int reply_size = 2048;
   5102 	int reply_len;
   5103 	int level = MSG_DEBUG;
   5104 
   5105 	if (os_strcmp(buf, "PING") == 0)
   5106 		level = MSG_EXCESSIVE;
   5107 	wpa_hexdump_ascii(level, "RX global ctrl_iface",
   5108 			  (const u8 *) buf, os_strlen(buf));
   5109 
   5110 	reply = os_malloc(reply_size);
   5111 	if (reply == NULL) {
   5112 		*resp_len = 1;
   5113 		return NULL;
   5114 	}
   5115 
   5116 	os_memcpy(reply, "OK\n", 3);
   5117 	reply_len = 3;
   5118 
   5119 	if (os_strcmp(buf, "PING") == 0) {
   5120 		os_memcpy(reply, "PONG\n", 5);
   5121 		reply_len = 5;
   5122 	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
   5123 		if (wpa_supplicant_global_iface_add(global, buf + 14))
   5124 			reply_len = -1;
   5125 	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
   5126 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
   5127 			reply_len = -1;
   5128 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
   5129 		reply_len = wpa_supplicant_global_iface_list(
   5130 			global, reply, reply_size);
   5131 	} else if (os_strcmp(buf, "INTERFACES") == 0) {
   5132 		reply_len = wpa_supplicant_global_iface_interfaces(
   5133 			global, reply, reply_size);
   5134 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   5135 		wpa_supplicant_terminate_proc(global);
   5136 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
   5137 		wpas_notify_suspend(global);
   5138 	} else if (os_strcmp(buf, "RESUME") == 0) {
   5139 		wpas_notify_resume(global);
   5140 	} else {
   5141 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   5142 		reply_len = 16;
   5143 	}
   5144 
   5145 	if (reply_len < 0) {
   5146 		os_memcpy(reply, "FAIL\n", 5);
   5147 		reply_len = 5;
   5148 	}
   5149 
   5150 	*resp_len = reply_len;
   5151 	return reply;
   5152 }
   5153