Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * WPA Supplicant / Control interface (shared code for all backends)
      3  * Copyright (c) 2004-2015, 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 #ifdef CONFIG_TESTING_OPTIONS
     11 #include <net/ethernet.h>
     12 #include <netinet/ip.h>
     13 #endif /* CONFIG_TESTING_OPTIONS */
     14 
     15 #include "utils/common.h"
     16 #include "utils/eloop.h"
     17 #include "utils/uuid.h"
     18 #include "utils/module_tests.h"
     19 #include "common/version.h"
     20 #include "common/ieee802_11_defs.h"
     21 #include "common/ieee802_11_common.h"
     22 #include "common/wpa_ctrl.h"
     23 #include "crypto/tls.h"
     24 #include "ap/hostapd.h"
     25 #include "eap_peer/eap.h"
     26 #include "eapol_supp/eapol_supp_sm.h"
     27 #include "rsn_supp/wpa.h"
     28 #include "rsn_supp/preauth.h"
     29 #include "rsn_supp/pmksa_cache.h"
     30 #include "l2_packet/l2_packet.h"
     31 #include "wps/wps.h"
     32 #include "fst/fst.h"
     33 #include "fst/fst_ctrl_iface.h"
     34 #include "config.h"
     35 #include "wpa_supplicant_i.h"
     36 #include "driver_i.h"
     37 #include "wps_supplicant.h"
     38 #include "ibss_rsn.h"
     39 #include "ap.h"
     40 #include "p2p_supplicant.h"
     41 #include "p2p/p2p.h"
     42 #include "hs20_supplicant.h"
     43 #include "wifi_display.h"
     44 #include "notify.h"
     45 #include "bss.h"
     46 #include "scan.h"
     47 #include "ctrl_iface.h"
     48 #include "interworking.h"
     49 #include "blacklist.h"
     50 #include "autoscan.h"
     51 #include "wnm_sta.h"
     52 #include "offchannel.h"
     53 #include "drivers/driver.h"
     54 #include "mesh.h"
     55 
     56 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
     57 					    char *buf, int len);
     58 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
     59 						  const char *input,
     60 						  char *buf, int len);
     61 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
     62 					char *val);
     63 
     64 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
     65 {
     66 	char *pos;
     67 	u8 addr[ETH_ALEN], *filter = NULL, *n;
     68 	size_t count = 0;
     69 
     70 	pos = val;
     71 	while (pos) {
     72 		if (*pos == '\0')
     73 			break;
     74 		if (hwaddr_aton(pos, addr)) {
     75 			os_free(filter);
     76 			return -1;
     77 		}
     78 		n = os_realloc_array(filter, count + 1, ETH_ALEN);
     79 		if (n == NULL) {
     80 			os_free(filter);
     81 			return -1;
     82 		}
     83 		filter = n;
     84 		os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
     85 		count++;
     86 
     87 		pos = os_strchr(pos, ' ');
     88 		if (pos)
     89 			pos++;
     90 	}
     91 
     92 	wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
     93 	os_free(wpa_s->bssid_filter);
     94 	wpa_s->bssid_filter = filter;
     95 	wpa_s->bssid_filter_count = count;
     96 
     97 	return 0;
     98 }
     99 
    100 
    101 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
    102 {
    103 	char *pos;
    104 	u8 addr[ETH_ALEN], *bssid = NULL, *n;
    105 	struct wpa_ssid_value *ssid = NULL, *ns;
    106 	size_t count = 0, ssid_count = 0;
    107 	struct wpa_ssid *c;
    108 
    109 	/*
    110 	 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
    111 	 * SSID_SPEC ::= ssid <SSID_HEX>
    112 	 * BSSID_SPEC ::= bssid <BSSID_HEX>
    113 	 */
    114 
    115 	pos = val;
    116 	while (pos) {
    117 		if (*pos == '\0')
    118 			break;
    119 		if (os_strncmp(pos, "bssid ", 6) == 0) {
    120 			int res;
    121 			pos += 6;
    122 			res = hwaddr_aton2(pos, addr);
    123 			if (res < 0) {
    124 				os_free(ssid);
    125 				os_free(bssid);
    126 				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
    127 					   "BSSID value '%s'", pos);
    128 				return -1;
    129 			}
    130 			pos += res;
    131 			n = os_realloc_array(bssid, count + 1, ETH_ALEN);
    132 			if (n == NULL) {
    133 				os_free(ssid);
    134 				os_free(bssid);
    135 				return -1;
    136 			}
    137 			bssid = n;
    138 			os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
    139 			count++;
    140 		} else if (os_strncmp(pos, "ssid ", 5) == 0) {
    141 			char *end;
    142 			pos += 5;
    143 
    144 			end = pos;
    145 			while (*end) {
    146 				if (*end == '\0' || *end == ' ')
    147 					break;
    148 				end++;
    149 			}
    150 
    151 			ns = os_realloc_array(ssid, ssid_count + 1,
    152 					      sizeof(struct wpa_ssid_value));
    153 			if (ns == NULL) {
    154 				os_free(ssid);
    155 				os_free(bssid);
    156 				return -1;
    157 			}
    158 			ssid = ns;
    159 
    160 			if ((end - pos) & 0x01 ||
    161 			    end - pos > 2 * SSID_MAX_LEN ||
    162 			    hexstr2bin(pos, ssid[ssid_count].ssid,
    163 				       (end - pos) / 2) < 0) {
    164 				os_free(ssid);
    165 				os_free(bssid);
    166 				wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
    167 					   "SSID value '%s'", pos);
    168 				return -1;
    169 			}
    170 			ssid[ssid_count].ssid_len = (end - pos) / 2;
    171 			wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
    172 					  ssid[ssid_count].ssid,
    173 					  ssid[ssid_count].ssid_len);
    174 			ssid_count++;
    175 			pos = end;
    176 		} else {
    177 			wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
    178 				   "'%s'", pos);
    179 			os_free(ssid);
    180 			os_free(bssid);
    181 			return -1;
    182 		}
    183 
    184 		pos = os_strchr(pos, ' ');
    185 		if (pos)
    186 			pos++;
    187 	}
    188 
    189 	wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
    190 	os_free(wpa_s->disallow_aps_bssid);
    191 	wpa_s->disallow_aps_bssid = bssid;
    192 	wpa_s->disallow_aps_bssid_count = count;
    193 
    194 	wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
    195 	os_free(wpa_s->disallow_aps_ssid);
    196 	wpa_s->disallow_aps_ssid = ssid;
    197 	wpa_s->disallow_aps_ssid_count = ssid_count;
    198 
    199 	if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
    200 		return 0;
    201 
    202 	c = wpa_s->current_ssid;
    203 	if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
    204 		return 0;
    205 
    206 	if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
    207 	    !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
    208 		return 0;
    209 
    210 	wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
    211 		   "because current AP was marked disallowed");
    212 
    213 #ifdef CONFIG_SME
    214 	wpa_s->sme.prev_bssid_set = 0;
    215 #endif /* CONFIG_SME */
    216 	wpa_s->reassociate = 1;
    217 	wpa_s->own_disconnect_req = 1;
    218 	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
    219 	wpa_supplicant_req_scan(wpa_s, 0, 0);
    220 
    221 	return 0;
    222 }
    223 
    224 
    225 #ifndef CONFIG_NO_CONFIG_BLOBS
    226 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
    227 {
    228 	char *name = pos;
    229 	struct wpa_config_blob *blob;
    230 	size_t len;
    231 
    232 	pos = os_strchr(pos, ' ');
    233 	if (pos == NULL)
    234 		return -1;
    235 	*pos++ = '\0';
    236 	len = os_strlen(pos);
    237 	if (len & 1)
    238 		return -1;
    239 
    240 	wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
    241 	blob = os_zalloc(sizeof(*blob));
    242 	if (blob == NULL)
    243 		return -1;
    244 	blob->name = os_strdup(name);
    245 	blob->data = os_malloc(len / 2);
    246 	if (blob->name == NULL || blob->data == NULL) {
    247 		wpa_config_free_blob(blob);
    248 		return -1;
    249 	}
    250 
    251 	if (hexstr2bin(pos, blob->data, len / 2) < 0) {
    252 		wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
    253 		wpa_config_free_blob(blob);
    254 		return -1;
    255 	}
    256 	blob->len = len / 2;
    257 
    258 	wpa_config_set_blob(wpa_s->conf, blob);
    259 
    260 	return 0;
    261 }
    262 #endif /* CONFIG_NO_CONFIG_BLOBS */
    263 
    264 
    265 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
    266 {
    267 	char *params;
    268 	char *pos;
    269 	int *freqs = NULL;
    270 	int ret;
    271 
    272 	if (atoi(cmd)) {
    273 		params = os_strchr(cmd, ' ');
    274 		os_free(wpa_s->manual_sched_scan_freqs);
    275 		if (params) {
    276 			params++;
    277 			pos = os_strstr(params, "freq=");
    278 			if (pos)
    279 				freqs = freq_range_to_channel_list(wpa_s,
    280 								   pos + 5);
    281 		}
    282 		wpa_s->manual_sched_scan_freqs = freqs;
    283 		ret = wpas_start_pno(wpa_s);
    284 	} else {
    285 		ret = wpas_stop_pno(wpa_s);
    286 	}
    287 	return ret;
    288 }
    289 
    290 
    291 static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
    292 {
    293 	union wpa_event_data event;
    294 
    295 	if (os_strcmp(band, "AUTO") == 0)
    296 		wpa_s->setband = WPA_SETBAND_AUTO;
    297 	else if (os_strcmp(band, "5G") == 0)
    298 		wpa_s->setband = WPA_SETBAND_5G;
    299 	else if (os_strcmp(band, "2G") == 0)
    300 		wpa_s->setband = WPA_SETBAND_2G;
    301 	else
    302 		return -1;
    303 
    304 	if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
    305 		os_memset(&event, 0, sizeof(event));
    306 		event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
    307 		event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
    308 		wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
    309 	}
    310 
    311 	return 0;
    312 }
    313 
    314 
    315 static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
    316 				   const char *cmd)
    317 {
    318 	struct wpabuf *lci;
    319 
    320 	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
    321 		wpabuf_free(wpa_s->lci);
    322 		wpa_s->lci = NULL;
    323 		return 0;
    324 	}
    325 
    326 	lci = wpabuf_parse_bin(cmd);
    327 	if (!lci)
    328 		return -1;
    329 
    330 	if (os_get_reltime(&wpa_s->lci_time)) {
    331 		wpabuf_free(lci);
    332 		return -1;
    333 	}
    334 
    335 	wpabuf_free(wpa_s->lci);
    336 	wpa_s->lci = lci;
    337 
    338 	return 0;
    339 }
    340 
    341 
    342 static int
    343 wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
    344 {
    345 	int relative_rssi;
    346 
    347 	if (os_strcmp(cmd, "disable") == 0) {
    348 		wpa_s->srp.relative_rssi_set = 0;
    349 		return 0;
    350 	}
    351 
    352 	relative_rssi = atoi(cmd);
    353 	if (relative_rssi < 0 || relative_rssi > 100)
    354 		return -1;
    355 	wpa_s->srp.relative_rssi = relative_rssi;
    356 	wpa_s->srp.relative_rssi_set = 1;
    357 	return 0;
    358 }
    359 
    360 
    361 static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
    362 					      const char *cmd)
    363 {
    364 	char *pos;
    365 	int adjust_rssi;
    366 
    367 	/* <band>:adjust_value */
    368 	pos = os_strchr(cmd, ':');
    369 	if (!pos)
    370 		return -1;
    371 	pos++;
    372 	adjust_rssi = atoi(pos);
    373 	if (adjust_rssi < -100 || adjust_rssi > 100)
    374 		return -1;
    375 
    376 	if (os_strncmp(cmd, "2G", 2) == 0)
    377 		wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
    378 	else if (os_strncmp(cmd, "5G", 2) == 0)
    379 		wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
    380 	else
    381 		return -1;
    382 
    383 	wpa_s->srp.relative_adjust_rssi = adjust_rssi;
    384 
    385 	return 0;
    386 }
    387 
    388 
    389 static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
    390 				   const char *cmd)
    391 {
    392 	struct wpabuf *ric_ies;
    393 
    394 	if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
    395 		wpabuf_free(wpa_s->ric_ies);
    396 		wpa_s->ric_ies = NULL;
    397 		return 0;
    398 	}
    399 
    400 	ric_ies = wpabuf_parse_bin(cmd);
    401 	if (!ric_ies)
    402 		return -1;
    403 
    404 	wpabuf_free(wpa_s->ric_ies);
    405 	wpa_s->ric_ies = ric_ies;
    406 
    407 	return 0;
    408 }
    409 
    410 
    411 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
    412 					 char *cmd)
    413 {
    414 	char *value;
    415 	int ret = 0;
    416 
    417 	value = os_strchr(cmd, ' ');
    418 	if (value == NULL)
    419 		return -1;
    420 	*value++ = '\0';
    421 
    422 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    423 	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
    424 		eapol_sm_configure(wpa_s->eapol,
    425 				   atoi(value), -1, -1, -1);
    426 	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
    427 		eapol_sm_configure(wpa_s->eapol,
    428 				   -1, atoi(value), -1, -1);
    429 	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
    430 		eapol_sm_configure(wpa_s->eapol,
    431 				   -1, -1, atoi(value), -1);
    432 	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
    433 		eapol_sm_configure(wpa_s->eapol,
    434 				   -1, -1, -1, atoi(value));
    435 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
    436 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
    437 				     atoi(value))) {
    438 			ret = -1;
    439 		} else {
    440 			value[-1] = '=';
    441 			wpa_config_process_global(wpa_s->conf, cmd, -1);
    442 		}
    443 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
    444 		   0) {
    445 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
    446 				     atoi(value))) {
    447 			ret = -1;
    448 		} else {
    449 			value[-1] = '=';
    450 			wpa_config_process_global(wpa_s->conf, cmd, -1);
    451 		}
    452 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
    453 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
    454 				     atoi(value))) {
    455 			ret = -1;
    456 		} else {
    457 			value[-1] = '=';
    458 			wpa_config_process_global(wpa_s->conf, cmd, -1);
    459 		}
    460 	} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
    461 		wpa_s->wps_fragment_size = atoi(value);
    462 #ifdef CONFIG_WPS_TESTING
    463 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
    464 		long int val;
    465 		val = strtol(value, NULL, 0);
    466 		if (val < 0 || val > 0xff) {
    467 			ret = -1;
    468 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
    469 				   "wps_version_number %ld", val);
    470 		} else {
    471 			wps_version_number = val;
    472 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
    473 				   "version %u.%u",
    474 				   (wps_version_number & 0xf0) >> 4,
    475 				   wps_version_number & 0x0f);
    476 		}
    477 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
    478 		wps_testing_dummy_cred = atoi(value);
    479 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
    480 			   wps_testing_dummy_cred);
    481 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
    482 		wps_corrupt_pkhash = atoi(value);
    483 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
    484 			   wps_corrupt_pkhash);
    485 	} else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
    486 		if (value[0] == '\0') {
    487 			wps_force_auth_types_in_use = 0;
    488 		} else {
    489 			wps_force_auth_types = strtol(value, NULL, 0);
    490 			wps_force_auth_types_in_use = 1;
    491 		}
    492 	} else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
    493 		if (value[0] == '\0') {
    494 			wps_force_encr_types_in_use = 0;
    495 		} else {
    496 			wps_force_encr_types = strtol(value, NULL, 0);
    497 			wps_force_encr_types_in_use = 1;
    498 		}
    499 #endif /* CONFIG_WPS_TESTING */
    500 	} else if (os_strcasecmp(cmd, "ampdu") == 0) {
    501 		if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
    502 			ret = -1;
    503 #ifdef CONFIG_TDLS
    504 #ifdef CONFIG_TDLS_TESTING
    505 	} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
    506 		tdls_testing = strtol(value, NULL, 0);
    507 		wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
    508 #endif /* CONFIG_TDLS_TESTING */
    509 	} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
    510 		int disabled = atoi(value);
    511 		wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
    512 		if (disabled) {
    513 			if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
    514 				ret = -1;
    515 		} else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
    516 			ret = -1;
    517 		wpa_tdls_enable(wpa_s->wpa, !disabled);
    518 #endif /* CONFIG_TDLS */
    519 	} else if (os_strcasecmp(cmd, "pno") == 0) {
    520 		ret = wpas_ctrl_pno(wpa_s, value);
    521 	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
    522 		int disabled = atoi(value);
    523 		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
    524 			ret = -1;
    525 		else if (disabled)
    526 			wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
    527 	} else if (os_strcasecmp(cmd, "uapsd") == 0) {
    528 		if (os_strcmp(value, "disable") == 0)
    529 			wpa_s->set_sta_uapsd = 0;
    530 		else {
    531 			int be, bk, vi, vo;
    532 			char *pos;
    533 			/* format: BE,BK,VI,VO;max SP Length */
    534 			be = atoi(value);
    535 			pos = os_strchr(value, ',');
    536 			if (pos == NULL)
    537 				return -1;
    538 			pos++;
    539 			bk = atoi(pos);
    540 			pos = os_strchr(pos, ',');
    541 			if (pos == NULL)
    542 				return -1;
    543 			pos++;
    544 			vi = atoi(pos);
    545 			pos = os_strchr(pos, ',');
    546 			if (pos == NULL)
    547 				return -1;
    548 			pos++;
    549 			vo = atoi(pos);
    550 			/* ignore max SP Length for now */
    551 
    552 			wpa_s->set_sta_uapsd = 1;
    553 			wpa_s->sta_uapsd = 0;
    554 			if (be)
    555 				wpa_s->sta_uapsd |= BIT(0);
    556 			if (bk)
    557 				wpa_s->sta_uapsd |= BIT(1);
    558 			if (vi)
    559 				wpa_s->sta_uapsd |= BIT(2);
    560 			if (vo)
    561 				wpa_s->sta_uapsd |= BIT(3);
    562 		}
    563 	} else if (os_strcasecmp(cmd, "ps") == 0) {
    564 		ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
    565 #ifdef CONFIG_WIFI_DISPLAY
    566 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
    567 		int enabled = !!atoi(value);
    568 		if (enabled && !wpa_s->global->p2p)
    569 			ret = -1;
    570 		else
    571 			wifi_display_enable(wpa_s->global, enabled);
    572 #endif /* CONFIG_WIFI_DISPLAY */
    573 	} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
    574 		ret = set_bssid_filter(wpa_s, value);
    575 	} else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
    576 		ret = set_disallow_aps(wpa_s, value);
    577 	} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
    578 		wpa_s->no_keep_alive = !!atoi(value);
    579 #ifdef CONFIG_TESTING_OPTIONS
    580 	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
    581 		wpa_s->ext_mgmt_frame_handling = !!atoi(value);
    582 	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
    583 		wpa_s->ext_eapol_frame_io = !!atoi(value);
    584 #ifdef CONFIG_AP
    585 		if (wpa_s->ap_iface) {
    586 			wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
    587 				wpa_s->ext_eapol_frame_io;
    588 		}
    589 #endif /* CONFIG_AP */
    590 	} else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
    591 		wpa_s->extra_roc_dur = atoi(value);
    592 	} else if (os_strcasecmp(cmd, "test_failure") == 0) {
    593 		wpa_s->test_failure = atoi(value);
    594 	} else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
    595 		wpa_s->p2p_go_csa_on_inv = !!atoi(value);
    596 	} else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
    597 		wpa_s->ignore_auth_resp = !!atoi(value);
    598 	} else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
    599 		wpa_s->ignore_assoc_disallow = !!atoi(value);
    600 	} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
    601 		wpa_s->reject_btm_req_reason = atoi(value);
    602 	} else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
    603 		os_free(wpa_s->get_pref_freq_list_override);
    604 		if (!value[0])
    605 			wpa_s->get_pref_freq_list_override = NULL;
    606 		else
    607 			wpa_s->get_pref_freq_list_override = os_strdup(value);
    608 #endif /* CONFIG_TESTING_OPTIONS */
    609 #ifndef CONFIG_NO_CONFIG_BLOBS
    610 	} else if (os_strcmp(cmd, "blob") == 0) {
    611 		ret = wpas_ctrl_set_blob(wpa_s, value);
    612 #endif /* CONFIG_NO_CONFIG_BLOBS */
    613 	} else if (os_strcasecmp(cmd, "setband") == 0) {
    614 		ret = wpas_ctrl_set_band(wpa_s, value);
    615 #ifdef CONFIG_MBO
    616 	} else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
    617 		ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
    618 		if (ret == 0) {
    619 			value[-1] = '=';
    620 			wpa_config_process_global(wpa_s->conf, cmd, -1);
    621 		}
    622 	} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
    623 		wpas_mbo_update_cell_capa(wpa_s, atoi(value));
    624 #endif /* CONFIG_MBO */
    625 	} else if (os_strcasecmp(cmd, "lci") == 0) {
    626 		ret = wpas_ctrl_iface_set_lci(wpa_s, value);
    627 	} else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
    628 		ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
    629 	} else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
    630 		ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
    631 	} else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
    632 		ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
    633 	} else if (os_strcasecmp(cmd, "ric_ies") == 0) {
    634 		ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
    635 	} else {
    636 		value[-1] = '=';
    637 		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
    638 		if (ret == 0)
    639 			wpa_supplicant_update_config(wpa_s);
    640 	}
    641 
    642 	return ret;
    643 }
    644 
    645 
    646 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
    647 					 char *cmd, char *buf, size_t buflen)
    648 {
    649 	int res = -1;
    650 
    651 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
    652 
    653 	if (os_strcmp(cmd, "version") == 0) {
    654 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
    655 	} else if (os_strcasecmp(cmd, "country") == 0) {
    656 		if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
    657 			res = os_snprintf(buf, buflen, "%c%c",
    658 					  wpa_s->conf->country[0],
    659 					  wpa_s->conf->country[1]);
    660 #ifdef CONFIG_WIFI_DISPLAY
    661 	} else if (os_strcasecmp(cmd, "wifi_display") == 0) {
    662 		int enabled;
    663 		if (wpa_s->global->p2p == NULL ||
    664 		    wpa_s->global->p2p_disabled)
    665 			enabled = 0;
    666 		else
    667 			enabled = wpa_s->global->wifi_display;
    668 		res = os_snprintf(buf, buflen, "%d", enabled);
    669 #endif /* CONFIG_WIFI_DISPLAY */
    670 #ifdef CONFIG_TESTING_GET_GTK
    671 	} else if (os_strcmp(cmd, "gtk") == 0) {
    672 		if (wpa_s->last_gtk_len == 0)
    673 			return -1;
    674 		res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
    675 				       wpa_s->last_gtk_len);
    676 		return res;
    677 #endif /* CONFIG_TESTING_GET_GTK */
    678 	} else if (os_strcmp(cmd, "tls_library") == 0) {
    679 		res = tls_get_library_version(buf, buflen);
    680 	} else {
    681 		res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
    682 	}
    683 
    684 	if (os_snprintf_error(buflen, res))
    685 		return -1;
    686 	return res;
    687 }
    688 
    689 
    690 #ifdef IEEE8021X_EAPOL
    691 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
    692 					     char *addr)
    693 {
    694 	u8 bssid[ETH_ALEN];
    695 	struct wpa_ssid *ssid = wpa_s->current_ssid;
    696 
    697 	if (hwaddr_aton(addr, bssid)) {
    698 		wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
    699 			   "'%s'", addr);
    700 		return -1;
    701 	}
    702 
    703 	wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
    704 	rsn_preauth_deinit(wpa_s->wpa);
    705 	if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
    706 		return -1;
    707 
    708 	return 0;
    709 }
    710 #endif /* IEEE8021X_EAPOL */
    711 
    712 
    713 #ifdef CONFIG_PEERKEY
    714 /* MLME-STKSTART.request(peer) */
    715 static int wpa_supplicant_ctrl_iface_stkstart(
    716 	struct wpa_supplicant *wpa_s, char *addr)
    717 {
    718 	u8 peer[ETH_ALEN];
    719 
    720 	if (hwaddr_aton(addr, peer)) {
    721 		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
    722 			   "address '%s'", addr);
    723 		return -1;
    724 	}
    725 
    726 	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
    727 		   MAC2STR(peer));
    728 
    729 	return wpa_sm_stkstart(wpa_s->wpa, peer);
    730 }
    731 #endif /* CONFIG_PEERKEY */
    732 
    733 
    734 #ifdef CONFIG_TDLS
    735 
    736 static int wpa_supplicant_ctrl_iface_tdls_discover(
    737 	struct wpa_supplicant *wpa_s, char *addr)
    738 {
    739 	u8 peer[ETH_ALEN];
    740 	int ret;
    741 
    742 	if (hwaddr_aton(addr, peer)) {
    743 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
    744 			   "address '%s'", addr);
    745 		return -1;
    746 	}
    747 
    748 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
    749 		   MAC2STR(peer));
    750 
    751 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
    752 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
    753 	else
    754 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
    755 
    756 	return ret;
    757 }
    758 
    759 
    760 static int wpa_supplicant_ctrl_iface_tdls_setup(
    761 	struct wpa_supplicant *wpa_s, char *addr)
    762 {
    763 	u8 peer[ETH_ALEN];
    764 	int ret;
    765 
    766 	if (hwaddr_aton(addr, peer)) {
    767 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
    768 			   "address '%s'", addr);
    769 		return -1;
    770 	}
    771 
    772 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
    773 		   MAC2STR(peer));
    774 
    775 	if ((wpa_s->conf->tdls_external_control) &&
    776 	    wpa_tdls_is_external_setup(wpa_s->wpa))
    777 		return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
    778 
    779 	wpa_tdls_remove(wpa_s->wpa, peer);
    780 
    781 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
    782 		ret = wpa_tdls_start(wpa_s->wpa, peer);
    783 	else
    784 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
    785 
    786 	return ret;
    787 }
    788 
    789 
    790 static int wpa_supplicant_ctrl_iface_tdls_teardown(
    791 	struct wpa_supplicant *wpa_s, char *addr)
    792 {
    793 	u8 peer[ETH_ALEN];
    794 	int ret;
    795 
    796 	if (os_strcmp(addr, "*") == 0) {
    797 		/* remove everyone */
    798 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
    799 		wpa_tdls_teardown_peers(wpa_s->wpa);
    800 		return 0;
    801 	}
    802 
    803 	if (hwaddr_aton(addr, peer)) {
    804 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
    805 			   "address '%s'", addr);
    806 		return -1;
    807 	}
    808 
    809 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
    810 		   MAC2STR(peer));
    811 
    812 	if ((wpa_s->conf->tdls_external_control) &&
    813 	    wpa_tdls_is_external_setup(wpa_s->wpa))
    814 		return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
    815 
    816 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
    817 		ret = wpa_tdls_teardown_link(
    818 			wpa_s->wpa, peer,
    819 			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
    820 	else
    821 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
    822 
    823 	return ret;
    824 }
    825 
    826 
    827 static int ctrl_iface_get_capability_tdls(
    828 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    829 {
    830 	int ret;
    831 
    832 	ret = os_snprintf(buf, buflen, "%s\n",
    833 			  wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
    834 			  (wpa_s->drv_flags &
    835 			   WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
    836 			   "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
    837 	if (os_snprintf_error(buflen, ret))
    838 		return -1;
    839 	return ret;
    840 }
    841 
    842 
    843 static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
    844 	struct wpa_supplicant *wpa_s, char *cmd)
    845 {
    846 	u8 peer[ETH_ALEN];
    847 	struct hostapd_freq_params freq_params;
    848 	u8 oper_class;
    849 	char *pos, *end;
    850 
    851 	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
    852 		wpa_printf(MSG_INFO,
    853 			   "tdls_chanswitch: Only supported with external setup");
    854 		return -1;
    855 	}
    856 
    857 	os_memset(&freq_params, 0, sizeof(freq_params));
    858 
    859 	pos = os_strchr(cmd, ' ');
    860 	if (pos == NULL)
    861 		return -1;
    862 	*pos++ = '\0';
    863 
    864 	oper_class = strtol(pos, &end, 10);
    865 	if (pos == end) {
    866 		wpa_printf(MSG_INFO,
    867 			   "tdls_chanswitch: Invalid op class provided");
    868 		return -1;
    869 	}
    870 
    871 	pos = end;
    872 	freq_params.freq = atoi(pos);
    873 	if (freq_params.freq == 0) {
    874 		wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
    875 		return -1;
    876 	}
    877 
    878 #define SET_FREQ_SETTING(str) \
    879 	do { \
    880 		const char *pos2 = os_strstr(pos, " " #str "="); \
    881 		if (pos2) { \
    882 			pos2 += sizeof(" " #str "=") - 1; \
    883 			freq_params.str = atoi(pos2); \
    884 		} \
    885 	} while (0)
    886 
    887 	SET_FREQ_SETTING(center_freq1);
    888 	SET_FREQ_SETTING(center_freq2);
    889 	SET_FREQ_SETTING(bandwidth);
    890 	SET_FREQ_SETTING(sec_channel_offset);
    891 #undef SET_FREQ_SETTING
    892 
    893 	freq_params.ht_enabled = !!os_strstr(pos, " ht");
    894 	freq_params.vht_enabled = !!os_strstr(pos, " vht");
    895 
    896 	if (hwaddr_aton(cmd, peer)) {
    897 		wpa_printf(MSG_DEBUG,
    898 			   "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
    899 			   cmd);
    900 		return -1;
    901 	}
    902 
    903 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
    904 		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
    905 		   MAC2STR(peer), oper_class, freq_params.freq,
    906 		   freq_params.center_freq1, freq_params.center_freq2,
    907 		   freq_params.bandwidth, freq_params.sec_channel_offset,
    908 		   freq_params.ht_enabled ? " HT" : "",
    909 		   freq_params.vht_enabled ? " VHT" : "");
    910 
    911 	return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
    912 					   &freq_params);
    913 }
    914 
    915 
    916 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
    917 	struct wpa_supplicant *wpa_s, char *cmd)
    918 {
    919 	u8 peer[ETH_ALEN];
    920 
    921 	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
    922 		wpa_printf(MSG_INFO,
    923 			   "tdls_chanswitch: Only supported with external setup");
    924 		return -1;
    925 	}
    926 
    927 	if (hwaddr_aton(cmd, peer)) {
    928 		wpa_printf(MSG_DEBUG,
    929 			   "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
    930 			   cmd);
    931 		return -1;
    932 	}
    933 
    934 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
    935 		   MAC2STR(peer));
    936 
    937 	return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
    938 }
    939 
    940 
    941 static int wpa_supplicant_ctrl_iface_tdls_link_status(
    942 	struct wpa_supplicant *wpa_s, const char *addr,
    943 	char *buf, size_t buflen)
    944 {
    945 	u8 peer[ETH_ALEN];
    946 	const char *tdls_status;
    947 	int ret;
    948 
    949 	if (hwaddr_aton(addr, peer)) {
    950 		wpa_printf(MSG_DEBUG,
    951 			   "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
    952 			   addr);
    953 		return -1;
    954 	}
    955 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
    956 		   MAC2STR(peer));
    957 
    958 	tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
    959 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
    960 	ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
    961 	if (os_snprintf_error(buflen, ret))
    962 		return -1;
    963 
    964 	return ret;
    965 }
    966 
    967 #endif /* CONFIG_TDLS */
    968 
    969 
    970 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
    971 {
    972 	char *token, *context = NULL;
    973 	struct wmm_ac_ts_setup_params params = {
    974 		.tsid = 0xff,
    975 		.direction = 0xff,
    976 	};
    977 
    978 	while ((token = str_token(cmd, " ", &context))) {
    979 		if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
    980 		    sscanf(token, "up=%i", &params.user_priority) == 1 ||
    981 		    sscanf(token, "nominal_msdu_size=%i",
    982 			   &params.nominal_msdu_size) == 1 ||
    983 		    sscanf(token, "mean_data_rate=%i",
    984 			   &params.mean_data_rate) == 1 ||
    985 		    sscanf(token, "min_phy_rate=%i",
    986 			   &params.minimum_phy_rate) == 1 ||
    987 		    sscanf(token, "sba=%i",
    988 			   &params.surplus_bandwidth_allowance) == 1)
    989 			continue;
    990 
    991 		if (os_strcasecmp(token, "downlink") == 0) {
    992 			params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
    993 		} else if (os_strcasecmp(token, "uplink") == 0) {
    994 			params.direction = WMM_TSPEC_DIRECTION_UPLINK;
    995 		} else if (os_strcasecmp(token, "bidi") == 0) {
    996 			params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
    997 		} else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
    998 			params.fixed_nominal_msdu = 1;
    999 		} else {
   1000 			wpa_printf(MSG_DEBUG,
   1001 				   "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
   1002 				   token);
   1003 			return -1;
   1004 		}
   1005 
   1006 	}
   1007 
   1008 	return wpas_wmm_ac_addts(wpa_s, &params);
   1009 }
   1010 
   1011 
   1012 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
   1013 {
   1014 	u8 tsid = atoi(cmd);
   1015 
   1016 	return wpas_wmm_ac_delts(wpa_s, tsid);
   1017 }
   1018 
   1019 
   1020 #ifdef CONFIG_IEEE80211R
   1021 static int wpa_supplicant_ctrl_iface_ft_ds(
   1022 	struct wpa_supplicant *wpa_s, char *addr)
   1023 {
   1024 	u8 target_ap[ETH_ALEN];
   1025 	struct wpa_bss *bss;
   1026 	const u8 *mdie;
   1027 
   1028 	if (hwaddr_aton(addr, target_ap)) {
   1029 		wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
   1030 			   "address '%s'", addr);
   1031 		return -1;
   1032 	}
   1033 
   1034 	wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
   1035 
   1036 	bss = wpa_bss_get_bssid(wpa_s, target_ap);
   1037 	if (bss)
   1038 		mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
   1039 	else
   1040 		mdie = NULL;
   1041 
   1042 	return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
   1043 }
   1044 #endif /* CONFIG_IEEE80211R */
   1045 
   1046 
   1047 #ifdef CONFIG_WPS
   1048 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
   1049 					     char *cmd)
   1050 {
   1051 	u8 bssid[ETH_ALEN], *_bssid = bssid;
   1052 #ifdef CONFIG_P2P
   1053 	u8 p2p_dev_addr[ETH_ALEN];
   1054 #endif /* CONFIG_P2P */
   1055 #ifdef CONFIG_AP
   1056 	u8 *_p2p_dev_addr = NULL;
   1057 #endif /* CONFIG_AP */
   1058 
   1059 	if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
   1060 		_bssid = NULL;
   1061 #ifdef CONFIG_P2P
   1062 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
   1063 		if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
   1064 			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
   1065 				   "P2P Device Address '%s'",
   1066 				   cmd + 13);
   1067 			return -1;
   1068 		}
   1069 		_p2p_dev_addr = p2p_dev_addr;
   1070 #endif /* CONFIG_P2P */
   1071 	} else if (hwaddr_aton(cmd, bssid)) {
   1072 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
   1073 			   cmd);
   1074 		return -1;
   1075 	}
   1076 
   1077 #ifdef CONFIG_AP
   1078 	if (wpa_s->ap_iface)
   1079 		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
   1080 #endif /* CONFIG_AP */
   1081 
   1082 	return wpas_wps_start_pbc(wpa_s, _bssid, 0);
   1083 }
   1084 
   1085 
   1086 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
   1087 					     char *cmd, char *buf,
   1088 					     size_t buflen)
   1089 {
   1090 	u8 bssid[ETH_ALEN], *_bssid = bssid;
   1091 	char *pin;
   1092 	int ret;
   1093 
   1094 	pin = os_strchr(cmd, ' ');
   1095 	if (pin)
   1096 		*pin++ = '\0';
   1097 
   1098 	if (os_strcmp(cmd, "any") == 0)
   1099 		_bssid = NULL;
   1100 	else if (os_strcmp(cmd, "get") == 0) {
   1101 		if (wps_generate_pin((unsigned int *) &ret) < 0)
   1102 			return -1;
   1103 		goto done;
   1104 	} else if (hwaddr_aton(cmd, bssid)) {
   1105 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
   1106 			   cmd);
   1107 		return -1;
   1108 	}
   1109 
   1110 #ifdef CONFIG_AP
   1111 	if (wpa_s->ap_iface) {
   1112 		int timeout = 0;
   1113 		char *pos;
   1114 
   1115 		if (pin) {
   1116 			pos = os_strchr(pin, ' ');
   1117 			if (pos) {
   1118 				*pos++ = '\0';
   1119 				timeout = atoi(pos);
   1120 			}
   1121 		}
   1122 
   1123 		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
   1124 						 buf, buflen, timeout);
   1125 	}
   1126 #endif /* CONFIG_AP */
   1127 
   1128 	if (pin) {
   1129 		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
   1130 					 DEV_PW_DEFAULT);
   1131 		if (ret < 0)
   1132 			return -1;
   1133 		ret = os_snprintf(buf, buflen, "%s", pin);
   1134 		if (os_snprintf_error(buflen, ret))
   1135 			return -1;
   1136 		return ret;
   1137 	}
   1138 
   1139 	ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
   1140 	if (ret < 0)
   1141 		return -1;
   1142 
   1143 done:
   1144 	/* Return the generated PIN */
   1145 	ret = os_snprintf(buf, buflen, "%08d", ret);
   1146 	if (os_snprintf_error(buflen, ret))
   1147 		return -1;
   1148 	return ret;
   1149 }
   1150 
   1151 
   1152 static int wpa_supplicant_ctrl_iface_wps_check_pin(
   1153 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
   1154 {
   1155 	char pin[9];
   1156 	size_t len;
   1157 	char *pos;
   1158 	int ret;
   1159 
   1160 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
   1161 			      (u8 *) cmd, os_strlen(cmd));
   1162 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
   1163 		if (*pos < '0' || *pos > '9')
   1164 			continue;
   1165 		pin[len++] = *pos;
   1166 		if (len == 9) {
   1167 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
   1168 			return -1;
   1169 		}
   1170 	}
   1171 	if (len != 4 && len != 8) {
   1172 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
   1173 		return -1;
   1174 	}
   1175 	pin[len] = '\0';
   1176 
   1177 	if (len == 8) {
   1178 		unsigned int pin_val;
   1179 		pin_val = atoi(pin);
   1180 		if (!wps_pin_valid(pin_val)) {
   1181 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
   1182 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
   1183 			if (os_snprintf_error(buflen, ret))
   1184 				return -1;
   1185 			return ret;
   1186 		}
   1187 	}
   1188 
   1189 	ret = os_snprintf(buf, buflen, "%s", pin);
   1190 	if (os_snprintf_error(buflen, ret))
   1191 		return -1;
   1192 
   1193 	return ret;
   1194 }
   1195 
   1196 
   1197 #ifdef CONFIG_WPS_NFC
   1198 
   1199 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
   1200 					     char *cmd)
   1201 {
   1202 	u8 bssid[ETH_ALEN], *_bssid = bssid;
   1203 
   1204 	if (cmd == NULL || cmd[0] == '\0')
   1205 		_bssid = NULL;
   1206 	else if (hwaddr_aton(cmd, bssid))
   1207 		return -1;
   1208 
   1209 	return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
   1210 				  0, 0);
   1211 }
   1212 
   1213 
   1214 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
   1215 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
   1216 {
   1217 	int ndef;
   1218 	struct wpabuf *buf;
   1219 	int res;
   1220 	char *pos;
   1221 
   1222 	pos = os_strchr(cmd, ' ');
   1223 	if (pos)
   1224 		*pos++ = '\0';
   1225 	if (os_strcmp(cmd, "WPS") == 0)
   1226 		ndef = 0;
   1227 	else if (os_strcmp(cmd, "NDEF") == 0)
   1228 		ndef = 1;
   1229 	else
   1230 		return -1;
   1231 
   1232 	buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
   1233 	if (buf == NULL)
   1234 		return -1;
   1235 
   1236 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
   1237 					 wpabuf_len(buf));
   1238 	reply[res++] = '\n';
   1239 	reply[res] = '\0';
   1240 
   1241 	wpabuf_free(buf);
   1242 
   1243 	return res;
   1244 }
   1245 
   1246 
   1247 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
   1248 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
   1249 {
   1250 	int ndef;
   1251 	struct wpabuf *buf;
   1252 	int res;
   1253 
   1254 	if (os_strcmp(cmd, "WPS") == 0)
   1255 		ndef = 0;
   1256 	else if (os_strcmp(cmd, "NDEF") == 0)
   1257 		ndef = 1;
   1258 	else
   1259 		return -1;
   1260 
   1261 	buf = wpas_wps_nfc_token(wpa_s, ndef);
   1262 	if (buf == NULL)
   1263 		return -1;
   1264 
   1265 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
   1266 					 wpabuf_len(buf));
   1267 	reply[res++] = '\n';
   1268 	reply[res] = '\0';
   1269 
   1270 	wpabuf_free(buf);
   1271 
   1272 	return res;
   1273 }
   1274 
   1275 
   1276 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
   1277 	struct wpa_supplicant *wpa_s, char *pos)
   1278 {
   1279 	size_t len;
   1280 	struct wpabuf *buf;
   1281 	int ret;
   1282 	char *freq;
   1283 	int forced_freq = 0;
   1284 
   1285 	freq = strstr(pos, " freq=");
   1286 	if (freq) {
   1287 		*freq = '\0';
   1288 		freq += 6;
   1289 		forced_freq = atoi(freq);
   1290 	}
   1291 
   1292 	len = os_strlen(pos);
   1293 	if (len & 0x01)
   1294 		return -1;
   1295 	len /= 2;
   1296 
   1297 	buf = wpabuf_alloc(len);
   1298 	if (buf == NULL)
   1299 		return -1;
   1300 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
   1301 		wpabuf_free(buf);
   1302 		return -1;
   1303 	}
   1304 
   1305 	ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
   1306 	wpabuf_free(buf);
   1307 
   1308 	return ret;
   1309 }
   1310 
   1311 
   1312 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
   1313 					      char *reply, size_t max_len,
   1314 					      int ndef)
   1315 {
   1316 	struct wpabuf *buf;
   1317 	int res;
   1318 
   1319 	buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
   1320 	if (buf == NULL)
   1321 		return -1;
   1322 
   1323 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
   1324 					 wpabuf_len(buf));
   1325 	reply[res++] = '\n';
   1326 	reply[res] = '\0';
   1327 
   1328 	wpabuf_free(buf);
   1329 
   1330 	return res;
   1331 }
   1332 
   1333 
   1334 #ifdef CONFIG_P2P
   1335 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
   1336 					      char *reply, size_t max_len,
   1337 					      int ndef)
   1338 {
   1339 	struct wpabuf *buf;
   1340 	int res;
   1341 
   1342 	buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
   1343 	if (buf == NULL) {
   1344 		wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
   1345 		return -1;
   1346 	}
   1347 
   1348 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
   1349 					 wpabuf_len(buf));
   1350 	reply[res++] = '\n';
   1351 	reply[res] = '\0';
   1352 
   1353 	wpabuf_free(buf);
   1354 
   1355 	return res;
   1356 }
   1357 #endif /* CONFIG_P2P */
   1358 
   1359 
   1360 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
   1361 					  char *cmd, char *reply,
   1362 					  size_t max_len)
   1363 {
   1364 	char *pos;
   1365 	int ndef;
   1366 
   1367 	pos = os_strchr(cmd, ' ');
   1368 	if (pos == NULL)
   1369 		return -1;
   1370 	*pos++ = '\0';
   1371 
   1372 	if (os_strcmp(cmd, "WPS") == 0)
   1373 		ndef = 0;
   1374 	else if (os_strcmp(cmd, "NDEF") == 0)
   1375 		ndef = 1;
   1376 	else
   1377 		return -1;
   1378 
   1379 	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
   1380 		if (!ndef)
   1381 			return -1;
   1382 		return wpas_ctrl_nfc_get_handover_req_wps(
   1383 			wpa_s, reply, max_len, ndef);
   1384 	}
   1385 
   1386 #ifdef CONFIG_P2P
   1387 	if (os_strcmp(pos, "P2P-CR") == 0) {
   1388 		return wpas_ctrl_nfc_get_handover_req_p2p(
   1389 			wpa_s, reply, max_len, ndef);
   1390 	}
   1391 #endif /* CONFIG_P2P */
   1392 
   1393 	return -1;
   1394 }
   1395 
   1396 
   1397 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
   1398 					      char *reply, size_t max_len,
   1399 					      int ndef, int cr, char *uuid)
   1400 {
   1401 	struct wpabuf *buf;
   1402 	int res;
   1403 
   1404 	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
   1405 	if (buf == NULL)
   1406 		return -1;
   1407 
   1408 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
   1409 					 wpabuf_len(buf));
   1410 	reply[res++] = '\n';
   1411 	reply[res] = '\0';
   1412 
   1413 	wpabuf_free(buf);
   1414 
   1415 	return res;
   1416 }
   1417 
   1418 
   1419 #ifdef CONFIG_P2P
   1420 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
   1421 					      char *reply, size_t max_len,
   1422 					      int ndef, int tag)
   1423 {
   1424 	struct wpabuf *buf;
   1425 	int res;
   1426 
   1427 	buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
   1428 	if (buf == NULL)
   1429 		return -1;
   1430 
   1431 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
   1432 					 wpabuf_len(buf));
   1433 	reply[res++] = '\n';
   1434 	reply[res] = '\0';
   1435 
   1436 	wpabuf_free(buf);
   1437 
   1438 	return res;
   1439 }
   1440 #endif /* CONFIG_P2P */
   1441 
   1442 
   1443 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
   1444 					  char *cmd, char *reply,
   1445 					  size_t max_len)
   1446 {
   1447 	char *pos, *pos2;
   1448 	int ndef;
   1449 
   1450 	pos = os_strchr(cmd, ' ');
   1451 	if (pos == NULL)
   1452 		return -1;
   1453 	*pos++ = '\0';
   1454 
   1455 	if (os_strcmp(cmd, "WPS") == 0)
   1456 		ndef = 0;
   1457 	else if (os_strcmp(cmd, "NDEF") == 0)
   1458 		ndef = 1;
   1459 	else
   1460 		return -1;
   1461 
   1462 	pos2 = os_strchr(pos, ' ');
   1463 	if (pos2)
   1464 		*pos2++ = '\0';
   1465 	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
   1466 		if (!ndef)
   1467 			return -1;
   1468 		return wpas_ctrl_nfc_get_handover_sel_wps(
   1469 			wpa_s, reply, max_len, ndef,
   1470 			os_strcmp(pos, "WPS-CR") == 0, pos2);
   1471 	}
   1472 
   1473 #ifdef CONFIG_P2P
   1474 	if (os_strcmp(pos, "P2P-CR") == 0) {
   1475 		return wpas_ctrl_nfc_get_handover_sel_p2p(
   1476 			wpa_s, reply, max_len, ndef, 0);
   1477 	}
   1478 
   1479 	if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
   1480 		return wpas_ctrl_nfc_get_handover_sel_p2p(
   1481 			wpa_s, reply, max_len, ndef, 1);
   1482 	}
   1483 #endif /* CONFIG_P2P */
   1484 
   1485 	return -1;
   1486 }
   1487 
   1488 
   1489 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
   1490 					 char *cmd)
   1491 {
   1492 	size_t len;
   1493 	struct wpabuf *req, *sel;
   1494 	int ret;
   1495 	char *pos, *role, *type, *pos2;
   1496 #ifdef CONFIG_P2P
   1497 	char *freq;
   1498 	int forced_freq = 0;
   1499 
   1500 	freq = strstr(cmd, " freq=");
   1501 	if (freq) {
   1502 		*freq = '\0';
   1503 		freq += 6;
   1504 		forced_freq = atoi(freq);
   1505 	}
   1506 #endif /* CONFIG_P2P */
   1507 
   1508 	role = cmd;
   1509 	pos = os_strchr(role, ' ');
   1510 	if (pos == NULL) {
   1511 		wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
   1512 		return -1;
   1513 	}
   1514 	*pos++ = '\0';
   1515 
   1516 	type = pos;
   1517 	pos = os_strchr(type, ' ');
   1518 	if (pos == NULL) {
   1519 		wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
   1520 		return -1;
   1521 	}
   1522 	*pos++ = '\0';
   1523 
   1524 	pos2 = os_strchr(pos, ' ');
   1525 	if (pos2 == NULL) {
   1526 		wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
   1527 		return -1;
   1528 	}
   1529 	*pos2++ = '\0';
   1530 
   1531 	len = os_strlen(pos);
   1532 	if (len & 0x01) {
   1533 		wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
   1534 		return -1;
   1535 	}
   1536 	len /= 2;
   1537 
   1538 	req = wpabuf_alloc(len);
   1539 	if (req == NULL) {
   1540 		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
   1541 		return -1;
   1542 	}
   1543 	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
   1544 		wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
   1545 		wpabuf_free(req);
   1546 		return -1;
   1547 	}
   1548 
   1549 	len = os_strlen(pos2);
   1550 	if (len & 0x01) {
   1551 		wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
   1552 		wpabuf_free(req);
   1553 		return -1;
   1554 	}
   1555 	len /= 2;
   1556 
   1557 	sel = wpabuf_alloc(len);
   1558 	if (sel == NULL) {
   1559 		wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
   1560 		wpabuf_free(req);
   1561 		return -1;
   1562 	}
   1563 	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
   1564 		wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
   1565 		wpabuf_free(req);
   1566 		wpabuf_free(sel);
   1567 		return -1;
   1568 	}
   1569 
   1570 	wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
   1571 		   role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
   1572 
   1573 	if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
   1574 		ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
   1575 #ifdef CONFIG_AP
   1576 	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
   1577 	{
   1578 		ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
   1579 		if (ret < 0)
   1580 			ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
   1581 #endif /* CONFIG_AP */
   1582 #ifdef CONFIG_P2P
   1583 	} else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
   1584 	{
   1585 		ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
   1586 	} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
   1587 	{
   1588 		ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
   1589 						   forced_freq);
   1590 #endif /* CONFIG_P2P */
   1591 	} else {
   1592 		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
   1593 			   "reported: role=%s type=%s", role, type);
   1594 		ret = -1;
   1595 	}
   1596 	wpabuf_free(req);
   1597 	wpabuf_free(sel);
   1598 
   1599 	if (ret)
   1600 		wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
   1601 
   1602 	return ret;
   1603 }
   1604 
   1605 #endif /* CONFIG_WPS_NFC */
   1606 
   1607 
   1608 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
   1609 					     char *cmd)
   1610 {
   1611 	u8 bssid[ETH_ALEN];
   1612 	char *pin;
   1613 	char *new_ssid;
   1614 	char *new_auth;
   1615 	char *new_encr;
   1616 	char *new_key;
   1617 	struct wps_new_ap_settings ap;
   1618 
   1619 	pin = os_strchr(cmd, ' ');
   1620 	if (pin == NULL)
   1621 		return -1;
   1622 	*pin++ = '\0';
   1623 
   1624 	if (hwaddr_aton(cmd, bssid)) {
   1625 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
   1626 			   cmd);
   1627 		return -1;
   1628 	}
   1629 
   1630 	new_ssid = os_strchr(pin, ' ');
   1631 	if (new_ssid == NULL)
   1632 		return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
   1633 	*new_ssid++ = '\0';
   1634 
   1635 	new_auth = os_strchr(new_ssid, ' ');
   1636 	if (new_auth == NULL)
   1637 		return -1;
   1638 	*new_auth++ = '\0';
   1639 
   1640 	new_encr = os_strchr(new_auth, ' ');
   1641 	if (new_encr == NULL)
   1642 		return -1;
   1643 	*new_encr++ = '\0';
   1644 
   1645 	new_key = os_strchr(new_encr, ' ');
   1646 	if (new_key == NULL)
   1647 		return -1;
   1648 	*new_key++ = '\0';
   1649 
   1650 	os_memset(&ap, 0, sizeof(ap));
   1651 	ap.ssid_hex = new_ssid;
   1652 	ap.auth = new_auth;
   1653 	ap.encr = new_encr;
   1654 	ap.key_hex = new_key;
   1655 	return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
   1656 }
   1657 
   1658 
   1659 #ifdef CONFIG_AP
   1660 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
   1661 						char *cmd, char *buf,
   1662 						size_t buflen)
   1663 {
   1664 	int timeout = 300;
   1665 	char *pos;
   1666 	const char *pin_txt;
   1667 
   1668 	if (!wpa_s->ap_iface)
   1669 		return -1;
   1670 
   1671 	pos = os_strchr(cmd, ' ');
   1672 	if (pos)
   1673 		*pos++ = '\0';
   1674 
   1675 	if (os_strcmp(cmd, "disable") == 0) {
   1676 		wpas_wps_ap_pin_disable(wpa_s);
   1677 		return os_snprintf(buf, buflen, "OK\n");
   1678 	}
   1679 
   1680 	if (os_strcmp(cmd, "random") == 0) {
   1681 		if (pos)
   1682 			timeout = atoi(pos);
   1683 		pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
   1684 		if (pin_txt == NULL)
   1685 			return -1;
   1686 		return os_snprintf(buf, buflen, "%s", pin_txt);
   1687 	}
   1688 
   1689 	if (os_strcmp(cmd, "get") == 0) {
   1690 		pin_txt = wpas_wps_ap_pin_get(wpa_s);
   1691 		if (pin_txt == NULL)
   1692 			return -1;
   1693 		return os_snprintf(buf, buflen, "%s", pin_txt);
   1694 	}
   1695 
   1696 	if (os_strcmp(cmd, "set") == 0) {
   1697 		char *pin;
   1698 		if (pos == NULL)
   1699 			return -1;
   1700 		pin = pos;
   1701 		pos = os_strchr(pos, ' ');
   1702 		if (pos) {
   1703 			*pos++ = '\0';
   1704 			timeout = atoi(pos);
   1705 		}
   1706 		if (os_strlen(pin) > buflen)
   1707 			return -1;
   1708 		if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
   1709 			return -1;
   1710 		return os_snprintf(buf, buflen, "%s", pin);
   1711 	}
   1712 
   1713 	return -1;
   1714 }
   1715 #endif /* CONFIG_AP */
   1716 
   1717 
   1718 #ifdef CONFIG_WPS_ER
   1719 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
   1720 						char *cmd)
   1721 {
   1722 	char *uuid = cmd, *pin, *pos;
   1723 	u8 addr_buf[ETH_ALEN], *addr = NULL;
   1724 	pin = os_strchr(uuid, ' ');
   1725 	if (pin == NULL)
   1726 		return -1;
   1727 	*pin++ = '\0';
   1728 	pos = os_strchr(pin, ' ');
   1729 	if (pos) {
   1730 		*pos++ = '\0';
   1731 		if (hwaddr_aton(pos, addr_buf) == 0)
   1732 			addr = addr_buf;
   1733 	}
   1734 	return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
   1735 }
   1736 
   1737 
   1738 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
   1739 						  char *cmd)
   1740 {
   1741 	char *uuid = cmd, *pin;
   1742 	pin = os_strchr(uuid, ' ');
   1743 	if (pin == NULL)
   1744 		return -1;
   1745 	*pin++ = '\0';
   1746 	return wpas_wps_er_learn(wpa_s, uuid, pin);
   1747 }
   1748 
   1749 
   1750 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
   1751 	struct wpa_supplicant *wpa_s, char *cmd)
   1752 {
   1753 	char *uuid = cmd, *id;
   1754 	id = os_strchr(uuid, ' ');
   1755 	if (id == NULL)
   1756 		return -1;
   1757 	*id++ = '\0';
   1758 	return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
   1759 }
   1760 
   1761 
   1762 static int wpa_supplicant_ctrl_iface_wps_er_config(
   1763 	struct wpa_supplicant *wpa_s, char *cmd)
   1764 {
   1765 	char *pin;
   1766 	char *new_ssid;
   1767 	char *new_auth;
   1768 	char *new_encr;
   1769 	char *new_key;
   1770 	struct wps_new_ap_settings ap;
   1771 
   1772 	pin = os_strchr(cmd, ' ');
   1773 	if (pin == NULL)
   1774 		return -1;
   1775 	*pin++ = '\0';
   1776 
   1777 	new_ssid = os_strchr(pin, ' ');
   1778 	if (new_ssid == NULL)
   1779 		return -1;
   1780 	*new_ssid++ = '\0';
   1781 
   1782 	new_auth = os_strchr(new_ssid, ' ');
   1783 	if (new_auth == NULL)
   1784 		return -1;
   1785 	*new_auth++ = '\0';
   1786 
   1787 	new_encr = os_strchr(new_auth, ' ');
   1788 	if (new_encr == NULL)
   1789 		return -1;
   1790 	*new_encr++ = '\0';
   1791 
   1792 	new_key = os_strchr(new_encr, ' ');
   1793 	if (new_key == NULL)
   1794 		return -1;
   1795 	*new_key++ = '\0';
   1796 
   1797 	os_memset(&ap, 0, sizeof(ap));
   1798 	ap.ssid_hex = new_ssid;
   1799 	ap.auth = new_auth;
   1800 	ap.encr = new_encr;
   1801 	ap.key_hex = new_key;
   1802 	return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
   1803 }
   1804 
   1805 
   1806 #ifdef CONFIG_WPS_NFC
   1807 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
   1808 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
   1809 {
   1810 	int ndef;
   1811 	struct wpabuf *buf;
   1812 	int res;
   1813 	char *uuid;
   1814 
   1815 	uuid = os_strchr(cmd, ' ');
   1816 	if (uuid == NULL)
   1817 		return -1;
   1818 	*uuid++ = '\0';
   1819 
   1820 	if (os_strcmp(cmd, "WPS") == 0)
   1821 		ndef = 0;
   1822 	else if (os_strcmp(cmd, "NDEF") == 0)
   1823 		ndef = 1;
   1824 	else
   1825 		return -1;
   1826 
   1827 	buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
   1828 	if (buf == NULL)
   1829 		return -1;
   1830 
   1831 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
   1832 					 wpabuf_len(buf));
   1833 	reply[res++] = '\n';
   1834 	reply[res] = '\0';
   1835 
   1836 	wpabuf_free(buf);
   1837 
   1838 	return res;
   1839 }
   1840 #endif /* CONFIG_WPS_NFC */
   1841 #endif /* CONFIG_WPS_ER */
   1842 
   1843 #endif /* CONFIG_WPS */
   1844 
   1845 
   1846 #ifdef CONFIG_IBSS_RSN
   1847 static int wpa_supplicant_ctrl_iface_ibss_rsn(
   1848 	struct wpa_supplicant *wpa_s, char *addr)
   1849 {
   1850 	u8 peer[ETH_ALEN];
   1851 
   1852 	if (hwaddr_aton(addr, peer)) {
   1853 		wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
   1854 			   "address '%s'", addr);
   1855 		return -1;
   1856 	}
   1857 
   1858 	wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
   1859 		   MAC2STR(peer));
   1860 
   1861 	return ibss_rsn_start(wpa_s->ibss_rsn, peer);
   1862 }
   1863 #endif /* CONFIG_IBSS_RSN */
   1864 
   1865 
   1866 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
   1867 					      char *rsp)
   1868 {
   1869 #ifdef IEEE8021X_EAPOL
   1870 	char *pos, *id_pos;
   1871 	int id;
   1872 	struct wpa_ssid *ssid;
   1873 
   1874 	pos = os_strchr(rsp, '-');
   1875 	if (pos == NULL)
   1876 		return -1;
   1877 	*pos++ = '\0';
   1878 	id_pos = pos;
   1879 	pos = os_strchr(pos, ':');
   1880 	if (pos == NULL)
   1881 		return -1;
   1882 	*pos++ = '\0';
   1883 	id = atoi(id_pos);
   1884 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
   1885 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
   1886 			      (u8 *) pos, os_strlen(pos));
   1887 
   1888 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1889 	if (ssid == NULL) {
   1890 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
   1891 			   "to update", id);
   1892 		return -1;
   1893 	}
   1894 
   1895 	return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
   1896 							 pos);
   1897 #else /* IEEE8021X_EAPOL */
   1898 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
   1899 	return -1;
   1900 #endif /* IEEE8021X_EAPOL */
   1901 }
   1902 
   1903 
   1904 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
   1905 					    const char *params,
   1906 					    char *buf, size_t buflen)
   1907 {
   1908 	char *pos, *end, tmp[30];
   1909 	int res, verbose, wps, ret;
   1910 #ifdef CONFIG_HS20
   1911 	const u8 *hs20;
   1912 #endif /* CONFIG_HS20 */
   1913 	const u8 *sess_id;
   1914 	size_t sess_id_len;
   1915 
   1916 	if (os_strcmp(params, "-DRIVER") == 0)
   1917 		return wpa_drv_status(wpa_s, buf, buflen);
   1918 	verbose = os_strcmp(params, "-VERBOSE") == 0;
   1919 	wps = os_strcmp(params, "-WPS") == 0;
   1920 	pos = buf;
   1921 	end = buf + buflen;
   1922 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
   1923 		struct wpa_ssid *ssid = wpa_s->current_ssid;
   1924 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
   1925 				  MAC2STR(wpa_s->bssid));
   1926 		if (os_snprintf_error(end - pos, ret))
   1927 			return pos - buf;
   1928 		pos += ret;
   1929 		ret = os_snprintf(pos, end - pos, "freq=%u\n",
   1930 				  wpa_s->assoc_freq);
   1931 		if (os_snprintf_error(end - pos, ret))
   1932 			return pos - buf;
   1933 		pos += ret;
   1934 		if (ssid) {
   1935 			u8 *_ssid = ssid->ssid;
   1936 			size_t ssid_len = ssid->ssid_len;
   1937 			u8 ssid_buf[SSID_MAX_LEN];
   1938 			if (ssid_len == 0) {
   1939 				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
   1940 				if (_res < 0)
   1941 					ssid_len = 0;
   1942 				else
   1943 					ssid_len = _res;
   1944 				_ssid = ssid_buf;
   1945 			}
   1946 			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
   1947 					  wpa_ssid_txt(_ssid, ssid_len),
   1948 					  ssid->id);
   1949 			if (os_snprintf_error(end - pos, ret))
   1950 				return pos - buf;
   1951 			pos += ret;
   1952 
   1953 			if (wps && ssid->passphrase &&
   1954 			    wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
   1955 			    (ssid->mode == WPAS_MODE_AP ||
   1956 			     ssid->mode == WPAS_MODE_P2P_GO)) {
   1957 				ret = os_snprintf(pos, end - pos,
   1958 						  "passphrase=%s\n",
   1959 						  ssid->passphrase);
   1960 				if (os_snprintf_error(end - pos, ret))
   1961 					return pos - buf;
   1962 				pos += ret;
   1963 			}
   1964 			if (ssid->id_str) {
   1965 				ret = os_snprintf(pos, end - pos,
   1966 						  "id_str=%s\n",
   1967 						  ssid->id_str);
   1968 				if (os_snprintf_error(end - pos, ret))
   1969 					return pos - buf;
   1970 				pos += ret;
   1971 			}
   1972 
   1973 			switch (ssid->mode) {
   1974 			case WPAS_MODE_INFRA:
   1975 				ret = os_snprintf(pos, end - pos,
   1976 						  "mode=station\n");
   1977 				break;
   1978 			case WPAS_MODE_IBSS:
   1979 				ret = os_snprintf(pos, end - pos,
   1980 						  "mode=IBSS\n");
   1981 				break;
   1982 			case WPAS_MODE_AP:
   1983 				ret = os_snprintf(pos, end - pos,
   1984 						  "mode=AP\n");
   1985 				break;
   1986 			case WPAS_MODE_P2P_GO:
   1987 				ret = os_snprintf(pos, end - pos,
   1988 						  "mode=P2P GO\n");
   1989 				break;
   1990 			case WPAS_MODE_P2P_GROUP_FORMATION:
   1991 				ret = os_snprintf(pos, end - pos,
   1992 						  "mode=P2P GO - group "
   1993 						  "formation\n");
   1994 				break;
   1995 			case WPAS_MODE_MESH:
   1996 				ret = os_snprintf(pos, end - pos,
   1997 						  "mode=mesh\n");
   1998 				break;
   1999 			default:
   2000 				ret = 0;
   2001 				break;
   2002 			}
   2003 			if (os_snprintf_error(end - pos, ret))
   2004 				return pos - buf;
   2005 			pos += ret;
   2006 		}
   2007 
   2008 #ifdef CONFIG_AP
   2009 		if (wpa_s->ap_iface) {
   2010 			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
   2011 							    end - pos,
   2012 							    verbose);
   2013 		} else
   2014 #endif /* CONFIG_AP */
   2015 		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
   2016 	}
   2017 #ifdef CONFIG_SME
   2018 #ifdef CONFIG_SAE
   2019 	if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
   2020 #ifdef CONFIG_AP
   2021 	    !wpa_s->ap_iface &&
   2022 #endif /* CONFIG_AP */
   2023 	    wpa_s->sme.sae.state == SAE_ACCEPTED) {
   2024 		ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
   2025 				  wpa_s->sme.sae.group);
   2026 		if (os_snprintf_error(end - pos, ret))
   2027 			return pos - buf;
   2028 		pos += ret;
   2029 	}
   2030 #endif /* CONFIG_SAE */
   2031 #endif /* CONFIG_SME */
   2032 	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
   2033 			  wpa_supplicant_state_txt(wpa_s->wpa_state));
   2034 	if (os_snprintf_error(end - pos, ret))
   2035 		return pos - buf;
   2036 	pos += ret;
   2037 
   2038 	if (wpa_s->l2 &&
   2039 	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
   2040 		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
   2041 		if (os_snprintf_error(end - pos, ret))
   2042 			return pos - buf;
   2043 		pos += ret;
   2044 	}
   2045 
   2046 #ifdef CONFIG_P2P
   2047 	if (wpa_s->global->p2p) {
   2048 		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
   2049 				  "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
   2050 		if (os_snprintf_error(end - pos, ret))
   2051 			return pos - buf;
   2052 		pos += ret;
   2053 	}
   2054 #endif /* CONFIG_P2P */
   2055 
   2056 	ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
   2057 			  MAC2STR(wpa_s->own_addr));
   2058 	if (os_snprintf_error(end - pos, ret))
   2059 		return pos - buf;
   2060 	pos += ret;
   2061 
   2062 #ifdef CONFIG_HS20
   2063 	if (wpa_s->current_bss &&
   2064 	    (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
   2065 					  HS20_IE_VENDOR_TYPE)) &&
   2066 	    wpa_s->wpa_proto == WPA_PROTO_RSN &&
   2067 	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
   2068 		int release = 1;
   2069 		if (hs20[1] >= 5) {
   2070 			u8 rel_num = (hs20[6] & 0xf0) >> 4;
   2071 			release = rel_num + 1;
   2072 		}
   2073 		ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
   2074 		if (os_snprintf_error(end - pos, ret))
   2075 			return pos - buf;
   2076 		pos += ret;
   2077 	}
   2078 
   2079 	if (wpa_s->current_ssid) {
   2080 		struct wpa_cred *cred;
   2081 		char *type;
   2082 
   2083 		for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
   2084 			size_t i;
   2085 
   2086 			if (wpa_s->current_ssid->parent_cred != cred)
   2087 				continue;
   2088 
   2089 			if (cred->provisioning_sp) {
   2090 				ret = os_snprintf(pos, end - pos,
   2091 						  "provisioning_sp=%s\n",
   2092 						  cred->provisioning_sp);
   2093 				if (os_snprintf_error(end - pos, ret))
   2094 					return pos - buf;
   2095 				pos += ret;
   2096 			}
   2097 
   2098 			if (!cred->domain)
   2099 				goto no_domain;
   2100 
   2101 			i = 0;
   2102 			if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
   2103 				struct wpabuf *names =
   2104 					wpa_s->current_bss->anqp->domain_name;
   2105 				for (i = 0; names && i < cred->num_domain; i++)
   2106 				{
   2107 					if (domain_name_list_contains(
   2108 						    names, cred->domain[i], 1))
   2109 						break;
   2110 				}
   2111 				if (i == cred->num_domain)
   2112 					i = 0; /* show first entry by default */
   2113 			}
   2114 			ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
   2115 					  cred->domain[i]);
   2116 			if (os_snprintf_error(end - pos, ret))
   2117 				return pos - buf;
   2118 			pos += ret;
   2119 
   2120 		no_domain:
   2121 			if (wpa_s->current_bss == NULL ||
   2122 			    wpa_s->current_bss->anqp == NULL)
   2123 				res = -1;
   2124 			else
   2125 				res = interworking_home_sp_cred(
   2126 					wpa_s, cred,
   2127 					wpa_s->current_bss->anqp->domain_name);
   2128 			if (res > 0)
   2129 				type = "home";
   2130 			else if (res == 0)
   2131 				type = "roaming";
   2132 			else
   2133 				type = "unknown";
   2134 
   2135 			ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
   2136 			if (os_snprintf_error(end - pos, ret))
   2137 				return pos - buf;
   2138 			pos += ret;
   2139 
   2140 			break;
   2141 		}
   2142 	}
   2143 #endif /* CONFIG_HS20 */
   2144 
   2145 	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
   2146 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
   2147 		res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
   2148 					  verbose);
   2149 		if (res >= 0)
   2150 			pos += res;
   2151 	}
   2152 
   2153 #ifdef CONFIG_MACSEC
   2154 	res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
   2155 	if (res > 0)
   2156 		pos += res;
   2157 #endif /* CONFIG_MACSEC */
   2158 
   2159 	sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
   2160 	if (sess_id) {
   2161 		char *start = pos;
   2162 
   2163 		ret = os_snprintf(pos, end - pos, "eap_session_id=");
   2164 		if (os_snprintf_error(end - pos, ret))
   2165 			return start - buf;
   2166 		pos += ret;
   2167 		ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
   2168 		if (ret <= 0)
   2169 			return start - buf;
   2170 		pos += ret;
   2171 		ret = os_snprintf(pos, end - pos, "\n");
   2172 		if (os_snprintf_error(end - pos, ret))
   2173 			return start - buf;
   2174 		pos += ret;
   2175 	}
   2176 
   2177 	res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
   2178 	if (res >= 0)
   2179 		pos += res;
   2180 
   2181 #ifdef CONFIG_WPS
   2182 	{
   2183 		char uuid_str[100];
   2184 		uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
   2185 		ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
   2186 		if (os_snprintf_error(end - pos, ret))
   2187 			return pos - buf;
   2188 		pos += ret;
   2189 	}
   2190 #endif /* CONFIG_WPS */
   2191 
   2192 #ifdef ANDROID
   2193 	/*
   2194 	 * Allow using the STATUS command with default behavior, say for debug,
   2195 	 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
   2196 	 * events with STATUS-NO_EVENTS.
   2197 	 */
   2198 	if (os_strcmp(params, "-NO_EVENTS")) {
   2199 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
   2200 			     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
   2201 			     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
   2202 			     wpa_s->wpa_state,
   2203 			     MAC2STR(wpa_s->bssid),
   2204 			     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
   2205 			     wpa_ssid_txt(wpa_s->current_ssid->ssid,
   2206 					  wpa_s->current_ssid->ssid_len) : "");
   2207 		if (wpa_s->wpa_state == WPA_COMPLETED) {
   2208 			struct wpa_ssid *ssid = wpa_s->current_ssid;
   2209 			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
   2210 				     "- connection to " MACSTR
   2211 				     " completed %s [id=%d id_str=%s]",
   2212 				     MAC2STR(wpa_s->bssid), "(auth)",
   2213 				     ssid ? ssid->id : -1,
   2214 				     ssid && ssid->id_str ? ssid->id_str : "");
   2215 		}
   2216 	}
   2217 #endif /* ANDROID */
   2218 
   2219 	return pos - buf;
   2220 }
   2221 
   2222 
   2223 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
   2224 					   char *cmd)
   2225 {
   2226 	char *pos;
   2227 	int id;
   2228 	struct wpa_ssid *ssid;
   2229 	u8 bssid[ETH_ALEN];
   2230 
   2231 	/* cmd: "<network id> <BSSID>" */
   2232 	pos = os_strchr(cmd, ' ');
   2233 	if (pos == NULL)
   2234 		return -1;
   2235 	*pos++ = '\0';
   2236 	id = atoi(cmd);
   2237 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
   2238 	if (hwaddr_aton(pos, bssid)) {
   2239 		wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
   2240 		return -1;
   2241 	}
   2242 
   2243 	ssid = wpa_config_get_network(wpa_s->conf, id);
   2244 	if (ssid == NULL) {
   2245 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
   2246 			   "to update", id);
   2247 		return -1;
   2248 	}
   2249 
   2250 	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
   2251 	ssid->bssid_set = !is_zero_ether_addr(bssid);
   2252 
   2253 	return 0;
   2254 }
   2255 
   2256 
   2257 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
   2258 					       char *cmd, char *buf,
   2259 					       size_t buflen)
   2260 {
   2261 	u8 bssid[ETH_ALEN];
   2262 	struct wpa_blacklist *e;
   2263 	char *pos, *end;
   2264 	int ret;
   2265 
   2266 	/* cmd: "BLACKLIST [<BSSID>]" */
   2267 	if (*cmd == '\0') {
   2268 		pos = buf;
   2269 		end = buf + buflen;
   2270 		e = wpa_s->blacklist;
   2271 		while (e) {
   2272 			ret = os_snprintf(pos, end - pos, MACSTR "\n",
   2273 					  MAC2STR(e->bssid));
   2274 			if (os_snprintf_error(end - pos, ret))
   2275 				return pos - buf;
   2276 			pos += ret;
   2277 			e = e->next;
   2278 		}
   2279 		return pos - buf;
   2280 	}
   2281 
   2282 	cmd++;
   2283 	if (os_strncmp(cmd, "clear", 5) == 0) {
   2284 		wpa_blacklist_clear(wpa_s);
   2285 		os_memcpy(buf, "OK\n", 3);
   2286 		return 3;
   2287 	}
   2288 
   2289 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
   2290 	if (hwaddr_aton(cmd, bssid)) {
   2291 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
   2292 		return -1;
   2293 	}
   2294 
   2295 	/*
   2296 	 * Add the BSSID twice, so its count will be 2, causing it to be
   2297 	 * skipped when processing scan results.
   2298 	 */
   2299 	ret = wpa_blacklist_add(wpa_s, bssid);
   2300 	if (ret < 0)
   2301 		return -1;
   2302 	ret = wpa_blacklist_add(wpa_s, bssid);
   2303 	if (ret < 0)
   2304 		return -1;
   2305 	os_memcpy(buf, "OK\n", 3);
   2306 	return 3;
   2307 }
   2308 
   2309 
   2310 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
   2311 					       char *cmd, char *buf,
   2312 					       size_t buflen)
   2313 {
   2314 	char *pos, *end, *stamp;
   2315 	int ret;
   2316 
   2317 	/* cmd: "LOG_LEVEL [<level>]" */
   2318 	if (*cmd == '\0') {
   2319 		pos = buf;
   2320 		end = buf + buflen;
   2321 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
   2322 				  "Timestamp: %d\n",
   2323 				  debug_level_str(wpa_debug_level),
   2324 				  wpa_debug_timestamp);
   2325 		if (os_snprintf_error(end - pos, ret))
   2326 			ret = 0;
   2327 
   2328 		return ret;
   2329 	}
   2330 
   2331 	while (*cmd == ' ')
   2332 		cmd++;
   2333 
   2334 	stamp = os_strchr(cmd, ' ');
   2335 	if (stamp) {
   2336 		*stamp++ = '\0';
   2337 		while (*stamp == ' ') {
   2338 			stamp++;
   2339 		}
   2340 	}
   2341 
   2342 	if (os_strlen(cmd)) {
   2343 		int level = str_to_debug_level(cmd);
   2344 		if (level < 0)
   2345 			return -1;
   2346 		wpa_debug_level = level;
   2347 	}
   2348 
   2349 	if (stamp && os_strlen(stamp))
   2350 		wpa_debug_timestamp = atoi(stamp);
   2351 
   2352 	os_memcpy(buf, "OK\n", 3);
   2353 	return 3;
   2354 }
   2355 
   2356 
   2357 static int wpa_supplicant_ctrl_iface_list_networks(
   2358 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
   2359 {
   2360 	char *pos, *end, *prev;
   2361 	struct wpa_ssid *ssid;
   2362 	int ret;
   2363 
   2364 	pos = buf;
   2365 	end = buf + buflen;
   2366 	ret = os_snprintf(pos, end - pos,
   2367 			  "network id / ssid / bssid / flags\n");
   2368 	if (os_snprintf_error(end - pos, ret))
   2369 		return pos - buf;
   2370 	pos += ret;
   2371 
   2372 	ssid = wpa_s->conf->ssid;
   2373 
   2374 	/* skip over ssids until we find next one */
   2375 	if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
   2376 		int last_id = atoi(cmd + 8);
   2377 		if (last_id != -1) {
   2378 			while (ssid != NULL && ssid->id <= last_id) {
   2379 				ssid = ssid->next;
   2380 			}
   2381 		}
   2382 	}
   2383 
   2384 	while (ssid) {
   2385 		prev = pos;
   2386 		ret = os_snprintf(pos, end - pos, "%d\t%s",
   2387 				  ssid->id,
   2388 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
   2389 		if (os_snprintf_error(end - pos, ret))
   2390 			return prev - buf;
   2391 		pos += ret;
   2392 		if (ssid->bssid_set) {
   2393 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
   2394 					  MAC2STR(ssid->bssid));
   2395 		} else {
   2396 			ret = os_snprintf(pos, end - pos, "\tany");
   2397 		}
   2398 		if (os_snprintf_error(end - pos, ret))
   2399 			return prev - buf;
   2400 		pos += ret;
   2401 		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
   2402 				  ssid == wpa_s->current_ssid ?
   2403 				  "[CURRENT]" : "",
   2404 				  ssid->disabled ? "[DISABLED]" : "",
   2405 				  ssid->disabled_until.sec ?
   2406 				  "[TEMP-DISABLED]" : "",
   2407 				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
   2408 				  "");
   2409 		if (os_snprintf_error(end - pos, ret))
   2410 			return prev - buf;
   2411 		pos += ret;
   2412 		ret = os_snprintf(pos, end - pos, "\n");
   2413 		if (os_snprintf_error(end - pos, ret))
   2414 			return prev - buf;
   2415 		pos += ret;
   2416 
   2417 		ssid = ssid->next;
   2418 	}
   2419 
   2420 	return pos - buf;
   2421 }
   2422 
   2423 
   2424 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
   2425 {
   2426 	int ret;
   2427 	ret = os_snprintf(pos, end - pos, "-");
   2428 	if (os_snprintf_error(end - pos, ret))
   2429 		return pos;
   2430 	pos += ret;
   2431 	ret = wpa_write_ciphers(pos, end, cipher, "+");
   2432 	if (ret < 0)
   2433 		return pos;
   2434 	pos += ret;
   2435 	return pos;
   2436 }
   2437 
   2438 
   2439 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
   2440 				    const u8 *ie, size_t ie_len)
   2441 {
   2442 	struct wpa_ie_data data;
   2443 	char *start;
   2444 	int ret;
   2445 
   2446 	ret = os_snprintf(pos, end - pos, "[%s-", proto);
   2447 	if (os_snprintf_error(end - pos, ret))
   2448 		return pos;
   2449 	pos += ret;
   2450 
   2451 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
   2452 		ret = os_snprintf(pos, end - pos, "?]");
   2453 		if (os_snprintf_error(end - pos, ret))
   2454 			return pos;
   2455 		pos += ret;
   2456 		return pos;
   2457 	}
   2458 
   2459 	start = pos;
   2460 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
   2461 		ret = os_snprintf(pos, end - pos, "%sEAP",
   2462 				  pos == start ? "" : "+");
   2463 		if (os_snprintf_error(end - pos, ret))
   2464 			return pos;
   2465 		pos += ret;
   2466 	}
   2467 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
   2468 		ret = os_snprintf(pos, end - pos, "%sPSK",
   2469 				  pos == start ? "" : "+");
   2470 		if (os_snprintf_error(end - pos, ret))
   2471 			return pos;
   2472 		pos += ret;
   2473 	}
   2474 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
   2475 		ret = os_snprintf(pos, end - pos, "%sNone",
   2476 				  pos == start ? "" : "+");
   2477 		if (os_snprintf_error(end - pos, ret))
   2478 			return pos;
   2479 		pos += ret;
   2480 	}
   2481 	if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
   2482 		ret = os_snprintf(pos, end - pos, "%sSAE",
   2483 				  pos == start ? "" : "+");
   2484 		if (os_snprintf_error(end - pos, ret))
   2485 			return pos;
   2486 		pos += ret;
   2487 	}
   2488 #ifdef CONFIG_IEEE80211R
   2489 	if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
   2490 		ret = os_snprintf(pos, end - pos, "%sFT/EAP",
   2491 				  pos == start ? "" : "+");
   2492 		if (os_snprintf_error(end - pos, ret))
   2493 			return pos;
   2494 		pos += ret;
   2495 	}
   2496 	if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
   2497 		ret = os_snprintf(pos, end - pos, "%sFT/PSK",
   2498 				  pos == start ? "" : "+");
   2499 		if (os_snprintf_error(end - pos, ret))
   2500 			return pos;
   2501 		pos += ret;
   2502 	}
   2503 	if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
   2504 		ret = os_snprintf(pos, end - pos, "%sFT/SAE",
   2505 				  pos == start ? "" : "+");
   2506 		if (os_snprintf_error(end - pos, ret))
   2507 			return pos;
   2508 		pos += ret;
   2509 	}
   2510 #endif /* CONFIG_IEEE80211R */
   2511 #ifdef CONFIG_IEEE80211W
   2512 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
   2513 		ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
   2514 				  pos == start ? "" : "+");
   2515 		if (os_snprintf_error(end - pos, ret))
   2516 			return pos;
   2517 		pos += ret;
   2518 	}
   2519 	if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
   2520 		ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
   2521 				  pos == start ? "" : "+");
   2522 		if (os_snprintf_error(end - pos, ret))
   2523 			return pos;
   2524 		pos += ret;
   2525 	}
   2526 #endif /* CONFIG_IEEE80211W */
   2527 
   2528 #ifdef CONFIG_SUITEB
   2529 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
   2530 		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
   2531 				  pos == start ? "" : "+");
   2532 		if (os_snprintf_error(end - pos, ret))
   2533 			return pos;
   2534 		pos += ret;
   2535 	}
   2536 #endif /* CONFIG_SUITEB */
   2537 
   2538 #ifdef CONFIG_SUITEB192
   2539 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
   2540 		ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
   2541 				  pos == start ? "" : "+");
   2542 		if (os_snprintf_error(end - pos, ret))
   2543 			return pos;
   2544 		pos += ret;
   2545 	}
   2546 #endif /* CONFIG_SUITEB192 */
   2547 
   2548 #ifdef CONFIG_FILS
   2549 	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
   2550 		ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
   2551 				  pos == start ? "" : "+");
   2552 		if (os_snprintf_error(end - pos, ret))
   2553 			return pos;
   2554 		pos += ret;
   2555 	}
   2556 	if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
   2557 		ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
   2558 				  pos == start ? "" : "+");
   2559 		if (os_snprintf_error(end - pos, ret))
   2560 			return pos;
   2561 		pos += ret;
   2562 	}
   2563 #ifdef CONFIG_IEEE80211R
   2564 	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
   2565 		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
   2566 				  pos == start ? "" : "+");
   2567 		if (os_snprintf_error(end - pos, ret))
   2568 			return pos;
   2569 		pos += ret;
   2570 	}
   2571 	if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
   2572 		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
   2573 				  pos == start ? "" : "+");
   2574 		if (os_snprintf_error(end - pos, ret))
   2575 			return pos;
   2576 		pos += ret;
   2577 	}
   2578 #endif /* CONFIG_IEEE80211R */
   2579 #endif /* CONFIG_FILS */
   2580 
   2581 	if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
   2582 		ret = os_snprintf(pos, end - pos, "%sOSEN",
   2583 				  pos == start ? "" : "+");
   2584 		if (os_snprintf_error(end - pos, ret))
   2585 			return pos;
   2586 		pos += ret;
   2587 	}
   2588 
   2589 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
   2590 
   2591 	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
   2592 		ret = os_snprintf(pos, end - pos, "-preauth");
   2593 		if (os_snprintf_error(end - pos, ret))
   2594 			return pos;
   2595 		pos += ret;
   2596 	}
   2597 
   2598 	ret = os_snprintf(pos, end - pos, "]");
   2599 	if (os_snprintf_error(end - pos, ret))
   2600 		return pos;
   2601 	pos += ret;
   2602 
   2603 	return pos;
   2604 }
   2605 
   2606 
   2607 #ifdef CONFIG_WPS
   2608 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
   2609 					    char *pos, char *end,
   2610 					    struct wpabuf *wps_ie)
   2611 {
   2612 	int ret;
   2613 	const char *txt;
   2614 
   2615 	if (wps_ie == NULL)
   2616 		return pos;
   2617 	if (wps_is_selected_pbc_registrar(wps_ie))
   2618 		txt = "[WPS-PBC]";
   2619 	else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
   2620 		txt = "[WPS-AUTH]";
   2621 	else if (wps_is_selected_pin_registrar(wps_ie))
   2622 		txt = "[WPS-PIN]";
   2623 	else
   2624 		txt = "[WPS]";
   2625 
   2626 	ret = os_snprintf(pos, end - pos, "%s", txt);
   2627 	if (!os_snprintf_error(end - pos, ret))
   2628 		pos += ret;
   2629 	wpabuf_free(wps_ie);
   2630 	return pos;
   2631 }
   2632 #endif /* CONFIG_WPS */
   2633 
   2634 
   2635 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
   2636 					char *pos, char *end,
   2637 					const struct wpa_bss *bss)
   2638 {
   2639 #ifdef CONFIG_WPS
   2640 	struct wpabuf *wps_ie;
   2641 	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
   2642 	return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
   2643 #else /* CONFIG_WPS */
   2644 	return pos;
   2645 #endif /* CONFIG_WPS */
   2646 }
   2647 
   2648 
   2649 /* Format one result on one text line into a buffer. */
   2650 static int wpa_supplicant_ctrl_iface_scan_result(
   2651 	struct wpa_supplicant *wpa_s,
   2652 	const struct wpa_bss *bss, char *buf, size_t buflen)
   2653 {
   2654 	char *pos, *end;
   2655 	int ret;
   2656 	const u8 *ie, *ie2, *osen_ie, *p2p, *mesh;
   2657 
   2658 	mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
   2659 	p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
   2660 	if (!p2p)
   2661 		p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
   2662 	if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
   2663 	    os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
   2664 	    0)
   2665 		return 0; /* Do not show P2P listen discovery results here */
   2666 
   2667 	pos = buf;
   2668 	end = buf + buflen;
   2669 
   2670 	ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
   2671 			  MAC2STR(bss->bssid), bss->freq, bss->level);
   2672 	if (os_snprintf_error(end - pos, ret))
   2673 		return -1;
   2674 	pos += ret;
   2675 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
   2676 	if (ie)
   2677 		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
   2678 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
   2679 	if (ie2) {
   2680 		pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
   2681 					    ie2, 2 + ie2[1]);
   2682 	}
   2683 	osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
   2684 	if (osen_ie)
   2685 		pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
   2686 					    osen_ie, 2 + osen_ie[1]);
   2687 	pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
   2688 	if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
   2689 		ret = os_snprintf(pos, end - pos, "[WEP]");
   2690 		if (os_snprintf_error(end - pos, ret))
   2691 			return -1;
   2692 		pos += ret;
   2693 	}
   2694 	if (mesh) {
   2695 		ret = os_snprintf(pos, end - pos, "[MESH]");
   2696 		if (os_snprintf_error(end - pos, ret))
   2697 			return -1;
   2698 		pos += ret;
   2699 	}
   2700 	if (bss_is_dmg(bss)) {
   2701 		const char *s;
   2702 		ret = os_snprintf(pos, end - pos, "[DMG]");
   2703 		if (os_snprintf_error(end - pos, ret))
   2704 			return -1;
   2705 		pos += ret;
   2706 		switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
   2707 		case IEEE80211_CAP_DMG_IBSS:
   2708 			s = "[IBSS]";
   2709 			break;
   2710 		case IEEE80211_CAP_DMG_AP:
   2711 			s = "[ESS]";
   2712 			break;
   2713 		case IEEE80211_CAP_DMG_PBSS:
   2714 			s = "[PBSS]";
   2715 			break;
   2716 		default:
   2717 			s = "";
   2718 			break;
   2719 		}
   2720 		ret = os_snprintf(pos, end - pos, "%s", s);
   2721 		if (os_snprintf_error(end - pos, ret))
   2722 			return -1;
   2723 		pos += ret;
   2724 	} else {
   2725 		if (bss->caps & IEEE80211_CAP_IBSS) {
   2726 			ret = os_snprintf(pos, end - pos, "[IBSS]");
   2727 			if (os_snprintf_error(end - pos, ret))
   2728 				return -1;
   2729 			pos += ret;
   2730 		}
   2731 		if (bss->caps & IEEE80211_CAP_ESS) {
   2732 			ret = os_snprintf(pos, end - pos, "[ESS]");
   2733 			if (os_snprintf_error(end - pos, ret))
   2734 				return -1;
   2735 			pos += ret;
   2736 		}
   2737 	}
   2738 	if (p2p) {
   2739 		ret = os_snprintf(pos, end - pos, "[P2P]");
   2740 		if (os_snprintf_error(end - pos, ret))
   2741 			return -1;
   2742 		pos += ret;
   2743 	}
   2744 #ifdef CONFIG_HS20
   2745 	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
   2746 		ret = os_snprintf(pos, end - pos, "[HS20]");
   2747 		if (os_snprintf_error(end - pos, ret))
   2748 			return -1;
   2749 		pos += ret;
   2750 	}
   2751 #endif /* CONFIG_HS20 */
   2752 #ifdef CONFIG_FILS
   2753 	if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
   2754 		ret = os_snprintf(pos, end - pos, "[FILS]");
   2755 		if (os_snprintf_error(end - pos, ret))
   2756 			return -1;
   2757 		pos += ret;
   2758 	}
   2759 #endif /* CONFIG_FILS */
   2760 #ifdef CONFIG_FST
   2761 	if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
   2762 		ret = os_snprintf(pos, end - pos, "[FST]");
   2763 		if (os_snprintf_error(end - pos, ret))
   2764 			return -1;
   2765 		pos += ret;
   2766 	}
   2767 #endif /* CONFIG_FST */
   2768 
   2769 	ret = os_snprintf(pos, end - pos, "\t%s",
   2770 			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
   2771 	if (os_snprintf_error(end - pos, ret))
   2772 		return -1;
   2773 	pos += ret;
   2774 
   2775 	ret = os_snprintf(pos, end - pos, "\n");
   2776 	if (os_snprintf_error(end - pos, ret))
   2777 		return -1;
   2778 	pos += ret;
   2779 
   2780 	return pos - buf;
   2781 }
   2782 
   2783 
   2784 static int wpa_supplicant_ctrl_iface_scan_results(
   2785 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
   2786 {
   2787 	char *pos, *end;
   2788 	struct wpa_bss *bss;
   2789 	int ret;
   2790 
   2791 	pos = buf;
   2792 	end = buf + buflen;
   2793 	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
   2794 			  "flags / ssid\n");
   2795 	if (os_snprintf_error(end - pos, ret))
   2796 		return pos - buf;
   2797 	pos += ret;
   2798 
   2799 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
   2800 		ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
   2801 							    end - pos);
   2802 		if (ret < 0 || ret >= end - pos)
   2803 			return pos - buf;
   2804 		pos += ret;
   2805 	}
   2806 
   2807 	return pos - buf;
   2808 }
   2809 
   2810 
   2811 #ifdef CONFIG_MESH
   2812 
   2813 static int wpa_supplicant_ctrl_iface_mesh_interface_add(
   2814 	struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
   2815 {
   2816 	char *pos, ifname[IFNAMSIZ + 1];
   2817 
   2818 	ifname[0] = '\0';
   2819 
   2820 	pos = os_strstr(cmd, "ifname=");
   2821 	if (pos) {
   2822 		pos += 7;
   2823 		os_strlcpy(ifname, pos, sizeof(ifname));
   2824 	}
   2825 
   2826 	if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
   2827 		return -1;
   2828 
   2829 	os_strlcpy(reply, ifname, max_len);
   2830 	return os_strlen(ifname);
   2831 }
   2832 
   2833 
   2834 static int wpa_supplicant_ctrl_iface_mesh_group_add(
   2835 	struct wpa_supplicant *wpa_s, char *cmd)
   2836 {
   2837 	int id;
   2838 	struct wpa_ssid *ssid;
   2839 
   2840 	id = atoi(cmd);
   2841 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
   2842 
   2843 	ssid = wpa_config_get_network(wpa_s->conf, id);
   2844 	if (ssid == NULL) {
   2845 		wpa_printf(MSG_DEBUG,
   2846 			   "CTRL_IFACE: Could not find network id=%d", id);
   2847 		return -1;
   2848 	}
   2849 	if (ssid->mode != WPAS_MODE_MESH) {
   2850 		wpa_printf(MSG_DEBUG,
   2851 			   "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
   2852 		return -1;
   2853 	}
   2854 	if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
   2855 	    ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
   2856 		wpa_printf(MSG_ERROR,
   2857 			   "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
   2858 		return -1;
   2859 	}
   2860 
   2861 	/*
   2862 	 * TODO: If necessary write our own group_add function,
   2863 	 * for now we can reuse select_network
   2864 	 */
   2865 	wpa_supplicant_select_network(wpa_s, ssid);
   2866 
   2867 	return 0;
   2868 }
   2869 
   2870 
   2871 static int wpa_supplicant_ctrl_iface_mesh_group_remove(
   2872 	struct wpa_supplicant *wpa_s, char *cmd)
   2873 {
   2874 	struct wpa_supplicant *orig;
   2875 	struct wpa_global *global;
   2876 	int found = 0;
   2877 
   2878 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
   2879 
   2880 	global = wpa_s->global;
   2881 	orig = wpa_s;
   2882 
   2883 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
   2884 		if (os_strcmp(wpa_s->ifname, cmd) == 0) {
   2885 			found = 1;
   2886 			break;
   2887 		}
   2888 	}
   2889 	if (!found) {
   2890 		wpa_printf(MSG_ERROR,
   2891 			   "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
   2892 			   cmd);
   2893 		return -1;
   2894 	}
   2895 	if (wpa_s->mesh_if_created && wpa_s == orig) {
   2896 		wpa_printf(MSG_ERROR,
   2897 			   "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
   2898 		return -1;
   2899 	}
   2900 
   2901 	wpa_s->reassociate = 0;
   2902 	wpa_s->disconnected = 1;
   2903 	wpa_supplicant_cancel_sched_scan(wpa_s);
   2904 	wpa_supplicant_cancel_scan(wpa_s);
   2905 
   2906 	/*
   2907 	 * TODO: If necessary write our own group_remove function,
   2908 	 * for now we can reuse deauthenticate
   2909 	 */
   2910 	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
   2911 
   2912 	if (wpa_s->mesh_if_created)
   2913 		wpa_supplicant_remove_iface(global, wpa_s, 0);
   2914 
   2915 	return 0;
   2916 }
   2917 
   2918 
   2919 static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
   2920 	struct wpa_supplicant *wpa_s, char *cmd)
   2921 {
   2922 	u8 addr[ETH_ALEN];
   2923 
   2924 	if (hwaddr_aton(cmd, addr) < 0)
   2925 		return -1;
   2926 
   2927 	return wpas_mesh_peer_remove(wpa_s, addr);
   2928 }
   2929 
   2930 
   2931 static int wpa_supplicant_ctrl_iface_mesh_peer_add(
   2932 	struct wpa_supplicant *wpa_s, char *cmd)
   2933 {
   2934 	u8 addr[ETH_ALEN];
   2935 	int duration;
   2936 	char *pos;
   2937 
   2938 	pos = os_strstr(cmd, " duration=");
   2939 	if (pos) {
   2940 		*pos = '\0';
   2941 		duration = atoi(pos + 10);
   2942 	} else {
   2943 		duration = -1;
   2944 	}
   2945 
   2946 	if (hwaddr_aton(cmd, addr))
   2947 		return -1;
   2948 
   2949 	return wpas_mesh_peer_add(wpa_s, addr, duration);
   2950 }
   2951 
   2952 #endif /* CONFIG_MESH */
   2953 
   2954 
   2955 static int wpa_supplicant_ctrl_iface_select_network(
   2956 	struct wpa_supplicant *wpa_s, char *cmd)
   2957 {
   2958 	int id;
   2959 	struct wpa_ssid *ssid;
   2960 	char *pos;
   2961 
   2962 	/* cmd: "<network id>" or "any" */
   2963 	if (os_strncmp(cmd, "any", 3) == 0) {
   2964 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
   2965 		ssid = NULL;
   2966 	} else {
   2967 		id = atoi(cmd);
   2968 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
   2969 
   2970 		ssid = wpa_config_get_network(wpa_s->conf, id);
   2971 		if (ssid == NULL) {
   2972 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   2973 				   "network id=%d", id);
   2974 			return -1;
   2975 		}
   2976 		if (ssid->disabled == 2) {
   2977 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
   2978 				   "SELECT_NETWORK with persistent P2P group");
   2979 			return -1;
   2980 		}
   2981 	}
   2982 
   2983 	pos = os_strstr(cmd, " freq=");
   2984 	if (pos) {
   2985 		int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
   2986 		if (freqs) {
   2987 			wpa_s->scan_req = MANUAL_SCAN_REQ;
   2988 			os_free(wpa_s->manual_scan_freqs);
   2989 			wpa_s->manual_scan_freqs = freqs;
   2990 		}
   2991 	}
   2992 
   2993 	wpa_s->scan_min_time.sec = 0;
   2994 	wpa_s->scan_min_time.usec = 0;
   2995 	wpa_supplicant_select_network(wpa_s, ssid);
   2996 
   2997 	return 0;
   2998 }
   2999 
   3000 
   3001 static int wpa_supplicant_ctrl_iface_enable_network(
   3002 	struct wpa_supplicant *wpa_s, char *cmd)
   3003 {
   3004 	int id;
   3005 	struct wpa_ssid *ssid;
   3006 
   3007 	/* cmd: "<network id>" or "all" */
   3008 	if (os_strcmp(cmd, "all") == 0) {
   3009 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
   3010 		ssid = NULL;
   3011 	} else {
   3012 		id = atoi(cmd);
   3013 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
   3014 
   3015 		ssid = wpa_config_get_network(wpa_s->conf, id);
   3016 		if (ssid == NULL) {
   3017 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   3018 				   "network id=%d", id);
   3019 			return -1;
   3020 		}
   3021 		if (ssid->disabled == 2) {
   3022 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
   3023 				   "ENABLE_NETWORK with persistent P2P group");
   3024 			return -1;
   3025 		}
   3026 
   3027 		if (os_strstr(cmd, " no-connect")) {
   3028 			ssid->disabled = 0;
   3029 			return 0;
   3030 		}
   3031 	}
   3032 	wpa_s->scan_min_time.sec = 0;
   3033 	wpa_s->scan_min_time.usec = 0;
   3034 	wpa_supplicant_enable_network(wpa_s, ssid);
   3035 
   3036 	return 0;
   3037 }
   3038 
   3039 
   3040 static int wpa_supplicant_ctrl_iface_disable_network(
   3041 	struct wpa_supplicant *wpa_s, char *cmd)
   3042 {
   3043 	int id;
   3044 	struct wpa_ssid *ssid;
   3045 
   3046 	/* cmd: "<network id>" or "all" */
   3047 	if (os_strcmp(cmd, "all") == 0) {
   3048 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
   3049 		ssid = NULL;
   3050 	} else {
   3051 		id = atoi(cmd);
   3052 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
   3053 
   3054 		ssid = wpa_config_get_network(wpa_s->conf, id);
   3055 		if (ssid == NULL) {
   3056 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   3057 				   "network id=%d", id);
   3058 			return -1;
   3059 		}
   3060 		if (ssid->disabled == 2) {
   3061 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
   3062 				   "DISABLE_NETWORK with persistent P2P "
   3063 				   "group");
   3064 			return -1;
   3065 		}
   3066 	}
   3067 	wpa_supplicant_disable_network(wpa_s, ssid);
   3068 
   3069 	return 0;
   3070 }
   3071 
   3072 
   3073 static int wpa_supplicant_ctrl_iface_add_network(
   3074 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
   3075 {
   3076 	struct wpa_ssid *ssid;
   3077 	int ret;
   3078 
   3079 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
   3080 
   3081 	ssid = wpa_supplicant_add_network(wpa_s);
   3082 	if (ssid == NULL)
   3083 		return -1;
   3084 
   3085 	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
   3086 	if (os_snprintf_error(buflen, ret))
   3087 		return -1;
   3088 	return ret;
   3089 }
   3090 
   3091 
   3092 static int wpa_supplicant_ctrl_iface_remove_network(
   3093 	struct wpa_supplicant *wpa_s, char *cmd)
   3094 {
   3095 	int id;
   3096 	struct wpa_ssid *ssid;
   3097 	int result;
   3098 
   3099 	/* cmd: "<network id>" or "all" */
   3100 	if (os_strcmp(cmd, "all") == 0) {
   3101 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
   3102 		if (wpa_s->sched_scanning)
   3103 			wpa_supplicant_cancel_sched_scan(wpa_s);
   3104 
   3105 		eapol_sm_invalidate_cached_session(wpa_s->eapol);
   3106 		if (wpa_s->current_ssid) {
   3107 #ifdef CONFIG_SME
   3108 			wpa_s->sme.prev_bssid_set = 0;
   3109 #endif /* CONFIG_SME */
   3110 			wpa_sm_set_config(wpa_s->wpa, NULL);
   3111 			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
   3112 			if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
   3113 				wpa_s->own_disconnect_req = 1;
   3114 			wpa_supplicant_deauthenticate(
   3115 				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
   3116 		}
   3117 		ssid = wpa_s->conf->ssid;
   3118 		while (ssid) {
   3119 			struct wpa_ssid *remove_ssid = ssid;
   3120 			id = ssid->id;
   3121 			ssid = ssid->next;
   3122 			if (wpa_s->last_ssid == remove_ssid)
   3123 				wpa_s->last_ssid = NULL;
   3124 			wpas_notify_network_removed(wpa_s, remove_ssid);
   3125 			wpa_config_remove_network(wpa_s->conf, id);
   3126 		}
   3127 		return 0;
   3128 	}
   3129 
   3130 	id = atoi(cmd);
   3131 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
   3132 
   3133 	result = wpa_supplicant_remove_network(wpa_s, id);
   3134 	if (result == -1) {
   3135 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   3136 			   "id=%d", id);
   3137 		return -1;
   3138 	}
   3139 	if (result == -2) {
   3140 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
   3141 			   "network id=%d", id);
   3142 		return -1;
   3143 	}
   3144 	return 0;
   3145 }
   3146 
   3147 
   3148 static int wpa_supplicant_ctrl_iface_update_network(
   3149 	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
   3150 	char *name, char *value)
   3151 {
   3152 	int ret;
   3153 
   3154 	ret = wpa_config_set(ssid, name, value, 0);
   3155 	if (ret < 0) {
   3156 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
   3157 			   "variable '%s'", name);
   3158 		return -1;
   3159 	}
   3160 	if (ret == 1)
   3161 		return 0; /* No change to the previously configured value */
   3162 
   3163 	if (os_strcmp(name, "bssid") != 0 &&
   3164 	    os_strcmp(name, "priority") != 0) {
   3165 		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
   3166 
   3167 		if (wpa_s->current_ssid == ssid ||
   3168 		    wpa_s->current_ssid == NULL) {
   3169 			/*
   3170 			 * Invalidate the EAP session cache if anything in the
   3171 			 * current or previously used configuration changes.
   3172 			 */
   3173 			eapol_sm_invalidate_cached_session(wpa_s->eapol);
   3174 		}
   3175 	}
   3176 
   3177 	if ((os_strcmp(name, "psk") == 0 &&
   3178 	     value[0] == '"' && ssid->ssid_len) ||
   3179 	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
   3180 		wpa_config_update_psk(ssid);
   3181 	else if (os_strcmp(name, "priority") == 0)
   3182 		wpa_config_update_prio_list(wpa_s->conf);
   3183 
   3184 	return 0;
   3185 }
   3186 
   3187 
   3188 static int wpa_supplicant_ctrl_iface_set_network(
   3189 	struct wpa_supplicant *wpa_s, char *cmd)
   3190 {
   3191 	int id, ret, prev_bssid_set, prev_disabled;
   3192 	struct wpa_ssid *ssid;
   3193 	char *name, *value;
   3194 	u8 prev_bssid[ETH_ALEN];
   3195 
   3196 	/* cmd: "<network id> <variable name> <value>" */
   3197 	name = os_strchr(cmd, ' ');
   3198 	if (name == NULL)
   3199 		return -1;
   3200 	*name++ = '\0';
   3201 
   3202 	value = os_strchr(name, ' ');
   3203 	if (value == NULL)
   3204 		return -1;
   3205 	*value++ = '\0';
   3206 
   3207 	id = atoi(cmd);
   3208 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
   3209 		   id, name);
   3210 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
   3211 			      (u8 *) value, os_strlen(value));
   3212 
   3213 	ssid = wpa_config_get_network(wpa_s->conf, id);
   3214 	if (ssid == NULL) {
   3215 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
   3216 			   "id=%d", id);
   3217 		return -1;
   3218 	}
   3219 
   3220 	prev_bssid_set = ssid->bssid_set;
   3221 	prev_disabled = ssid->disabled;
   3222 	os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
   3223 	ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
   3224 						       value);
   3225 	if (ret == 0 &&
   3226 	    (ssid->bssid_set != prev_bssid_set ||
   3227 	     os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
   3228 		wpas_notify_network_bssid_set_changed(wpa_s, ssid);
   3229 
   3230 	if (prev_disabled != ssid->disabled &&
   3231 	    (prev_disabled == 2 || ssid->disabled == 2))
   3232 		wpas_notify_network_type_changed(wpa_s, ssid);
   3233 
   3234 	return ret;
   3235 }
   3236 
   3237 
   3238 static int wpa_supplicant_ctrl_iface_get_network(
   3239 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
   3240 {
   3241 	int id;
   3242 	size_t res;
   3243 	struct wpa_ssid *ssid;
   3244 	char *name, *value;
   3245 
   3246 	/* cmd: "<network id> <variable name>" */
   3247 	name = os_strchr(cmd, ' ');
   3248 	if (name == NULL || buflen == 0)
   3249 		return -1;
   3250 	*name++ = '\0';
   3251 
   3252 	id = atoi(cmd);
   3253 	wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
   3254 		   id, name);
   3255 
   3256 	ssid = wpa_config_get_network(wpa_s->conf, id);
   3257 	if (ssid == NULL) {
   3258 		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
   3259 			   "id=%d", id);
   3260 		return -1;
   3261 	}
   3262 
   3263 	value = wpa_config_get_no_key(ssid, name);
   3264 	if (value == NULL) {
   3265 		wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
   3266 			   "variable '%s'", name);
   3267 		return -1;
   3268 	}
   3269 
   3270 	res = os_strlcpy(buf, value, buflen);
   3271 	if (res >= buflen) {
   3272 		os_free(value);
   3273 		return -1;
   3274 	}
   3275 
   3276 	os_free(value);
   3277 
   3278 	return res;
   3279 }
   3280 
   3281 
   3282 static int wpa_supplicant_ctrl_iface_dup_network(
   3283 	struct wpa_supplicant *wpa_s, char *cmd,
   3284 	struct wpa_supplicant *dst_wpa_s)
   3285 {
   3286 	struct wpa_ssid *ssid_s, *ssid_d;
   3287 	char *name, *id, *value;
   3288 	int id_s, id_d, ret;
   3289 
   3290 	/* cmd: "<src network id> <dst network id> <variable name>" */
   3291 	id = os_strchr(cmd, ' ');
   3292 	if (id == NULL)
   3293 		return -1;
   3294 	*id++ = '\0';
   3295 
   3296 	name = os_strchr(id, ' ');
   3297 	if (name == NULL)
   3298 		return -1;
   3299 	*name++ = '\0';
   3300 
   3301 	id_s = atoi(cmd);
   3302 	id_d = atoi(id);
   3303 
   3304 	wpa_printf(MSG_DEBUG,
   3305 		   "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
   3306 		   wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
   3307 
   3308 	ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
   3309 	if (ssid_s == NULL) {
   3310 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   3311 			   "network id=%d", id_s);
   3312 		return -1;
   3313 	}
   3314 
   3315 	ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
   3316 	if (ssid_d == NULL) {
   3317 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   3318 			   "network id=%d", id_d);
   3319 		return -1;
   3320 	}
   3321 
   3322 	value = wpa_config_get(ssid_s, name);
   3323 	if (value == NULL) {
   3324 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
   3325 			   "variable '%s'", name);
   3326 		return -1;
   3327 	}
   3328 
   3329 	ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
   3330 						       value);
   3331 
   3332 	os_free(value);
   3333 
   3334 	return ret;
   3335 }
   3336 
   3337 
   3338 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
   3339 						char *buf, size_t buflen)
   3340 {
   3341 	char *pos, *end;
   3342 	struct wpa_cred *cred;
   3343 	int ret;
   3344 
   3345 	pos = buf;
   3346 	end = buf + buflen;
   3347 	ret = os_snprintf(pos, end - pos,
   3348 			  "cred id / realm / username / domain / imsi\n");
   3349 	if (os_snprintf_error(end - pos, ret))
   3350 		return pos - buf;
   3351 	pos += ret;
   3352 
   3353 	cred = wpa_s->conf->cred;
   3354 	while (cred) {
   3355 		ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
   3356 				  cred->id, cred->realm ? cred->realm : "",
   3357 				  cred->username ? cred->username : "",
   3358 				  cred->domain ? cred->domain[0] : "",
   3359 				  cred->imsi ? cred->imsi : "");
   3360 		if (os_snprintf_error(end - pos, ret))
   3361 			return pos - buf;
   3362 		pos += ret;
   3363 
   3364 		cred = cred->next;
   3365 	}
   3366 
   3367 	return pos - buf;
   3368 }
   3369 
   3370 
   3371 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
   3372 					      char *buf, size_t buflen)
   3373 {
   3374 	struct wpa_cred *cred;
   3375 	int ret;
   3376 
   3377 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
   3378 
   3379 	cred = wpa_config_add_cred(wpa_s->conf);
   3380 	if (cred == NULL)
   3381 		return -1;
   3382 
   3383 	wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
   3384 
   3385 	ret = os_snprintf(buf, buflen, "%d\n", cred->id);
   3386 	if (os_snprintf_error(buflen, ret))
   3387 		return -1;
   3388 	return ret;
   3389 }
   3390 
   3391 
   3392 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
   3393 				 struct wpa_cred *cred)
   3394 {
   3395 	struct wpa_ssid *ssid;
   3396 	char str[20];
   3397 	int id;
   3398 
   3399 	if (cred == NULL) {
   3400 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
   3401 		return -1;
   3402 	}
   3403 
   3404 	id = cred->id;
   3405 	if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
   3406 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
   3407 		return -1;
   3408 	}
   3409 
   3410 	wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
   3411 
   3412 	/* Remove any network entry created based on the removed credential */
   3413 	ssid = wpa_s->conf->ssid;
   3414 	while (ssid) {
   3415 		if (ssid->parent_cred == cred) {
   3416 			int res;
   3417 
   3418 			wpa_printf(MSG_DEBUG, "Remove network id %d since it "
   3419 				   "used the removed credential", ssid->id);
   3420 			res = os_snprintf(str, sizeof(str), "%d", ssid->id);
   3421 			if (os_snprintf_error(sizeof(str), res))
   3422 				str[sizeof(str) - 1] = '\0';
   3423 			ssid = ssid->next;
   3424 			wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
   3425 		} else
   3426 			ssid = ssid->next;
   3427 	}
   3428 
   3429 	return 0;
   3430 }
   3431 
   3432 
   3433 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
   3434 						 char *cmd)
   3435 {
   3436 	int id;
   3437 	struct wpa_cred *cred, *prev;
   3438 
   3439 	/* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
   3440 	 * "provisioning_sp=<FQDN> */
   3441 	if (os_strcmp(cmd, "all") == 0) {
   3442 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
   3443 		cred = wpa_s->conf->cred;
   3444 		while (cred) {
   3445 			prev = cred;
   3446 			cred = cred->next;
   3447 			wpas_ctrl_remove_cred(wpa_s, prev);
   3448 		}
   3449 		return 0;
   3450 	}
   3451 
   3452 	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
   3453 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
   3454 			   cmd + 8);
   3455 		cred = wpa_s->conf->cred;
   3456 		while (cred) {
   3457 			prev = cred;
   3458 			cred = cred->next;
   3459 			if (prev->domain) {
   3460 				size_t i;
   3461 				for (i = 0; i < prev->num_domain; i++) {
   3462 					if (os_strcmp(prev->domain[i], cmd + 8)
   3463 					    != 0)
   3464 						continue;
   3465 					wpas_ctrl_remove_cred(wpa_s, prev);
   3466 					break;
   3467 				}
   3468 			}
   3469 		}
   3470 		return 0;
   3471 	}
   3472 
   3473 	if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
   3474 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
   3475 			   cmd + 16);
   3476 		cred = wpa_s->conf->cred;
   3477 		while (cred) {
   3478 			prev = cred;
   3479 			cred = cred->next;
   3480 			if (prev->provisioning_sp &&
   3481 			    os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
   3482 				wpas_ctrl_remove_cred(wpa_s, prev);
   3483 		}
   3484 		return 0;
   3485 	}
   3486 
   3487 	id = atoi(cmd);
   3488 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
   3489 
   3490 	cred = wpa_config_get_cred(wpa_s->conf, id);
   3491 	return wpas_ctrl_remove_cred(wpa_s, cred);
   3492 }
   3493 
   3494 
   3495 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
   3496 					      char *cmd)
   3497 {
   3498 	int id;
   3499 	struct wpa_cred *cred;
   3500 	char *name, *value;
   3501 
   3502 	/* cmd: "<cred id> <variable name> <value>" */
   3503 	name = os_strchr(cmd, ' ');
   3504 	if (name == NULL)
   3505 		return -1;
   3506 	*name++ = '\0';
   3507 
   3508 	value = os_strchr(name, ' ');
   3509 	if (value == NULL)
   3510 		return -1;
   3511 	*value++ = '\0';
   3512 
   3513 	id = atoi(cmd);
   3514 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
   3515 		   id, name);
   3516 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
   3517 			      (u8 *) value, os_strlen(value));
   3518 
   3519 	cred = wpa_config_get_cred(wpa_s->conf, id);
   3520 	if (cred == NULL) {
   3521 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
   3522 			   id);
   3523 		return -1;
   3524 	}
   3525 
   3526 	if (wpa_config_set_cred(cred, name, value, 0) < 0) {
   3527 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
   3528 			   "variable '%s'", name);
   3529 		return -1;
   3530 	}
   3531 
   3532 	wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
   3533 
   3534 	return 0;
   3535 }
   3536 
   3537 
   3538 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
   3539 					      char *cmd, char *buf,
   3540 					      size_t buflen)
   3541 {
   3542 	int id;
   3543 	size_t res;
   3544 	struct wpa_cred *cred;
   3545 	char *name, *value;
   3546 
   3547 	/* cmd: "<cred id> <variable name>" */
   3548 	name = os_strchr(cmd, ' ');
   3549 	if (name == NULL)
   3550 		return -1;
   3551 	*name++ = '\0';
   3552 
   3553 	id = atoi(cmd);
   3554 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
   3555 		   id, name);
   3556 
   3557 	cred = wpa_config_get_cred(wpa_s->conf, id);
   3558 	if (cred == NULL) {
   3559 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
   3560 			   id);
   3561 		return -1;
   3562 	}
   3563 
   3564 	value = wpa_config_get_cred_no_key(cred, name);
   3565 	if (value == NULL) {
   3566 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
   3567 			   name);
   3568 		return -1;
   3569 	}
   3570 
   3571 	res = os_strlcpy(buf, value, buflen);
   3572 	if (res >= buflen) {
   3573 		os_free(value);
   3574 		return -1;
   3575 	}
   3576 
   3577 	os_free(value);
   3578 
   3579 	return res;
   3580 }
   3581 
   3582 
   3583 #ifndef CONFIG_NO_CONFIG_WRITE
   3584 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
   3585 {
   3586 	int ret;
   3587 
   3588 	if (!wpa_s->conf->update_config) {
   3589 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
   3590 			   "to update configuration (update_config=0)");
   3591 		return -1;
   3592 	}
   3593 
   3594 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
   3595 	if (ret) {
   3596 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
   3597 			   "update configuration");
   3598 	} else {
   3599 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
   3600 			   " updated");
   3601 	}
   3602 
   3603 	return ret;
   3604 }
   3605 #endif /* CONFIG_NO_CONFIG_WRITE */
   3606 
   3607 
   3608 struct cipher_info {
   3609 	unsigned int capa;
   3610 	const char *name;
   3611 	int group_only;
   3612 };
   3613 
   3614 static const struct cipher_info ciphers[] = {
   3615 	{ WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
   3616 	{ WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
   3617 	{ WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
   3618 	{ WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
   3619 	{ WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
   3620 	{ WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
   3621 	{ WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
   3622 	{ WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
   3623 };
   3624 
   3625 static const struct cipher_info ciphers_group_mgmt[] = {
   3626 	{ WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
   3627 	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
   3628 	{ WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
   3629 	{ WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
   3630 };
   3631 
   3632 
   3633 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
   3634 					      struct wpa_driver_capa *capa,
   3635 					      char *buf, size_t buflen)
   3636 {
   3637 	int ret;
   3638 	char *pos, *end;
   3639 	size_t len;
   3640 	unsigned int i;
   3641 
   3642 	pos = buf;
   3643 	end = pos + buflen;
   3644 
   3645 	if (res < 0) {
   3646 		if (strict)
   3647 			return 0;
   3648 		len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
   3649 		if (len >= buflen)
   3650 			return -1;
   3651 		return len;
   3652 	}
   3653 
   3654 	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
   3655 		if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
   3656 			ret = os_snprintf(pos, end - pos, "%s%s",
   3657 					  pos == buf ? "" : " ",
   3658 					  ciphers[i].name);
   3659 			if (os_snprintf_error(end - pos, ret))
   3660 				return pos - buf;
   3661 			pos += ret;
   3662 		}
   3663 	}
   3664 
   3665 	return pos - buf;
   3666 }
   3667 
   3668 
   3669 static int ctrl_iface_get_capability_group(int res, char *strict,
   3670 					   struct wpa_driver_capa *capa,
   3671 					   char *buf, size_t buflen)
   3672 {
   3673 	int ret;
   3674 	char *pos, *end;
   3675 	size_t len;
   3676 	unsigned int i;
   3677 
   3678 	pos = buf;
   3679 	end = pos + buflen;
   3680 
   3681 	if (res < 0) {
   3682 		if (strict)
   3683 			return 0;
   3684 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
   3685 		if (len >= buflen)
   3686 			return -1;
   3687 		return len;
   3688 	}
   3689 
   3690 	for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
   3691 		if (capa->enc & ciphers[i].capa) {
   3692 			ret = os_snprintf(pos, end - pos, "%s%s",
   3693 					  pos == buf ? "" : " ",
   3694 					  ciphers[i].name);
   3695 			if (os_snprintf_error(end - pos, ret))
   3696 				return pos - buf;
   3697 			pos += ret;
   3698 		}
   3699 	}
   3700 
   3701 	return pos - buf;
   3702 }
   3703 
   3704 
   3705 static int ctrl_iface_get_capability_group_mgmt(int res, char *strict,
   3706 						struct wpa_driver_capa *capa,
   3707 						char *buf, size_t buflen)
   3708 {
   3709 	int ret;
   3710 	char *pos, *end;
   3711 	unsigned int i;
   3712 
   3713 	pos = buf;
   3714 	end = pos + buflen;
   3715 
   3716 	if (res < 0)
   3717 		return 0;
   3718 
   3719 	for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
   3720 		if (capa->enc & ciphers_group_mgmt[i].capa) {
   3721 			ret = os_snprintf(pos, end - pos, "%s%s",
   3722 					  pos == buf ? "" : " ",
   3723 					  ciphers_group_mgmt[i].name);
   3724 			if (os_snprintf_error(end - pos, ret))
   3725 				return pos - buf;
   3726 			pos += ret;
   3727 		}
   3728 	}
   3729 
   3730 	return pos - buf;
   3731 }
   3732 
   3733 
   3734 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
   3735 					      struct wpa_driver_capa *capa,
   3736 					      char *buf, size_t buflen)
   3737 {
   3738 	int ret;
   3739 	char *pos, *end;
   3740 	size_t len;
   3741 
   3742 	pos = buf;
   3743 	end = pos + buflen;
   3744 
   3745 	if (res < 0) {
   3746 		if (strict)
   3747 			return 0;
   3748 		len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
   3749 				 "NONE", buflen);
   3750 		if (len >= buflen)
   3751 			return -1;
   3752 		return len;
   3753 	}
   3754 
   3755 	ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
   3756 	if (os_snprintf_error(end - pos, ret))
   3757 		return pos - buf;
   3758 	pos += ret;
   3759 
   3760 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   3761 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
   3762 		ret = os_snprintf(pos, end - pos, " WPA-EAP");
   3763 		if (os_snprintf_error(end - pos, ret))
   3764 			return pos - buf;
   3765 		pos += ret;
   3766 	}
   3767 
   3768 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
   3769 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   3770 		ret = os_snprintf(pos, end - pos, " WPA-PSK");
   3771 		if (os_snprintf_error(end - pos, ret))
   3772 			return pos - buf;
   3773 		pos += ret;
   3774 	}
   3775 
   3776 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
   3777 		ret = os_snprintf(pos, end - pos, " WPA-NONE");
   3778 		if (os_snprintf_error(end - pos, ret))
   3779 			return pos - buf;
   3780 		pos += ret;
   3781 	}
   3782 
   3783 #ifdef CONFIG_SUITEB
   3784 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
   3785 		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
   3786 		if (os_snprintf_error(end - pos, ret))
   3787 			return pos - buf;
   3788 		pos += ret;
   3789 	}
   3790 #endif /* CONFIG_SUITEB */
   3791 #ifdef CONFIG_SUITEB192
   3792 	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
   3793 		ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
   3794 		if (os_snprintf_error(end - pos, ret))
   3795 			return pos - buf;
   3796 		pos += ret;
   3797 	}
   3798 #endif /* CONFIG_SUITEB192 */
   3799 
   3800 	return pos - buf;
   3801 }
   3802 
   3803 
   3804 static int ctrl_iface_get_capability_proto(int res, char *strict,
   3805 					   struct wpa_driver_capa *capa,
   3806 					   char *buf, size_t buflen)
   3807 {
   3808 	int ret;
   3809 	char *pos, *end;
   3810 	size_t len;
   3811 
   3812 	pos = buf;
   3813 	end = pos + buflen;
   3814 
   3815 	if (res < 0) {
   3816 		if (strict)
   3817 			return 0;
   3818 		len = os_strlcpy(buf, "RSN WPA", buflen);
   3819 		if (len >= buflen)
   3820 			return -1;
   3821 		return len;
   3822 	}
   3823 
   3824 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
   3825 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   3826 		ret = os_snprintf(pos, end - pos, "%sRSN",
   3827 				  pos == buf ? "" : " ");
   3828 		if (os_snprintf_error(end - pos, ret))
   3829 			return pos - buf;
   3830 		pos += ret;
   3831 	}
   3832 
   3833 	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   3834 			      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
   3835 		ret = os_snprintf(pos, end - pos, "%sWPA",
   3836 				  pos == buf ? "" : " ");
   3837 		if (os_snprintf_error(end - pos, ret))
   3838 			return pos - buf;
   3839 		pos += ret;
   3840 	}
   3841 
   3842 	return pos - buf;
   3843 }
   3844 
   3845 
   3846 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
   3847 					      int res, char *strict,
   3848 					      struct wpa_driver_capa *capa,
   3849 					      char *buf, size_t buflen)
   3850 {
   3851 	int ret;
   3852 	char *pos, *end;
   3853 	size_t len;
   3854 
   3855 	pos = buf;
   3856 	end = pos + buflen;
   3857 
   3858 	if (res < 0) {
   3859 		if (strict)
   3860 			return 0;
   3861 		len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
   3862 		if (len >= buflen)
   3863 			return -1;
   3864 		return len;
   3865 	}
   3866 
   3867 	if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
   3868 		ret = os_snprintf(pos, end - pos, "%sOPEN",
   3869 				  pos == buf ? "" : " ");
   3870 		if (os_snprintf_error(end - pos, ret))
   3871 			return pos - buf;
   3872 		pos += ret;
   3873 	}
   3874 
   3875 	if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
   3876 		ret = os_snprintf(pos, end - pos, "%sSHARED",
   3877 				  pos == buf ? "" : " ");
   3878 		if (os_snprintf_error(end - pos, ret))
   3879 			return pos - buf;
   3880 		pos += ret;
   3881 	}
   3882 
   3883 	if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
   3884 		ret = os_snprintf(pos, end - pos, "%sLEAP",
   3885 				  pos == buf ? "" : " ");
   3886 		if (os_snprintf_error(end - pos, ret))
   3887 			return pos - buf;
   3888 		pos += ret;
   3889 	}
   3890 
   3891 #ifdef CONFIG_SAE
   3892 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
   3893 		ret = os_snprintf(pos, end - pos, "%sSAE",
   3894 				  pos == buf ? "" : " ");
   3895 		if (os_snprintf_error(end - pos, ret))
   3896 			return pos - buf;
   3897 		pos += ret;
   3898 	}
   3899 #endif /* CONFIG_SAE */
   3900 
   3901 	return pos - buf;
   3902 }
   3903 
   3904 
   3905 static int ctrl_iface_get_capability_modes(int res, char *strict,
   3906 					   struct wpa_driver_capa *capa,
   3907 					   char *buf, size_t buflen)
   3908 {
   3909 	int ret;
   3910 	char *pos, *end;
   3911 	size_t len;
   3912 
   3913 	pos = buf;
   3914 	end = pos + buflen;
   3915 
   3916 	if (res < 0) {
   3917 		if (strict)
   3918 			return 0;
   3919 		len = os_strlcpy(buf, "IBSS AP", buflen);
   3920 		if (len >= buflen)
   3921 			return -1;
   3922 		return len;
   3923 	}
   3924 
   3925 	if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
   3926 		ret = os_snprintf(pos, end - pos, "%sIBSS",
   3927 				  pos == buf ? "" : " ");
   3928 		if (os_snprintf_error(end - pos, ret))
   3929 			return pos - buf;
   3930 		pos += ret;
   3931 	}
   3932 
   3933 	if (capa->flags & WPA_DRIVER_FLAGS_AP) {
   3934 		ret = os_snprintf(pos, end - pos, "%sAP",
   3935 				  pos == buf ? "" : " ");
   3936 		if (os_snprintf_error(end - pos, ret))
   3937 			return pos - buf;
   3938 		pos += ret;
   3939 	}
   3940 
   3941 #ifdef CONFIG_MESH
   3942 	if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
   3943 		ret = os_snprintf(pos, end - pos, "%sMESH",
   3944 				  pos == buf ? "" : " ");
   3945 		if (os_snprintf_error(end - pos, ret))
   3946 			return pos - buf;
   3947 		pos += ret;
   3948 	}
   3949 #endif /* CONFIG_MESH */
   3950 
   3951 	return pos - buf;
   3952 }
   3953 
   3954 
   3955 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
   3956 					      char *buf, size_t buflen)
   3957 {
   3958 	struct hostapd_channel_data *chnl;
   3959 	int ret, i, j;
   3960 	char *pos, *end, *hmode;
   3961 
   3962 	pos = buf;
   3963 	end = pos + buflen;
   3964 
   3965 	for (j = 0; j < wpa_s->hw.num_modes; j++) {
   3966 		switch (wpa_s->hw.modes[j].mode) {
   3967 		case HOSTAPD_MODE_IEEE80211B:
   3968 			hmode = "B";
   3969 			break;
   3970 		case HOSTAPD_MODE_IEEE80211G:
   3971 			hmode = "G";
   3972 			break;
   3973 		case HOSTAPD_MODE_IEEE80211A:
   3974 			hmode = "A";
   3975 			break;
   3976 		case HOSTAPD_MODE_IEEE80211AD:
   3977 			hmode = "AD";
   3978 			break;
   3979 		default:
   3980 			continue;
   3981 		}
   3982 		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
   3983 		if (os_snprintf_error(end - pos, ret))
   3984 			return pos - buf;
   3985 		pos += ret;
   3986 		chnl = wpa_s->hw.modes[j].channels;
   3987 		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
   3988 			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
   3989 				continue;
   3990 			ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
   3991 			if (os_snprintf_error(end - pos, ret))
   3992 				return pos - buf;
   3993 			pos += ret;
   3994 		}
   3995 		ret = os_snprintf(pos, end - pos, "\n");
   3996 		if (os_snprintf_error(end - pos, ret))
   3997 			return pos - buf;
   3998 		pos += ret;
   3999 	}
   4000 
   4001 	return pos - buf;
   4002 }
   4003 
   4004 
   4005 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
   4006 					  char *buf, size_t buflen)
   4007 {
   4008 	struct hostapd_channel_data *chnl;
   4009 	int ret, i, j;
   4010 	char *pos, *end, *hmode;
   4011 
   4012 	pos = buf;
   4013 	end = pos + buflen;
   4014 
   4015 	for (j = 0; j < wpa_s->hw.num_modes; j++) {
   4016 		switch (wpa_s->hw.modes[j].mode) {
   4017 		case HOSTAPD_MODE_IEEE80211B:
   4018 			hmode = "B";
   4019 			break;
   4020 		case HOSTAPD_MODE_IEEE80211G:
   4021 			hmode = "G";
   4022 			break;
   4023 		case HOSTAPD_MODE_IEEE80211A:
   4024 			hmode = "A";
   4025 			break;
   4026 		case HOSTAPD_MODE_IEEE80211AD:
   4027 			hmode = "AD";
   4028 			break;
   4029 		default:
   4030 			continue;
   4031 		}
   4032 		ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
   4033 				  hmode);
   4034 		if (os_snprintf_error(end - pos, ret))
   4035 			return pos - buf;
   4036 		pos += ret;
   4037 		chnl = wpa_s->hw.modes[j].channels;
   4038 		for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
   4039 			if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
   4040 				continue;
   4041 			ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
   4042 					  chnl[i].chan, chnl[i].freq,
   4043 					  chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
   4044 					  " (NO_IR)" : "",
   4045 					  chnl[i].flag & HOSTAPD_CHAN_RADAR ?
   4046 					  " (DFS)" : "");
   4047 
   4048 			if (os_snprintf_error(end - pos, ret))
   4049 				return pos - buf;
   4050 			pos += ret;
   4051 		}
   4052 		ret = os_snprintf(pos, end - pos, "\n");
   4053 		if (os_snprintf_error(end - pos, ret))
   4054 			return pos - buf;
   4055 		pos += ret;
   4056 	}
   4057 
   4058 	return pos - buf;
   4059 }
   4060 
   4061 
   4062 static int wpa_supplicant_ctrl_iface_get_capability(
   4063 	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
   4064 	size_t buflen)
   4065 {
   4066 	struct wpa_driver_capa capa;
   4067 	int res;
   4068 	char *strict;
   4069 	char field[30];
   4070 	size_t len;
   4071 
   4072 	/* Determine whether or not strict checking was requested */
   4073 	len = os_strlcpy(field, _field, sizeof(field));
   4074 	if (len >= sizeof(field))
   4075 		return -1;
   4076 	strict = os_strchr(field, ' ');
   4077 	if (strict != NULL) {
   4078 		*strict++ = '\0';
   4079 		if (os_strcmp(strict, "strict") != 0)
   4080 			return -1;
   4081 	}
   4082 
   4083 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
   4084 		field, strict ? strict : "");
   4085 
   4086 	if (os_strcmp(field, "eap") == 0) {
   4087 		return eap_get_names(buf, buflen);
   4088 	}
   4089 
   4090 	res = wpa_drv_get_capa(wpa_s, &capa);
   4091 
   4092 	if (os_strcmp(field, "pairwise") == 0)
   4093 		return ctrl_iface_get_capability_pairwise(res, strict, &capa,
   4094 							  buf, buflen);
   4095 
   4096 	if (os_strcmp(field, "group") == 0)
   4097 		return ctrl_iface_get_capability_group(res, strict, &capa,
   4098 						       buf, buflen);
   4099 
   4100 	if (os_strcmp(field, "group_mgmt") == 0)
   4101 		return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
   4102 							    buf, buflen);
   4103 
   4104 	if (os_strcmp(field, "key_mgmt") == 0)
   4105 		return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
   4106 							  buf, buflen);
   4107 
   4108 	if (os_strcmp(field, "proto") == 0)
   4109 		return ctrl_iface_get_capability_proto(res, strict, &capa,
   4110 						       buf, buflen);
   4111 
   4112 	if (os_strcmp(field, "auth_alg") == 0)
   4113 		return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
   4114 							  &capa, buf, buflen);
   4115 
   4116 	if (os_strcmp(field, "modes") == 0)
   4117 		return ctrl_iface_get_capability_modes(res, strict, &capa,
   4118 						       buf, buflen);
   4119 
   4120 	if (os_strcmp(field, "channels") == 0)
   4121 		return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
   4122 
   4123 	if (os_strcmp(field, "freq") == 0)
   4124 		return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
   4125 
   4126 #ifdef CONFIG_TDLS
   4127 	if (os_strcmp(field, "tdls") == 0)
   4128 		return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
   4129 #endif /* CONFIG_TDLS */
   4130 
   4131 #ifdef CONFIG_ERP
   4132 	if (os_strcmp(field, "erp") == 0) {
   4133 		res = os_snprintf(buf, buflen, "ERP");
   4134 		if (os_snprintf_error(buflen, res))
   4135 			return -1;
   4136 		return res;
   4137 	}
   4138 #endif /* CONFIG_EPR */
   4139 
   4140 #ifdef CONFIG_FIPS
   4141 	if (os_strcmp(field, "fips") == 0) {
   4142 		res = os_snprintf(buf, buflen, "FIPS");
   4143 		if (os_snprintf_error(buflen, res))
   4144 			return -1;
   4145 		return res;
   4146 	}
   4147 #endif /* CONFIG_FIPS */
   4148 
   4149 #ifdef CONFIG_ACS
   4150 	if (os_strcmp(field, "acs") == 0) {
   4151 		res = os_snprintf(buf, buflen, "ACS");
   4152 		if (os_snprintf_error(buflen, res))
   4153 			return -1;
   4154 		return res;
   4155 	}
   4156 #endif /* CONFIG_ACS */
   4157 
   4158 #ifdef CONFIG_FILS
   4159 	if (os_strcmp(field, "fils") == 0 &&
   4160 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) {
   4161 		res = os_snprintf(buf, buflen, "FILS");
   4162 		if (os_snprintf_error(buflen, res))
   4163 			return -1;
   4164 		return res;
   4165 	}
   4166 #endif /* CONFIG_FILS */
   4167 
   4168 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
   4169 		   field);
   4170 
   4171 	return -1;
   4172 }
   4173 
   4174 
   4175 #ifdef CONFIG_INTERWORKING
   4176 static char * anqp_add_hex(char *pos, char *end, const char *title,
   4177 			   struct wpabuf *data)
   4178 {
   4179 	char *start = pos;
   4180 	size_t i;
   4181 	int ret;
   4182 	const u8 *d;
   4183 
   4184 	if (data == NULL)
   4185 		return start;
   4186 
   4187 	ret = os_snprintf(pos, end - pos, "%s=", title);
   4188 	if (os_snprintf_error(end - pos, ret))
   4189 		return start;
   4190 	pos += ret;
   4191 
   4192 	d = wpabuf_head_u8(data);
   4193 	for (i = 0; i < wpabuf_len(data); i++) {
   4194 		ret = os_snprintf(pos, end - pos, "%02x", *d++);
   4195 		if (os_snprintf_error(end - pos, ret))
   4196 			return start;
   4197 		pos += ret;
   4198 	}
   4199 
   4200 	ret = os_snprintf(pos, end - pos, "\n");
   4201 	if (os_snprintf_error(end - pos, ret))
   4202 		return start;
   4203 	pos += ret;
   4204 
   4205 	return pos;
   4206 }
   4207 #endif /* CONFIG_INTERWORKING */
   4208 
   4209 
   4210 #ifdef CONFIG_FILS
   4211 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
   4212 {
   4213 	char *start = pos;
   4214 	const u8 *ie, *ie_end;
   4215 	u16 info, realms;
   4216 	int ret;
   4217 
   4218 	ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
   4219 	if (!ie)
   4220 		return 0;
   4221 	ie_end = ie + 2 + ie[1];
   4222 	ie += 2;
   4223 	if (ie_end - ie < 2)
   4224 		return -1;
   4225 
   4226 	info = WPA_GET_LE16(ie);
   4227 	ie += 2;
   4228 	ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
   4229 	if (os_snprintf_error(end - pos, ret))
   4230 		return 0;
   4231 	pos += ret;
   4232 
   4233 	if (info & BIT(7)) {
   4234 		/* Cache Identifier Included */
   4235 		if (ie_end - ie < 2)
   4236 			return -1;
   4237 		ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
   4238 				  ie[0], ie[1]);
   4239 		if (os_snprintf_error(end - pos, ret))
   4240 			return 0;
   4241 		pos += ret;
   4242 		ie += 2;
   4243 	}
   4244 
   4245 	if (info & BIT(8)) {
   4246 		/* HESSID Included */
   4247 		if (ie_end - ie < ETH_ALEN)
   4248 			return -1;
   4249 		ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
   4250 				  MAC2STR(ie));
   4251 		if (os_snprintf_error(end - pos, ret))
   4252 			return 0;
   4253 		pos += ret;
   4254 		ie += ETH_ALEN;
   4255 	}
   4256 
   4257 	realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
   4258 	if (realms) {
   4259 		if (ie_end - ie < realms * 2)
   4260 			return -1;
   4261 		ret = os_snprintf(pos, end - pos, "fils_realms=");
   4262 		if (os_snprintf_error(end - pos, ret))
   4263 			return 0;
   4264 		pos += ret;
   4265 
   4266 		ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
   4267 		if (ret <= 0)
   4268 			return 0;
   4269 		pos += ret;
   4270 		ie += realms * 2;
   4271 		ret = os_snprintf(pos, end - pos, "\n");
   4272 		if (os_snprintf_error(end - pos, ret))
   4273 			return 0;
   4274 		pos += ret;
   4275 	}
   4276 
   4277 	return pos - start;
   4278 }
   4279 #endif /* CONFIG_FILS */
   4280 
   4281 
   4282 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
   4283 			  unsigned long mask, char *buf, size_t buflen)
   4284 {
   4285 	size_t i;
   4286 	int ret;
   4287 	char *pos, *end;
   4288 	const u8 *ie, *ie2, *osen_ie, *mesh;
   4289 
   4290 	pos = buf;
   4291 	end = buf + buflen;
   4292 
   4293 	if (mask & WPA_BSS_MASK_ID) {
   4294 		ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
   4295 		if (os_snprintf_error(end - pos, ret))
   4296 			return 0;
   4297 		pos += ret;
   4298 	}
   4299 
   4300 	if (mask & WPA_BSS_MASK_BSSID) {
   4301 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
   4302 				  MAC2STR(bss->bssid));
   4303 		if (os_snprintf_error(end - pos, ret))
   4304 			return 0;
   4305 		pos += ret;
   4306 	}
   4307 
   4308 	if (mask & WPA_BSS_MASK_FREQ) {
   4309 		ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
   4310 		if (os_snprintf_error(end - pos, ret))
   4311 			return 0;
   4312 		pos += ret;
   4313 	}
   4314 
   4315 	if (mask & WPA_BSS_MASK_BEACON_INT) {
   4316 		ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
   4317 				  bss->beacon_int);
   4318 		if (os_snprintf_error(end - pos, ret))
   4319 			return 0;
   4320 		pos += ret;
   4321 	}
   4322 
   4323 	if (mask & WPA_BSS_MASK_CAPABILITIES) {
   4324 		ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
   4325 				  bss->caps);
   4326 		if (os_snprintf_error(end - pos, ret))
   4327 			return 0;
   4328 		pos += ret;
   4329 	}
   4330 
   4331 	if (mask & WPA_BSS_MASK_QUAL) {
   4332 		ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
   4333 		if (os_snprintf_error(end - pos, ret))
   4334 			return 0;
   4335 		pos += ret;
   4336 	}
   4337 
   4338 	if (mask & WPA_BSS_MASK_NOISE) {
   4339 		ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
   4340 		if (os_snprintf_error(end - pos, ret))
   4341 			return 0;
   4342 		pos += ret;
   4343 	}
   4344 
   4345 	if (mask & WPA_BSS_MASK_LEVEL) {
   4346 		ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
   4347 		if (os_snprintf_error(end - pos, ret))
   4348 			return 0;
   4349 		pos += ret;
   4350 	}
   4351 
   4352 	if (mask & WPA_BSS_MASK_TSF) {
   4353 		ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
   4354 				  (unsigned long long) bss->tsf);
   4355 		if (os_snprintf_error(end - pos, ret))
   4356 			return 0;
   4357 		pos += ret;
   4358 	}
   4359 
   4360 	if (mask & WPA_BSS_MASK_AGE) {
   4361 		struct os_reltime now;
   4362 
   4363 		os_get_reltime(&now);
   4364 		ret = os_snprintf(pos, end - pos, "age=%d\n",
   4365 				  (int) (now.sec - bss->last_update.sec));
   4366 		if (os_snprintf_error(end - pos, ret))
   4367 			return 0;
   4368 		pos += ret;
   4369 	}
   4370 
   4371 	if (mask & WPA_BSS_MASK_IE) {
   4372 		ret = os_snprintf(pos, end - pos, "ie=");
   4373 		if (os_snprintf_error(end - pos, ret))
   4374 			return 0;
   4375 		pos += ret;
   4376 
   4377 		ie = (const u8 *) (bss + 1);
   4378 		for (i = 0; i < bss->ie_len; i++) {
   4379 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
   4380 			if (os_snprintf_error(end - pos, ret))
   4381 				return 0;
   4382 			pos += ret;
   4383 		}
   4384 
   4385 		ret = os_snprintf(pos, end - pos, "\n");
   4386 		if (os_snprintf_error(end - pos, ret))
   4387 			return 0;
   4388 		pos += ret;
   4389 	}
   4390 
   4391 	if (mask & WPA_BSS_MASK_FLAGS) {
   4392 		ret = os_snprintf(pos, end - pos, "flags=");
   4393 		if (os_snprintf_error(end - pos, ret))
   4394 			return 0;
   4395 		pos += ret;
   4396 
   4397 		mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
   4398 
   4399 		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
   4400 		if (ie)
   4401 			pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
   4402 						    2 + ie[1]);
   4403 		ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
   4404 		if (ie2)
   4405 			pos = wpa_supplicant_ie_txt(pos, end,
   4406 						    mesh ? "RSN" : "WPA2", ie2,
   4407 						    2 + ie2[1]);
   4408 		osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
   4409 		if (osen_ie)
   4410 			pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
   4411 						    osen_ie, 2 + osen_ie[1]);
   4412 		pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
   4413 		if (!ie && !ie2 && !osen_ie &&
   4414 		    (bss->caps & IEEE80211_CAP_PRIVACY)) {
   4415 			ret = os_snprintf(pos, end - pos, "[WEP]");
   4416 			if (os_snprintf_error(end - pos, ret))
   4417 				return 0;
   4418 			pos += ret;
   4419 		}
   4420 
   4421 		if (mesh) {
   4422 			ret = os_snprintf(pos, end - pos, "[MESH]");
   4423 			if (os_snprintf_error(end - pos, ret))
   4424 				return 0;
   4425 			pos += ret;
   4426 		}
   4427 
   4428 		if (bss_is_dmg(bss)) {
   4429 			const char *s;
   4430 			ret = os_snprintf(pos, end - pos, "[DMG]");
   4431 			if (os_snprintf_error(end - pos, ret))
   4432 				return 0;
   4433 			pos += ret;
   4434 			switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
   4435 			case IEEE80211_CAP_DMG_IBSS:
   4436 				s = "[IBSS]";
   4437 				break;
   4438 			case IEEE80211_CAP_DMG_AP:
   4439 				s = "[ESS]";
   4440 				break;
   4441 			case IEEE80211_CAP_DMG_PBSS:
   4442 				s = "[PBSS]";
   4443 				break;
   4444 			default:
   4445 				s = "";
   4446 				break;
   4447 			}
   4448 			ret = os_snprintf(pos, end - pos, "%s", s);
   4449 			if (os_snprintf_error(end - pos, ret))
   4450 				return 0;
   4451 			pos += ret;
   4452 		} else {
   4453 			if (bss->caps & IEEE80211_CAP_IBSS) {
   4454 				ret = os_snprintf(pos, end - pos, "[IBSS]");
   4455 				if (os_snprintf_error(end - pos, ret))
   4456 					return 0;
   4457 				pos += ret;
   4458 			}
   4459 			if (bss->caps & IEEE80211_CAP_ESS) {
   4460 				ret = os_snprintf(pos, end - pos, "[ESS]");
   4461 				if (os_snprintf_error(end - pos, ret))
   4462 					return 0;
   4463 				pos += ret;
   4464 			}
   4465 		}
   4466 		if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
   4467 		    wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
   4468 			ret = os_snprintf(pos, end - pos, "[P2P]");
   4469 			if (os_snprintf_error(end - pos, ret))
   4470 				return 0;
   4471 			pos += ret;
   4472 		}
   4473 #ifdef CONFIG_HS20
   4474 		if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
   4475 			ret = os_snprintf(pos, end - pos, "[HS20]");
   4476 			if (os_snprintf_error(end - pos, ret))
   4477 				return 0;
   4478 			pos += ret;
   4479 		}
   4480 #endif /* CONFIG_HS20 */
   4481 #ifdef CONFIG_FILS
   4482 		if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
   4483 			ret = os_snprintf(pos, end - pos, "[FILS]");
   4484 			if (os_snprintf_error(end - pos, ret))
   4485 				return 0;
   4486 			pos += ret;
   4487 		}
   4488 #endif /* CONFIG_FILS */
   4489 
   4490 		ret = os_snprintf(pos, end - pos, "\n");
   4491 		if (os_snprintf_error(end - pos, ret))
   4492 			return 0;
   4493 		pos += ret;
   4494 	}
   4495 
   4496 	if (mask & WPA_BSS_MASK_SSID) {
   4497 		ret = os_snprintf(pos, end - pos, "ssid=%s\n",
   4498 				  wpa_ssid_txt(bss->ssid, bss->ssid_len));
   4499 		if (os_snprintf_error(end - pos, ret))
   4500 			return 0;
   4501 		pos += ret;
   4502 	}
   4503 
   4504 #ifdef CONFIG_WPS
   4505 	if (mask & WPA_BSS_MASK_WPS_SCAN) {
   4506 		ie = (const u8 *) (bss + 1);
   4507 		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
   4508 		if (ret >= end - pos)
   4509 			return 0;
   4510 		if (ret > 0)
   4511 			pos += ret;
   4512 	}
   4513 #endif /* CONFIG_WPS */
   4514 
   4515 #ifdef CONFIG_P2P
   4516 	if (mask & WPA_BSS_MASK_P2P_SCAN) {
   4517 		ie = (const u8 *) (bss + 1);
   4518 		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
   4519 		if (ret >= end - pos)
   4520 			return 0;
   4521 		if (ret > 0)
   4522 			pos += ret;
   4523 	}
   4524 #endif /* CONFIG_P2P */
   4525 
   4526 #ifdef CONFIG_WIFI_DISPLAY
   4527 	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
   4528 		struct wpabuf *wfd;
   4529 		ie = (const u8 *) (bss + 1);
   4530 		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
   4531 						  WFD_IE_VENDOR_TYPE);
   4532 		if (wfd) {
   4533 			ret = os_snprintf(pos, end - pos, "wfd_subelems=");
   4534 			if (os_snprintf_error(end - pos, ret)) {
   4535 				wpabuf_free(wfd);
   4536 				return 0;
   4537 			}
   4538 			pos += ret;
   4539 
   4540 			pos += wpa_snprintf_hex(pos, end - pos,
   4541 						wpabuf_head(wfd),
   4542 						wpabuf_len(wfd));
   4543 			wpabuf_free(wfd);
   4544 
   4545 			ret = os_snprintf(pos, end - pos, "\n");
   4546 			if (os_snprintf_error(end - pos, ret))
   4547 				return 0;
   4548 			pos += ret;
   4549 		}
   4550 	}
   4551 #endif /* CONFIG_WIFI_DISPLAY */
   4552 
   4553 #ifdef CONFIG_INTERWORKING
   4554 	if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
   4555 		struct wpa_bss_anqp *anqp = bss->anqp;
   4556 		struct wpa_bss_anqp_elem *elem;
   4557 
   4558 		pos = anqp_add_hex(pos, end, "anqp_capability_list",
   4559 				   anqp->capability_list);
   4560 		pos = anqp_add_hex(pos, end, "anqp_venue_name",
   4561 				   anqp->venue_name);
   4562 		pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
   4563 				   anqp->network_auth_type);
   4564 		pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
   4565 				   anqp->roaming_consortium);
   4566 		pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
   4567 				   anqp->ip_addr_type_availability);
   4568 		pos = anqp_add_hex(pos, end, "anqp_nai_realm",
   4569 				   anqp->nai_realm);
   4570 		pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
   4571 		pos = anqp_add_hex(pos, end, "anqp_domain_name",
   4572 				   anqp->domain_name);
   4573 		pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
   4574 				   anqp->fils_realm_info);
   4575 #ifdef CONFIG_HS20
   4576 		pos = anqp_add_hex(pos, end, "hs20_capability_list",
   4577 				   anqp->hs20_capability_list);
   4578 		pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
   4579 				   anqp->hs20_operator_friendly_name);
   4580 		pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
   4581 				   anqp->hs20_wan_metrics);
   4582 		pos = anqp_add_hex(pos, end, "hs20_connection_capability",
   4583 				   anqp->hs20_connection_capability);
   4584 		pos = anqp_add_hex(pos, end, "hs20_operating_class",
   4585 				   anqp->hs20_operating_class);
   4586 		pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
   4587 				   anqp->hs20_osu_providers_list);
   4588 #endif /* CONFIG_HS20 */
   4589 
   4590 		dl_list_for_each(elem, &anqp->anqp_elems,
   4591 				 struct wpa_bss_anqp_elem, list) {
   4592 			char title[20];
   4593 
   4594 			os_snprintf(title, sizeof(title), "anqp[%u]",
   4595 				    elem->infoid);
   4596 			pos = anqp_add_hex(pos, end, title, elem->payload);
   4597 		}
   4598 	}
   4599 #endif /* CONFIG_INTERWORKING */
   4600 
   4601 #ifdef CONFIG_MESH
   4602 	if (mask & WPA_BSS_MASK_MESH_SCAN) {
   4603 		ie = (const u8 *) (bss + 1);
   4604 		ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
   4605 		if (ret >= end - pos)
   4606 			return 0;
   4607 		if (ret > 0)
   4608 			pos += ret;
   4609 	}
   4610 #endif /* CONFIG_MESH */
   4611 
   4612 	if (mask & WPA_BSS_MASK_SNR) {
   4613 		ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
   4614 		if (os_snprintf_error(end - pos, ret))
   4615 			return 0;
   4616 		pos += ret;
   4617 	}
   4618 
   4619 	if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
   4620 		ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
   4621 				  bss->est_throughput);
   4622 		if (os_snprintf_error(end - pos, ret))
   4623 			return 0;
   4624 		pos += ret;
   4625 	}
   4626 
   4627 #ifdef CONFIG_FST
   4628 	if (mask & WPA_BSS_MASK_FST) {
   4629 		ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
   4630 		if (ret < 0 || ret >= end - pos)
   4631 			return 0;
   4632 		pos += ret;
   4633 	}
   4634 #endif /* CONFIG_FST */
   4635 
   4636 	if (mask & WPA_BSS_MASK_UPDATE_IDX) {
   4637 		ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
   4638 				  bss->last_update_idx);
   4639 		if (os_snprintf_error(end - pos, ret))
   4640 			return 0;
   4641 		pos += ret;
   4642 	}
   4643 
   4644 	if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
   4645 		ret = os_snprintf(pos, end - pos, "beacon_ie=");
   4646 		if (os_snprintf_error(end - pos, ret))
   4647 			return 0;
   4648 		pos += ret;
   4649 
   4650 		ie = (const u8 *) (bss + 1);
   4651 		ie += bss->ie_len;
   4652 		for (i = 0; i < bss->beacon_ie_len; i++) {
   4653 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
   4654 			if (os_snprintf_error(end - pos, ret))
   4655 				return 0;
   4656 			pos += ret;
   4657 		}
   4658 
   4659 		ret = os_snprintf(pos, end - pos, "\n");
   4660 		if (os_snprintf_error(end - pos, ret))
   4661 			return 0;
   4662 		pos += ret;
   4663 	}
   4664 
   4665 #ifdef CONFIG_FILS
   4666 	if (mask & WPA_BSS_MASK_FILS_INDICATION) {
   4667 		ret = print_fils_indication(bss, pos, end);
   4668 		if (ret < 0)
   4669 			return 0;
   4670 		pos += ret;
   4671 	}
   4672 #endif /* CONFIG_FILS */
   4673 
   4674 	if (mask & WPA_BSS_MASK_DELIM) {
   4675 		ret = os_snprintf(pos, end - pos, "====\n");
   4676 		if (os_snprintf_error(end - pos, ret))
   4677 			return 0;
   4678 		pos += ret;
   4679 	}
   4680 
   4681 	return pos - buf;
   4682 }
   4683 
   4684 
   4685 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
   4686 					 const char *cmd, char *buf,
   4687 					 size_t buflen)
   4688 {
   4689 	u8 bssid[ETH_ALEN];
   4690 	size_t i;
   4691 	struct wpa_bss *bss;
   4692 	struct wpa_bss *bsslast = NULL;
   4693 	struct dl_list *next;
   4694 	int ret = 0;
   4695 	int len;
   4696 	char *ctmp, *end = buf + buflen;
   4697 	unsigned long mask = WPA_BSS_MASK_ALL;
   4698 
   4699 	if (os_strncmp(cmd, "RANGE=", 6) == 0) {
   4700 		if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
   4701 			bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
   4702 					    list_id);
   4703 			bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
   4704 					       list_id);
   4705 		} else { /* N1-N2 */
   4706 			unsigned int id1, id2;
   4707 
   4708 			if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
   4709 				wpa_printf(MSG_INFO, "Wrong BSS range "
   4710 					   "format");
   4711 				return 0;
   4712 			}
   4713 
   4714 			if (*(cmd + 6) == '-')
   4715 				id1 = 0;
   4716 			else
   4717 				id1 = atoi(cmd + 6);
   4718 			ctmp++;
   4719 			if (*ctmp >= '0' && *ctmp <= '9')
   4720 				id2 = atoi(ctmp);
   4721 			else
   4722 				id2 = (unsigned int) -1;
   4723 			bss = wpa_bss_get_id_range(wpa_s, id1, id2);
   4724 			if (id2 == (unsigned int) -1)
   4725 				bsslast = dl_list_last(&wpa_s->bss_id,
   4726 						       struct wpa_bss,
   4727 						       list_id);
   4728 			else {
   4729 				bsslast = wpa_bss_get_id(wpa_s, id2);
   4730 				if (bsslast == NULL && bss && id2 > id1) {
   4731 					struct wpa_bss *tmp = bss;
   4732 					for (;;) {
   4733 						next = tmp->list_id.next;
   4734 						if (next == &wpa_s->bss_id)
   4735 							break;
   4736 						tmp = dl_list_entry(
   4737 							next, struct wpa_bss,
   4738 							list_id);
   4739 						if (tmp->id > id2)
   4740 							break;
   4741 						bsslast = tmp;
   4742 					}
   4743 				}
   4744 			}
   4745 		}
   4746 	} else if (os_strncmp(cmd, "FIRST", 5) == 0)
   4747 		bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
   4748 	else if (os_strncmp(cmd, "LAST", 4) == 0)
   4749 		bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
   4750 	else if (os_strncmp(cmd, "ID-", 3) == 0) {
   4751 		i = atoi(cmd + 3);
   4752 		bss = wpa_bss_get_id(wpa_s, i);
   4753 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
   4754 		i = atoi(cmd + 5);
   4755 		bss = wpa_bss_get_id(wpa_s, i);
   4756 		if (bss) {
   4757 			next = bss->list_id.next;
   4758 			if (next == &wpa_s->bss_id)
   4759 				bss = NULL;
   4760 			else
   4761 				bss = dl_list_entry(next, struct wpa_bss,
   4762 						    list_id);
   4763 		}
   4764 	} else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
   4765 		bss = wpa_s->current_bss;
   4766 #ifdef CONFIG_P2P
   4767 	} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
   4768 		if (hwaddr_aton(cmd + 13, bssid) == 0)
   4769 			bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
   4770 		else
   4771 			bss = NULL;
   4772 #endif /* CONFIG_P2P */
   4773 	} else if (hwaddr_aton(cmd, bssid) == 0)
   4774 		bss = wpa_bss_get_bssid(wpa_s, bssid);
   4775 	else {
   4776 		struct wpa_bss *tmp;
   4777 		i = atoi(cmd);
   4778 		bss = NULL;
   4779 		dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
   4780 		{
   4781 			if (i-- == 0) {
   4782 				bss = tmp;
   4783 				break;
   4784 			}
   4785 		}
   4786 	}
   4787 
   4788 	if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
   4789 		mask = strtoul(ctmp + 5, NULL, 0x10);
   4790 		if (mask == 0)
   4791 			mask = WPA_BSS_MASK_ALL;
   4792 	}
   4793 
   4794 	if (bss == NULL)
   4795 		return 0;
   4796 
   4797 	if (bsslast == NULL)
   4798 		bsslast = bss;
   4799 	do {
   4800 		len = print_bss_info(wpa_s, bss, mask, buf, buflen);
   4801 		ret += len;
   4802 		buf += len;
   4803 		buflen -= len;
   4804 		if (bss == bsslast) {
   4805 			if ((mask & WPA_BSS_MASK_DELIM) && len &&
   4806 			    (bss == dl_list_last(&wpa_s->bss_id,
   4807 						 struct wpa_bss, list_id))) {
   4808 				int res;
   4809 
   4810 				res = os_snprintf(buf - 5, end - buf + 5,
   4811 						  "####\n");
   4812 				if (os_snprintf_error(end - buf + 5, res)) {
   4813 					wpa_printf(MSG_DEBUG,
   4814 						   "Could not add end delim");
   4815 				}
   4816 			}
   4817 			break;
   4818 		}
   4819 		next = bss->list_id.next;
   4820 		if (next == &wpa_s->bss_id)
   4821 			break;
   4822 		bss = dl_list_entry(next, struct wpa_bss, list_id);
   4823 	} while (bss && len);
   4824 
   4825 	return ret;
   4826 }
   4827 
   4828 
   4829 static int wpa_supplicant_ctrl_iface_ap_scan(
   4830 	struct wpa_supplicant *wpa_s, char *cmd)
   4831 {
   4832 	int ap_scan = atoi(cmd);
   4833 	return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
   4834 }
   4835 
   4836 
   4837 static int wpa_supplicant_ctrl_iface_scan_interval(
   4838 	struct wpa_supplicant *wpa_s, char *cmd)
   4839 {
   4840 	int scan_int = atoi(cmd);
   4841 	return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
   4842 }
   4843 
   4844 
   4845 static int wpa_supplicant_ctrl_iface_bss_expire_age(
   4846 	struct wpa_supplicant *wpa_s, char *cmd)
   4847 {
   4848 	int expire_age = atoi(cmd);
   4849 	return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
   4850 }
   4851 
   4852 
   4853 static int wpa_supplicant_ctrl_iface_bss_expire_count(
   4854 	struct wpa_supplicant *wpa_s, char *cmd)
   4855 {
   4856 	int expire_count = atoi(cmd);
   4857 	return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
   4858 }
   4859 
   4860 
   4861 static void wpa_supplicant_ctrl_iface_bss_flush(
   4862 	struct wpa_supplicant *wpa_s, char *cmd)
   4863 {
   4864 	int flush_age = atoi(cmd);
   4865 
   4866 	if (flush_age == 0)
   4867 		wpa_bss_flush(wpa_s);
   4868 	else
   4869 		wpa_bss_flush_by_age(wpa_s, flush_age);
   4870 }
   4871 
   4872 
   4873 #ifdef CONFIG_TESTING_OPTIONS
   4874 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
   4875 {
   4876 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
   4877 	/* MLME-DELETEKEYS.request */
   4878 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
   4879 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
   4880 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
   4881 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
   4882 #ifdef CONFIG_IEEE80211W
   4883 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
   4884 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
   4885 #endif /* CONFIG_IEEE80211W */
   4886 
   4887 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
   4888 			0);
   4889 	/* MLME-SETPROTECTION.request(None) */
   4890 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
   4891 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
   4892 				   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
   4893 	wpa_sm_drop_sa(wpa_s->wpa);
   4894 }
   4895 #endif /* CONFIG_TESTING_OPTIONS */
   4896 
   4897 
   4898 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
   4899 					  char *addr)
   4900 {
   4901 #ifdef CONFIG_NO_SCAN_PROCESSING
   4902 	return -1;
   4903 #else /* CONFIG_NO_SCAN_PROCESSING */
   4904 	u8 bssid[ETH_ALEN];
   4905 	struct wpa_bss *bss;
   4906 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   4907 
   4908 	if (hwaddr_aton(addr, bssid)) {
   4909 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
   4910 			   "address '%s'", addr);
   4911 		return -1;
   4912 	}
   4913 
   4914 	wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
   4915 
   4916 	if (!ssid) {
   4917 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
   4918 			   "configuration known for the target AP");
   4919 		return -1;
   4920 	}
   4921 
   4922 	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
   4923 	if (!bss) {
   4924 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
   4925 			   "from BSS table");
   4926 		return -1;
   4927 	}
   4928 
   4929 	/*
   4930 	 * TODO: Find best network configuration block from configuration to
   4931 	 * allow roaming to other networks
   4932 	 */
   4933 
   4934 	wpa_s->reassociate = 1;
   4935 	wpa_supplicant_connect(wpa_s, bss, ssid);
   4936 
   4937 	return 0;
   4938 #endif /* CONFIG_NO_SCAN_PROCESSING */
   4939 }
   4940 
   4941 
   4942 #ifdef CONFIG_P2P
   4943 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
   4944 {
   4945 	unsigned int timeout = atoi(cmd);
   4946 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
   4947 	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
   4948 	u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
   4949 	char *pos;
   4950 	unsigned int search_delay;
   4951 	const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
   4952 	u8 seek_count = 0;
   4953 	int freq = 0;
   4954 
   4955 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
   4956 		wpa_dbg(wpa_s, MSG_INFO,
   4957 			"Reject P2P_FIND since interface is disabled");
   4958 		return -1;
   4959 	}
   4960 	if (os_strstr(cmd, "type=social"))
   4961 		type = P2P_FIND_ONLY_SOCIAL;
   4962 	else if (os_strstr(cmd, "type=progressive"))
   4963 		type = P2P_FIND_PROGRESSIVE;
   4964 
   4965 	pos = os_strstr(cmd, "dev_id=");
   4966 	if (pos) {
   4967 		pos += 7;
   4968 		if (hwaddr_aton(pos, dev_id))
   4969 			return -1;
   4970 		_dev_id = dev_id;
   4971 	}
   4972 
   4973 	pos = os_strstr(cmd, "dev_type=");
   4974 	if (pos) {
   4975 		pos += 9;
   4976 		if (wps_dev_type_str2bin(pos, dev_type) < 0)
   4977 			return -1;
   4978 		_dev_type = dev_type;
   4979 	}
   4980 
   4981 	pos = os_strstr(cmd, "delay=");
   4982 	if (pos) {
   4983 		pos += 6;
   4984 		search_delay = atoi(pos);
   4985 	} else
   4986 		search_delay = wpas_p2p_search_delay(wpa_s);
   4987 
   4988 	pos = os_strstr(cmd, "freq=");
   4989 	if (pos) {
   4990 		pos += 5;
   4991 		freq = atoi(pos);
   4992 		if (freq <= 0)
   4993 			return -1;
   4994 	}
   4995 
   4996 	/* Must be searched for last, because it adds nul termination */
   4997 	pos = os_strstr(cmd, " seek=");
   4998 	if (pos)
   4999 		pos += 6;
   5000 	while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
   5001 		char *term;
   5002 
   5003 		_seek[seek_count++] = pos;
   5004 		seek = _seek;
   5005 		term = os_strchr(pos, ' ');
   5006 		if (!term)
   5007 			break;
   5008 		*term = '\0';
   5009 		pos = os_strstr(term + 1, "seek=");
   5010 		if (pos)
   5011 			pos += 5;
   5012 	}
   5013 	if (seek_count > P2P_MAX_QUERY_HASH) {
   5014 		seek[0] = NULL;
   5015 		seek_count = 1;
   5016 	}
   5017 
   5018 	return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
   5019 			     _dev_id, search_delay, seek_count, seek, freq);
   5020 }
   5021 
   5022 
   5023 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
   5024 {
   5025 	const char *last = NULL;
   5026 	const char *token;
   5027 	long int token_len;
   5028 	unsigned int i;
   5029 
   5030 	/* Expected predefined CPT names delimited by ':' */
   5031 	for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
   5032 		if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
   5033 			wpa_printf(MSG_ERROR,
   5034 				   "P2PS: CPT name list is too long, expected up to %d names",
   5035 				   P2PS_FEATURE_CAPAB_CPT_MAX);
   5036 			cpt[0] = 0;
   5037 			return -1;
   5038 		}
   5039 
   5040 		token_len = last - token;
   5041 
   5042 		if (token_len  == 3 &&
   5043 		    os_memcmp(token, "UDP", token_len) == 0) {
   5044 			cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
   5045 		} else if (token_len == 3 &&
   5046 			   os_memcmp(token, "MAC", token_len) == 0) {
   5047 			cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
   5048 		} else {
   5049 			wpa_printf(MSG_ERROR,
   5050 				   "P2PS: Unsupported CPT name '%s'", token);
   5051 			cpt[0] = 0;
   5052 			return -1;
   5053 		}
   5054 
   5055 		if (isblank((unsigned char) *last)) {
   5056 			i++;
   5057 			break;
   5058 		}
   5059 	}
   5060 	cpt[i] = 0;
   5061 	return 0;
   5062 }
   5063 
   5064 
   5065 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
   5066 {
   5067 	struct p2ps_provision *p2ps_prov;
   5068 	char *pos;
   5069 	size_t info_len = 0;
   5070 	char *info = NULL;
   5071 	u8 role = P2PS_SETUP_NONE;
   5072 	long long unsigned val;
   5073 	int i;
   5074 
   5075 	pos = os_strstr(cmd, "info=");
   5076 	if (pos) {
   5077 		pos += 5;
   5078 		info_len = os_strlen(pos);
   5079 
   5080 		if (info_len) {
   5081 			info = os_malloc(info_len + 1);
   5082 			if (info) {
   5083 				info_len = utf8_unescape(pos, info_len,
   5084 							 info, info_len + 1);
   5085 			} else
   5086 				info_len = 0;
   5087 		}
   5088 	}
   5089 
   5090 	p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
   5091 	if (p2ps_prov == NULL) {
   5092 		os_free(info);
   5093 		return NULL;
   5094 	}
   5095 
   5096 	if (info) {
   5097 		os_memcpy(p2ps_prov->info, info, info_len);
   5098 		p2ps_prov->info[info_len] = '\0';
   5099 		os_free(info);
   5100 	}
   5101 
   5102 	pos = os_strstr(cmd, "status=");
   5103 	if (pos)
   5104 		p2ps_prov->status = atoi(pos + 7);
   5105 	else
   5106 		p2ps_prov->status = -1;
   5107 
   5108 	pos = os_strstr(cmd, "adv_id=");
   5109 	if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
   5110 		goto invalid_args;
   5111 	p2ps_prov->adv_id = val;
   5112 
   5113 	pos = os_strstr(cmd, "method=");
   5114 	if (pos)
   5115 		p2ps_prov->method = strtol(pos + 7, NULL, 16);
   5116 	else
   5117 		p2ps_prov->method = 0;
   5118 
   5119 	pos = os_strstr(cmd, "session=");
   5120 	if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
   5121 		goto invalid_args;
   5122 	p2ps_prov->session_id = val;
   5123 
   5124 	pos = os_strstr(cmd, "adv_mac=");
   5125 	if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
   5126 		goto invalid_args;
   5127 
   5128 	pos = os_strstr(cmd, "session_mac=");
   5129 	if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
   5130 		goto invalid_args;
   5131 
   5132 	pos = os_strstr(cmd, "cpt=");
   5133 	if (pos) {
   5134 		if (p2ps_ctrl_parse_cpt_priority(pos + 4,
   5135 						 p2ps_prov->cpt_priority))
   5136 			goto invalid_args;
   5137 	} else {
   5138 		p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
   5139 	}
   5140 
   5141 	for (i = 0; p2ps_prov->cpt_priority[i]; i++)
   5142 		p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
   5143 
   5144 	/* force conncap with tstCap (no sanity checks) */
   5145 	pos = os_strstr(cmd, "tstCap=");
   5146 	if (pos) {
   5147 		role = strtol(pos + 7, NULL, 16);
   5148 	} else {
   5149 		pos = os_strstr(cmd, "role=");
   5150 		if (pos) {
   5151 			role = strtol(pos + 5, NULL, 16);
   5152 			if (role != P2PS_SETUP_CLIENT &&
   5153 			    role != P2PS_SETUP_GROUP_OWNER)
   5154 				role = P2PS_SETUP_NONE;
   5155 		}
   5156 	}
   5157 	p2ps_prov->role = role;
   5158 
   5159 	return p2ps_prov;
   5160 
   5161 invalid_args:
   5162 	os_free(p2ps_prov);
   5163 	return NULL;
   5164 }
   5165 
   5166 
   5167 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
   5168 {
   5169 	u8 addr[ETH_ALEN];
   5170 	struct p2ps_provision *p2ps_prov;
   5171 	char *pos;
   5172 
   5173 	/* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
   5174 
   5175 	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
   5176 
   5177 	if (hwaddr_aton(cmd, addr))
   5178 		return -1;
   5179 
   5180 	pos = cmd + 17;
   5181 	if (*pos != ' ')
   5182 		return -1;
   5183 
   5184 	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
   5185 	if (!p2ps_prov)
   5186 		return -1;
   5187 
   5188 	if (p2ps_prov->status < 0) {
   5189 		os_free(p2ps_prov);
   5190 		return -1;
   5191 	}
   5192 
   5193 	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
   5194 				  p2ps_prov);
   5195 }
   5196 
   5197 
   5198 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
   5199 {
   5200 	u8 addr[ETH_ALEN];
   5201 	struct p2ps_provision *p2ps_prov;
   5202 	char *pos;
   5203 
   5204 	/* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
   5205 	 *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
   5206 	 */
   5207 
   5208 	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
   5209 	if (hwaddr_aton(cmd, addr))
   5210 		return -1;
   5211 
   5212 	pos = cmd + 17;
   5213 	if (*pos != ' ')
   5214 		return -1;
   5215 
   5216 	p2ps_prov = p2p_parse_asp_provision_cmd(pos);
   5217 	if (!p2ps_prov)
   5218 		return -1;
   5219 
   5220 	p2ps_prov->pd_seeker = 1;
   5221 
   5222 	return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
   5223 				  p2ps_prov);
   5224 }
   5225 
   5226 
   5227 static int parse_freq(int chwidth, int freq2)
   5228 {
   5229 	if (freq2 < 0)
   5230 		return -1;
   5231 	if (freq2)
   5232 		return VHT_CHANWIDTH_80P80MHZ;
   5233 
   5234 	switch (chwidth) {
   5235 	case 0:
   5236 	case 20:
   5237 	case 40:
   5238 		return VHT_CHANWIDTH_USE_HT;
   5239 	case 80:
   5240 		return VHT_CHANWIDTH_80MHZ;
   5241 	case 160:
   5242 		return VHT_CHANWIDTH_160MHZ;
   5243 	default:
   5244 		wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
   5245 			   chwidth);
   5246 		return -1;
   5247 	}
   5248 }
   5249 
   5250 
   5251 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
   5252 			    char *buf, size_t buflen)
   5253 {
   5254 	u8 addr[ETH_ALEN];
   5255 	char *pos, *pos2;
   5256 	char *pin = NULL;
   5257 	enum p2p_wps_method wps_method;
   5258 	int new_pin;
   5259 	int ret;
   5260 	int persistent_group, persistent_id = -1;
   5261 	int join;
   5262 	int auth;
   5263 	int automatic;
   5264 	int go_intent = -1;
   5265 	int freq = 0;
   5266 	int pd;
   5267 	int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
   5268 	u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
   5269 	size_t group_ssid_len = 0;
   5270 
   5271 	if (!wpa_s->global->p2p_init_wpa_s)
   5272 		return -1;
   5273 	if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
   5274 		wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
   5275 			wpa_s->global->p2p_init_wpa_s->ifname);
   5276 		wpa_s = wpa_s->global->p2p_init_wpa_s;
   5277 	}
   5278 
   5279 	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
   5280 	 * [persistent|persistent=<network id>]
   5281 	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
   5282 	 * [ht40] [vht] [auto] [ssid=<hexdump>] */
   5283 
   5284 	if (hwaddr_aton(cmd, addr))
   5285 		return -1;
   5286 
   5287 	pos = cmd + 17;
   5288 	if (*pos != ' ')
   5289 		return -1;
   5290 	pos++;
   5291 
   5292 	persistent_group = os_strstr(pos, " persistent") != NULL;
   5293 	pos2 = os_strstr(pos, " persistent=");
   5294 	if (pos2) {
   5295 		struct wpa_ssid *ssid;
   5296 		persistent_id = atoi(pos2 + 12);
   5297 		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
   5298 		if (ssid == NULL || ssid->disabled != 2 ||
   5299 		    ssid->mode != WPAS_MODE_P2P_GO) {
   5300 			wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
   5301 				   "SSID id=%d for persistent P2P group (GO)",
   5302 				   persistent_id);
   5303 			return -1;
   5304 		}
   5305 	}
   5306 	join = os_strstr(pos, " join") != NULL;
   5307 	auth = os_strstr(pos, " auth") != NULL;
   5308 	automatic = os_strstr(pos, " auto") != NULL;
   5309 	pd = os_strstr(pos, " provdisc") != NULL;
   5310 	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
   5311 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
   5312 		vht;
   5313 
   5314 	pos2 = os_strstr(pos, " go_intent=");
   5315 	if (pos2) {
   5316 		pos2 += 11;
   5317 		go_intent = atoi(pos2);
   5318 		if (go_intent < 0 || go_intent > 15)
   5319 			return -1;
   5320 	}
   5321 
   5322 	pos2 = os_strstr(pos, " freq=");
   5323 	if (pos2) {
   5324 		pos2 += 6;
   5325 		freq = atoi(pos2);
   5326 		if (freq <= 0)
   5327 			return -1;
   5328 	}
   5329 
   5330 	pos2 = os_strstr(pos, " freq2=");
   5331 	if (pos2)
   5332 		freq2 = atoi(pos2 + 7);
   5333 
   5334 	pos2 = os_strstr(pos, " max_oper_chwidth=");
   5335 	if (pos2)
   5336 		chwidth = atoi(pos2 + 18);
   5337 
   5338 	max_oper_chwidth = parse_freq(chwidth, freq2);
   5339 	if (max_oper_chwidth < 0)
   5340 		return -1;
   5341 
   5342 	pos2 = os_strstr(pos, " ssid=");
   5343 	if (pos2) {
   5344 		char *end;
   5345 
   5346 		pos2 += 6;
   5347 		end = os_strchr(pos2, ' ');
   5348 		if (!end)
   5349 			group_ssid_len = os_strlen(pos2) / 2;
   5350 		else
   5351 			group_ssid_len = (end - pos2) / 2;
   5352 		if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
   5353 		    hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
   5354 			return -1;
   5355 		group_ssid = _group_ssid;
   5356 	}
   5357 
   5358 	if (os_strncmp(pos, "pin", 3) == 0) {
   5359 		/* Request random PIN (to be displayed) and enable the PIN */
   5360 		wps_method = WPS_PIN_DISPLAY;
   5361 	} else if (os_strncmp(pos, "pbc", 3) == 0) {
   5362 		wps_method = WPS_PBC;
   5363 	} else if (os_strstr(pos, "p2ps") != NULL) {
   5364 		wps_method = WPS_P2PS;
   5365 	} else {
   5366 		pin = pos;
   5367 		pos = os_strchr(pin, ' ');
   5368 		wps_method = WPS_PIN_KEYPAD;
   5369 		if (pos) {
   5370 			*pos++ = '\0';
   5371 			if (os_strncmp(pos, "display", 7) == 0)
   5372 				wps_method = WPS_PIN_DISPLAY;
   5373 		}
   5374 		if (!wps_pin_str_valid(pin)) {
   5375 			os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
   5376 			return 17;
   5377 		}
   5378 	}
   5379 
   5380 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
   5381 				   persistent_group, automatic, join,
   5382 				   auth, go_intent, freq, freq2, persistent_id,
   5383 				   pd, ht40, vht, max_oper_chwidth,
   5384 				   group_ssid, group_ssid_len);
   5385 	if (new_pin == -2) {
   5386 		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
   5387 		return 25;
   5388 	}
   5389 	if (new_pin == -3) {
   5390 		os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
   5391 		return 25;
   5392 	}
   5393 	if (new_pin < 0)
   5394 		return -1;
   5395 	if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
   5396 		ret = os_snprintf(buf, buflen, "%08d", new_pin);
   5397 		if (os_snprintf_error(buflen, ret))
   5398 			return -1;
   5399 		return ret;
   5400 	}
   5401 
   5402 	os_memcpy(buf, "OK\n", 3);
   5403 	return 3;
   5404 }
   5405 
   5406 
   5407 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
   5408 {
   5409 	unsigned int timeout = atoi(cmd);
   5410 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
   5411 		wpa_dbg(wpa_s, MSG_INFO,
   5412 			"Reject P2P_LISTEN since interface is disabled");
   5413 		return -1;
   5414 	}
   5415 	return wpas_p2p_listen(wpa_s, timeout);
   5416 }
   5417 
   5418 
   5419 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
   5420 {
   5421 	u8 addr[ETH_ALEN];
   5422 	char *pos;
   5423 	enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
   5424 
   5425 	/* <addr> <config method> [join|auto] */
   5426 
   5427 	if (hwaddr_aton(cmd, addr))
   5428 		return -1;
   5429 
   5430 	pos = cmd + 17;
   5431 	if (*pos != ' ')
   5432 		return -1;
   5433 	pos++;
   5434 
   5435 	if (os_strstr(pos, " join") != NULL)
   5436 		use = WPAS_P2P_PD_FOR_JOIN;
   5437 	else if (os_strstr(pos, " auto") != NULL)
   5438 		use = WPAS_P2P_PD_AUTO;
   5439 
   5440 	return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
   5441 }
   5442 
   5443 
   5444 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
   5445 			      size_t buflen)
   5446 {
   5447 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   5448 
   5449 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
   5450 	    ssid->passphrase == NULL)
   5451 		return -1;
   5452 
   5453 	os_strlcpy(buf, ssid->passphrase, buflen);
   5454 	return os_strlen(buf);
   5455 }
   5456 
   5457 
   5458 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
   5459 				  char *buf, size_t buflen)
   5460 {
   5461 	u64 ref;
   5462 	int res;
   5463 	u8 dst_buf[ETH_ALEN], *dst;
   5464 	struct wpabuf *tlvs;
   5465 	char *pos;
   5466 	size_t len;
   5467 
   5468 	if (hwaddr_aton(cmd, dst_buf))
   5469 		return -1;
   5470 	dst = dst_buf;
   5471 	if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
   5472 	    dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
   5473 		dst = NULL;
   5474 	pos = cmd + 17;
   5475 	if (*pos != ' ')
   5476 		return -1;
   5477 	pos++;
   5478 
   5479 	if (os_strncmp(pos, "upnp ", 5) == 0) {
   5480 		u8 version;
   5481 		pos += 5;
   5482 		if (hexstr2bin(pos, &version, 1) < 0)
   5483 			return -1;
   5484 		pos += 2;
   5485 		if (*pos != ' ')
   5486 			return -1;
   5487 		pos++;
   5488 		ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
   5489 #ifdef CONFIG_WIFI_DISPLAY
   5490 	} else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
   5491 		ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
   5492 #endif /* CONFIG_WIFI_DISPLAY */
   5493 	} else if (os_strncmp(pos, "asp ", 4) == 0) {
   5494 		char *svc_str;
   5495 		char *svc_info = NULL;
   5496 		u32 id;
   5497 
   5498 		pos += 4;
   5499 		if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
   5500 			return -1;
   5501 
   5502 		pos = os_strchr(pos, ' ');
   5503 		if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
   5504 			return -1;
   5505 
   5506 		svc_str = pos + 1;
   5507 
   5508 		pos = os_strchr(svc_str, ' ');
   5509 
   5510 		if (pos)
   5511 			*pos++ = '\0';
   5512 
   5513 		/* All remaining data is the svc_info string */
   5514 		if (pos && pos[0] && pos[0] != ' ') {
   5515 			len = os_strlen(pos);
   5516 
   5517 			/* Unescape in place */
   5518 			len = utf8_unescape(pos, len, pos, len);
   5519 			if (len > 0xff)
   5520 				return -1;
   5521 
   5522 			svc_info = pos;
   5523 		}
   5524 
   5525 		ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
   5526 					      svc_str, svc_info);
   5527 	} else {
   5528 		len = os_strlen(pos);
   5529 		if (len & 1)
   5530 			return -1;
   5531 		len /= 2;
   5532 		tlvs = wpabuf_alloc(len);
   5533 		if (tlvs == NULL)
   5534 			return -1;
   5535 		if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
   5536 			wpabuf_free(tlvs);
   5537 			return -1;
   5538 		}
   5539 
   5540 		ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
   5541 		wpabuf_free(tlvs);
   5542 	}
   5543 	if (ref == 0)
   5544 		return -1;
   5545 	res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
   5546 	if (os_snprintf_error(buflen, res))
   5547 		return -1;
   5548 	return res;
   5549 }
   5550 
   5551 
   5552 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
   5553 					 char *cmd)
   5554 {
   5555 	long long unsigned val;
   5556 	u64 req;
   5557 	if (sscanf(cmd, "%llx", &val) != 1)
   5558 		return -1;
   5559 	req = val;
   5560 	return wpas_p2p_sd_cancel_request(wpa_s, req);
   5561 }
   5562 
   5563 
   5564 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
   5565 {
   5566 	int freq;
   5567 	u8 dst[ETH_ALEN];
   5568 	u8 dialog_token;
   5569 	struct wpabuf *resp_tlvs;
   5570 	char *pos, *pos2;
   5571 	size_t len;
   5572 
   5573 	pos = os_strchr(cmd, ' ');
   5574 	if (pos == NULL)
   5575 		return -1;
   5576 	*pos++ = '\0';
   5577 	freq = atoi(cmd);
   5578 	if (freq == 0)
   5579 		return -1;
   5580 
   5581 	if (hwaddr_aton(pos, dst))
   5582 		return -1;
   5583 	pos += 17;
   5584 	if (*pos != ' ')
   5585 		return -1;
   5586 	pos++;
   5587 
   5588 	pos2 = os_strchr(pos, ' ');
   5589 	if (pos2 == NULL)
   5590 		return -1;
   5591 	*pos2++ = '\0';
   5592 	dialog_token = atoi(pos);
   5593 
   5594 	len = os_strlen(pos2);
   5595 	if (len & 1)
   5596 		return -1;
   5597 	len /= 2;
   5598 	resp_tlvs = wpabuf_alloc(len);
   5599 	if (resp_tlvs == NULL)
   5600 		return -1;
   5601 	if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
   5602 		wpabuf_free(resp_tlvs);
   5603 		return -1;
   5604 	}
   5605 
   5606 	wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
   5607 	wpabuf_free(resp_tlvs);
   5608 	return 0;
   5609 }
   5610 
   5611 
   5612 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
   5613 				       char *cmd)
   5614 {
   5615 	if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
   5616 		return -1;
   5617 	wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
   5618 	return 0;
   5619 }
   5620 
   5621 
   5622 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
   5623 					char *cmd)
   5624 {
   5625 	char *pos;
   5626 	size_t len;
   5627 	struct wpabuf *query, *resp;
   5628 
   5629 	pos = os_strchr(cmd, ' ');
   5630 	if (pos == NULL)
   5631 		return -1;
   5632 	*pos++ = '\0';
   5633 
   5634 	len = os_strlen(cmd);
   5635 	if (len & 1)
   5636 		return -1;
   5637 	len /= 2;
   5638 	query = wpabuf_alloc(len);
   5639 	if (query == NULL)
   5640 		return -1;
   5641 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
   5642 		wpabuf_free(query);
   5643 		return -1;
   5644 	}
   5645 
   5646 	len = os_strlen(pos);
   5647 	if (len & 1) {
   5648 		wpabuf_free(query);
   5649 		return -1;
   5650 	}
   5651 	len /= 2;
   5652 	resp = wpabuf_alloc(len);
   5653 	if (resp == NULL) {
   5654 		wpabuf_free(query);
   5655 		return -1;
   5656 	}
   5657 	if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
   5658 		wpabuf_free(query);
   5659 		wpabuf_free(resp);
   5660 		return -1;
   5661 	}
   5662 
   5663 	if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
   5664 		wpabuf_free(query);
   5665 		wpabuf_free(resp);
   5666 		return -1;
   5667 	}
   5668 	return 0;
   5669 }
   5670 
   5671 
   5672 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
   5673 {
   5674 	char *pos;
   5675 	u8 version;
   5676 
   5677 	pos = os_strchr(cmd, ' ');
   5678 	if (pos == NULL)
   5679 		return -1;
   5680 	*pos++ = '\0';
   5681 
   5682 	if (hexstr2bin(cmd, &version, 1) < 0)
   5683 		return -1;
   5684 
   5685 	return wpas_p2p_service_add_upnp(wpa_s, version, pos);
   5686 }
   5687 
   5688 
   5689 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
   5690 				    u8 replace, char *cmd)
   5691 {
   5692 	char *pos;
   5693 	char *adv_str;
   5694 	u32 auto_accept, adv_id, svc_state, config_methods;
   5695 	char *svc_info = NULL;
   5696 	char *cpt_prio_str;
   5697 	u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
   5698 
   5699 	pos = os_strchr(cmd, ' ');
   5700 	if (pos == NULL)
   5701 		return -1;
   5702 	*pos++ = '\0';
   5703 
   5704 	/* Auto-Accept value is mandatory, and must be one of the
   5705 	 * single values (0, 1, 2, 4) */
   5706 	auto_accept = atoi(cmd);
   5707 	switch (auto_accept) {
   5708 	case P2PS_SETUP_NONE: /* No auto-accept */
   5709 	case P2PS_SETUP_NEW:
   5710 	case P2PS_SETUP_CLIENT:
   5711 	case P2PS_SETUP_GROUP_OWNER:
   5712 		break;
   5713 	default:
   5714 		return -1;
   5715 	}
   5716 
   5717 	/* Advertisement ID is mandatory */
   5718 	cmd = pos;
   5719 	pos = os_strchr(cmd, ' ');
   5720 	if (pos == NULL)
   5721 		return -1;
   5722 	*pos++ = '\0';
   5723 
   5724 	/* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
   5725 	if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
   5726 		return -1;
   5727 
   5728 	/* Only allow replacements if exist, and adds if not */
   5729 	if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
   5730 		if (!replace)
   5731 			return -1;
   5732 	} else {
   5733 		if (replace)
   5734 			return -1;
   5735 	}
   5736 
   5737 	/* svc_state between 0 - 0xff is mandatory */
   5738 	if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
   5739 		return -1;
   5740 
   5741 	pos = os_strchr(pos, ' ');
   5742 	if (pos == NULL)
   5743 		return -1;
   5744 
   5745 	/* config_methods is mandatory */
   5746 	pos++;
   5747 	if (sscanf(pos, "%x", &config_methods) != 1)
   5748 		return -1;
   5749 
   5750 	if (!(config_methods &
   5751 	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
   5752 		return -1;
   5753 
   5754 	pos = os_strchr(pos, ' ');
   5755 	if (pos == NULL)
   5756 		return -1;
   5757 
   5758 	pos++;
   5759 	adv_str = pos;
   5760 
   5761 	/* Advertisement string is mandatory */
   5762 	if (!pos[0] || pos[0] == ' ')
   5763 		return -1;
   5764 
   5765 	/* Terminate svc string */
   5766 	pos = os_strchr(pos, ' ');
   5767 	if (pos != NULL)
   5768 		*pos++ = '\0';
   5769 
   5770 	cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
   5771 	if (cpt_prio_str) {
   5772 		pos = os_strchr(pos, ' ');
   5773 		if (pos != NULL)
   5774 			*pos++ = '\0';
   5775 
   5776 		if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
   5777 			return -1;
   5778 	} else {
   5779 		cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
   5780 		cpt_prio[1] = 0;
   5781 	}
   5782 
   5783 	/* Service and Response Information are optional */
   5784 	if (pos && pos[0]) {
   5785 		size_t len;
   5786 
   5787 		/* Note the bare ' included, which cannot exist legally
   5788 		 * in unescaped string. */
   5789 		svc_info = os_strstr(pos, "svc_info='");
   5790 
   5791 		if (svc_info) {
   5792 			svc_info += 9;
   5793 			len = os_strlen(svc_info);
   5794 			utf8_unescape(svc_info, len, svc_info, len);
   5795 		}
   5796 	}
   5797 
   5798 	return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
   5799 					(u8) svc_state, (u16) config_methods,
   5800 					svc_info, cpt_prio);
   5801 }
   5802 
   5803 
   5804 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
   5805 {
   5806 	char *pos;
   5807 
   5808 	pos = os_strchr(cmd, ' ');
   5809 	if (pos == NULL)
   5810 		return -1;
   5811 	*pos++ = '\0';
   5812 
   5813 	if (os_strcmp(cmd, "bonjour") == 0)
   5814 		return p2p_ctrl_service_add_bonjour(wpa_s, pos);
   5815 	if (os_strcmp(cmd, "upnp") == 0)
   5816 		return p2p_ctrl_service_add_upnp(wpa_s, pos);
   5817 	if (os_strcmp(cmd, "asp") == 0)
   5818 		return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
   5819 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
   5820 	return -1;
   5821 }
   5822 
   5823 
   5824 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
   5825 					char *cmd)
   5826 {
   5827 	size_t len;
   5828 	struct wpabuf *query;
   5829 	int ret;
   5830 
   5831 	len = os_strlen(cmd);
   5832 	if (len & 1)
   5833 		return -1;
   5834 	len /= 2;
   5835 	query = wpabuf_alloc(len);
   5836 	if (query == NULL)
   5837 		return -1;
   5838 	if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
   5839 		wpabuf_free(query);
   5840 		return -1;
   5841 	}
   5842 
   5843 	ret = wpas_p2p_service_del_bonjour(wpa_s, query);
   5844 	wpabuf_free(query);
   5845 	return ret;
   5846 }
   5847 
   5848 
   5849 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
   5850 {
   5851 	char *pos;
   5852 	u8 version;
   5853 
   5854 	pos = os_strchr(cmd, ' ');
   5855 	if (pos == NULL)
   5856 		return -1;
   5857 	*pos++ = '\0';
   5858 
   5859 	if (hexstr2bin(cmd, &version, 1) < 0)
   5860 		return -1;
   5861 
   5862 	return wpas_p2p_service_del_upnp(wpa_s, version, pos);
   5863 }
   5864 
   5865 
   5866 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
   5867 {
   5868 	u32 adv_id;
   5869 
   5870 	if (os_strcmp(cmd, "all") == 0) {
   5871 		wpas_p2p_service_flush_asp(wpa_s);
   5872 		return 0;
   5873 	}
   5874 
   5875 	if (sscanf(cmd, "%x", &adv_id) != 1)
   5876 		return -1;
   5877 
   5878 	return wpas_p2p_service_del_asp(wpa_s, adv_id);
   5879 }
   5880 
   5881 
   5882 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
   5883 {
   5884 	char *pos;
   5885 
   5886 	pos = os_strchr(cmd, ' ');
   5887 	if (pos == NULL)
   5888 		return -1;
   5889 	*pos++ = '\0';
   5890 
   5891 	if (os_strcmp(cmd, "bonjour") == 0)
   5892 		return p2p_ctrl_service_del_bonjour(wpa_s, pos);
   5893 	if (os_strcmp(cmd, "upnp") == 0)
   5894 		return p2p_ctrl_service_del_upnp(wpa_s, pos);
   5895 	if (os_strcmp(cmd, "asp") == 0)
   5896 		return p2p_ctrl_service_del_asp(wpa_s, pos);
   5897 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
   5898 	return -1;
   5899 }
   5900 
   5901 
   5902 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
   5903 {
   5904 	char *pos;
   5905 
   5906 	pos = os_strchr(cmd, ' ');
   5907 	if (pos == NULL)
   5908 		return -1;
   5909 	*pos++ = '\0';
   5910 
   5911 	if (os_strcmp(cmd, "asp") == 0)
   5912 		return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
   5913 
   5914 	wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
   5915 	return -1;
   5916 }
   5917 
   5918 
   5919 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
   5920 {
   5921 	u8 addr[ETH_ALEN];
   5922 
   5923 	/* <addr> */
   5924 
   5925 	if (hwaddr_aton(cmd, addr))
   5926 		return -1;
   5927 
   5928 	return wpas_p2p_reject(wpa_s, addr);
   5929 }
   5930 
   5931 
   5932 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
   5933 {
   5934 	char *pos;
   5935 	int id;
   5936 	struct wpa_ssid *ssid;
   5937 	u8 *_peer = NULL, peer[ETH_ALEN];
   5938 	int freq = 0, pref_freq = 0;
   5939 	int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
   5940 
   5941 	id = atoi(cmd);
   5942 	pos = os_strstr(cmd, " peer=");
   5943 	if (pos) {
   5944 		pos += 6;
   5945 		if (hwaddr_aton(pos, peer))
   5946 			return -1;
   5947 		_peer = peer;
   5948 	}
   5949 	ssid = wpa_config_get_network(wpa_s->conf, id);
   5950 	if (ssid == NULL || ssid->disabled != 2) {
   5951 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
   5952 			   "for persistent P2P group",
   5953 			   id);
   5954 		return -1;
   5955 	}
   5956 
   5957 	pos = os_strstr(cmd, " freq=");
   5958 	if (pos) {
   5959 		pos += 6;
   5960 		freq = atoi(pos);
   5961 		if (freq <= 0)
   5962 			return -1;
   5963 	}
   5964 
   5965 	pos = os_strstr(cmd, " pref=");
   5966 	if (pos) {
   5967 		pos += 6;
   5968 		pref_freq = atoi(pos);
   5969 		if (pref_freq <= 0)
   5970 			return -1;
   5971 	}
   5972 
   5973 	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
   5974 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
   5975 		vht;
   5976 
   5977 	pos = os_strstr(cmd, "freq2=");
   5978 	if (pos)
   5979 		freq2 = atoi(pos + 6);
   5980 
   5981 	pos = os_strstr(cmd, " max_oper_chwidth=");
   5982 	if (pos)
   5983 		chwidth = atoi(pos + 18);
   5984 
   5985 	max_oper_chwidth = parse_freq(chwidth, freq2);
   5986 	if (max_oper_chwidth < 0)
   5987 		return -1;
   5988 
   5989 	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
   5990 			       max_oper_chwidth, pref_freq);
   5991 }
   5992 
   5993 
   5994 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
   5995 {
   5996 	char *pos;
   5997 	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
   5998 
   5999 	pos = os_strstr(cmd, " peer=");
   6000 	if (!pos)
   6001 		return -1;
   6002 
   6003 	*pos = '\0';
   6004 	pos += 6;
   6005 	if (hwaddr_aton(pos, peer)) {
   6006 		wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
   6007 		return -1;
   6008 	}
   6009 
   6010 	pos = os_strstr(pos, " go_dev_addr=");
   6011 	if (pos) {
   6012 		pos += 13;
   6013 		if (hwaddr_aton(pos, go_dev_addr)) {
   6014 			wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
   6015 				   pos);
   6016 			return -1;
   6017 		}
   6018 		go_dev = go_dev_addr;
   6019 	}
   6020 
   6021 	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
   6022 }
   6023 
   6024 
   6025 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
   6026 {
   6027 	if (os_strncmp(cmd, "persistent=", 11) == 0)
   6028 		return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
   6029 	if (os_strncmp(cmd, "group=", 6) == 0)
   6030 		return p2p_ctrl_invite_group(wpa_s, cmd + 6);
   6031 
   6032 	return -1;
   6033 }
   6034 
   6035 
   6036 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
   6037 					 int id, int freq, int vht_center_freq2,
   6038 					 int ht40, int vht, int vht_chwidth)
   6039 {
   6040 	struct wpa_ssid *ssid;
   6041 
   6042 	ssid = wpa_config_get_network(wpa_s->conf, id);
   6043 	if (ssid == NULL || ssid->disabled != 2) {
   6044 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
   6045 			   "for persistent P2P group",
   6046 			   id);
   6047 		return -1;
   6048 	}
   6049 
   6050 	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
   6051 					     vht_center_freq2, 0, ht40, vht,
   6052 					     vht_chwidth, NULL, 0, 0);
   6053 }
   6054 
   6055 
   6056 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
   6057 {
   6058 	int freq = 0, persistent = 0, group_id = -1;
   6059 	int vht = wpa_s->conf->p2p_go_vht;
   6060 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
   6061 	int max_oper_chwidth, chwidth = 0, freq2 = 0;
   6062 	char *token, *context = NULL;
   6063 
   6064 	while ((token = str_token(cmd, " ", &context))) {
   6065 		if (sscanf(token, "freq=%d", &freq) == 1 ||
   6066 		    sscanf(token, "freq2=%d", &freq2) == 1 ||
   6067 		    sscanf(token, "persistent=%d", &group_id) == 1 ||
   6068 		    sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
   6069 			continue;
   6070 		} else if (os_strcmp(token, "ht40") == 0) {
   6071 			ht40 = 1;
   6072 		} else if (os_strcmp(token, "vht") == 0) {
   6073 			vht = 1;
   6074 			ht40 = 1;
   6075 		} else if (os_strcmp(token, "persistent") == 0) {
   6076 			persistent = 1;
   6077 		} else {
   6078 			wpa_printf(MSG_DEBUG,
   6079 				   "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
   6080 				   token);
   6081 			return -1;
   6082 		}
   6083 	}
   6084 
   6085 	max_oper_chwidth = parse_freq(chwidth, freq2);
   6086 	if (max_oper_chwidth < 0)
   6087 		return -1;
   6088 
   6089 	if (group_id >= 0)
   6090 		return p2p_ctrl_group_add_persistent(wpa_s, group_id,
   6091 						     freq, freq2, ht40, vht,
   6092 						     max_oper_chwidth);
   6093 
   6094 	return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
   6095 				  max_oper_chwidth);
   6096 }
   6097 
   6098 
   6099 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
   6100 				 char *buf, size_t buflen)
   6101 {
   6102 	u8 dev_addr[ETH_ALEN];
   6103 	struct wpa_ssid *ssid;
   6104 	int res;
   6105 	const u8 *iaddr;
   6106 
   6107 	ssid = wpa_s->current_ssid;
   6108 	if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
   6109 	    hwaddr_aton(cmd, dev_addr))
   6110 		return -1;
   6111 
   6112 	iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
   6113 	if (!iaddr)
   6114 		return -1;
   6115 	res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
   6116 	if (os_snprintf_error(buflen, res))
   6117 		return -1;
   6118 	return res;
   6119 }
   6120 
   6121 
   6122 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
   6123 				      const u8 *p2p_dev_addr)
   6124 {
   6125 	struct wpa_supplicant *wpa_s;
   6126 
   6127 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
   6128 		if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
   6129 			return 1;
   6130 	}
   6131 
   6132 	return 0;
   6133 }
   6134 
   6135 
   6136 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
   6137 			 char *buf, size_t buflen)
   6138 {
   6139 	u8 addr[ETH_ALEN], *addr_ptr, group_capab;
   6140 	int next, res;
   6141 	const struct p2p_peer_info *info;
   6142 	char *pos, *end;
   6143 	char devtype[WPS_DEV_TYPE_BUFSIZE];
   6144 	struct wpa_ssid *ssid;
   6145 	size_t i;
   6146 
   6147 	if (!wpa_s->global->p2p)
   6148 		return -1;
   6149 
   6150 	if (os_strcmp(cmd, "FIRST") == 0) {
   6151 		addr_ptr = NULL;
   6152 		next = 0;
   6153 	} else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
   6154 		if (hwaddr_aton(cmd + 5, addr) < 0)
   6155 			return -1;
   6156 		addr_ptr = addr;
   6157 		next = 1;
   6158 	} else {
   6159 		if (hwaddr_aton(cmd, addr) < 0)
   6160 			return -1;
   6161 		addr_ptr = addr;
   6162 		next = 0;
   6163 	}
   6164 
   6165 	info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
   6166 	if (info == NULL)
   6167 		return -1;
   6168 	group_capab = info->group_capab;
   6169 
   6170 	if (group_capab &&
   6171 	    !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
   6172 		wpa_printf(MSG_DEBUG,
   6173 			   "P2P: Could not find any BSS with p2p_dev_addr "
   6174 			   MACSTR ", hence override group_capab from 0x%x to 0",
   6175 			   MAC2STR(info->p2p_device_addr), group_capab);
   6176 		group_capab = 0;
   6177 	}
   6178 
   6179 	pos = buf;
   6180 	end = buf + buflen;
   6181 
   6182 	res = os_snprintf(pos, end - pos, MACSTR "\n"
   6183 			  "pri_dev_type=%s\n"
   6184 			  "device_name=%s\n"
   6185 			  "manufacturer=%s\n"
   6186 			  "model_name=%s\n"
   6187 			  "model_number=%s\n"
   6188 			  "serial_number=%s\n"
   6189 			  "config_methods=0x%x\n"
   6190 			  "dev_capab=0x%x\n"
   6191 			  "group_capab=0x%x\n"
   6192 			  "level=%d\n",
   6193 			  MAC2STR(info->p2p_device_addr),
   6194 			  wps_dev_type_bin2str(info->pri_dev_type,
   6195 					       devtype, sizeof(devtype)),
   6196 			  info->device_name,
   6197 			  info->manufacturer,
   6198 			  info->model_name,
   6199 			  info->model_number,
   6200 			  info->serial_number,
   6201 			  info->config_methods,
   6202 			  info->dev_capab,
   6203 			  group_capab,
   6204 			  info->level);
   6205 	if (os_snprintf_error(end - pos, res))
   6206 		return pos - buf;
   6207 	pos += res;
   6208 
   6209 	for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
   6210 	{
   6211 		const u8 *t;
   6212 		t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
   6213 		res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
   6214 				  wps_dev_type_bin2str(t, devtype,
   6215 						       sizeof(devtype)));
   6216 		if (os_snprintf_error(end - pos, res))
   6217 			return pos - buf;
   6218 		pos += res;
   6219 	}
   6220 
   6221 	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
   6222 	if (ssid) {
   6223 		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
   6224 		if (os_snprintf_error(end - pos, res))
   6225 			return pos - buf;
   6226 		pos += res;
   6227 	}
   6228 
   6229 	res = p2p_get_peer_info_txt(info, pos, end - pos);
   6230 	if (res < 0)
   6231 		return pos - buf;
   6232 	pos += res;
   6233 
   6234 	if (info->vendor_elems) {
   6235 		res = os_snprintf(pos, end - pos, "vendor_elems=");
   6236 		if (os_snprintf_error(end - pos, res))
   6237 			return pos - buf;
   6238 		pos += res;
   6239 
   6240 		pos += wpa_snprintf_hex(pos, end - pos,
   6241 					wpabuf_head(info->vendor_elems),
   6242 					wpabuf_len(info->vendor_elems));
   6243 
   6244 		res = os_snprintf(pos, end - pos, "\n");
   6245 		if (os_snprintf_error(end - pos, res))
   6246 			return pos - buf;
   6247 		pos += res;
   6248 	}
   6249 
   6250 	return pos - buf;
   6251 }
   6252 
   6253 
   6254 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
   6255 				  const char *param)
   6256 {
   6257 	unsigned int i;
   6258 
   6259 	if (wpa_s->global->p2p == NULL)
   6260 		return -1;
   6261 
   6262 	if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
   6263 		return -1;
   6264 
   6265 	for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
   6266 		struct wpa_freq_range *freq;
   6267 		freq = &wpa_s->global->p2p_disallow_freq.range[i];
   6268 		wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
   6269 			   freq->min, freq->max);
   6270 	}
   6271 
   6272 	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
   6273 	return 0;
   6274 }
   6275 
   6276 
   6277 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
   6278 {
   6279 	char *param;
   6280 
   6281 	if (wpa_s->global->p2p == NULL)
   6282 		return -1;
   6283 
   6284 	param = os_strchr(cmd, ' ');
   6285 	if (param == NULL)
   6286 		return -1;
   6287 	*param++ = '\0';
   6288 
   6289 	if (os_strcmp(cmd, "discoverability") == 0) {
   6290 		p2p_set_client_discoverability(wpa_s->global->p2p,
   6291 					       atoi(param));
   6292 		return 0;
   6293 	}
   6294 
   6295 	if (os_strcmp(cmd, "managed") == 0) {
   6296 		p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
   6297 		return 0;
   6298 	}
   6299 
   6300 	if (os_strcmp(cmd, "listen_channel") == 0) {
   6301 		char *pos;
   6302 		u8 channel, op_class;
   6303 
   6304 		channel = atoi(param);
   6305 		pos = os_strchr(param, ' ');
   6306 		op_class = pos ? atoi(pos) : 81;
   6307 
   6308 		return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
   6309 					      channel, 1);
   6310 	}
   6311 
   6312 	if (os_strcmp(cmd, "ssid_postfix") == 0) {
   6313 		return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
   6314 					    os_strlen(param));
   6315 	}
   6316 
   6317 	if (os_strcmp(cmd, "noa") == 0) {
   6318 		char *pos;
   6319 		int count, start, duration;
   6320 		/* GO NoA parameters: count,start_offset(ms),duration(ms) */
   6321 		count = atoi(param);
   6322 		pos = os_strchr(param, ',');
   6323 		if (pos == NULL)
   6324 			return -1;
   6325 		pos++;
   6326 		start = atoi(pos);
   6327 		pos = os_strchr(pos, ',');
   6328 		if (pos == NULL)
   6329 			return -1;
   6330 		pos++;
   6331 		duration = atoi(pos);
   6332 		if (count < 0 || count > 255 || start < 0 || duration < 0)
   6333 			return -1;
   6334 		if (count == 0 && duration > 0)
   6335 			return -1;
   6336 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
   6337 			   "start=%d duration=%d", count, start, duration);
   6338 		return wpas_p2p_set_noa(wpa_s, count, start, duration);
   6339 	}
   6340 
   6341 	if (os_strcmp(cmd, "ps") == 0)
   6342 		return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
   6343 
   6344 	if (os_strcmp(cmd, "oppps") == 0)
   6345 		return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
   6346 
   6347 	if (os_strcmp(cmd, "ctwindow") == 0)
   6348 		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
   6349 
   6350 	if (os_strcmp(cmd, "disabled") == 0) {
   6351 		wpa_s->global->p2p_disabled = atoi(param);
   6352 		wpa_printf(MSG_DEBUG, "P2P functionality %s",
   6353 			   wpa_s->global->p2p_disabled ?
   6354 			   "disabled" : "enabled");
   6355 		if (wpa_s->global->p2p_disabled) {
   6356 			wpas_p2p_stop_find(wpa_s);
   6357 			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
   6358 			p2p_flush(wpa_s->global->p2p);
   6359 		}
   6360 		return 0;
   6361 	}
   6362 
   6363 	if (os_strcmp(cmd, "conc_pref") == 0) {
   6364 		if (os_strcmp(param, "sta") == 0)
   6365 			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
   6366 		else if (os_strcmp(param, "p2p") == 0)
   6367 			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
   6368 		else {
   6369 			wpa_printf(MSG_INFO, "Invalid conc_pref value");
   6370 			return -1;
   6371 		}
   6372 		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
   6373 			   "%s", param);
   6374 		return 0;
   6375 	}
   6376 
   6377 	if (os_strcmp(cmd, "force_long_sd") == 0) {
   6378 		wpa_s->force_long_sd = atoi(param);
   6379 		return 0;
   6380 	}
   6381 
   6382 	if (os_strcmp(cmd, "peer_filter") == 0) {
   6383 		u8 addr[ETH_ALEN];
   6384 		if (hwaddr_aton(param, addr))
   6385 			return -1;
   6386 		p2p_set_peer_filter(wpa_s->global->p2p, addr);
   6387 		return 0;
   6388 	}
   6389 
   6390 	if (os_strcmp(cmd, "cross_connect") == 0)
   6391 		return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
   6392 
   6393 	if (os_strcmp(cmd, "go_apsd") == 0) {
   6394 		if (os_strcmp(param, "disable") == 0)
   6395 			wpa_s->set_ap_uapsd = 0;
   6396 		else {
   6397 			wpa_s->set_ap_uapsd = 1;
   6398 			wpa_s->ap_uapsd = atoi(param);
   6399 		}
   6400 		return 0;
   6401 	}
   6402 
   6403 	if (os_strcmp(cmd, "client_apsd") == 0) {
   6404 		if (os_strcmp(param, "disable") == 0)
   6405 			wpa_s->set_sta_uapsd = 0;
   6406 		else {
   6407 			int be, bk, vi, vo;
   6408 			char *pos;
   6409 			/* format: BE,BK,VI,VO;max SP Length */
   6410 			be = atoi(param);
   6411 			pos = os_strchr(param, ',');
   6412 			if (pos == NULL)
   6413 				return -1;
   6414 			pos++;
   6415 			bk = atoi(pos);
   6416 			pos = os_strchr(pos, ',');
   6417 			if (pos == NULL)
   6418 				return -1;
   6419 			pos++;
   6420 			vi = atoi(pos);
   6421 			pos = os_strchr(pos, ',');
   6422 			if (pos == NULL)
   6423 				return -1;
   6424 			pos++;
   6425 			vo = atoi(pos);
   6426 			/* ignore max SP Length for now */
   6427 
   6428 			wpa_s->set_sta_uapsd = 1;
   6429 			wpa_s->sta_uapsd = 0;
   6430 			if (be)
   6431 				wpa_s->sta_uapsd |= BIT(0);
   6432 			if (bk)
   6433 				wpa_s->sta_uapsd |= BIT(1);
   6434 			if (vi)
   6435 				wpa_s->sta_uapsd |= BIT(2);
   6436 			if (vo)
   6437 				wpa_s->sta_uapsd |= BIT(3);
   6438 		}
   6439 		return 0;
   6440 	}
   6441 
   6442 	if (os_strcmp(cmd, "disallow_freq") == 0)
   6443 		return p2p_ctrl_disallow_freq(wpa_s, param);
   6444 
   6445 	if (os_strcmp(cmd, "disc_int") == 0) {
   6446 		int min_disc_int, max_disc_int, max_disc_tu;
   6447 		char *pos;
   6448 
   6449 		pos = param;
   6450 
   6451 		min_disc_int = atoi(pos);
   6452 		pos = os_strchr(pos, ' ');
   6453 		if (pos == NULL)
   6454 			return -1;
   6455 		*pos++ = '\0';
   6456 
   6457 		max_disc_int = atoi(pos);
   6458 		pos = os_strchr(pos, ' ');
   6459 		if (pos == NULL)
   6460 			return -1;
   6461 		*pos++ = '\0';
   6462 
   6463 		max_disc_tu = atoi(pos);
   6464 
   6465 		return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
   6466 					max_disc_int, max_disc_tu);
   6467 	}
   6468 
   6469 	if (os_strcmp(cmd, "per_sta_psk") == 0) {
   6470 		wpa_s->global->p2p_per_sta_psk = !!atoi(param);
   6471 		return 0;
   6472 	}
   6473 
   6474 #ifdef CONFIG_WPS_NFC
   6475 	if (os_strcmp(cmd, "nfc_tag") == 0)
   6476 		return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
   6477 #endif /* CONFIG_WPS_NFC */
   6478 
   6479 	if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
   6480 		wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
   6481 		return 0;
   6482 	}
   6483 
   6484 	if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
   6485 		int op_class, chan;
   6486 
   6487 		op_class = atoi(param);
   6488 		param = os_strchr(param, ':');
   6489 		if (!param)
   6490 			return -1;
   6491 		param++;
   6492 		chan = atoi(param);
   6493 		p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
   6494 					      chan);
   6495 		return 0;
   6496 	}
   6497 
   6498 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
   6499 		   cmd);
   6500 
   6501 	return -1;
   6502 }
   6503 
   6504 
   6505 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
   6506 {
   6507 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
   6508 	wpa_s->force_long_sd = 0;
   6509 	wpas_p2p_stop_find(wpa_s);
   6510 	wpa_s->parent->p2ps_method_config_any = 0;
   6511 	if (wpa_s->global->p2p)
   6512 		p2p_flush(wpa_s->global->p2p);
   6513 }
   6514 
   6515 
   6516 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
   6517 {
   6518 	char *pos, *pos2;
   6519 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
   6520 
   6521 	if (cmd[0]) {
   6522 		pos = os_strchr(cmd, ' ');
   6523 		if (pos == NULL)
   6524 			return -1;
   6525 		*pos++ = '\0';
   6526 		dur1 = atoi(cmd);
   6527 
   6528 		pos2 = os_strchr(pos, ' ');
   6529 		if (pos2)
   6530 			*pos2++ = '\0';
   6531 		int1 = atoi(pos);
   6532 	} else
   6533 		pos2 = NULL;
   6534 
   6535 	if (pos2) {
   6536 		pos = os_strchr(pos2, ' ');
   6537 		if (pos == NULL)
   6538 			return -1;
   6539 		*pos++ = '\0';
   6540 		dur2 = atoi(pos2);
   6541 		int2 = atoi(pos);
   6542 	}
   6543 
   6544 	return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
   6545 }
   6546 
   6547 
   6548 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
   6549 {
   6550 	char *pos;
   6551 	unsigned int period = 0, interval = 0;
   6552 
   6553 	if (cmd[0]) {
   6554 		pos = os_strchr(cmd, ' ');
   6555 		if (pos == NULL)
   6556 			return -1;
   6557 		*pos++ = '\0';
   6558 		period = atoi(cmd);
   6559 		interval = atoi(pos);
   6560 	}
   6561 
   6562 	return wpas_p2p_ext_listen(wpa_s, period, interval);
   6563 }
   6564 
   6565 
   6566 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
   6567 {
   6568 	const char *pos;
   6569 	u8 peer[ETH_ALEN];
   6570 	int iface_addr = 0;
   6571 
   6572 	pos = cmd;
   6573 	if (os_strncmp(pos, "iface=", 6) == 0) {
   6574 		iface_addr = 1;
   6575 		pos += 6;
   6576 	}
   6577 	if (hwaddr_aton(pos, peer))
   6578 		return -1;
   6579 
   6580 	wpas_p2p_remove_client(wpa_s, peer, iface_addr);
   6581 	return 0;
   6582 }
   6583 
   6584 
   6585 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
   6586 {
   6587 	int freq = 0, period = 0, interval = 0, count = 0;
   6588 
   6589 	if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
   6590 	{
   6591 		wpa_printf(MSG_DEBUG,
   6592 			   "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
   6593 		return -1;
   6594 	}
   6595 
   6596 	return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
   6597 }
   6598 
   6599 #endif /* CONFIG_P2P */
   6600 
   6601 
   6602 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
   6603 {
   6604 	struct wpa_freq_range_list ranges;
   6605 	int *freqs = NULL;
   6606 	struct hostapd_hw_modes *mode;
   6607 	u16 i;
   6608 
   6609 	if (wpa_s->hw.modes == NULL)
   6610 		return NULL;
   6611 
   6612 	os_memset(&ranges, 0, sizeof(ranges));
   6613 	if (freq_range_list_parse(&ranges, val) < 0)
   6614 		return NULL;
   6615 
   6616 	for (i = 0; i < wpa_s->hw.num_modes; i++) {
   6617 		int j;
   6618 
   6619 		mode = &wpa_s->hw.modes[i];
   6620 		for (j = 0; j < mode->num_channels; j++) {
   6621 			unsigned int freq;
   6622 
   6623 			if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
   6624 				continue;
   6625 
   6626 			freq = mode->channels[j].freq;
   6627 			if (!freq_range_list_includes(&ranges, freq))
   6628 				continue;
   6629 
   6630 			int_array_add_unique(&freqs, freq);
   6631 		}
   6632 	}
   6633 
   6634 	os_free(ranges.range);
   6635 	return freqs;
   6636 }
   6637 
   6638 
   6639 #ifdef CONFIG_INTERWORKING
   6640 
   6641 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
   6642 {
   6643 	int auto_sel = 0;
   6644 	int *freqs = NULL;
   6645 
   6646 	if (param) {
   6647 		char *pos;
   6648 
   6649 		auto_sel = os_strstr(param, "auto") != NULL;
   6650 
   6651 		pos = os_strstr(param, "freq=");
   6652 		if (pos) {
   6653 			freqs = freq_range_to_channel_list(wpa_s, pos + 5);
   6654 			if (freqs == NULL)
   6655 				return -1;
   6656 		}
   6657 
   6658 	}
   6659 
   6660 	return interworking_select(wpa_s, auto_sel, freqs);
   6661 }
   6662 
   6663 
   6664 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
   6665 				     int only_add)
   6666 {
   6667 	u8 bssid[ETH_ALEN];
   6668 	struct wpa_bss *bss;
   6669 
   6670 	if (hwaddr_aton(dst, bssid)) {
   6671 		wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
   6672 		return -1;
   6673 	}
   6674 
   6675 	bss = wpa_bss_get_bssid(wpa_s, bssid);
   6676 	if (bss == NULL) {
   6677 		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
   6678 			   MAC2STR(bssid));
   6679 		return -1;
   6680 	}
   6681 
   6682 	if (bss->ssid_len == 0) {
   6683 		int found = 0;
   6684 
   6685 		wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
   6686 			   " does not have SSID information", MAC2STR(bssid));
   6687 
   6688 		dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
   6689 					 list) {
   6690 			if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
   6691 			    bss->ssid_len > 0) {
   6692 				found = 1;
   6693 				break;
   6694 			}
   6695 		}
   6696 
   6697 		if (!found)
   6698 			return -1;
   6699 		wpa_printf(MSG_DEBUG,
   6700 			   "Found another matching BSS entry with SSID");
   6701 	}
   6702 
   6703 	return interworking_connect(wpa_s, bss, only_add);
   6704 }
   6705 
   6706 
   6707 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
   6708 {
   6709 	u8 dst_addr[ETH_ALEN];
   6710 	int used;
   6711 	char *pos;
   6712 #define MAX_ANQP_INFO_ID 100
   6713 	u16 id[MAX_ANQP_INFO_ID];
   6714 	size_t num_id = 0;
   6715 	u32 subtypes = 0;
   6716 	int get_cell_pref = 0;
   6717 
   6718 	used = hwaddr_aton2(dst, dst_addr);
   6719 	if (used < 0)
   6720 		return -1;
   6721 	pos = dst + used;
   6722 	if (*pos == ' ')
   6723 		pos++;
   6724 	while (num_id < MAX_ANQP_INFO_ID) {
   6725 		if (os_strncmp(pos, "hs20:", 5) == 0) {
   6726 #ifdef CONFIG_HS20
   6727 			int num = atoi(pos + 5);
   6728 			if (num <= 0 || num > 31)
   6729 				return -1;
   6730 			subtypes |= BIT(num);
   6731 #else /* CONFIG_HS20 */
   6732 			return -1;
   6733 #endif /* CONFIG_HS20 */
   6734 		} else if (os_strncmp(pos, "mbo:", 4) == 0) {
   6735 #ifdef CONFIG_MBO
   6736 			int num = atoi(pos + 4);
   6737 			if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF)
   6738 				return -1;
   6739 			get_cell_pref = 1;
   6740 #else /* CONFIG_MBO */
   6741 			return -1;
   6742 #endif /* CONFIG_MBO */
   6743 		} else {
   6744 			id[num_id] = atoi(pos);
   6745 			if (id[num_id])
   6746 				num_id++;
   6747 		}
   6748 		pos = os_strchr(pos + 1, ',');
   6749 		if (pos == NULL)
   6750 			break;
   6751 		pos++;
   6752 	}
   6753 
   6754 	if (num_id == 0)
   6755 		return -1;
   6756 
   6757 	return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes,
   6758 			     get_cell_pref);
   6759 }
   6760 
   6761 
   6762 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
   6763 {
   6764 	u8 dst_addr[ETH_ALEN];
   6765 	struct wpabuf *advproto, *query = NULL;
   6766 	int used, ret = -1;
   6767 	char *pos, *end;
   6768 	size_t len;
   6769 
   6770 	used = hwaddr_aton2(cmd, dst_addr);
   6771 	if (used < 0)
   6772 		return -1;
   6773 
   6774 	pos = cmd + used;
   6775 	while (*pos == ' ')
   6776 		pos++;
   6777 
   6778 	/* Advertisement Protocol ID */
   6779 	end = os_strchr(pos, ' ');
   6780 	if (end)
   6781 		len = end - pos;
   6782 	else
   6783 		len = os_strlen(pos);
   6784 	if (len & 0x01)
   6785 		return -1;
   6786 	len /= 2;
   6787 	if (len == 0)
   6788 		return -1;
   6789 	advproto = wpabuf_alloc(len);
   6790 	if (advproto == NULL)
   6791 		return -1;
   6792 	if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
   6793 		goto fail;
   6794 
   6795 	if (end) {
   6796 		/* Optional Query Request */
   6797 		pos = end + 1;
   6798 		while (*pos == ' ')
   6799 			pos++;
   6800 
   6801 		len = os_strlen(pos);
   6802 		if (len) {
   6803 			if (len & 0x01)
   6804 				goto fail;
   6805 			len /= 2;
   6806 			if (len == 0)
   6807 				goto fail;
   6808 			query = wpabuf_alloc(len);
   6809 			if (query == NULL)
   6810 				goto fail;
   6811 			if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
   6812 				goto fail;
   6813 		}
   6814 	}
   6815 
   6816 	ret = gas_send_request(wpa_s, dst_addr, advproto, query);
   6817 
   6818 fail:
   6819 	wpabuf_free(advproto);
   6820 	wpabuf_free(query);
   6821 
   6822 	return ret;
   6823 }
   6824 
   6825 
   6826 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
   6827 			    size_t buflen)
   6828 {
   6829 	u8 addr[ETH_ALEN];
   6830 	int dialog_token;
   6831 	int used;
   6832 	char *pos;
   6833 	size_t resp_len, start, requested_len;
   6834 	struct wpabuf *resp;
   6835 	int ret;
   6836 
   6837 	used = hwaddr_aton2(cmd, addr);
   6838 	if (used < 0)
   6839 		return -1;
   6840 
   6841 	pos = cmd + used;
   6842 	while (*pos == ' ')
   6843 		pos++;
   6844 	dialog_token = atoi(pos);
   6845 
   6846 	if (wpa_s->last_gas_resp &&
   6847 	    os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
   6848 	    dialog_token == wpa_s->last_gas_dialog_token)
   6849 		resp = wpa_s->last_gas_resp;
   6850 	else if (wpa_s->prev_gas_resp &&
   6851 		 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
   6852 		 dialog_token == wpa_s->prev_gas_dialog_token)
   6853 		resp = wpa_s->prev_gas_resp;
   6854 	else
   6855 		return -1;
   6856 
   6857 	resp_len = wpabuf_len(resp);
   6858 	start = 0;
   6859 	requested_len = resp_len;
   6860 
   6861 	pos = os_strchr(pos, ' ');
   6862 	if (pos) {
   6863 		start = atoi(pos);
   6864 		if (start > resp_len)
   6865 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
   6866 		pos = os_strchr(pos, ',');
   6867 		if (pos == NULL)
   6868 			return -1;
   6869 		pos++;
   6870 		requested_len = atoi(pos);
   6871 		if (start + requested_len > resp_len)
   6872 			return os_snprintf(buf, buflen, "FAIL-Invalid range");
   6873 	}
   6874 
   6875 	if (requested_len * 2 + 1 > buflen)
   6876 		return os_snprintf(buf, buflen, "FAIL-Too long response");
   6877 
   6878 	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
   6879 			       requested_len);
   6880 
   6881 	if (start + requested_len == resp_len) {
   6882 		/*
   6883 		 * Free memory by dropping the response after it has been
   6884 		 * fetched.
   6885 		 */
   6886 		if (resp == wpa_s->prev_gas_resp) {
   6887 			wpabuf_free(wpa_s->prev_gas_resp);
   6888 			wpa_s->prev_gas_resp = NULL;
   6889 		} else {
   6890 			wpabuf_free(wpa_s->last_gas_resp);
   6891 			wpa_s->last_gas_resp = NULL;
   6892 		}
   6893 	}
   6894 
   6895 	return ret;
   6896 }
   6897 #endif /* CONFIG_INTERWORKING */
   6898 
   6899 
   6900 #ifdef CONFIG_HS20
   6901 
   6902 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
   6903 {
   6904 	u8 dst_addr[ETH_ALEN];
   6905 	int used;
   6906 	char *pos;
   6907 	u32 subtypes = 0;
   6908 
   6909 	used = hwaddr_aton2(dst, dst_addr);
   6910 	if (used < 0)
   6911 		return -1;
   6912 	pos = dst + used;
   6913 	if (*pos == ' ')
   6914 		pos++;
   6915 	for (;;) {
   6916 		int num = atoi(pos);
   6917 		if (num <= 0 || num > 31)
   6918 			return -1;
   6919 		subtypes |= BIT(num);
   6920 		pos = os_strchr(pos + 1, ',');
   6921 		if (pos == NULL)
   6922 			break;
   6923 		pos++;
   6924 	}
   6925 
   6926 	if (subtypes == 0)
   6927 		return -1;
   6928 
   6929 	return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
   6930 }
   6931 
   6932 
   6933 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
   6934 				    const u8 *addr, const char *realm)
   6935 {
   6936 	u8 *buf;
   6937 	size_t rlen, len;
   6938 	int ret;
   6939 
   6940 	rlen = os_strlen(realm);
   6941 	len = 3 + rlen;
   6942 	buf = os_malloc(len);
   6943 	if (buf == NULL)
   6944 		return -1;
   6945 	buf[0] = 1; /* NAI Home Realm Count */
   6946 	buf[1] = 0; /* Formatted in accordance with RFC 4282 */
   6947 	buf[2] = rlen;
   6948 	os_memcpy(buf + 3, realm, rlen);
   6949 
   6950 	ret = hs20_anqp_send_req(wpa_s, addr,
   6951 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
   6952 				 buf, len, 0);
   6953 
   6954 	os_free(buf);
   6955 
   6956 	return ret;
   6957 }
   6958 
   6959 
   6960 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
   6961 					char *dst)
   6962 {
   6963 	struct wpa_cred *cred = wpa_s->conf->cred;
   6964 	u8 dst_addr[ETH_ALEN];
   6965 	int used;
   6966 	u8 *buf;
   6967 	size_t len;
   6968 	int ret;
   6969 
   6970 	used = hwaddr_aton2(dst, dst_addr);
   6971 	if (used < 0)
   6972 		return -1;
   6973 
   6974 	while (dst[used] == ' ')
   6975 		used++;
   6976 	if (os_strncmp(dst + used, "realm=", 6) == 0)
   6977 		return hs20_nai_home_realm_list(wpa_s, dst_addr,
   6978 						dst + used + 6);
   6979 
   6980 	len = os_strlen(dst + used);
   6981 
   6982 	if (len == 0 && cred && cred->realm)
   6983 		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
   6984 
   6985 	if (len & 1)
   6986 		return -1;
   6987 	len /= 2;
   6988 	buf = os_malloc(len);
   6989 	if (buf == NULL)
   6990 		return -1;
   6991 	if (hexstr2bin(dst + used, buf, len) < 0) {
   6992 		os_free(buf);
   6993 		return -1;
   6994 	}
   6995 
   6996 	ret = hs20_anqp_send_req(wpa_s, dst_addr,
   6997 				 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
   6998 				 buf, len, 0);
   6999 	os_free(buf);
   7000 
   7001 	return ret;
   7002 }
   7003 
   7004 
   7005 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
   7006 			 int buflen)
   7007 {
   7008 	u8 dst_addr[ETH_ALEN];
   7009 	int used;
   7010 	char *ctx = NULL, *icon, *poffset, *psize;
   7011 
   7012 	used = hwaddr_aton2(cmd, dst_addr);
   7013 	if (used < 0)
   7014 		return -1;
   7015 	cmd += used;
   7016 
   7017 	icon = str_token(cmd, " ", &ctx);
   7018 	poffset = str_token(cmd, " ", &ctx);
   7019 	psize = str_token(cmd, " ", &ctx);
   7020 	if (!icon || !poffset || !psize)
   7021 		return -1;
   7022 
   7023 	wpa_s->fetch_osu_icon_in_progress = 0;
   7024 	return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
   7025 			     reply, buflen);
   7026 }
   7027 
   7028 
   7029 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
   7030 {
   7031 	u8 dst_addr[ETH_ALEN];
   7032 	int used;
   7033 	char *icon;
   7034 
   7035 	if (!cmd[0])
   7036 		return hs20_del_icon(wpa_s, NULL, NULL);
   7037 
   7038 	used = hwaddr_aton2(cmd, dst_addr);
   7039 	if (used < 0)
   7040 		return -1;
   7041 
   7042 	while (cmd[used] == ' ')
   7043 		used++;
   7044 	icon = cmd[used] ? &cmd[used] : NULL;
   7045 
   7046 	return hs20_del_icon(wpa_s, dst_addr, icon);
   7047 }
   7048 
   7049 
   7050 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
   7051 {
   7052 	u8 dst_addr[ETH_ALEN];
   7053 	int used;
   7054 	char *icon;
   7055 
   7056 	used = hwaddr_aton2(cmd, dst_addr);
   7057 	if (used < 0)
   7058 		return -1;
   7059 
   7060 	while (cmd[used] == ' ')
   7061 		used++;
   7062 	icon = &cmd[used];
   7063 
   7064 	wpa_s->fetch_osu_icon_in_progress = 0;
   7065 	return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
   7066 				  (u8 *) icon, os_strlen(icon), inmem);
   7067 }
   7068 
   7069 #endif /* CONFIG_HS20 */
   7070 
   7071 
   7072 #ifdef CONFIG_AUTOSCAN
   7073 
   7074 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
   7075 					      char *cmd)
   7076 {
   7077 	enum wpa_states state = wpa_s->wpa_state;
   7078 	char *new_params = NULL;
   7079 
   7080 	if (os_strlen(cmd) > 0) {
   7081 		new_params = os_strdup(cmd);
   7082 		if (new_params == NULL)
   7083 			return -1;
   7084 	}
   7085 
   7086 	os_free(wpa_s->conf->autoscan);
   7087 	wpa_s->conf->autoscan = new_params;
   7088 
   7089 	if (wpa_s->conf->autoscan == NULL)
   7090 		autoscan_deinit(wpa_s);
   7091 	else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
   7092 		autoscan_init(wpa_s, 1);
   7093 	else if (state == WPA_SCANNING)
   7094 		wpa_supplicant_reinit_autoscan(wpa_s);
   7095 	else
   7096 		wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
   7097 			   wpa_supplicant_state_txt(state));
   7098 
   7099 	return 0;
   7100 }
   7101 
   7102 #endif /* CONFIG_AUTOSCAN */
   7103 
   7104 
   7105 #ifdef CONFIG_WNM
   7106 
   7107 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
   7108 {
   7109 	int enter;
   7110 	int intval = 0;
   7111 	char *pos;
   7112 	int ret;
   7113 	struct wpabuf *tfs_req = NULL;
   7114 
   7115 	if (os_strncmp(cmd, "enter", 5) == 0)
   7116 		enter = 1;
   7117 	else if (os_strncmp(cmd, "exit", 4) == 0)
   7118 		enter = 0;
   7119 	else
   7120 		return -1;
   7121 
   7122 	pos = os_strstr(cmd, " interval=");
   7123 	if (pos)
   7124 		intval = atoi(pos + 10);
   7125 
   7126 	pos = os_strstr(cmd, " tfs_req=");
   7127 	if (pos) {
   7128 		char *end;
   7129 		size_t len;
   7130 		pos += 9;
   7131 		end = os_strchr(pos, ' ');
   7132 		if (end)
   7133 			len = end - pos;
   7134 		else
   7135 			len = os_strlen(pos);
   7136 		if (len & 1)
   7137 			return -1;
   7138 		len /= 2;
   7139 		tfs_req = wpabuf_alloc(len);
   7140 		if (tfs_req == NULL)
   7141 			return -1;
   7142 		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
   7143 			wpabuf_free(tfs_req);
   7144 			return -1;
   7145 		}
   7146 	}
   7147 
   7148 	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
   7149 					   WNM_SLEEP_MODE_EXIT, intval,
   7150 					   tfs_req);
   7151 	wpabuf_free(tfs_req);
   7152 
   7153 	return ret;
   7154 }
   7155 
   7156 
   7157 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
   7158 {
   7159 	int query_reason, list = 0;
   7160 
   7161 	query_reason = atoi(cmd);
   7162 
   7163 	cmd = os_strchr(cmd, ' ');
   7164 	if (cmd) {
   7165 		cmd++;
   7166 		if (os_strncmp(cmd, "list", 4) == 0) {
   7167 			list = 1;
   7168 		} else {
   7169 			wpa_printf(MSG_DEBUG, "WNM Query: Invalid option %s",
   7170 				   cmd);
   7171 			return -1;
   7172 		}
   7173 	}
   7174 
   7175 	wpa_printf(MSG_DEBUG,
   7176 		   "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
   7177 		   query_reason, list ? " candidate list" : "");
   7178 
   7179 	return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, list);
   7180 }
   7181 
   7182 #endif /* CONFIG_WNM */
   7183 
   7184 
   7185 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
   7186 				      size_t buflen)
   7187 {
   7188 	struct wpa_signal_info si;
   7189 	int ret;
   7190 	char *pos, *end;
   7191 
   7192 	ret = wpa_drv_signal_poll(wpa_s, &si);
   7193 	if (ret)
   7194 		return -1;
   7195 
   7196 	pos = buf;
   7197 	end = buf + buflen;
   7198 
   7199 	ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
   7200 			  "NOISE=%d\nFREQUENCY=%u\n",
   7201 			  si.current_signal, si.current_txrate / 1000,
   7202 			  si.current_noise, si.frequency);
   7203 	if (os_snprintf_error(end - pos, ret))
   7204 		return -1;
   7205 	pos += ret;
   7206 
   7207 	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
   7208 		ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
   7209 				  channel_width_to_string(si.chanwidth));
   7210 		if (os_snprintf_error(end - pos, ret))
   7211 			return -1;
   7212 		pos += ret;
   7213 	}
   7214 
   7215 	if (si.center_frq1 > 0 && si.center_frq2 > 0) {
   7216 		ret = os_snprintf(pos, end - pos,
   7217 				  "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
   7218 				  si.center_frq1, si.center_frq2);
   7219 		if (os_snprintf_error(end - pos, ret))
   7220 			return -1;
   7221 		pos += ret;
   7222 	}
   7223 
   7224 	if (si.avg_signal) {
   7225 		ret = os_snprintf(pos, end - pos,
   7226 				  "AVG_RSSI=%d\n", si.avg_signal);
   7227 		if (os_snprintf_error(end - pos, ret))
   7228 			return -1;
   7229 		pos += ret;
   7230 	}
   7231 
   7232 	if (si.avg_beacon_signal) {
   7233 		ret = os_snprintf(pos, end - pos,
   7234 				  "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal);
   7235 		if (os_snprintf_error(end - pos, ret))
   7236 			return -1;
   7237 		pos += ret;
   7238 	}
   7239 
   7240 	return pos - buf;
   7241 }
   7242 
   7243 
   7244 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
   7245 					  const char *cmd)
   7246 {
   7247 	const char *pos;
   7248 	int threshold = 0;
   7249 	int hysteresis = 0;
   7250 
   7251 	if (wpa_s->bgscan && wpa_s->bgscan_priv) {
   7252 		wpa_printf(MSG_DEBUG,
   7253 			   "Reject SIGNAL_MONITOR command - bgscan is active");
   7254 		return -1;
   7255 	}
   7256 	pos = os_strstr(cmd, "THRESHOLD=");
   7257 	if (pos)
   7258 		threshold = atoi(pos + 10);
   7259 	pos = os_strstr(cmd, "HYSTERESIS=");
   7260 	if (pos)
   7261 		hysteresis = atoi(pos + 11);
   7262 	return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
   7263 }
   7264 
   7265 
   7266 #ifdef CONFIG_TESTING_OPTIONS
   7267 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
   7268 						enum wpa_driver_if_type if_type,
   7269 						unsigned int *num,
   7270 						unsigned int *freq_list)
   7271 {
   7272 	char *pos = wpa_s->get_pref_freq_list_override;
   7273 	char *end;
   7274 	unsigned int count = 0;
   7275 
   7276 	/* Override string format:
   7277 	 *  <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
   7278 
   7279 	while (pos) {
   7280 		if (atoi(pos) == (int) if_type)
   7281 			break;
   7282 		pos = os_strchr(pos, ' ');
   7283 		if (pos)
   7284 			pos++;
   7285 	}
   7286 	if (!pos)
   7287 		return -1;
   7288 	pos = os_strchr(pos, ':');
   7289 	if (!pos)
   7290 		return -1;
   7291 	pos++;
   7292 	end = os_strchr(pos, ' ');
   7293 	while (pos && (!end || pos < end) && count < *num) {
   7294 		freq_list[count++] = atoi(pos);
   7295 		pos = os_strchr(pos, ',');
   7296 		if (pos)
   7297 			pos++;
   7298 	}
   7299 
   7300 	*num = count;
   7301 	return 0;
   7302 }
   7303 #endif /* CONFIG_TESTING_OPTIONS */
   7304 
   7305 
   7306 static int wpas_ctrl_iface_get_pref_freq_list(
   7307 	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
   7308 {
   7309 	unsigned int freq_list[100], num = 100, i;
   7310 	int ret;
   7311 	enum wpa_driver_if_type iface_type;
   7312 	char *pos, *end;
   7313 
   7314 	pos = buf;
   7315 	end = buf + buflen;
   7316 
   7317 	/* buf: "<interface_type>" */
   7318 	if (os_strcmp(cmd, "STATION") == 0)
   7319 		iface_type = WPA_IF_STATION;
   7320 	else if (os_strcmp(cmd, "AP") == 0)
   7321 		iface_type = WPA_IF_AP_BSS;
   7322 	else if (os_strcmp(cmd, "P2P_GO") == 0)
   7323 		iface_type = WPA_IF_P2P_GO;
   7324 	else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
   7325 		iface_type = WPA_IF_P2P_CLIENT;
   7326 	else if (os_strcmp(cmd, "IBSS") == 0)
   7327 		iface_type = WPA_IF_IBSS;
   7328 	else if (os_strcmp(cmd, "TDLS") == 0)
   7329 		iface_type = WPA_IF_TDLS;
   7330 	else
   7331 		return -1;
   7332 
   7333 	wpa_printf(MSG_DEBUG,
   7334 		   "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
   7335 		   iface_type, buf);
   7336 
   7337 	ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
   7338 	if (ret)
   7339 		return -1;
   7340 
   7341 	for (i = 0; i < num; i++) {
   7342 		ret = os_snprintf(pos, end - pos, "%s%u",
   7343 				  i > 0 ? "," : "", freq_list[i]);
   7344 		if (os_snprintf_error(end - pos, ret))
   7345 			return -1;
   7346 		pos += ret;
   7347 	}
   7348 
   7349 	return pos - buf;
   7350 }
   7351 
   7352 
   7353 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
   7354 					char *buf, size_t buflen)
   7355 {
   7356 	int ret, i;
   7357 	char *pos, *end;
   7358 
   7359 	ret = os_snprintf(buf, buflen, "%016llX:\n",
   7360 			  (long long unsigned) wpa_s->drv_flags);
   7361 	if (os_snprintf_error(buflen, ret))
   7362 		return -1;
   7363 
   7364 	pos = buf + ret;
   7365 	end = buf + buflen;
   7366 
   7367 	for (i = 0; i < 64; i++) {
   7368 		if (wpa_s->drv_flags & (1LLU << i)) {
   7369 			ret = os_snprintf(pos, end - pos, "%s\n",
   7370 					  driver_flag_to_string(1LLU << i));
   7371 			if (os_snprintf_error(end - pos, ret))
   7372 				return -1;
   7373 			pos += ret;
   7374 		}
   7375 	}
   7376 
   7377 	return pos - buf;
   7378 }
   7379 
   7380 
   7381 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
   7382 				      size_t buflen)
   7383 {
   7384 	struct hostap_sta_driver_data sta;
   7385 	int ret;
   7386 
   7387 	ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
   7388 	if (ret)
   7389 		return -1;
   7390 
   7391 	ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
   7392 			  sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
   7393 	if (os_snprintf_error(buflen, ret))
   7394 		return -1;
   7395 	return ret;
   7396 }
   7397 
   7398 
   7399 #ifdef ANDROID
   7400 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
   7401 				     char *buf, size_t buflen)
   7402 {
   7403 	int ret;
   7404 
   7405 	ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
   7406 	if (ret == 0) {
   7407 		if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
   7408 			struct p2p_data *p2p = wpa_s->global->p2p;
   7409 			if (p2p) {
   7410 				char country[3];
   7411 				country[0] = cmd[8];
   7412 				country[1] = cmd[9];
   7413 				country[2] = 0x04;
   7414 				p2p_set_country(p2p, country);
   7415 			}
   7416 		}
   7417 		ret = os_snprintf(buf, buflen, "%s\n", "OK");
   7418 		if (os_snprintf_error(buflen, ret))
   7419 			ret = -1;
   7420 	}
   7421 	return ret;
   7422 }
   7423 #endif /* ANDROID */
   7424 
   7425 
   7426 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
   7427 				     char *buf, size_t buflen)
   7428 {
   7429 	int ret;
   7430 	char *pos;
   7431 	u8 *data = NULL;
   7432 	unsigned int vendor_id, subcmd;
   7433 	struct wpabuf *reply;
   7434 	size_t data_len = 0;
   7435 
   7436 	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
   7437 	vendor_id = strtoul(cmd, &pos, 16);
   7438 	if (!isblank((unsigned char) *pos))
   7439 		return -EINVAL;
   7440 
   7441 	subcmd = strtoul(pos, &pos, 10);
   7442 
   7443 	if (*pos != '\0') {
   7444 		if (!isblank((unsigned char) *pos++))
   7445 			return -EINVAL;
   7446 		data_len = os_strlen(pos);
   7447 	}
   7448 
   7449 	if (data_len) {
   7450 		data_len /= 2;
   7451 		data = os_malloc(data_len);
   7452 		if (!data)
   7453 			return -1;
   7454 
   7455 		if (hexstr2bin(pos, data, data_len)) {
   7456 			wpa_printf(MSG_DEBUG,
   7457 				   "Vendor command: wrong parameter format");
   7458 			os_free(data);
   7459 			return -EINVAL;
   7460 		}
   7461 	}
   7462 
   7463 	reply = wpabuf_alloc((buflen - 1) / 2);
   7464 	if (!reply) {
   7465 		os_free(data);
   7466 		return -1;
   7467 	}
   7468 
   7469 	ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
   7470 				 reply);
   7471 
   7472 	if (ret == 0)
   7473 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
   7474 				       wpabuf_len(reply));
   7475 
   7476 	wpabuf_free(reply);
   7477 	os_free(data);
   7478 
   7479 	return ret;
   7480 }
   7481 
   7482 
   7483 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
   7484 {
   7485 #ifdef CONFIG_P2P
   7486 	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
   7487 		wpa_s->global->p2p_init_wpa_s : wpa_s;
   7488 #endif /* CONFIG_P2P */
   7489 
   7490 	wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
   7491 
   7492 	if (wpas_abort_ongoing_scan(wpa_s) == 0)
   7493 		wpa_s->ignore_post_flush_scan_res = 1;
   7494 
   7495 	if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
   7496 		/*
   7497 		 * Avoid possible auto connect re-connection on getting
   7498 		 * disconnected due to state flush.
   7499 		 */
   7500 		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
   7501 	}
   7502 
   7503 #ifdef CONFIG_P2P
   7504 	wpas_p2p_group_remove(p2p_wpa_s, "*");
   7505 	wpas_p2p_cancel(p2p_wpa_s);
   7506 	p2p_ctrl_flush(p2p_wpa_s);
   7507 	wpas_p2p_service_flush(p2p_wpa_s);
   7508 	p2p_wpa_s->global->p2p_disabled = 0;
   7509 	p2p_wpa_s->global->p2p_per_sta_psk = 0;
   7510 	p2p_wpa_s->conf->num_sec_device_types = 0;
   7511 	p2p_wpa_s->p2p_disable_ip_addr_req = 0;
   7512 	os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
   7513 	p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
   7514 	p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
   7515 	p2p_wpa_s->global->pending_p2ps_group = 0;
   7516 	p2p_wpa_s->global->pending_p2ps_group_freq = 0;
   7517 #endif /* CONFIG_P2P */
   7518 
   7519 #ifdef CONFIG_WPS_TESTING
   7520 	wps_version_number = 0x20;
   7521 	wps_testing_dummy_cred = 0;
   7522 	wps_corrupt_pkhash = 0;
   7523 	wps_force_auth_types_in_use = 0;
   7524 	wps_force_encr_types_in_use = 0;
   7525 #endif /* CONFIG_WPS_TESTING */
   7526 #ifdef CONFIG_WPS
   7527 	wpa_s->wps_fragment_size = 0;
   7528 	wpas_wps_cancel(wpa_s);
   7529 	wps_registrar_flush(wpa_s->wps->registrar);
   7530 #endif /* CONFIG_WPS */
   7531 	wpa_s->after_wps = 0;
   7532 	wpa_s->known_wps_freq = 0;
   7533 
   7534 #ifdef CONFIG_TDLS
   7535 #ifdef CONFIG_TDLS_TESTING
   7536 	tdls_testing = 0;
   7537 #endif /* CONFIG_TDLS_TESTING */
   7538 	wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
   7539 	wpa_tdls_enable(wpa_s->wpa, 1);
   7540 #endif /* CONFIG_TDLS */
   7541 
   7542 	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
   7543 	wpa_supplicant_stop_countermeasures(wpa_s, NULL);
   7544 
   7545 	wpa_s->no_keep_alive = 0;
   7546 	wpa_s->own_disconnect_req = 0;
   7547 
   7548 	os_free(wpa_s->disallow_aps_bssid);
   7549 	wpa_s->disallow_aps_bssid = NULL;
   7550 	wpa_s->disallow_aps_bssid_count = 0;
   7551 	os_free(wpa_s->disallow_aps_ssid);
   7552 	wpa_s->disallow_aps_ssid = NULL;
   7553 	wpa_s->disallow_aps_ssid_count = 0;
   7554 
   7555 	wpa_s->set_sta_uapsd = 0;
   7556 	wpa_s->sta_uapsd = 0;
   7557 
   7558 	wpa_drv_radio_disable(wpa_s, 0);
   7559 	wpa_blacklist_clear(wpa_s);
   7560 	wpa_s->extra_blacklist_count = 0;
   7561 	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
   7562 	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
   7563 	wpa_config_flush_blobs(wpa_s->conf);
   7564 	wpa_s->conf->auto_interworking = 0;
   7565 	wpa_s->conf->okc = 0;
   7566 
   7567 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
   7568 	rsn_preauth_deinit(wpa_s->wpa);
   7569 
   7570 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
   7571 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
   7572 	wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
   7573 	eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
   7574 
   7575 	radio_remove_works(wpa_s, NULL, 1);
   7576 	wpa_s->ext_work_in_progress = 0;
   7577 
   7578 	wpa_s->next_ssid = NULL;
   7579 
   7580 #ifdef CONFIG_INTERWORKING
   7581 #ifdef CONFIG_HS20
   7582 	hs20_cancel_fetch_osu(wpa_s);
   7583 	hs20_del_icon(wpa_s, NULL, NULL);
   7584 #endif /* CONFIG_HS20 */
   7585 #endif /* CONFIG_INTERWORKING */
   7586 
   7587 	wpa_s->ext_mgmt_frame_handling = 0;
   7588 	wpa_s->ext_eapol_frame_io = 0;
   7589 #ifdef CONFIG_TESTING_OPTIONS
   7590 	wpa_s->extra_roc_dur = 0;
   7591 	wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
   7592 	wpa_s->p2p_go_csa_on_inv = 0;
   7593 	wpa_s->ignore_auth_resp = 0;
   7594 	wpa_s->ignore_assoc_disallow = 0;
   7595 	wpa_s->reject_btm_req_reason = 0;
   7596 	wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
   7597 	os_free(wpa_s->get_pref_freq_list_override);
   7598 	wpa_s->get_pref_freq_list_override = NULL;
   7599 #endif /* CONFIG_TESTING_OPTIONS */
   7600 
   7601 	wpa_s->disconnected = 0;
   7602 	os_free(wpa_s->next_scan_freqs);
   7603 	wpa_s->next_scan_freqs = NULL;
   7604 
   7605 	wpa_bss_flush(wpa_s);
   7606 	if (!dl_list_empty(&wpa_s->bss)) {
   7607 		wpa_printf(MSG_DEBUG,
   7608 			   "BSS table not empty after flush: %u entries, current_bss=%p bssid="
   7609 			   MACSTR " pending_bssid=" MACSTR,
   7610 			   dl_list_len(&wpa_s->bss), wpa_s->current_bss,
   7611 			   MAC2STR(wpa_s->bssid),
   7612 			   MAC2STR(wpa_s->pending_bssid));
   7613 	}
   7614 
   7615 	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
   7616 	wpa_s->wnmsleep_used = 0;
   7617 
   7618 #ifdef CONFIG_SME
   7619 	wpa_s->sme.last_unprot_disconnect.sec = 0;
   7620 #endif /* CONFIG_SME */
   7621 
   7622 	wpabuf_free(wpa_s->ric_ies);
   7623 	wpa_s->ric_ies = NULL;
   7624 }
   7625 
   7626 
   7627 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
   7628 				     char *buf, size_t buflen)
   7629 {
   7630 	struct wpa_radio_work *work;
   7631 	char *pos, *end;
   7632 	struct os_reltime now, diff;
   7633 
   7634 	pos = buf;
   7635 	end = buf + buflen;
   7636 
   7637 	os_get_reltime(&now);
   7638 
   7639 	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
   7640 	{
   7641 		int ret;
   7642 
   7643 		os_reltime_sub(&now, &work->time, &diff);
   7644 		ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
   7645 				  work->type, work->wpa_s->ifname, work->freq,
   7646 				  work->started, diff.sec, diff.usec);
   7647 		if (os_snprintf_error(end - pos, ret))
   7648 			break;
   7649 		pos += ret;
   7650 	}
   7651 
   7652 	return pos - buf;
   7653 }
   7654 
   7655 
   7656 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
   7657 {
   7658 	struct wpa_radio_work *work = eloop_ctx;
   7659 	struct wpa_external_work *ework = work->ctx;
   7660 
   7661 	wpa_dbg(work->wpa_s, MSG_DEBUG,
   7662 		"Timing out external radio work %u (%s)",
   7663 		ework->id, work->type);
   7664 	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
   7665 	work->wpa_s->ext_work_in_progress = 0;
   7666 	radio_work_done(work);
   7667 	os_free(ework);
   7668 }
   7669 
   7670 
   7671 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
   7672 {
   7673 	struct wpa_external_work *ework = work->ctx;
   7674 
   7675 	if (deinit) {
   7676 		if (work->started)
   7677 			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
   7678 					     work, NULL);
   7679 
   7680 		/*
   7681 		 * work->type points to a buffer in ework, so need to replace
   7682 		 * that here with a fixed string to avoid use of freed memory
   7683 		 * in debug prints.
   7684 		 */
   7685 		work->type = "freed-ext-work";
   7686 		work->ctx = NULL;
   7687 		os_free(ework);
   7688 		return;
   7689 	}
   7690 
   7691 	wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
   7692 		ework->id, ework->type);
   7693 	wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
   7694 	work->wpa_s->ext_work_in_progress = 1;
   7695 	if (!ework->timeout)
   7696 		ework->timeout = 10;
   7697 	eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
   7698 			       work, NULL);
   7699 }
   7700 
   7701 
   7702 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
   7703 				    char *buf, size_t buflen)
   7704 {
   7705 	struct wpa_external_work *ework;
   7706 	char *pos, *pos2;
   7707 	size_t type_len;
   7708 	int ret;
   7709 	unsigned int freq = 0;
   7710 
   7711 	/* format: <name> [freq=<MHz>] [timeout=<seconds>] */
   7712 
   7713 	ework = os_zalloc(sizeof(*ework));
   7714 	if (ework == NULL)
   7715 		return -1;
   7716 
   7717 	pos = os_strchr(cmd, ' ');
   7718 	if (pos) {
   7719 		type_len = pos - cmd;
   7720 		pos++;
   7721 
   7722 		pos2 = os_strstr(pos, "freq=");
   7723 		if (pos2)
   7724 			freq = atoi(pos2 + 5);
   7725 
   7726 		pos2 = os_strstr(pos, "timeout=");
   7727 		if (pos2)
   7728 			ework->timeout = atoi(pos2 + 8);
   7729 	} else {
   7730 		type_len = os_strlen(cmd);
   7731 	}
   7732 	if (4 + type_len >= sizeof(ework->type))
   7733 		type_len = sizeof(ework->type) - 4 - 1;
   7734 	os_strlcpy(ework->type, "ext:", sizeof(ework->type));
   7735 	os_memcpy(ework->type + 4, cmd, type_len);
   7736 	ework->type[4 + type_len] = '\0';
   7737 
   7738 	wpa_s->ext_work_id++;
   7739 	if (wpa_s->ext_work_id == 0)
   7740 		wpa_s->ext_work_id++;
   7741 	ework->id = wpa_s->ext_work_id;
   7742 
   7743 	if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
   7744 			   ework) < 0) {
   7745 		os_free(ework);
   7746 		return -1;
   7747 	}
   7748 
   7749 	ret = os_snprintf(buf, buflen, "%u", ework->id);
   7750 	if (os_snprintf_error(buflen, ret))
   7751 		return -1;
   7752 	return ret;
   7753 }
   7754 
   7755 
   7756 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
   7757 {
   7758 	struct wpa_radio_work *work;
   7759 	unsigned int id = atoi(cmd);
   7760 
   7761 	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
   7762 	{
   7763 		struct wpa_external_work *ework;
   7764 
   7765 		if (os_strncmp(work->type, "ext:", 4) != 0)
   7766 			continue;
   7767 		ework = work->ctx;
   7768 		if (id && ework->id != id)
   7769 			continue;
   7770 		wpa_dbg(wpa_s, MSG_DEBUG,
   7771 			"Completed external radio work %u (%s)",
   7772 			ework->id, ework->type);
   7773 		eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
   7774 		wpa_s->ext_work_in_progress = 0;
   7775 		radio_work_done(work);
   7776 		os_free(ework);
   7777 		return 3; /* "OK\n" */
   7778 	}
   7779 
   7780 	return -1;
   7781 }
   7782 
   7783 
   7784 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
   7785 				char *buf, size_t buflen)
   7786 {
   7787 	if (os_strcmp(cmd, "show") == 0)
   7788 		return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
   7789 	if (os_strncmp(cmd, "add ", 4) == 0)
   7790 		return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
   7791 	if (os_strncmp(cmd, "done ", 5) == 0)
   7792 		return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
   7793 	return -1;
   7794 }
   7795 
   7796 
   7797 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
   7798 {
   7799 	struct wpa_radio_work *work, *tmp;
   7800 
   7801 	if (!wpa_s || !wpa_s->radio)
   7802 		return;
   7803 
   7804 	dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
   7805 			      struct wpa_radio_work, list) {
   7806 		struct wpa_external_work *ework;
   7807 
   7808 		if (os_strncmp(work->type, "ext:", 4) != 0)
   7809 			continue;
   7810 		ework = work->ctx;
   7811 		wpa_dbg(wpa_s, MSG_DEBUG,
   7812 			"Flushing%s external radio work %u (%s)",
   7813 			work->started ? " started" : "", ework->id,
   7814 			ework->type);
   7815 		if (work->started)
   7816 			eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
   7817 					     work, NULL);
   7818 		radio_work_done(work);
   7819 		os_free(ework);
   7820 	}
   7821 }
   7822 
   7823 
   7824 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
   7825 {
   7826 	struct wpa_supplicant *wpa_s = eloop_ctx;
   7827 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
   7828 }
   7829 
   7830 
   7831 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
   7832 			      unsigned int *scan_id_count, int scan_id[])
   7833 {
   7834 	const char *pos = value;
   7835 
   7836 	while (pos) {
   7837 		if (*pos == ' ' || *pos == '\0')
   7838 			break;
   7839 		if (*scan_id_count == MAX_SCAN_ID)
   7840 			return -1;
   7841 		scan_id[(*scan_id_count)++] = atoi(pos);
   7842 		pos = os_strchr(pos, ',');
   7843 		if (pos)
   7844 			pos++;
   7845 	}
   7846 
   7847 	return 0;
   7848 }
   7849 
   7850 
   7851 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
   7852 			   char *reply, int reply_size, int *reply_len)
   7853 {
   7854 	char *pos;
   7855 	unsigned int manual_scan_passive = 0;
   7856 	unsigned int manual_scan_use_id = 0;
   7857 	unsigned int manual_scan_only_new = 0;
   7858 	unsigned int scan_only = 0;
   7859 	unsigned int scan_id_count = 0;
   7860 	int scan_id[MAX_SCAN_ID];
   7861 	void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
   7862 				 struct wpa_scan_results *scan_res);
   7863 	int *manual_scan_freqs = NULL;
   7864 	struct wpa_ssid_value *ssid = NULL, *ns;
   7865 	unsigned int ssid_count = 0;
   7866 
   7867 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
   7868 		*reply_len = -1;
   7869 		return;
   7870 	}
   7871 
   7872 	if (radio_work_pending(wpa_s, "scan")) {
   7873 		wpa_printf(MSG_DEBUG,
   7874 			   "Pending scan scheduled - reject new request");
   7875 		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
   7876 		return;
   7877 	}
   7878 
   7879 #ifdef CONFIG_INTERWORKING
   7880 	if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
   7881 		wpa_printf(MSG_DEBUG,
   7882 			   "Interworking select in progress - reject new scan");
   7883 		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
   7884 		return;
   7885 	}
   7886 #endif /* CONFIG_INTERWORKING */
   7887 
   7888 	if (params) {
   7889 		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
   7890 			scan_only = 1;
   7891 
   7892 		pos = os_strstr(params, "freq=");
   7893 		if (pos) {
   7894 			manual_scan_freqs = freq_range_to_channel_list(wpa_s,
   7895 								       pos + 5);
   7896 			if (manual_scan_freqs == NULL) {
   7897 				*reply_len = -1;
   7898 				goto done;
   7899 			}
   7900 		}
   7901 
   7902 		pos = os_strstr(params, "passive=");
   7903 		if (pos)
   7904 			manual_scan_passive = !!atoi(pos + 8);
   7905 
   7906 		pos = os_strstr(params, "use_id=");
   7907 		if (pos)
   7908 			manual_scan_use_id = atoi(pos + 7);
   7909 
   7910 		pos = os_strstr(params, "only_new=1");
   7911 		if (pos)
   7912 			manual_scan_only_new = 1;
   7913 
   7914 		pos = os_strstr(params, "scan_id=");
   7915 		if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
   7916 					      scan_id) < 0) {
   7917 			*reply_len = -1;
   7918 			goto done;
   7919 		}
   7920 
   7921 		pos = params;
   7922 		while (pos && *pos != '\0') {
   7923 			if (os_strncmp(pos, "ssid ", 5) == 0) {
   7924 				char *end;
   7925 
   7926 				pos += 5;
   7927 				end = pos;
   7928 				while (*end) {
   7929 					if (*end == '\0' || *end == ' ')
   7930 						break;
   7931 					end++;
   7932 				}
   7933 
   7934 				ns = os_realloc_array(
   7935 					ssid, ssid_count + 1,
   7936 					sizeof(struct wpa_ssid_value));
   7937 				if (ns == NULL) {
   7938 					*reply_len = -1;
   7939 					goto done;
   7940 				}
   7941 				ssid = ns;
   7942 
   7943 				if ((end - pos) & 0x01 ||
   7944 				    end - pos > 2 * SSID_MAX_LEN ||
   7945 				    hexstr2bin(pos, ssid[ssid_count].ssid,
   7946 					       (end - pos) / 2) < 0) {
   7947 					wpa_printf(MSG_DEBUG,
   7948 						   "Invalid SSID value '%s'",
   7949 						   pos);
   7950 					*reply_len = -1;
   7951 					goto done;
   7952 				}
   7953 				ssid[ssid_count].ssid_len = (end - pos) / 2;
   7954 				wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
   7955 						  ssid[ssid_count].ssid,
   7956 						  ssid[ssid_count].ssid_len);
   7957 				ssid_count++;
   7958 				pos = end;
   7959 			}
   7960 
   7961 			pos = os_strchr(pos, ' ');
   7962 			if (pos)
   7963 				pos++;
   7964 		}
   7965 	}
   7966 
   7967 	wpa_s->num_ssids_from_scan_req = ssid_count;
   7968 	os_free(wpa_s->ssids_from_scan_req);
   7969 	if (ssid_count) {
   7970 		wpa_s->ssids_from_scan_req = ssid;
   7971 		ssid = NULL;
   7972 	} else {
   7973 		wpa_s->ssids_from_scan_req = NULL;
   7974 	}
   7975 
   7976 	if (scan_only)
   7977 		scan_res_handler = scan_only_handler;
   7978 	else if (wpa_s->scan_res_handler == scan_only_handler)
   7979 		scan_res_handler = NULL;
   7980 	else
   7981 		scan_res_handler = wpa_s->scan_res_handler;
   7982 
   7983 	if (!wpa_s->sched_scanning && !wpa_s->scanning &&
   7984 	    ((wpa_s->wpa_state <= WPA_SCANNING) ||
   7985 	     (wpa_s->wpa_state == WPA_COMPLETED))) {
   7986 		wpa_s->manual_scan_passive = manual_scan_passive;
   7987 		wpa_s->manual_scan_use_id = manual_scan_use_id;
   7988 		wpa_s->manual_scan_only_new = manual_scan_only_new;
   7989 		wpa_s->scan_id_count = scan_id_count;
   7990 		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
   7991 		wpa_s->scan_res_handler = scan_res_handler;
   7992 		os_free(wpa_s->manual_scan_freqs);
   7993 		wpa_s->manual_scan_freqs = manual_scan_freqs;
   7994 		manual_scan_freqs = NULL;
   7995 
   7996 		wpa_s->normal_scans = 0;
   7997 		wpa_s->scan_req = MANUAL_SCAN_REQ;
   7998 		wpa_s->after_wps = 0;
   7999 		wpa_s->known_wps_freq = 0;
   8000 		wpa_supplicant_req_scan(wpa_s, 0, 0);
   8001 		if (wpa_s->manual_scan_use_id) {
   8002 			wpa_s->manual_scan_id++;
   8003 			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
   8004 				wpa_s->manual_scan_id);
   8005 			*reply_len = os_snprintf(reply, reply_size, "%u\n",
   8006 						 wpa_s->manual_scan_id);
   8007 		}
   8008 	} else if (wpa_s->sched_scanning) {
   8009 		wpa_s->manual_scan_passive = manual_scan_passive;
   8010 		wpa_s->manual_scan_use_id = manual_scan_use_id;
   8011 		wpa_s->manual_scan_only_new = manual_scan_only_new;
   8012 		wpa_s->scan_id_count = scan_id_count;
   8013 		os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
   8014 		wpa_s->scan_res_handler = scan_res_handler;
   8015 		os_free(wpa_s->manual_scan_freqs);
   8016 		wpa_s->manual_scan_freqs = manual_scan_freqs;
   8017 		manual_scan_freqs = NULL;
   8018 
   8019 		wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
   8020 		wpa_supplicant_cancel_sched_scan(wpa_s);
   8021 		wpa_s->scan_req = MANUAL_SCAN_REQ;
   8022 		wpa_supplicant_req_scan(wpa_s, 0, 0);
   8023 		if (wpa_s->manual_scan_use_id) {
   8024 			wpa_s->manual_scan_id++;
   8025 			*reply_len = os_snprintf(reply, reply_size, "%u\n",
   8026 						 wpa_s->manual_scan_id);
   8027 			wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
   8028 				wpa_s->manual_scan_id);
   8029 		}
   8030 	} else {
   8031 		wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
   8032 		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
   8033 	}
   8034 
   8035 done:
   8036 	os_free(manual_scan_freqs);
   8037 	os_free(ssid);
   8038 }
   8039 
   8040 
   8041 #ifdef CONFIG_TESTING_OPTIONS
   8042 
   8043 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
   8044 				       unsigned int freq, const u8 *dst,
   8045 				       const u8 *src, const u8 *bssid,
   8046 				       const u8 *data, size_t data_len,
   8047 				       enum offchannel_send_action_result
   8048 				       result)
   8049 {
   8050 	wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
   8051 		" src=" MACSTR " bssid=" MACSTR " result=%s",
   8052 		freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
   8053 		result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
   8054 		"SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
   8055 			     "NO_ACK" : "FAILED"));
   8056 }
   8057 
   8058 
   8059 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
   8060 {
   8061 	char *pos, *param;
   8062 	size_t len;
   8063 	u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
   8064 	int res, used;
   8065 	int freq = 0, no_cck = 0, wait_time = 0;
   8066 
   8067 	/* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
   8068 	 *    <action=Action frame payload> */
   8069 
   8070 	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
   8071 
   8072 	pos = cmd;
   8073 	used = hwaddr_aton2(pos, da);
   8074 	if (used < 0)
   8075 		return -1;
   8076 	pos += used;
   8077 	while (*pos == ' ')
   8078 		pos++;
   8079 	used = hwaddr_aton2(pos, bssid);
   8080 	if (used < 0)
   8081 		return -1;
   8082 	pos += used;
   8083 
   8084 	param = os_strstr(pos, " freq=");
   8085 	if (param) {
   8086 		param += 6;
   8087 		freq = atoi(param);
   8088 	}
   8089 
   8090 	param = os_strstr(pos, " no_cck=");
   8091 	if (param) {
   8092 		param += 8;
   8093 		no_cck = atoi(param);
   8094 	}
   8095 
   8096 	param = os_strstr(pos, " wait_time=");
   8097 	if (param) {
   8098 		param += 11;
   8099 		wait_time = atoi(param);
   8100 	}
   8101 
   8102 	param = os_strstr(pos, " action=");
   8103 	if (param == NULL)
   8104 		return -1;
   8105 	param += 8;
   8106 
   8107 	len = os_strlen(param);
   8108 	if (len & 1)
   8109 		return -1;
   8110 	len /= 2;
   8111 
   8112 	buf = os_malloc(len);
   8113 	if (buf == NULL)
   8114 		return -1;
   8115 
   8116 	if (hexstr2bin(param, buf, len) < 0) {
   8117 		os_free(buf);
   8118 		return -1;
   8119 	}
   8120 
   8121 	res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
   8122 				     buf, len, wait_time,
   8123 				     wpas_ctrl_iface_mgmt_tx_cb, no_cck);
   8124 	os_free(buf);
   8125 	return res;
   8126 }
   8127 
   8128 
   8129 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
   8130 {
   8131 	wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
   8132 	offchannel_send_action_done(wpa_s);
   8133 }
   8134 
   8135 
   8136 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
   8137 					   char *cmd)
   8138 {
   8139 	char *pos, *param;
   8140 	size_t len;
   8141 	u8 *buf;
   8142 	int freq = 0, datarate = 0, ssi_signal = 0;
   8143 	union wpa_event_data event;
   8144 
   8145 	if (!wpa_s->ext_mgmt_frame_handling)
   8146 		return -1;
   8147 
   8148 	/* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
   8149 
   8150 	wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
   8151 
   8152 	pos = cmd;
   8153 	param = os_strstr(pos, "freq=");
   8154 	if (param) {
   8155 		param += 5;
   8156 		freq = atoi(param);
   8157 	}
   8158 
   8159 	param = os_strstr(pos, " datarate=");
   8160 	if (param) {
   8161 		param += 10;
   8162 		datarate = atoi(param);
   8163 	}
   8164 
   8165 	param = os_strstr(pos, " ssi_signal=");
   8166 	if (param) {
   8167 		param += 12;
   8168 		ssi_signal = atoi(param);
   8169 	}
   8170 
   8171 	param = os_strstr(pos, " frame=");
   8172 	if (param == NULL)
   8173 		return -1;
   8174 	param += 7;
   8175 
   8176 	len = os_strlen(param);
   8177 	if (len & 1)
   8178 		return -1;
   8179 	len /= 2;
   8180 
   8181 	buf = os_malloc(len);
   8182 	if (buf == NULL)
   8183 		return -1;
   8184 
   8185 	if (hexstr2bin(param, buf, len) < 0) {
   8186 		os_free(buf);
   8187 		return -1;
   8188 	}
   8189 
   8190 	os_memset(&event, 0, sizeof(event));
   8191 	event.rx_mgmt.freq = freq;
   8192 	event.rx_mgmt.frame = buf;
   8193 	event.rx_mgmt.frame_len = len;
   8194 	event.rx_mgmt.ssi_signal = ssi_signal;
   8195 	event.rx_mgmt.datarate = datarate;
   8196 	wpa_s->ext_mgmt_frame_handling = 0;
   8197 	wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
   8198 	wpa_s->ext_mgmt_frame_handling = 1;
   8199 
   8200 	os_free(buf);
   8201 
   8202 	return 0;
   8203 }
   8204 
   8205 
   8206 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
   8207 					   char *param)
   8208 {
   8209 	struct wpa_scan_res *res;
   8210 	struct os_reltime now;
   8211 	char *pos, *end;
   8212 	int ret = -1;
   8213 
   8214 	if (!param)
   8215 		return -1;
   8216 
   8217 	if (os_strcmp(param, "START") == 0) {
   8218 		wpa_bss_update_start(wpa_s);
   8219 		return 0;
   8220 	}
   8221 
   8222 	if (os_strcmp(param, "END") == 0) {
   8223 		wpa_bss_update_end(wpa_s, NULL, 1);
   8224 		return 0;
   8225 	}
   8226 
   8227 	if (os_strncmp(param, "BSS ", 4) != 0)
   8228 		return -1;
   8229 	param += 3;
   8230 
   8231 	res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
   8232 	if (!res)
   8233 		return -1;
   8234 
   8235 	pos = os_strstr(param, " flags=");
   8236 	if (pos)
   8237 		res->flags = strtol(pos + 7, NULL, 16);
   8238 
   8239 	pos = os_strstr(param, " bssid=");
   8240 	if (pos && hwaddr_aton(pos + 7, res->bssid))
   8241 		goto fail;
   8242 
   8243 	pos = os_strstr(param, " freq=");
   8244 	if (pos)
   8245 		res->freq = atoi(pos + 6);
   8246 
   8247 	pos = os_strstr(param, " beacon_int=");
   8248 	if (pos)
   8249 		res->beacon_int = atoi(pos + 12);
   8250 
   8251 	pos = os_strstr(param, " caps=");
   8252 	if (pos)
   8253 		res->caps = strtol(pos + 6, NULL, 16);
   8254 
   8255 	pos = os_strstr(param, " qual=");
   8256 	if (pos)
   8257 		res->qual = atoi(pos + 6);
   8258 
   8259 	pos = os_strstr(param, " noise=");
   8260 	if (pos)
   8261 		res->noise = atoi(pos + 7);
   8262 
   8263 	pos = os_strstr(param, " level=");
   8264 	if (pos)
   8265 		res->level = atoi(pos + 7);
   8266 
   8267 	pos = os_strstr(param, " tsf=");
   8268 	if (pos)
   8269 		res->tsf = strtoll(pos + 5, NULL, 16);
   8270 
   8271 	pos = os_strstr(param, " age=");
   8272 	if (pos)
   8273 		res->age = atoi(pos + 5);
   8274 
   8275 	pos = os_strstr(param, " est_throughput=");
   8276 	if (pos)
   8277 		res->est_throughput = atoi(pos + 16);
   8278 
   8279 	pos = os_strstr(param, " snr=");
   8280 	if (pos)
   8281 		res->snr = atoi(pos + 5);
   8282 
   8283 	pos = os_strstr(param, " parent_tsf=");
   8284 	if (pos)
   8285 		res->parent_tsf = strtoll(pos + 7, NULL, 16);
   8286 
   8287 	pos = os_strstr(param, " tsf_bssid=");
   8288 	if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
   8289 		goto fail;
   8290 
   8291 	pos = os_strstr(param, " ie=");
   8292 	if (pos) {
   8293 		pos += 4;
   8294 		end = os_strchr(pos, ' ');
   8295 		if (!end)
   8296 			end = pos + os_strlen(pos);
   8297 		res->ie_len = (end - pos) / 2;
   8298 		if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
   8299 			goto fail;
   8300 	}
   8301 
   8302 	pos = os_strstr(param, " beacon_ie=");
   8303 	if (pos) {
   8304 		pos += 11;
   8305 		end = os_strchr(pos, ' ');
   8306 		if (!end)
   8307 			end = pos + os_strlen(pos);
   8308 		res->beacon_ie_len = (end - pos) / 2;
   8309 		if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
   8310 			       res->beacon_ie_len))
   8311 			goto fail;
   8312 	}
   8313 
   8314 	os_get_reltime(&now);
   8315 	wpa_bss_update_scan_res(wpa_s, res, &now);
   8316 	ret = 0;
   8317 fail:
   8318 	os_free(res);
   8319 
   8320 	return ret;
   8321 }
   8322 
   8323 
   8324 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
   8325 {
   8326 	char *pos, *param;
   8327 	union wpa_event_data event;
   8328 	enum wpa_event_type ev;
   8329 
   8330 	/* <event name> [parameters..] */
   8331 
   8332 	wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
   8333 
   8334 	pos = cmd;
   8335 	param = os_strchr(pos, ' ');
   8336 	if (param)
   8337 		*param++ = '\0';
   8338 
   8339 	os_memset(&event, 0, sizeof(event));
   8340 
   8341 	if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
   8342 		ev = EVENT_INTERFACE_ENABLED;
   8343 	} else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
   8344 		ev = EVENT_INTERFACE_DISABLED;
   8345 	} else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
   8346 		ev = EVENT_AVOID_FREQUENCIES;
   8347 		if (param == NULL)
   8348 			param = "";
   8349 		if (freq_range_list_parse(&event.freq_range, param) < 0)
   8350 			return -1;
   8351 		wpa_supplicant_event(wpa_s, ev, &event);
   8352 		os_free(event.freq_range.range);
   8353 		return 0;
   8354 	} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
   8355 		return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
   8356 	} else {
   8357 		wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
   8358 			cmd);
   8359 		return -1;
   8360 	}
   8361 
   8362 	wpa_supplicant_event(wpa_s, ev, &event);
   8363 
   8364 	return 0;
   8365 }
   8366 
   8367 
   8368 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
   8369 {
   8370 	char *pos;
   8371 	u8 src[ETH_ALEN], *buf;
   8372 	int used;
   8373 	size_t len;
   8374 
   8375 	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
   8376 
   8377 	pos = cmd;
   8378 	used = hwaddr_aton2(pos, src);
   8379 	if (used < 0)
   8380 		return -1;
   8381 	pos += used;
   8382 	while (*pos == ' ')
   8383 		pos++;
   8384 
   8385 	len = os_strlen(pos);
   8386 	if (len & 1)
   8387 		return -1;
   8388 	len /= 2;
   8389 
   8390 	buf = os_malloc(len);
   8391 	if (buf == NULL)
   8392 		return -1;
   8393 
   8394 	if (hexstr2bin(pos, buf, len) < 0) {
   8395 		os_free(buf);
   8396 		return -1;
   8397 	}
   8398 
   8399 	wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
   8400 	os_free(buf);
   8401 
   8402 	return 0;
   8403 }
   8404 
   8405 
   8406 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
   8407 {
   8408 	size_t i;
   8409 	u32 sum = 0;
   8410 	const u16 *pos = buf;
   8411 
   8412 	for (i = 0; i < len / 2; i++)
   8413 		sum += *pos++;
   8414 
   8415 	while (sum >> 16)
   8416 		sum = (sum & 0xffff) + (sum >> 16);
   8417 
   8418 	return sum ^ 0xffff;
   8419 }
   8420 
   8421 
   8422 #define HWSIM_PACKETLEN 1500
   8423 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
   8424 
   8425 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
   8426 			      size_t len)
   8427 {
   8428 	struct wpa_supplicant *wpa_s = ctx;
   8429 	const struct ether_header *eth;
   8430 	struct iphdr ip;
   8431 	const u8 *pos;
   8432 	unsigned int i;
   8433 
   8434 	if (len != HWSIM_PACKETLEN)
   8435 		return;
   8436 
   8437 	eth = (const struct ether_header *) buf;
   8438 	os_memcpy(&ip, eth + 1, sizeof(ip));
   8439 	pos = &buf[sizeof(*eth) + sizeof(ip)];
   8440 
   8441 	if (ip.ihl != 5 || ip.version != 4 ||
   8442 	    ntohs(ip.tot_len) != HWSIM_IP_LEN)
   8443 		return;
   8444 
   8445 	for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
   8446 		if (*pos != (u8) i)
   8447 			return;
   8448 		pos++;
   8449 	}
   8450 
   8451 	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
   8452 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
   8453 }
   8454 
   8455 
   8456 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
   8457 					    char *cmd)
   8458 {
   8459 	int enabled = atoi(cmd);
   8460 	char *pos;
   8461 	const char *ifname;
   8462 
   8463 	if (!enabled) {
   8464 		if (wpa_s->l2_test) {
   8465 			l2_packet_deinit(wpa_s->l2_test);
   8466 			wpa_s->l2_test = NULL;
   8467 			wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
   8468 		}
   8469 		return 0;
   8470 	}
   8471 
   8472 	if (wpa_s->l2_test)
   8473 		return 0;
   8474 
   8475 	pos = os_strstr(cmd, " ifname=");
   8476 	if (pos)
   8477 		ifname = pos + 8;
   8478 	else
   8479 		ifname = wpa_s->ifname;
   8480 
   8481 	wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
   8482 					ETHERTYPE_IP, wpas_data_test_rx,
   8483 					wpa_s, 1);
   8484 	if (wpa_s->l2_test == NULL)
   8485 		return -1;
   8486 
   8487 	wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
   8488 
   8489 	return 0;
   8490 }
   8491 
   8492 
   8493 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
   8494 {
   8495 	u8 dst[ETH_ALEN], src[ETH_ALEN];
   8496 	char *pos;
   8497 	int used;
   8498 	long int val;
   8499 	u8 tos;
   8500 	u8 buf[2 + HWSIM_PACKETLEN];
   8501 	struct ether_header *eth;
   8502 	struct iphdr *ip;
   8503 	u8 *dpos;
   8504 	unsigned int i;
   8505 
   8506 	if (wpa_s->l2_test == NULL)
   8507 		return -1;
   8508 
   8509 	/* format: <dst> <src> <tos> */
   8510 
   8511 	pos = cmd;
   8512 	used = hwaddr_aton2(pos, dst);
   8513 	if (used < 0)
   8514 		return -1;
   8515 	pos += used;
   8516 	while (*pos == ' ')
   8517 		pos++;
   8518 	used = hwaddr_aton2(pos, src);
   8519 	if (used < 0)
   8520 		return -1;
   8521 	pos += used;
   8522 
   8523 	val = strtol(pos, NULL, 0);
   8524 	if (val < 0 || val > 0xff)
   8525 		return -1;
   8526 	tos = val;
   8527 
   8528 	eth = (struct ether_header *) &buf[2];
   8529 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
   8530 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
   8531 	eth->ether_type = htons(ETHERTYPE_IP);
   8532 	ip = (struct iphdr *) (eth + 1);
   8533 	os_memset(ip, 0, sizeof(*ip));
   8534 	ip->ihl = 5;
   8535 	ip->version = 4;
   8536 	ip->ttl = 64;
   8537 	ip->tos = tos;
   8538 	ip->tot_len = htons(HWSIM_IP_LEN);
   8539 	ip->protocol = 1;
   8540 	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
   8541 	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
   8542 	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
   8543 	dpos = (u8 *) (ip + 1);
   8544 	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
   8545 		*dpos++ = i;
   8546 
   8547 	if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
   8548 			   HWSIM_PACKETLEN) < 0)
   8549 		return -1;
   8550 
   8551 	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
   8552 		" tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
   8553 
   8554 	return 0;
   8555 }
   8556 
   8557 
   8558 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
   8559 					   char *cmd)
   8560 {
   8561 	u8 *buf;
   8562 	struct ether_header *eth;
   8563 	struct l2_packet_data *l2 = NULL;
   8564 	size_t len;
   8565 	u16 ethertype;
   8566 	int res = -1;
   8567 
   8568 	len = os_strlen(cmd);
   8569 	if (len & 1 || len < ETH_HLEN * 2)
   8570 		return -1;
   8571 	len /= 2;
   8572 
   8573 	buf = os_malloc(len);
   8574 	if (buf == NULL)
   8575 		return -1;
   8576 
   8577 	if (hexstr2bin(cmd, buf, len) < 0)
   8578 		goto done;
   8579 
   8580 	eth = (struct ether_header *) buf;
   8581 	ethertype = ntohs(eth->ether_type);
   8582 
   8583 	l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
   8584 			    wpas_data_test_rx, wpa_s, 1);
   8585 	if (l2 == NULL)
   8586 		goto done;
   8587 
   8588 	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
   8589 	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
   8590 done:
   8591 	if (l2)
   8592 		l2_packet_deinit(l2);
   8593 	os_free(buf);
   8594 
   8595 	return res < 0 ? -1 : 0;
   8596 }
   8597 
   8598 
   8599 static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
   8600 {
   8601 #ifdef WPA_TRACE_BFD
   8602 	char *pos;
   8603 
   8604 	wpa_trace_fail_after = atoi(cmd);
   8605 	pos = os_strchr(cmd, ':');
   8606 	if (pos) {
   8607 		pos++;
   8608 		os_strlcpy(wpa_trace_fail_func, pos,
   8609 			   sizeof(wpa_trace_fail_func));
   8610 	} else {
   8611 		wpa_trace_fail_after = 0;
   8612 	}
   8613 	return 0;
   8614 #else /* WPA_TRACE_BFD */
   8615 	return -1;
   8616 #endif /* WPA_TRACE_BFD */
   8617 }
   8618 
   8619 
   8620 static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
   8621 				    char *buf, size_t buflen)
   8622 {
   8623 #ifdef WPA_TRACE_BFD
   8624 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
   8625 			   wpa_trace_fail_func);
   8626 #else /* WPA_TRACE_BFD */
   8627 	return -1;
   8628 #endif /* WPA_TRACE_BFD */
   8629 }
   8630 
   8631 
   8632 static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
   8633 {
   8634 #ifdef WPA_TRACE_BFD
   8635 	char *pos;
   8636 
   8637 	wpa_trace_test_fail_after = atoi(cmd);
   8638 	pos = os_strchr(cmd, ':');
   8639 	if (pos) {
   8640 		pos++;
   8641 		os_strlcpy(wpa_trace_test_fail_func, pos,
   8642 			   sizeof(wpa_trace_test_fail_func));
   8643 	} else {
   8644 		wpa_trace_test_fail_after = 0;
   8645 	}
   8646 	return 0;
   8647 #else /* WPA_TRACE_BFD */
   8648 	return -1;
   8649 #endif /* WPA_TRACE_BFD */
   8650 }
   8651 
   8652 
   8653 static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
   8654 				    char *buf, size_t buflen)
   8655 {
   8656 #ifdef WPA_TRACE_BFD
   8657 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
   8658 			   wpa_trace_test_fail_func);
   8659 #else /* WPA_TRACE_BFD */
   8660 	return -1;
   8661 #endif /* WPA_TRACE_BFD */
   8662 }
   8663 
   8664 
   8665 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
   8666 {
   8667 	struct wpa_supplicant *wpa_s = eloop_ctx;
   8668 	int i, count = (intptr_t) timeout_ctx;
   8669 
   8670 	wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
   8671 		   count);
   8672 	for (i = 0; i < count; i++) {
   8673 		wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
   8674 			     i + 1, count);
   8675 	}
   8676 }
   8677 
   8678 
   8679 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
   8680 {
   8681 	int count;
   8682 
   8683 	count = atoi(cmd);
   8684 	if (count <= 0)
   8685 		return -1;
   8686 
   8687 	return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
   8688 				      (void *) (intptr_t) count);
   8689 }
   8690 
   8691 
   8692 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
   8693 				   const char *cmd)
   8694 {
   8695 	struct wpabuf *buf;
   8696 	size_t len;
   8697 
   8698 	len = os_strlen(cmd);
   8699 	if (len & 1)
   8700 		return -1;
   8701 	len /= 2;
   8702 
   8703 	if (len == 0) {
   8704 		buf = NULL;
   8705 	} else {
   8706 		buf = wpabuf_alloc(len);
   8707 		if (buf == NULL)
   8708 			return -1;
   8709 
   8710 		if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
   8711 			wpabuf_free(buf);
   8712 			return -1;
   8713 		}
   8714 	}
   8715 
   8716 	wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
   8717 	return 0;
   8718 }
   8719 
   8720 #endif /* CONFIG_TESTING_OPTIONS */
   8721 
   8722 
   8723 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
   8724 {
   8725 	char *pos = cmd;
   8726 	int frame;
   8727 	size_t len;
   8728 	struct wpabuf *buf;
   8729 	struct ieee802_11_elems elems;
   8730 
   8731 	frame = atoi(pos);
   8732 	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
   8733 		return -1;
   8734 	wpa_s = wpas_vendor_elem(wpa_s, frame);
   8735 
   8736 	pos = os_strchr(pos, ' ');
   8737 	if (pos == NULL)
   8738 		return -1;
   8739 	pos++;
   8740 
   8741 	len = os_strlen(pos);
   8742 	if (len == 0)
   8743 		return 0;
   8744 	if (len & 1)
   8745 		return -1;
   8746 	len /= 2;
   8747 
   8748 	buf = wpabuf_alloc(len);
   8749 	if (buf == NULL)
   8750 		return -1;
   8751 
   8752 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
   8753 		wpabuf_free(buf);
   8754 		return -1;
   8755 	}
   8756 
   8757 	if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
   8758 	    ParseFailed) {
   8759 		wpabuf_free(buf);
   8760 		return -1;
   8761 	}
   8762 
   8763 	if (wpa_s->vendor_elem[frame] == NULL) {
   8764 		wpa_s->vendor_elem[frame] = buf;
   8765 		wpas_vendor_elem_update(wpa_s);
   8766 		return 0;
   8767 	}
   8768 
   8769 	if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
   8770 		wpabuf_free(buf);
   8771 		return -1;
   8772 	}
   8773 
   8774 	wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
   8775 	wpabuf_free(buf);
   8776 	wpas_vendor_elem_update(wpa_s);
   8777 
   8778 	return 0;
   8779 }
   8780 
   8781 
   8782 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
   8783 				     char *buf, size_t buflen)
   8784 {
   8785 	int frame = atoi(cmd);
   8786 
   8787 	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
   8788 		return -1;
   8789 	wpa_s = wpas_vendor_elem(wpa_s, frame);
   8790 
   8791 	if (wpa_s->vendor_elem[frame] == NULL)
   8792 		return 0;
   8793 
   8794 	return wpa_snprintf_hex(buf, buflen,
   8795 				wpabuf_head_u8(wpa_s->vendor_elem[frame]),
   8796 				wpabuf_len(wpa_s->vendor_elem[frame]));
   8797 }
   8798 
   8799 
   8800 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
   8801 {
   8802 	char *pos = cmd;
   8803 	int frame;
   8804 	size_t len;
   8805 	u8 *buf;
   8806 	struct ieee802_11_elems elems;
   8807 	int res;
   8808 
   8809 	frame = atoi(pos);
   8810 	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
   8811 		return -1;
   8812 	wpa_s = wpas_vendor_elem(wpa_s, frame);
   8813 
   8814 	pos = os_strchr(pos, ' ');
   8815 	if (pos == NULL)
   8816 		return -1;
   8817 	pos++;
   8818 
   8819 	if (*pos == '*') {
   8820 		wpabuf_free(wpa_s->vendor_elem[frame]);
   8821 		wpa_s->vendor_elem[frame] = NULL;
   8822 		wpas_vendor_elem_update(wpa_s);
   8823 		return 0;
   8824 	}
   8825 
   8826 	if (wpa_s->vendor_elem[frame] == NULL)
   8827 		return -1;
   8828 
   8829 	len = os_strlen(pos);
   8830 	if (len == 0)
   8831 		return 0;
   8832 	if (len & 1)
   8833 		return -1;
   8834 	len /= 2;
   8835 
   8836 	buf = os_malloc(len);
   8837 	if (buf == NULL)
   8838 		return -1;
   8839 
   8840 	if (hexstr2bin(pos, buf, len) < 0) {
   8841 		os_free(buf);
   8842 		return -1;
   8843 	}
   8844 
   8845 	if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
   8846 		os_free(buf);
   8847 		return -1;
   8848 	}
   8849 
   8850 	res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
   8851 	os_free(buf);
   8852 	return res;
   8853 }
   8854 
   8855 
   8856 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
   8857 {
   8858 	struct wpa_supplicant *wpa_s = ctx;
   8859 	size_t len;
   8860 	const u8 *data;
   8861 
   8862 	/*
   8863 	 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
   8864 	 * BSSID[6]
   8865 	 * BSSID Information[4]
   8866 	 * Operating Class[1]
   8867 	 * Channel Number[1]
   8868 	 * PHY Type[1]
   8869 	 * Optional Subelements[variable]
   8870 	 */
   8871 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
   8872 
   8873 	if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
   8874 		wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
   8875 		goto out;
   8876 	}
   8877 
   8878 	data = wpabuf_head_u8(neighbor_rep);
   8879 	len = wpabuf_len(neighbor_rep);
   8880 
   8881 	while (len >= 2 + NR_IE_MIN_LEN) {
   8882 		const u8 *nr;
   8883 		char lci[256 * 2 + 1];
   8884 		char civic[256 * 2 + 1];
   8885 		u8 nr_len = data[1];
   8886 		const u8 *pos = data, *end;
   8887 
   8888 		if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
   8889 		    nr_len < NR_IE_MIN_LEN) {
   8890 			wpa_printf(MSG_DEBUG,
   8891 				   "CTRL: Invalid Neighbor Report element: id=%u len=%u",
   8892 				   data[0], nr_len);
   8893 			goto out;
   8894 		}
   8895 
   8896 		if (2U + nr_len > len) {
   8897 			wpa_printf(MSG_DEBUG,
   8898 				   "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
   8899 				   data[0], len, nr_len);
   8900 			goto out;
   8901 		}
   8902 		pos += 2;
   8903 		end = pos + nr_len;
   8904 
   8905 		nr = pos;
   8906 		pos += NR_IE_MIN_LEN;
   8907 
   8908 		lci[0] = '\0';
   8909 		civic[0] = '\0';
   8910 		while (end - pos > 2) {
   8911 			u8 s_id, s_len;
   8912 
   8913 			s_id = *pos++;
   8914 			s_len = *pos++;
   8915 			if (s_len > end - pos)
   8916 				goto out;
   8917 			if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
   8918 				/* Measurement Token[1] */
   8919 				/* Measurement Report Mode[1] */
   8920 				/* Measurement Type[1] */
   8921 				/* Measurement Report[variable] */
   8922 				switch (pos[2]) {
   8923 				case MEASURE_TYPE_LCI:
   8924 					if (lci[0])
   8925 						break;
   8926 					wpa_snprintf_hex(lci, sizeof(lci),
   8927 							 pos, s_len);
   8928 					break;
   8929 				case MEASURE_TYPE_LOCATION_CIVIC:
   8930 					if (civic[0])
   8931 						break;
   8932 					wpa_snprintf_hex(civic, sizeof(civic),
   8933 							 pos, s_len);
   8934 					break;
   8935 				}
   8936 			}
   8937 
   8938 			pos += s_len;
   8939 		}
   8940 
   8941 		wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
   8942 			"bssid=" MACSTR
   8943 			" info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
   8944 			MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
   8945 			nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
   8946 			nr[ETH_ALEN + 6],
   8947 			lci[0] ? " lci=" : "", lci,
   8948 			civic[0] ? " civic=" : "", civic);
   8949 
   8950 		data = end;
   8951 		len -= 2 + nr_len;
   8952 	}
   8953 
   8954 out:
   8955 	wpabuf_free(neighbor_rep);
   8956 }
   8957 
   8958 
   8959 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
   8960 					     char *cmd)
   8961 {
   8962 	struct wpa_ssid_value ssid, *ssid_p = NULL;
   8963 	int ret, lci = 0, civic = 0;
   8964 	char *ssid_s;
   8965 
   8966 	ssid_s = os_strstr(cmd, "ssid=");
   8967 	if (ssid_s) {
   8968 		if (ssid_parse(ssid_s + 5, &ssid)) {
   8969 			wpa_printf(MSG_ERROR,
   8970 				   "CTRL: Send Neighbor Report: bad SSID");
   8971 			return -1;
   8972 		}
   8973 
   8974 		ssid_p = &ssid;
   8975 
   8976 		/*
   8977 		 * Move cmd after the SSID text that may include "lci" or
   8978 		 * "civic".
   8979 		 */
   8980 		cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
   8981 		if (cmd)
   8982 			cmd++;
   8983 
   8984 	}
   8985 
   8986 	if (cmd && os_strstr(cmd, "lci"))
   8987 		lci = 1;
   8988 
   8989 	if (cmd && os_strstr(cmd, "civic"))
   8990 		civic = 1;
   8991 
   8992 	ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
   8993 						 wpas_ctrl_neighbor_rep_cb,
   8994 						 wpa_s);
   8995 
   8996 	return ret;
   8997 }
   8998 
   8999 
   9000 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
   9001 {
   9002 	eapol_sm_erp_flush(wpa_s->eapol);
   9003 	return 0;
   9004 }
   9005 
   9006 
   9007 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
   9008 					 char *cmd)
   9009 {
   9010 	char *token, *context = NULL;
   9011 	unsigned int enable = ~0, type = 0;
   9012 	u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
   9013 	u8 *addr = NULL, *mask = NULL;
   9014 
   9015 	while ((token = str_token(cmd, " ", &context))) {
   9016 		if (os_strcasecmp(token, "scan") == 0) {
   9017 			type |= MAC_ADDR_RAND_SCAN;
   9018 		} else if (os_strcasecmp(token, "sched") == 0) {
   9019 			type |= MAC_ADDR_RAND_SCHED_SCAN;
   9020 		} else if (os_strcasecmp(token, "pno") == 0) {
   9021 			type |= MAC_ADDR_RAND_PNO;
   9022 		} else if (os_strcasecmp(token, "all") == 0) {
   9023 			type = wpa_s->mac_addr_rand_supported;
   9024 		} else if (os_strncasecmp(token, "enable=", 7) == 0) {
   9025 			enable = atoi(token + 7);
   9026 		} else if (os_strncasecmp(token, "addr=", 5) == 0) {
   9027 			addr = _addr;
   9028 			if (hwaddr_aton(token + 5, addr)) {
   9029 				wpa_printf(MSG_INFO,
   9030 					   "CTRL: Invalid MAC address: %s",
   9031 					   token);
   9032 				return -1;
   9033 			}
   9034 		} else if (os_strncasecmp(token, "mask=", 5) == 0) {
   9035 			mask = _mask;
   9036 			if (hwaddr_aton(token + 5, mask)) {
   9037 				wpa_printf(MSG_INFO,
   9038 					   "CTRL: Invalid MAC address mask: %s",
   9039 					   token);
   9040 				return -1;
   9041 			}
   9042 		} else {
   9043 			wpa_printf(MSG_INFO,
   9044 				   "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
   9045 				   token);
   9046 			return -1;
   9047 		}
   9048 	}
   9049 
   9050 	if (!type) {
   9051 		wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
   9052 		return -1;
   9053 	}
   9054 
   9055 	if ((wpa_s->mac_addr_rand_supported & type) != type) {
   9056 		wpa_printf(MSG_INFO,
   9057 			   "CTRL: MAC_RAND_SCAN types=%u != supported=%u",
   9058 			   type, wpa_s->mac_addr_rand_supported);
   9059 		return -1;
   9060 	}
   9061 
   9062 	if (enable > 1) {
   9063 		wpa_printf(MSG_INFO,
   9064 			   "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
   9065 		return -1;
   9066 	}
   9067 
   9068 	if (!enable) {
   9069 		wpas_mac_addr_rand_scan_clear(wpa_s, type);
   9070 		if (wpa_s->pno) {
   9071 			if (type & MAC_ADDR_RAND_PNO) {
   9072 				wpas_stop_pno(wpa_s);
   9073 				wpas_start_pno(wpa_s);
   9074 			}
   9075 		} else if (wpa_s->sched_scanning &&
   9076 			   (type & MAC_ADDR_RAND_SCHED_SCAN)) {
   9077 			wpas_scan_restart_sched_scan(wpa_s);
   9078 		}
   9079 		return 0;
   9080 	}
   9081 
   9082 	if ((addr && !mask) || (!addr && mask)) {
   9083 		wpa_printf(MSG_INFO,
   9084 			   "CTRL: MAC_RAND_SCAN invalid addr/mask combination");
   9085 		return -1;
   9086 	}
   9087 
   9088 	if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
   9089 		wpa_printf(MSG_INFO,
   9090 			   "CTRL: MAC_RAND_SCAN cannot allow multicast address");
   9091 		return -1;
   9092 	}
   9093 
   9094 	if (type & MAC_ADDR_RAND_SCAN) {
   9095 		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
   9096 					    addr, mask);
   9097 	}
   9098 
   9099 	if (type & MAC_ADDR_RAND_SCHED_SCAN) {
   9100 		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
   9101 					    addr, mask);
   9102 
   9103 		if (wpa_s->sched_scanning && !wpa_s->pno)
   9104 			wpas_scan_restart_sched_scan(wpa_s);
   9105 	}
   9106 
   9107 	if (type & MAC_ADDR_RAND_PNO) {
   9108 		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
   9109 					    addr, mask);
   9110 		if (wpa_s->pno) {
   9111 			wpas_stop_pno(wpa_s);
   9112 			wpas_start_pno(wpa_s);
   9113 		}
   9114 	}
   9115 
   9116 	return 0;
   9117 }
   9118 
   9119 
   9120 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
   9121 				 char *buf, size_t buflen)
   9122 {
   9123 	size_t reply_len;
   9124 
   9125 	reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
   9126 #ifdef CONFIG_AP
   9127 	reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
   9128 					      buflen - reply_len);
   9129 #endif /* CONFIG_AP */
   9130 	return reply_len;
   9131 }
   9132 
   9133 
   9134 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
   9135 {
   9136 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
   9137 #ifdef CONFIG_AP
   9138 	wpas_ap_pmksa_cache_flush(wpa_s);
   9139 #endif /* CONFIG_AP */
   9140 }
   9141 
   9142 
   9143 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
   9144 
   9145 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
   9146 				     const char *cmd, char *buf, size_t buflen)
   9147 {
   9148 	struct rsn_pmksa_cache_entry *entry;
   9149 	struct wpa_ssid *ssid;
   9150 	char *pos, *pos2, *end;
   9151 	int ret;
   9152 	struct os_reltime now;
   9153 
   9154 	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
   9155 	if (!ssid)
   9156 		return -1;
   9157 
   9158 	pos = buf;
   9159 	end = buf + buflen;
   9160 
   9161 	os_get_reltime(&now);
   9162 
   9163 	/*
   9164 	 * Entry format:
   9165 	 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
   9166 	 * <expiration in seconds> <akmp> <opportunistic>
   9167 	 */
   9168 
   9169 	for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
   9170 	     entry = entry->next) {
   9171 		if (entry->network_ctx != ssid)
   9172 			continue;
   9173 
   9174 		pos2 = pos;
   9175 		ret = os_snprintf(pos2, end - pos2, MACSTR " ",
   9176 				  MAC2STR(entry->aa));
   9177 		if (os_snprintf_error(end - pos2, ret))
   9178 			break;
   9179 		pos2 += ret;
   9180 
   9181 		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
   9182 					 PMKID_LEN);
   9183 
   9184 		ret = os_snprintf(pos2, end - pos2, " ");
   9185 		if (os_snprintf_error(end - pos2, ret))
   9186 			break;
   9187 		pos2 += ret;
   9188 
   9189 		pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
   9190 					 entry->pmk_len);
   9191 
   9192 		ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
   9193 				  (int) (entry->reauth_time - now.sec),
   9194 				  (int) (entry->expiration - now.sec),
   9195 				  entry->akmp,
   9196 				  entry->opportunistic);
   9197 		if (os_snprintf_error(end - pos2, ret))
   9198 			break;
   9199 		pos2 += ret;
   9200 
   9201 		ret = os_snprintf(pos2, end - pos2, "\n");
   9202 		if (os_snprintf_error(end - pos2, ret))
   9203 			break;
   9204 		pos2 += ret;
   9205 
   9206 		pos = pos2;
   9207 	}
   9208 
   9209 	return pos - buf;
   9210 }
   9211 
   9212 
   9213 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
   9214 				     char *cmd)
   9215 {
   9216 	struct rsn_pmksa_cache_entry *entry;
   9217 	struct wpa_ssid *ssid;
   9218 	char *pos, *pos2;
   9219 	int ret = -1;
   9220 	struct os_reltime now;
   9221 	int reauth_time = 0, expiration = 0;
   9222 
   9223 	/*
   9224 	 * Entry format:
   9225 	 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
   9226 	 * <expiration in seconds> <akmp> <opportunistic>
   9227 	 */
   9228 
   9229 	ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
   9230 	if (!ssid)
   9231 		return -1;
   9232 
   9233 	pos = os_strchr(cmd, ' ');
   9234 	if (!pos)
   9235 		return -1;
   9236 	pos++;
   9237 
   9238 	entry = os_zalloc(sizeof(*entry));
   9239 	if (!entry)
   9240 		return -1;
   9241 
   9242 	if (hwaddr_aton(pos, entry->aa))
   9243 		goto fail;
   9244 
   9245 	pos = os_strchr(pos, ' ');
   9246 	if (!pos)
   9247 		goto fail;
   9248 	pos++;
   9249 
   9250 	if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
   9251 		goto fail;
   9252 
   9253 	pos = os_strchr(pos, ' ');
   9254 	if (!pos)
   9255 		goto fail;
   9256 	pos++;
   9257 
   9258 	pos2 = os_strchr(pos, ' ');
   9259 	if (!pos2)
   9260 		goto fail;
   9261 	entry->pmk_len = (pos2 - pos) / 2;
   9262 	if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
   9263 	    hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
   9264 		goto fail;
   9265 
   9266 	pos = os_strchr(pos, ' ');
   9267 	if (!pos)
   9268 		goto fail;
   9269 	pos++;
   9270 
   9271 	if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
   9272 		   &entry->akmp, &entry->opportunistic) != 4)
   9273 		goto fail;
   9274 	os_get_reltime(&now);
   9275 	entry->expiration = now.sec + expiration;
   9276 	entry->reauth_time = now.sec + reauth_time;
   9277 
   9278 	entry->network_ctx = ssid;
   9279 
   9280 	wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
   9281 	entry = NULL;
   9282 	ret = 0;
   9283 fail:
   9284 	os_free(entry);
   9285 	return ret;
   9286 }
   9287 
   9288 
   9289 #ifdef CONFIG_MESH
   9290 
   9291 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
   9292 					  const char *cmd, char *buf,
   9293 					  size_t buflen)
   9294 {
   9295 	u8 spa[ETH_ALEN];
   9296 
   9297 	if (!wpa_s->ifmsh)
   9298 		return -1;
   9299 
   9300 	if (os_strcasecmp(cmd, "any") == 0)
   9301 		return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
   9302 
   9303 	if (hwaddr_aton(cmd, spa))
   9304 		return -1;
   9305 
   9306 	return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
   9307 }
   9308 
   9309 
   9310 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
   9311 					  char *cmd)
   9312 {
   9313 	/*
   9314 	 * We do not check mesh interface existance because PMKSA should be
   9315 	 * stored before wpa_s->ifmsh creation to suppress commit message
   9316 	 * creation.
   9317 	 */
   9318 	return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
   9319 }
   9320 
   9321 #endif /* CONFIG_MESH */
   9322 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
   9323 
   9324 
   9325 #ifdef CONFIG_FILS
   9326 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
   9327 					    const char *cmd)
   9328 {
   9329 	struct fils_hlp_req *req;
   9330 	const char *pos;
   9331 
   9332 	/* format: <dst> <packet starting from ethertype> */
   9333 
   9334 	req = os_zalloc(sizeof(*req));
   9335 	if (!req)
   9336 		return -1;
   9337 
   9338 	if (hwaddr_aton(cmd, req->dst))
   9339 		goto fail;
   9340 
   9341 	pos = os_strchr(cmd, ' ');
   9342 	if (!pos)
   9343 		goto fail;
   9344 	pos++;
   9345 	req->pkt = wpabuf_parse_bin(pos);
   9346 	if (!req->pkt)
   9347 		goto fail;
   9348 
   9349 	dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
   9350 	return 0;
   9351 fail:
   9352 	wpabuf_free(req->pkt);
   9353 	os_free(req);
   9354 	return -1;
   9355 }
   9356 #endif /* CONFIG_FILS */
   9357 
   9358 
   9359 static int wpas_ctrl_cmd_debug_level(const char *cmd)
   9360 {
   9361 	if (os_strcmp(cmd, "PING") == 0 ||
   9362 	    os_strncmp(cmd, "BSS ", 4) == 0 ||
   9363 	    os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
   9364 	    os_strncmp(cmd, "STATUS", 6) == 0 ||
   9365 	    os_strncmp(cmd, "STA ", 4) == 0 ||
   9366 	    os_strncmp(cmd, "STA-", 4) == 0)
   9367 		return MSG_EXCESSIVE;
   9368 	return MSG_DEBUG;
   9369 }
   9370 
   9371 
   9372 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
   9373 					 char *buf, size_t *resp_len)
   9374 {
   9375 	char *reply;
   9376 	const int reply_size = 4096;
   9377 	int reply_len;
   9378 
   9379 	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
   9380 	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
   9381 		if (wpa_debug_show_keys)
   9382 			wpa_dbg(wpa_s, MSG_DEBUG,
   9383 				"Control interface command '%s'", buf);
   9384 		else
   9385 			wpa_dbg(wpa_s, MSG_DEBUG,
   9386 				"Control interface command '%s [REMOVED]'",
   9387 				os_strncmp(buf, WPA_CTRL_RSP,
   9388 					   os_strlen(WPA_CTRL_RSP)) == 0 ?
   9389 				WPA_CTRL_RSP : "SET_NETWORK");
   9390 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
   9391 		   os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
   9392 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
   9393 				      (const u8 *) buf, os_strlen(buf));
   9394 	} else {
   9395 		int level = wpas_ctrl_cmd_debug_level(buf);
   9396 		wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
   9397 	}
   9398 
   9399 	reply = os_malloc(reply_size);
   9400 	if (reply == NULL) {
   9401 		*resp_len = 1;
   9402 		return NULL;
   9403 	}
   9404 
   9405 	os_memcpy(reply, "OK\n", 3);
   9406 	reply_len = 3;
   9407 
   9408 	if (os_strcmp(buf, "PING") == 0) {
   9409 		os_memcpy(reply, "PONG\n", 5);
   9410 		reply_len = 5;
   9411 	} else if (os_strcmp(buf, "IFNAME") == 0) {
   9412 		reply_len = os_strlen(wpa_s->ifname);
   9413 		os_memcpy(reply, wpa_s->ifname, reply_len);
   9414 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
   9415 		if (wpa_debug_reopen_file() < 0)
   9416 			reply_len = -1;
   9417 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
   9418 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
   9419 	} else if (os_strcmp(buf, "MIB") == 0) {
   9420 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
   9421 		if (reply_len >= 0) {
   9422 			reply_len += eapol_sm_get_mib(wpa_s->eapol,
   9423 						      reply + reply_len,
   9424 						      reply_size - reply_len);
   9425 		}
   9426 	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
   9427 		reply_len = wpa_supplicant_ctrl_iface_status(
   9428 			wpa_s, buf + 6, reply, reply_size);
   9429 	} else if (os_strcmp(buf, "PMKSA") == 0) {
   9430 		reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
   9431 	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
   9432 		wpas_ctrl_iface_pmksa_flush(wpa_s);
   9433 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
   9434 	} else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
   9435 		reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
   9436 						      reply, reply_size);
   9437 	} else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
   9438 		if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
   9439 			reply_len = -1;
   9440 #ifdef CONFIG_MESH
   9441 	} else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
   9442 		reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
   9443 							   reply, reply_size);
   9444 	} else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
   9445 		if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
   9446 			reply_len = -1;
   9447 #endif /* CONFIG_MESH */
   9448 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
   9449 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
   9450 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
   9451 			reply_len = -1;
   9452 	} else if (os_strncmp(buf, "DUMP", 4) == 0) {
   9453 		reply_len = wpa_config_dump_values(wpa_s->conf,
   9454 						   reply, reply_size);
   9455 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
   9456 		reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
   9457 							  reply, reply_size);
   9458 	} else if (os_strcmp(buf, "LOGON") == 0) {
   9459 		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
   9460 	} else if (os_strcmp(buf, "LOGOFF") == 0) {
   9461 		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
   9462 	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
   9463 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
   9464 			reply_len = -1;
   9465 		else
   9466 			wpas_request_connection(wpa_s);
   9467 	} else if (os_strcmp(buf, "REATTACH") == 0) {
   9468 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
   9469 		    !wpa_s->current_ssid)
   9470 			reply_len = -1;
   9471 		else {
   9472 			wpa_s->reattach = 1;
   9473 			wpas_request_connection(wpa_s);
   9474 		}
   9475 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
   9476 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
   9477 			reply_len = -1;
   9478 		else if (wpa_s->disconnected)
   9479 			wpas_request_connection(wpa_s);
   9480 #ifdef IEEE8021X_EAPOL
   9481 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
   9482 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
   9483 			reply_len = -1;
   9484 #endif /* IEEE8021X_EAPOL */
   9485 #ifdef CONFIG_PEERKEY
   9486 	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
   9487 		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
   9488 			reply_len = -1;
   9489 #endif /* CONFIG_PEERKEY */
   9490 #ifdef CONFIG_IEEE80211R
   9491 	} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
   9492 		if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
   9493 			reply_len = -1;
   9494 #endif /* CONFIG_IEEE80211R */
   9495 #ifdef CONFIG_WPS
   9496 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
   9497 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
   9498 		if (res == -2) {
   9499 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
   9500 			reply_len = 17;
   9501 		} else if (res)
   9502 			reply_len = -1;
   9503 	} else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
   9504 		int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
   9505 		if (res == -2) {
   9506 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
   9507 			reply_len = 17;
   9508 		} else if (res)
   9509 			reply_len = -1;
   9510 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
   9511 		reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
   9512 							      reply,
   9513 							      reply_size);
   9514 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
   9515 		reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
   9516 			wpa_s, buf + 14, reply, reply_size);
   9517 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
   9518 		if (wpas_wps_cancel(wpa_s))
   9519 			reply_len = -1;
   9520 #ifdef CONFIG_WPS_NFC
   9521 	} else if (os_strcmp(buf, "WPS_NFC") == 0) {
   9522 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
   9523 			reply_len = -1;
   9524 	} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
   9525 		if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
   9526 			reply_len = -1;
   9527 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
   9528 		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
   9529 			wpa_s, buf + 21, reply, reply_size);
   9530 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
   9531 		reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
   9532 			wpa_s, buf + 14, reply, reply_size);
   9533 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
   9534 		if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
   9535 							       buf + 17))
   9536 			reply_len = -1;
   9537 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
   9538 		reply_len = wpas_ctrl_nfc_get_handover_req(
   9539 			wpa_s, buf + 21, reply, reply_size);
   9540 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
   9541 		reply_len = wpas_ctrl_nfc_get_handover_sel(
   9542 			wpa_s, buf + 21, reply, reply_size);
   9543 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
   9544 		if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
   9545 			reply_len = -1;
   9546 #endif /* CONFIG_WPS_NFC */
   9547 	} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
   9548 		if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
   9549 			reply_len = -1;
   9550 #ifdef CONFIG_AP
   9551 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
   9552 		reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
   9553 			wpa_s, buf + 11, reply, reply_size);
   9554 #endif /* CONFIG_AP */
   9555 #ifdef CONFIG_WPS_ER
   9556 	} else if (os_strcmp(buf, "WPS_ER_START") == 0) {
   9557 		if (wpas_wps_er_start(wpa_s, NULL))
   9558 			reply_len = -1;
   9559 	} else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
   9560 		if (wpas_wps_er_start(wpa_s, buf + 13))
   9561 			reply_len = -1;
   9562 	} else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
   9563 		wpas_wps_er_stop(wpa_s);
   9564 	} else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
   9565 		if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
   9566 			reply_len = -1;
   9567 	} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
   9568 		int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
   9569 		if (ret == -2) {
   9570 			os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
   9571 			reply_len = 17;
   9572 		} else if (ret == -3) {
   9573 			os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
   9574 			reply_len = 18;
   9575 		} else if (ret == -4) {
   9576 			os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
   9577 			reply_len = 20;
   9578 		} else if (ret)
   9579 			reply_len = -1;
   9580 	} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
   9581 		if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
   9582 			reply_len = -1;
   9583 	} else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
   9584 		if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
   9585 								buf + 18))
   9586 			reply_len = -1;
   9587 	} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
   9588 		if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
   9589 			reply_len = -1;
   9590 #ifdef CONFIG_WPS_NFC
   9591 	} else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
   9592 		reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
   9593 			wpa_s, buf + 24, reply, reply_size);
   9594 #endif /* CONFIG_WPS_NFC */
   9595 #endif /* CONFIG_WPS_ER */
   9596 #endif /* CONFIG_WPS */
   9597 #ifdef CONFIG_IBSS_RSN
   9598 	} else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
   9599 		if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
   9600 			reply_len = -1;
   9601 #endif /* CONFIG_IBSS_RSN */
   9602 #ifdef CONFIG_MESH
   9603 	} else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
   9604 		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
   9605 			wpa_s, buf + 19, reply, reply_size);
   9606 	} else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
   9607 		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
   9608 			wpa_s, "", reply, reply_size);
   9609 	} else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
   9610 		if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
   9611 			reply_len = -1;
   9612 	} else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
   9613 		if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
   9614 								buf + 18))
   9615 			reply_len = -1;
   9616 	} else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
   9617 		if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
   9618 			reply_len = -1;
   9619 	} else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
   9620 		if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
   9621 			reply_len = -1;
   9622 #endif /* CONFIG_MESH */
   9623 #ifdef CONFIG_P2P
   9624 	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
   9625 		if (p2p_ctrl_find(wpa_s, buf + 8))
   9626 			reply_len = -1;
   9627 	} else if (os_strcmp(buf, "P2P_FIND") == 0) {
   9628 		if (p2p_ctrl_find(wpa_s, ""))
   9629 			reply_len = -1;
   9630 	} else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
   9631 		wpas_p2p_stop_find(wpa_s);
   9632 	} else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
   9633 		if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
   9634 			reply_len = -1;
   9635 	} else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
   9636 		if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
   9637 			reply_len = -1;
   9638 	} else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
   9639 		reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
   9640 					     reply_size);
   9641 	} else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
   9642 		if (p2p_ctrl_listen(wpa_s, buf + 11))
   9643 			reply_len = -1;
   9644 	} else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
   9645 		if (p2p_ctrl_listen(wpa_s, ""))
   9646 			reply_len = -1;
   9647 	} else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
   9648 		if (wpas_p2p_group_remove(wpa_s, buf + 17))
   9649 			reply_len = -1;
   9650 	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
   9651 		if (p2p_ctrl_group_add(wpa_s, ""))
   9652 			reply_len = -1;
   9653 	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
   9654 		if (p2p_ctrl_group_add(wpa_s, buf + 14))
   9655 			reply_len = -1;
   9656 	} else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
   9657 		reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
   9658 						  reply_size);
   9659 	} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
   9660 		if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
   9661 			reply_len = -1;
   9662 	} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
   9663 		reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
   9664 	} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
   9665 		reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
   9666 						   reply_size);
   9667 	} else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
   9668 		if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
   9669 			reply_len = -1;
   9670 	} else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
   9671 		if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
   9672 			reply_len = -1;
   9673 	} else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
   9674 		wpas_p2p_sd_service_update(wpa_s);
   9675 	} else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
   9676 		if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
   9677 			reply_len = -1;
   9678 	} else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
   9679 		wpas_p2p_service_flush(wpa_s);
   9680 	} else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
   9681 		if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
   9682 			reply_len = -1;
   9683 	} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
   9684 		if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
   9685 			reply_len = -1;
   9686 	} else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
   9687 		if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
   9688 			reply_len = -1;
   9689 	} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
   9690 		if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
   9691 			reply_len = -1;
   9692 	} else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
   9693 		if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
   9694 			reply_len = -1;
   9695 	} else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
   9696 		reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
   9697 					      reply_size);
   9698 	} else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
   9699 		if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
   9700 			reply_len = -1;
   9701 	} else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
   9702 		p2p_ctrl_flush(wpa_s);
   9703 	} else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
   9704 		if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
   9705 			reply_len = -1;
   9706 	} else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
   9707 		if (wpas_p2p_cancel(wpa_s))
   9708 			reply_len = -1;
   9709 	} else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
   9710 		if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
   9711 			reply_len = -1;
   9712 	} else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
   9713 		if (p2p_ctrl_presence_req(wpa_s, "") < 0)
   9714 			reply_len = -1;
   9715 	} else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
   9716 		if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
   9717 			reply_len = -1;
   9718 	} else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
   9719 		if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
   9720 			reply_len = -1;
   9721 	} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
   9722 		if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
   9723 			reply_len = -1;
   9724 	} else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
   9725 		if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
   9726 			reply_len = -1;
   9727 	} else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
   9728 		if (wpas_p2p_lo_stop(wpa_s))
   9729 			reply_len = -1;
   9730 #endif /* CONFIG_P2P */
   9731 #ifdef CONFIG_WIFI_DISPLAY
   9732 	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
   9733 		if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
   9734 			reply_len = -1;
   9735 	} else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
   9736 		reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
   9737 						     reply, reply_size);
   9738 #endif /* CONFIG_WIFI_DISPLAY */
   9739 #ifdef CONFIG_INTERWORKING
   9740 	} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
   9741 		if (interworking_fetch_anqp(wpa_s) < 0)
   9742 			reply_len = -1;
   9743 	} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
   9744 		interworking_stop_fetch_anqp(wpa_s);
   9745 	} else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
   9746 		if (ctrl_interworking_select(wpa_s, NULL) < 0)
   9747 			reply_len = -1;
   9748 	} else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
   9749 		if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
   9750 			reply_len = -1;
   9751 	} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
   9752 		if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
   9753 			reply_len = -1;
   9754 	} else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
   9755 		int id;
   9756 
   9757 		id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
   9758 		if (id < 0)
   9759 			reply_len = -1;
   9760 		else {
   9761 			reply_len = os_snprintf(reply, reply_size, "%d\n", id);
   9762 			if (os_snprintf_error(reply_size, reply_len))
   9763 				reply_len = -1;
   9764 		}
   9765 	} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
   9766 		if (get_anqp(wpa_s, buf + 9) < 0)
   9767 			reply_len = -1;
   9768 	} else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
   9769 		if (gas_request(wpa_s, buf + 12) < 0)
   9770 			reply_len = -1;
   9771 	} else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
   9772 		reply_len = gas_response_get(wpa_s, buf + 17, reply,
   9773 					     reply_size);
   9774 #endif /* CONFIG_INTERWORKING */
   9775 #ifdef CONFIG_HS20
   9776 	} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
   9777 		if (get_hs20_anqp(wpa_s, buf + 14) < 0)
   9778 			reply_len = -1;
   9779 	} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
   9780 		if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
   9781 			reply_len = -1;
   9782 	} else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
   9783 		if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
   9784 			reply_len = -1;
   9785 	} else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
   9786 		if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
   9787 			reply_len = -1;
   9788 	} else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
   9789 		reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
   9790 	} else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
   9791 		if (del_hs20_icon(wpa_s, buf + 14) < 0)
   9792 			reply_len = -1;
   9793 	} else if (os_strcmp(buf, "FETCH_OSU") == 0) {
   9794 		if (hs20_fetch_osu(wpa_s, 0) < 0)
   9795 			reply_len = -1;
   9796 	} else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
   9797 		if (hs20_fetch_osu(wpa_s, 1) < 0)
   9798 			reply_len = -1;
   9799 	} else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
   9800 		hs20_cancel_fetch_osu(wpa_s);
   9801 #endif /* CONFIG_HS20 */
   9802 	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
   9803 	{
   9804 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
   9805 			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
   9806 			reply_len = -1;
   9807 		else {
   9808 			/*
   9809 			 * Notify response from timeout to allow the control
   9810 			 * interface response to be sent first.
   9811 			 */
   9812 			eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
   9813 					       wpa_s, NULL);
   9814 		}
   9815 	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
   9816 		if (wpa_supplicant_reload_configuration(wpa_s))
   9817 			reply_len = -1;
   9818 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   9819 		wpa_supplicant_terminate_proc(wpa_s->global);
   9820 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
   9821 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
   9822 			reply_len = -1;
   9823 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
   9824 		reply_len = wpa_supplicant_ctrl_iface_blacklist(
   9825 			wpa_s, buf + 9, reply, reply_size);
   9826 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
   9827 		reply_len = wpa_supplicant_ctrl_iface_log_level(
   9828 			wpa_s, buf + 9, reply, reply_size);
   9829 	} else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
   9830 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
   9831 			wpa_s, buf + 14, reply, reply_size);
   9832 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
   9833 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
   9834 			wpa_s, NULL, reply, reply_size);
   9835 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
   9836 		wpas_request_disconnection(wpa_s);
   9837 	} else if (os_strcmp(buf, "SCAN") == 0) {
   9838 		wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
   9839 	} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
   9840 		wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
   9841 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
   9842 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
   9843 			wpa_s, reply, reply_size);
   9844 	} else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
   9845 		if (wpas_abort_ongoing_scan(wpa_s) < 0)
   9846 			reply_len = -1;
   9847 	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
   9848 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
   9849 			reply_len = -1;
   9850 	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
   9851 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
   9852 			reply_len = -1;
   9853 	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
   9854 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
   9855 			reply_len = -1;
   9856 	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
   9857 		reply_len = wpa_supplicant_ctrl_iface_add_network(
   9858 			wpa_s, reply, reply_size);
   9859 	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
   9860 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
   9861 			reply_len = -1;
   9862 	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
   9863 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
   9864 			reply_len = -1;
   9865 	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
   9866 		reply_len = wpa_supplicant_ctrl_iface_get_network(
   9867 			wpa_s, buf + 12, reply, reply_size);
   9868 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
   9869 		if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
   9870 							  wpa_s))
   9871 			reply_len = -1;
   9872 	} else if (os_strcmp(buf, "LIST_CREDS") == 0) {
   9873 		reply_len = wpa_supplicant_ctrl_iface_list_creds(
   9874 			wpa_s, reply, reply_size);
   9875 	} else if (os_strcmp(buf, "ADD_CRED") == 0) {
   9876 		reply_len = wpa_supplicant_ctrl_iface_add_cred(
   9877 			wpa_s, reply, reply_size);
   9878 	} else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
   9879 		if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
   9880 			reply_len = -1;
   9881 	} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
   9882 		if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
   9883 			reply_len = -1;
   9884 	} else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
   9885 		reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
   9886 							       reply,
   9887 							       reply_size);
   9888 #ifndef CONFIG_NO_CONFIG_WRITE
   9889 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
   9890 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
   9891 			reply_len = -1;
   9892 #endif /* CONFIG_NO_CONFIG_WRITE */
   9893 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
   9894 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
   9895 			wpa_s, buf + 15, reply, reply_size);
   9896 	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
   9897 		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
   9898 			reply_len = -1;
   9899 	} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
   9900 		if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
   9901 			reply_len = -1;
   9902 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
   9903 		reply_len = wpa_supplicant_global_iface_list(
   9904 			wpa_s->global, reply, reply_size);
   9905 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
   9906 		reply_len = wpa_supplicant_global_iface_interfaces(
   9907 			wpa_s->global, buf + 10, reply, reply_size);
   9908 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
   9909 		reply_len = wpa_supplicant_ctrl_iface_bss(
   9910 			wpa_s, buf + 4, reply, reply_size);
   9911 #ifdef CONFIG_AP
   9912 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
   9913 		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
   9914 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
   9915 		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
   9916 					      reply_size);
   9917 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
   9918 		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
   9919 						   reply_size);
   9920 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
   9921 		if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
   9922 			reply_len = -1;
   9923 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
   9924 		if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
   9925 			reply_len = -1;
   9926 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
   9927 		if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
   9928 			reply_len = -1;
   9929 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
   9930 		if (wpas_ap_stop_ap(wpa_s))
   9931 			reply_len = -1;
   9932 #endif /* CONFIG_AP */
   9933 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
   9934 		wpas_notify_suspend(wpa_s->global);
   9935 	} else if (os_strcmp(buf, "RESUME") == 0) {
   9936 		wpas_notify_resume(wpa_s->global);
   9937 #ifdef CONFIG_TESTING_OPTIONS
   9938 	} else if (os_strcmp(buf, "DROP_SA") == 0) {
   9939 		wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
   9940 #endif /* CONFIG_TESTING_OPTIONS */
   9941 	} else if (os_strncmp(buf, "ROAM ", 5) == 0) {
   9942 		if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
   9943 			reply_len = -1;
   9944 	} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
   9945 		wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
   9946 	} else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
   9947 		if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
   9948 			reply_len = -1;
   9949 	} else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
   9950 		if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
   9951 							       buf + 17))
   9952 			reply_len = -1;
   9953 	} else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
   9954 		wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
   9955 #ifdef CONFIG_TDLS
   9956 	} else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
   9957 		if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
   9958 			reply_len = -1;
   9959 	} else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
   9960 		if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
   9961 			reply_len = -1;
   9962 	} else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
   9963 		if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
   9964 			reply_len = -1;
   9965 	} else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
   9966 		if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
   9967 							       buf + 17))
   9968 			reply_len = -1;
   9969 	} else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
   9970 		if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
   9971 								      buf + 24))
   9972 			reply_len = -1;
   9973 	} else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
   9974 		reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
   9975 			wpa_s, buf + 17, reply, reply_size);
   9976 #endif /* CONFIG_TDLS */
   9977 	} else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
   9978 		reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
   9979 	} else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
   9980 		if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
   9981 			reply_len = -1;
   9982 	} else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
   9983 		if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
   9984 			reply_len = -1;
   9985 	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
   9986 		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
   9987 						       reply_size);
   9988 	} else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
   9989 		if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
   9990 			reply_len = -1;
   9991 	} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
   9992 		reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
   9993 						       reply_size);
   9994 #ifdef CONFIG_AUTOSCAN
   9995 	} else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
   9996 		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
   9997 			reply_len = -1;
   9998 #endif /* CONFIG_AUTOSCAN */
   9999 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
   10000 		reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
   10001 							 reply_size);
   10002 #ifdef ANDROID
   10003 	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
   10004 		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
   10005 						      reply_size);
   10006 #endif /* ANDROID */
   10007 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
   10008 		reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
   10009 						      reply_size);
   10010 	} else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
   10011 		pmksa_cache_clear_current(wpa_s->wpa);
   10012 		eapol_sm_request_reauth(wpa_s->eapol);
   10013 #ifdef CONFIG_WNM
   10014 	} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
   10015 		if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
   10016 			reply_len = -1;
   10017 	} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
   10018 		if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
   10019 				reply_len = -1;
   10020 #endif /* CONFIG_WNM */
   10021 	} else if (os_strcmp(buf, "FLUSH") == 0) {
   10022 		wpa_supplicant_ctrl_iface_flush(wpa_s);
   10023 	} else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
   10024 		reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
   10025 						 reply_size);
   10026 #ifdef CONFIG_TESTING_OPTIONS
   10027 	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
   10028 		if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
   10029 			reply_len = -1;
   10030 	} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
   10031 		wpas_ctrl_iface_mgmt_tx_done(wpa_s);
   10032 	} else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
   10033 		if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
   10034 			reply_len = -1;
   10035 	} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
   10036 		if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
   10037 			reply_len = -1;
   10038 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
   10039 		if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
   10040 			reply_len = -1;
   10041 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
   10042 		if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
   10043 			reply_len = -1;
   10044 	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
   10045 		if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
   10046 			reply_len = -1;
   10047 	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
   10048 		if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
   10049 			reply_len = -1;
   10050 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
   10051 		if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
   10052 			reply_len = -1;
   10053 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
   10054 		reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
   10055 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
   10056 		if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0)
   10057 			reply_len = -1;
   10058 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
   10059 		reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
   10060 	} else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
   10061 		if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
   10062 			reply_len = -1;
   10063 	} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
   10064 		if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
   10065 			reply_len = -1;
   10066 #endif /* CONFIG_TESTING_OPTIONS */
   10067 	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
   10068 		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
   10069 			reply_len = -1;
   10070 	} else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
   10071 		reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
   10072 						      reply_size);
   10073 	} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
   10074 		if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
   10075 			reply_len = -1;
   10076 	} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
   10077 		if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
   10078 			reply_len = -1;
   10079 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
   10080 		wpas_ctrl_iface_erp_flush(wpa_s);
   10081 	} else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
   10082 		if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
   10083 			reply_len = -1;
   10084 	} else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
   10085 		reply_len = wpas_ctrl_iface_get_pref_freq_list(
   10086 			wpa_s, buf + 19, reply, reply_size);
   10087 #ifdef CONFIG_FILS
   10088 	} else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
   10089 		if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
   10090 			reply_len = -1;
   10091 	} else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
   10092 		wpas_flush_fils_hlp_req(wpa_s);
   10093 #endif /* CONFIG_FILS */
   10094 	} else {
   10095 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   10096 		reply_len = 16;
   10097 	}
   10098 
   10099 	if (reply_len < 0) {
   10100 		os_memcpy(reply, "FAIL\n", 5);
   10101 		reply_len = 5;
   10102 	}
   10103 
   10104 	*resp_len = reply_len;
   10105 	return reply;
   10106 }
   10107 
   10108 
   10109 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
   10110 					   char *cmd)
   10111 {
   10112 	struct wpa_interface iface;
   10113 	char *pos, *extra;
   10114 	struct wpa_supplicant *wpa_s;
   10115 	unsigned int create_iface = 0;
   10116 	u8 mac_addr[ETH_ALEN];
   10117 	enum wpa_driver_if_type type = WPA_IF_STATION;
   10118 
   10119 	/*
   10120 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
   10121 	 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
   10122 	 */
   10123 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
   10124 
   10125 	os_memset(&iface, 0, sizeof(iface));
   10126 
   10127 	do {
   10128 		iface.ifname = pos = cmd;
   10129 		pos = os_strchr(pos, '\t');
   10130 		if (pos)
   10131 			*pos++ = '\0';
   10132 		if (iface.ifname[0] == '\0')
   10133 			return -1;
   10134 		if (pos == NULL)
   10135 			break;
   10136 
   10137 		iface.confname = pos;
   10138 		pos = os_strchr(pos, '\t');
   10139 		if (pos)
   10140 			*pos++ = '\0';
   10141 		if (iface.confname[0] == '\0')
   10142 			iface.confname = NULL;
   10143 		if (pos == NULL)
   10144 			break;
   10145 
   10146 		iface.driver = pos;
   10147 		pos = os_strchr(pos, '\t');
   10148 		if (pos)
   10149 			*pos++ = '\0';
   10150 		if (iface.driver[0] == '\0')
   10151 			iface.driver = NULL;
   10152 		if (pos == NULL)
   10153 			break;
   10154 
   10155 		iface.ctrl_interface = pos;
   10156 		pos = os_strchr(pos, '\t');
   10157 		if (pos)
   10158 			*pos++ = '\0';
   10159 		if (iface.ctrl_interface[0] == '\0')
   10160 			iface.ctrl_interface = NULL;
   10161 		if (pos == NULL)
   10162 			break;
   10163 
   10164 		iface.driver_param = pos;
   10165 		pos = os_strchr(pos, '\t');
   10166 		if (pos)
   10167 			*pos++ = '\0';
   10168 		if (iface.driver_param[0] == '\0')
   10169 			iface.driver_param = NULL;
   10170 		if (pos == NULL)
   10171 			break;
   10172 
   10173 		iface.bridge_ifname = pos;
   10174 		pos = os_strchr(pos, '\t');
   10175 		if (pos)
   10176 			*pos++ = '\0';
   10177 		if (iface.bridge_ifname[0] == '\0')
   10178 			iface.bridge_ifname = NULL;
   10179 		if (pos == NULL)
   10180 			break;
   10181 
   10182 		extra = pos;
   10183 		pos = os_strchr(pos, '\t');
   10184 		if (pos)
   10185 			*pos++ = '\0';
   10186 		if (!extra[0])
   10187 			break;
   10188 
   10189 		if (os_strcmp(extra, "create") == 0) {
   10190 			create_iface = 1;
   10191 			if (!pos)
   10192 				break;
   10193 
   10194 			if (os_strcmp(pos, "sta") == 0) {
   10195 				type = WPA_IF_STATION;
   10196 			} else if (os_strcmp(pos, "ap") == 0) {
   10197 				type = WPA_IF_AP_BSS;
   10198 			} else {
   10199 				wpa_printf(MSG_DEBUG,
   10200 					   "INTERFACE_ADD unsupported interface type: '%s'",
   10201 					   pos);
   10202 				return -1;
   10203 			}
   10204 		} else {
   10205 			wpa_printf(MSG_DEBUG,
   10206 				   "INTERFACE_ADD unsupported extra parameter: '%s'",
   10207 				   extra);
   10208 			return -1;
   10209 		}
   10210 	} while (0);
   10211 
   10212 	if (create_iface) {
   10213 		wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
   10214 			   iface.ifname);
   10215 		if (!global->ifaces)
   10216 			return -1;
   10217 		if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
   10218 				   NULL, NULL, NULL, mac_addr, NULL) < 0) {
   10219 			wpa_printf(MSG_ERROR,
   10220 				   "CTRL_IFACE interface creation failed");
   10221 			return -1;
   10222 		}
   10223 
   10224 		wpa_printf(MSG_DEBUG,
   10225 			   "CTRL_IFACE interface '%s' created with MAC addr: "
   10226 			   MACSTR, iface.ifname, MAC2STR(mac_addr));
   10227 	}
   10228 
   10229 	if (wpa_supplicant_get_iface(global, iface.ifname))
   10230 		goto fail;
   10231 
   10232 	wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
   10233 	if (!wpa_s)
   10234 		goto fail;
   10235 	wpa_s->added_vif = create_iface;
   10236 	return 0;
   10237 
   10238 fail:
   10239 	if (create_iface)
   10240 		wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
   10241 	return -1;
   10242 }
   10243 
   10244 
   10245 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
   10246 					      char *cmd)
   10247 {
   10248 	struct wpa_supplicant *wpa_s;
   10249 	int ret;
   10250 	unsigned int delete_iface;
   10251 
   10252 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
   10253 
   10254 	wpa_s = wpa_supplicant_get_iface(global, cmd);
   10255 	if (wpa_s == NULL)
   10256 		return -1;
   10257 	delete_iface = wpa_s->added_vif;
   10258 	ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
   10259 	if (!ret && delete_iface) {
   10260 		wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
   10261 			   cmd);
   10262 		ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
   10263 	}
   10264 	return ret;
   10265 }
   10266 
   10267 
   10268 static void wpa_free_iface_info(struct wpa_interface_info *iface)
   10269 {
   10270 	struct wpa_interface_info *prev;
   10271 
   10272 	while (iface) {
   10273 		prev = iface;
   10274 		iface = iface->next;
   10275 
   10276 		os_free(prev->ifname);
   10277 		os_free(prev->desc);
   10278 		os_free(prev);
   10279 	}
   10280 }
   10281 
   10282 
   10283 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
   10284 					    char *buf, int len)
   10285 {
   10286 	int i, res;
   10287 	struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
   10288 	char *pos, *end;
   10289 
   10290 	for (i = 0; wpa_drivers[i]; i++) {
   10291 		const struct wpa_driver_ops *drv = wpa_drivers[i];
   10292 		if (drv->get_interfaces == NULL)
   10293 			continue;
   10294 		tmp = drv->get_interfaces(global->drv_priv[i]);
   10295 		if (tmp == NULL)
   10296 			continue;
   10297 
   10298 		if (last == NULL)
   10299 			iface = last = tmp;
   10300 		else
   10301 			last->next = tmp;
   10302 		while (last->next)
   10303 			last = last->next;
   10304 	}
   10305 
   10306 	pos = buf;
   10307 	end = buf + len;
   10308 	for (tmp = iface; tmp; tmp = tmp->next) {
   10309 		res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
   10310 				  tmp->drv_name, tmp->ifname,
   10311 				  tmp->desc ? tmp->desc : "");
   10312 		if (os_snprintf_error(end - pos, res)) {
   10313 			*pos = '\0';
   10314 			break;
   10315 		}
   10316 		pos += res;
   10317 	}
   10318 
   10319 	wpa_free_iface_info(iface);
   10320 
   10321 	return pos - buf;
   10322 }
   10323 
   10324 
   10325 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
   10326 						  const char *input,
   10327 						  char *buf, int len)
   10328 {
   10329 	int res;
   10330 	char *pos, *end;
   10331 	struct wpa_supplicant *wpa_s;
   10332 	int show_ctrl = 0;
   10333 
   10334 	if (input)
   10335 		show_ctrl = !!os_strstr(input, "ctrl");
   10336 
   10337 	wpa_s = global->ifaces;
   10338 	pos = buf;
   10339 	end = buf + len;
   10340 
   10341 	while (wpa_s) {
   10342 		if (show_ctrl)
   10343 			res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
   10344 					  wpa_s->ifname,
   10345 					  wpa_s->conf->ctrl_interface ?
   10346 					  wpa_s->conf->ctrl_interface : "N/A");
   10347 		else
   10348 			res = os_snprintf(pos, end - pos, "%s\n",
   10349 					  wpa_s->ifname);
   10350 
   10351 		if (os_snprintf_error(end - pos, res)) {
   10352 			*pos = '\0';
   10353 			break;
   10354 		}
   10355 		pos += res;
   10356 		wpa_s = wpa_s->next;
   10357 	}
   10358 	return pos - buf;
   10359 }
   10360 
   10361 
   10362 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
   10363 					    const char *ifname,
   10364 					    char *cmd, size_t *resp_len)
   10365 {
   10366 	struct wpa_supplicant *wpa_s;
   10367 
   10368 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
   10369 		if (os_strcmp(ifname, wpa_s->ifname) == 0)
   10370 			break;
   10371 	}
   10372 
   10373 	if (wpa_s == NULL) {
   10374 		char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
   10375 		if (resp)
   10376 			*resp_len = os_strlen(resp);
   10377 		else
   10378 			*resp_len = 1;
   10379 		return resp;
   10380 	}
   10381 
   10382 	return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
   10383 }
   10384 
   10385 
   10386 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
   10387 					       char *buf, size_t *resp_len)
   10388 {
   10389 #ifdef CONFIG_P2P
   10390 	static const char * cmd[] = {
   10391 		"LIST_NETWORKS",
   10392 		"P2P_FIND",
   10393 		"P2P_STOP_FIND",
   10394 		"P2P_LISTEN",
   10395 		"P2P_GROUP_ADD",
   10396 		"P2P_GET_PASSPHRASE",
   10397 		"P2P_SERVICE_UPDATE",
   10398 		"P2P_SERVICE_FLUSH",
   10399 		"P2P_FLUSH",
   10400 		"P2P_CANCEL",
   10401 		"P2P_PRESENCE_REQ",
   10402 		"P2P_EXT_LISTEN",
   10403 #ifdef CONFIG_AP
   10404 		"STA-FIRST",
   10405 #endif /* CONFIG_AP */
   10406 		NULL
   10407 	};
   10408 	static const char * prefix[] = {
   10409 #ifdef ANDROID
   10410 		"DRIVER ",
   10411 #endif /* ANDROID */
   10412 		"GET_NETWORK ",
   10413 		"REMOVE_NETWORK ",
   10414 		"P2P_FIND ",
   10415 		"P2P_CONNECT ",
   10416 		"P2P_LISTEN ",
   10417 		"P2P_GROUP_REMOVE ",
   10418 		"P2P_GROUP_ADD ",
   10419 		"P2P_GROUP_MEMBER ",
   10420 		"P2P_PROV_DISC ",
   10421 		"P2P_SERV_DISC_REQ ",
   10422 		"P2P_SERV_DISC_CANCEL_REQ ",
   10423 		"P2P_SERV_DISC_RESP ",
   10424 		"P2P_SERV_DISC_EXTERNAL ",
   10425 		"P2P_SERVICE_ADD ",
   10426 		"P2P_SERVICE_DEL ",
   10427 		"P2P_SERVICE_REP ",
   10428 		"P2P_REJECT ",
   10429 		"P2P_INVITE ",
   10430 		"P2P_PEER ",
   10431 		"P2P_SET ",
   10432 		"P2P_UNAUTHORIZE ",
   10433 		"P2P_PRESENCE_REQ ",
   10434 		"P2P_EXT_LISTEN ",
   10435 		"P2P_REMOVE_CLIENT ",
   10436 		"WPS_NFC_TOKEN ",
   10437 		"WPS_NFC_TAG_READ ",
   10438 		"NFC_GET_HANDOVER_SEL ",
   10439 		"NFC_GET_HANDOVER_REQ ",
   10440 		"NFC_REPORT_HANDOVER ",
   10441 		"P2P_ASP_PROVISION ",
   10442 		"P2P_ASP_PROVISION_RESP ",
   10443 #ifdef CONFIG_AP
   10444 		"STA ",
   10445 		"STA-NEXT ",
   10446 #endif /* CONFIG_AP */
   10447 		NULL
   10448 	};
   10449 	int found = 0;
   10450 	int i;
   10451 
   10452 	if (global->p2p_init_wpa_s == NULL)
   10453 		return NULL;
   10454 
   10455 	for (i = 0; !found && cmd[i]; i++) {
   10456 		if (os_strcmp(buf, cmd[i]) == 0)
   10457 			found = 1;
   10458 	}
   10459 
   10460 	for (i = 0; !found && prefix[i]; i++) {
   10461 		if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
   10462 			found = 1;
   10463 	}
   10464 
   10465 	if (found)
   10466 		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
   10467 							 buf, resp_len);
   10468 #endif /* CONFIG_P2P */
   10469 	return NULL;
   10470 }
   10471 
   10472 
   10473 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
   10474 					       char *buf, size_t *resp_len)
   10475 {
   10476 #ifdef CONFIG_WIFI_DISPLAY
   10477 	if (global->p2p_init_wpa_s == NULL)
   10478 		return NULL;
   10479 	if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
   10480 	    os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
   10481 		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
   10482 							 buf, resp_len);
   10483 #endif /* CONFIG_WIFI_DISPLAY */
   10484 	return NULL;
   10485 }
   10486 
   10487 
   10488 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
   10489 					   char *buf, size_t *resp_len)
   10490 {
   10491 	char *ret;
   10492 
   10493 	ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
   10494 	if (ret)
   10495 		return ret;
   10496 
   10497 	ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
   10498 	if (ret)
   10499 		return ret;
   10500 
   10501 	return NULL;
   10502 }
   10503 
   10504 
   10505 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
   10506 {
   10507 	char *value;
   10508 
   10509 	value = os_strchr(cmd, ' ');
   10510 	if (value == NULL)
   10511 		return -1;
   10512 	*value++ = '\0';
   10513 
   10514 	wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
   10515 
   10516 #ifdef CONFIG_WIFI_DISPLAY
   10517 	if (os_strcasecmp(cmd, "wifi_display") == 0) {
   10518 		wifi_display_enable(global, !!atoi(value));
   10519 		return 0;
   10520 	}
   10521 #endif /* CONFIG_WIFI_DISPLAY */
   10522 
   10523 	/* Restore cmd to its original value to allow redirection */
   10524 	value[-1] = ' ';
   10525 
   10526 	return -1;
   10527 }
   10528 
   10529 
   10530 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
   10531 					      char *cmd)
   10532 {
   10533 	struct wpa_supplicant *wpa_s[2]; /* src, dst */
   10534 	char *p;
   10535 	unsigned int i;
   10536 
   10537 	/* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
   10538 	 * <variable name> */
   10539 
   10540 	for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
   10541 		p = os_strchr(cmd, ' ');
   10542 		if (p == NULL)
   10543 			return -1;
   10544 		*p = '\0';
   10545 
   10546 		wpa_s[i] = global->ifaces;
   10547 		for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
   10548 			if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
   10549 				break;
   10550 		}
   10551 
   10552 		if (!wpa_s[i]) {
   10553 			wpa_printf(MSG_DEBUG,
   10554 				   "CTRL_IFACE: Could not find iface=%s", cmd);
   10555 			return -1;
   10556 		}
   10557 
   10558 		cmd = p + 1;
   10559 	}
   10560 
   10561 	return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
   10562 }
   10563 
   10564 
   10565 #ifndef CONFIG_NO_CONFIG_WRITE
   10566 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
   10567 {
   10568 	int ret = 0, saved = 0;
   10569 	struct wpa_supplicant *wpa_s;
   10570 
   10571 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
   10572 		if (!wpa_s->conf->update_config) {
   10573 			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
   10574 			continue;
   10575 		}
   10576 
   10577 		if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
   10578 			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
   10579 			ret = 1;
   10580 		} else {
   10581 			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
   10582 			saved++;
   10583 		}
   10584 	}
   10585 
   10586 	if (!saved && !ret) {
   10587 		wpa_dbg(wpa_s, MSG_DEBUG,
   10588 			"CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
   10589 		ret = 1;
   10590 	}
   10591 
   10592 	return ret;
   10593 }
   10594 #endif /* CONFIG_NO_CONFIG_WRITE */
   10595 
   10596 
   10597 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
   10598 					 char *buf, size_t buflen)
   10599 {
   10600 	char *pos, *end;
   10601 	int ret;
   10602 	struct wpa_supplicant *wpa_s;
   10603 
   10604 	pos = buf;
   10605 	end = buf + buflen;
   10606 
   10607 #ifdef CONFIG_P2P
   10608 	if (global->p2p && !global->p2p_disabled) {
   10609 		ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
   10610 				  "\n"
   10611 				  "p2p_state=%s\n",
   10612 				  MAC2STR(global->p2p_dev_addr),
   10613 				  p2p_get_state_txt(global->p2p));
   10614 		if (os_snprintf_error(end - pos, ret))
   10615 			return pos - buf;
   10616 		pos += ret;
   10617 	} else if (global->p2p) {
   10618 		ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
   10619 		if (os_snprintf_error(end - pos, ret))
   10620 			return pos - buf;
   10621 		pos += ret;
   10622 	}
   10623 #endif /* CONFIG_P2P */
   10624 
   10625 #ifdef CONFIG_WIFI_DISPLAY
   10626 	ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
   10627 			  !!global->wifi_display);
   10628 	if (os_snprintf_error(end - pos, ret))
   10629 		return pos - buf;
   10630 	pos += ret;
   10631 #endif /* CONFIG_WIFI_DISPLAY */
   10632 
   10633 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
   10634 		ret = os_snprintf(pos, end - pos, "ifname=%s\n"
   10635 				  "address=" MACSTR "\n",
   10636 				  wpa_s->ifname, MAC2STR(wpa_s->own_addr));
   10637 		if (os_snprintf_error(end - pos, ret))
   10638 			return pos - buf;
   10639 		pos += ret;
   10640 	}
   10641 
   10642 	return pos - buf;
   10643 }
   10644 
   10645 
   10646 #ifdef CONFIG_FST
   10647 
   10648 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
   10649 					     char *cmd, char *buf,
   10650 					     size_t reply_size)
   10651 {
   10652 	char ifname[IFNAMSIZ + 1];
   10653 	struct fst_iface_cfg cfg;
   10654 	struct wpa_supplicant *wpa_s;
   10655 	struct fst_wpa_obj iface_obj;
   10656 
   10657 	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
   10658 		wpa_s = wpa_supplicant_get_iface(global, ifname);
   10659 		if (wpa_s) {
   10660 			if (wpa_s->fst) {
   10661 				wpa_printf(MSG_INFO, "FST: Already attached");
   10662 				return -1;
   10663 			}
   10664 			fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
   10665 			wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
   10666 						&iface_obj, &cfg);
   10667 			if (wpa_s->fst)
   10668 				return os_snprintf(buf, reply_size, "OK\n");
   10669 		}
   10670 	}
   10671 
   10672 	return -1;
   10673 }
   10674 
   10675 
   10676 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
   10677 					     char *cmd, char *buf,
   10678 					     size_t reply_size)
   10679 {
   10680 	char ifname[IFNAMSIZ + 1];
   10681 	struct wpa_supplicant *wpa_s;
   10682 
   10683 	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
   10684 		wpa_s = wpa_supplicant_get_iface(global, ifname);
   10685 		if (wpa_s) {
   10686 			if (!fst_iface_detach(ifname)) {
   10687 				wpa_s->fst = NULL;
   10688 				return os_snprintf(buf, reply_size, "OK\n");
   10689 			}
   10690 		}
   10691 	}
   10692 
   10693 	return -1;
   10694 }
   10695 
   10696 #endif /* CONFIG_FST */
   10697 
   10698 
   10699 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
   10700 						char *buf, size_t *resp_len)
   10701 {
   10702 	char *reply;
   10703 	const int reply_size = 2048;
   10704 	int reply_len;
   10705 	int level = MSG_DEBUG;
   10706 
   10707 	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
   10708 		char *pos = os_strchr(buf + 7, ' ');
   10709 		if (pos) {
   10710 			*pos++ = '\0';
   10711 			return wpas_global_ctrl_iface_ifname(global,
   10712 							     buf + 7, pos,
   10713 							     resp_len);
   10714 		}
   10715 	}
   10716 
   10717 	reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
   10718 	if (reply)
   10719 		return reply;
   10720 
   10721 	if (os_strcmp(buf, "PING") == 0)
   10722 		level = MSG_EXCESSIVE;
   10723 	wpa_hexdump_ascii(level, "RX global ctrl_iface",
   10724 			  (const u8 *) buf, os_strlen(buf));
   10725 
   10726 	reply = os_malloc(reply_size);
   10727 	if (reply == NULL) {
   10728 		*resp_len = 1;
   10729 		return NULL;
   10730 	}
   10731 
   10732 	os_memcpy(reply, "OK\n", 3);
   10733 	reply_len = 3;
   10734 
   10735 	if (os_strcmp(buf, "PING") == 0) {
   10736 		os_memcpy(reply, "PONG\n", 5);
   10737 		reply_len = 5;
   10738 	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
   10739 		if (wpa_supplicant_global_iface_add(global, buf + 14))
   10740 			reply_len = -1;
   10741 	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
   10742 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
   10743 			reply_len = -1;
   10744 	} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
   10745 		reply_len = wpa_supplicant_global_iface_list(
   10746 			global, reply, reply_size);
   10747 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
   10748 		reply_len = wpa_supplicant_global_iface_interfaces(
   10749 			global, buf + 10, reply, reply_size);
   10750 #ifdef CONFIG_FST
   10751 	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
   10752 		reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
   10753 							      reply,
   10754 							      reply_size);
   10755 	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
   10756 		reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
   10757 							      reply,
   10758 							      reply_size);
   10759 	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
   10760 		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
   10761 #endif /* CONFIG_FST */
   10762 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   10763 		wpa_supplicant_terminate_proc(global);
   10764 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
   10765 		wpas_notify_suspend(global);
   10766 	} else if (os_strcmp(buf, "RESUME") == 0) {
   10767 		wpas_notify_resume(global);
   10768 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
   10769 		if (wpas_global_ctrl_iface_set(global, buf + 4)) {
   10770 #ifdef CONFIG_P2P
   10771 			if (global->p2p_init_wpa_s) {
   10772 				os_free(reply);
   10773 				/* Check if P2P redirection would work for this
   10774 				 * command. */
   10775 				return wpa_supplicant_ctrl_iface_process(
   10776 					global->p2p_init_wpa_s,
   10777 					buf, resp_len);
   10778 			}
   10779 #endif /* CONFIG_P2P */
   10780 			reply_len = -1;
   10781 		}
   10782 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
   10783 		if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
   10784 			reply_len = -1;
   10785 #ifndef CONFIG_NO_CONFIG_WRITE
   10786 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
   10787 		if (wpas_global_ctrl_iface_save_config(global))
   10788 			reply_len = -1;
   10789 #endif /* CONFIG_NO_CONFIG_WRITE */
   10790 	} else if (os_strcmp(buf, "STATUS") == 0) {
   10791 		reply_len = wpas_global_ctrl_iface_status(global, reply,
   10792 							  reply_size);
   10793 #ifdef CONFIG_MODULE_TESTS
   10794 	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
   10795 		if (wpas_module_tests() < 0)
   10796 			reply_len = -1;
   10797 #endif /* CONFIG_MODULE_TESTS */
   10798 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
   10799 		if (wpa_debug_reopen_file() < 0)
   10800 			reply_len = -1;
   10801 	} else {
   10802 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   10803 		reply_len = 16;
   10804 	}
   10805 
   10806 	if (reply_len < 0) {
   10807 		os_memcpy(reply, "FAIL\n", 5);
   10808 		reply_len = 5;
   10809 	}
   10810 
   10811 	*resp_len = reply_len;
   10812 	return reply;
   10813 }
   10814