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