Home | History | Annotate | Download | only in hostapd
      1 /*
      2  * hostapd / UNIX domain socket -based control interface
      3  * Copyright (c) 2004-2018, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "utils/includes.h"
     10 
     11 #ifndef CONFIG_NATIVE_WINDOWS
     12 
     13 #ifdef CONFIG_TESTING_OPTIONS
     14 #include <net/ethernet.h>
     15 #include <netinet/ip.h>
     16 #endif /* CONFIG_TESTING_OPTIONS */
     17 
     18 #include <sys/un.h>
     19 #include <sys/stat.h>
     20 #include <stddef.h>
     21 
     22 #ifdef CONFIG_CTRL_IFACE_UDP
     23 #include <netdb.h>
     24 #endif /* CONFIG_CTRL_IFACE_UDP */
     25 
     26 #include "utils/common.h"
     27 #include "utils/eloop.h"
     28 #include "utils/module_tests.h"
     29 #include "common/version.h"
     30 #include "common/ieee802_11_defs.h"
     31 #include "common/ctrl_iface_common.h"
     32 #ifdef CONFIG_DPP
     33 #include "common/dpp.h"
     34 #endif /* CONFIG_DPP */
     35 #include "common/wpa_ctrl.h"
     36 #include "crypto/tls.h"
     37 #include "drivers/driver.h"
     38 #include "eapol_auth/eapol_auth_sm.h"
     39 #include "radius/radius_client.h"
     40 #include "radius/radius_server.h"
     41 #include "l2_packet/l2_packet.h"
     42 #include "ap/hostapd.h"
     43 #include "ap/ap_config.h"
     44 #include "ap/ieee802_1x.h"
     45 #include "ap/wpa_auth.h"
     46 #include "ap/ieee802_11.h"
     47 #include "ap/sta_info.h"
     48 #include "ap/wps_hostapd.h"
     49 #include "ap/ctrl_iface_ap.h"
     50 #include "ap/ap_drv_ops.h"
     51 #include "ap/hs20.h"
     52 #include "ap/wnm_ap.h"
     53 #include "ap/wpa_auth.h"
     54 #include "ap/beacon.h"
     55 #include "ap/neighbor_db.h"
     56 #include "ap/rrm.h"
     57 #include "ap/dpp_hostapd.h"
     58 #include "wps/wps_defs.h"
     59 #include "wps/wps.h"
     60 #include "fst/fst_ctrl_iface.h"
     61 #include "config_file.h"
     62 #include "ctrl_iface.h"
     63 
     64 
     65 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
     66 
     67 #ifdef CONFIG_CTRL_IFACE_UDP
     68 #define COOKIE_LEN 8
     69 static unsigned char cookie[COOKIE_LEN];
     70 static unsigned char gcookie[COOKIE_LEN];
     71 #define HOSTAPD_CTRL_IFACE_PORT		8877
     72 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT	50
     73 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT		8878
     74 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT	50
     75 #endif /* CONFIG_CTRL_IFACE_UDP */
     76 
     77 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
     78 				    enum wpa_msg_type type,
     79 				    const char *buf, size_t len);
     80 
     81 
     82 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
     83 				     struct sockaddr_storage *from,
     84 				     socklen_t fromlen, const char *input)
     85 {
     86 	return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen, input);
     87 }
     88 
     89 
     90 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
     91 				     struct sockaddr_storage *from,
     92 				     socklen_t fromlen)
     93 {
     94 	return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
     95 }
     96 
     97 
     98 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
     99 				    struct sockaddr_storage *from,
    100 				    socklen_t fromlen,
    101 				    char *level)
    102 {
    103 	return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
    104 }
    105 
    106 
    107 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
    108 				      const char *txtaddr)
    109 {
    110 	u8 addr[ETH_ALEN];
    111 	struct sta_info *sta;
    112 
    113 	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
    114 
    115 	if (hwaddr_aton(txtaddr, addr))
    116 		return -1;
    117 
    118 	sta = ap_get_sta(hapd, addr);
    119 	if (sta)
    120 		return 0;
    121 
    122 	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
    123 		   "notification", MAC2STR(addr));
    124 	sta = ap_sta_add(hapd, addr);
    125 	if (sta == NULL)
    126 		return -1;
    127 
    128 	hostapd_new_assoc_sta(hapd, sta, 0);
    129 	return 0;
    130 }
    131 
    132 
    133 #ifdef CONFIG_IEEE80211W
    134 #ifdef NEED_AP_MLME
    135 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
    136 				       const char *txtaddr)
    137 {
    138 	u8 addr[ETH_ALEN];
    139 	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
    140 
    141 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
    142 
    143 	if (hwaddr_aton(txtaddr, addr) ||
    144 	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
    145 		return -1;
    146 
    147 	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
    148 
    149 	return 0;
    150 }
    151 #endif /* NEED_AP_MLME */
    152 #endif /* CONFIG_IEEE80211W */
    153 
    154 
    155 #ifdef CONFIG_WPS
    156 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
    157 {
    158 	char *pin = os_strchr(txt, ' ');
    159 	char *timeout_txt;
    160 	int timeout;
    161 	u8 addr_buf[ETH_ALEN], *addr = NULL;
    162 	char *pos;
    163 
    164 	if (pin == NULL)
    165 		return -1;
    166 	*pin++ = '\0';
    167 
    168 	timeout_txt = os_strchr(pin, ' ');
    169 	if (timeout_txt) {
    170 		*timeout_txt++ = '\0';
    171 		timeout = atoi(timeout_txt);
    172 		pos = os_strchr(timeout_txt, ' ');
    173 		if (pos) {
    174 			*pos++ = '\0';
    175 			if (hwaddr_aton(pos, addr_buf) == 0)
    176 				addr = addr_buf;
    177 		}
    178 	} else
    179 		timeout = 0;
    180 
    181 	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
    182 }
    183 
    184 
    185 static int hostapd_ctrl_iface_wps_check_pin(
    186 	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
    187 {
    188 	char pin[9];
    189 	size_t len;
    190 	char *pos;
    191 	int ret;
    192 
    193 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
    194 			      (u8 *) cmd, os_strlen(cmd));
    195 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
    196 		if (*pos < '0' || *pos > '9')
    197 			continue;
    198 		pin[len++] = *pos;
    199 		if (len == 9) {
    200 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
    201 			return -1;
    202 		}
    203 	}
    204 	if (len != 4 && len != 8) {
    205 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
    206 		return -1;
    207 	}
    208 	pin[len] = '\0';
    209 
    210 	if (len == 8) {
    211 		unsigned int pin_val;
    212 		pin_val = atoi(pin);
    213 		if (!wps_pin_valid(pin_val)) {
    214 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
    215 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
    216 			if (os_snprintf_error(buflen, ret))
    217 				return -1;
    218 			return ret;
    219 		}
    220 	}
    221 
    222 	ret = os_snprintf(buf, buflen, "%s", pin);
    223 	if (os_snprintf_error(buflen, ret))
    224 		return -1;
    225 
    226 	return ret;
    227 }
    228 
    229 
    230 #ifdef CONFIG_WPS_NFC
    231 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
    232 					       char *pos)
    233 {
    234 	size_t len;
    235 	struct wpabuf *buf;
    236 	int ret;
    237 
    238 	len = os_strlen(pos);
    239 	if (len & 0x01)
    240 		return -1;
    241 	len /= 2;
    242 
    243 	buf = wpabuf_alloc(len);
    244 	if (buf == NULL)
    245 		return -1;
    246 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
    247 		wpabuf_free(buf);
    248 		return -1;
    249 	}
    250 
    251 	ret = hostapd_wps_nfc_tag_read(hapd, buf);
    252 	wpabuf_free(buf);
    253 
    254 	return ret;
    255 }
    256 
    257 
    258 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
    259 						   char *cmd, char *reply,
    260 						   size_t max_len)
    261 {
    262 	int ndef;
    263 	struct wpabuf *buf;
    264 	int res;
    265 
    266 	if (os_strcmp(cmd, "WPS") == 0)
    267 		ndef = 0;
    268 	else if (os_strcmp(cmd, "NDEF") == 0)
    269 		ndef = 1;
    270 	else
    271 		return -1;
    272 
    273 	buf = hostapd_wps_nfc_config_token(hapd, ndef);
    274 	if (buf == NULL)
    275 		return -1;
    276 
    277 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    278 					 wpabuf_len(buf));
    279 	reply[res++] = '\n';
    280 	reply[res] = '\0';
    281 
    282 	wpabuf_free(buf);
    283 
    284 	return res;
    285 }
    286 
    287 
    288 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
    289 						char *reply, size_t max_len,
    290 						int ndef)
    291 {
    292 	struct wpabuf *buf;
    293 	int res;
    294 
    295 	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
    296 	if (buf == NULL)
    297 		return -1;
    298 
    299 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    300 					 wpabuf_len(buf));
    301 	reply[res++] = '\n';
    302 	reply[res] = '\0';
    303 
    304 	wpabuf_free(buf);
    305 
    306 	return res;
    307 }
    308 
    309 
    310 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
    311 					    char *cmd, char *reply,
    312 					    size_t max_len)
    313 {
    314 	if (os_strcmp(cmd, "WPS") == 0)
    315 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    316 							    max_len, 0);
    317 
    318 	if (os_strcmp(cmd, "NDEF") == 0)
    319 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    320 							    max_len, 1);
    321 
    322 	if (os_strcmp(cmd, "enable") == 0)
    323 		return hostapd_wps_nfc_token_enable(hapd);
    324 
    325 	if (os_strcmp(cmd, "disable") == 0) {
    326 		hostapd_wps_nfc_token_disable(hapd);
    327 		return 0;
    328 	}
    329 
    330 	return -1;
    331 }
    332 
    333 
    334 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
    335 						   char *cmd, char *reply,
    336 						   size_t max_len)
    337 {
    338 	struct wpabuf *buf;
    339 	int res;
    340 	char *pos;
    341 	int ndef;
    342 
    343 	pos = os_strchr(cmd, ' ');
    344 	if (pos == NULL)
    345 		return -1;
    346 	*pos++ = '\0';
    347 
    348 	if (os_strcmp(cmd, "WPS") == 0)
    349 		ndef = 0;
    350 	else if (os_strcmp(cmd, "NDEF") == 0)
    351 		ndef = 1;
    352 	else
    353 		return -1;
    354 
    355 	if (os_strcmp(pos, "WPS-CR") == 0)
    356 		buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
    357 	else
    358 		buf = NULL;
    359 	if (buf == NULL)
    360 		return -1;
    361 
    362 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    363 					 wpabuf_len(buf));
    364 	reply[res++] = '\n';
    365 	reply[res] = '\0';
    366 
    367 	wpabuf_free(buf);
    368 
    369 	return res;
    370 }
    371 
    372 
    373 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
    374 						  char *cmd)
    375 {
    376 	size_t len;
    377 	struct wpabuf *req, *sel;
    378 	int ret;
    379 	char *pos, *role, *type, *pos2;
    380 
    381 	role = cmd;
    382 	pos = os_strchr(role, ' ');
    383 	if (pos == NULL)
    384 		return -1;
    385 	*pos++ = '\0';
    386 
    387 	type = pos;
    388 	pos = os_strchr(type, ' ');
    389 	if (pos == NULL)
    390 		return -1;
    391 	*pos++ = '\0';
    392 
    393 	pos2 = os_strchr(pos, ' ');
    394 	if (pos2 == NULL)
    395 		return -1;
    396 	*pos2++ = '\0';
    397 
    398 	len = os_strlen(pos);
    399 	if (len & 0x01)
    400 		return -1;
    401 	len /= 2;
    402 
    403 	req = wpabuf_alloc(len);
    404 	if (req == NULL)
    405 		return -1;
    406 	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
    407 		wpabuf_free(req);
    408 		return -1;
    409 	}
    410 
    411 	len = os_strlen(pos2);
    412 	if (len & 0x01) {
    413 		wpabuf_free(req);
    414 		return -1;
    415 	}
    416 	len /= 2;
    417 
    418 	sel = wpabuf_alloc(len);
    419 	if (sel == NULL) {
    420 		wpabuf_free(req);
    421 		return -1;
    422 	}
    423 	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
    424 		wpabuf_free(req);
    425 		wpabuf_free(sel);
    426 		return -1;
    427 	}
    428 
    429 	if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
    430 		ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
    431 	} else {
    432 		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
    433 			   "reported: role=%s type=%s", role, type);
    434 		ret = -1;
    435 	}
    436 	wpabuf_free(req);
    437 	wpabuf_free(sel);
    438 
    439 	return ret;
    440 }
    441 
    442 #endif /* CONFIG_WPS_NFC */
    443 
    444 
    445 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
    446 					 char *buf, size_t buflen)
    447 {
    448 	int timeout = 300;
    449 	char *pos;
    450 	const char *pin_txt;
    451 
    452 	pos = os_strchr(txt, ' ');
    453 	if (pos)
    454 		*pos++ = '\0';
    455 
    456 	if (os_strcmp(txt, "disable") == 0) {
    457 		hostapd_wps_ap_pin_disable(hapd);
    458 		return os_snprintf(buf, buflen, "OK\n");
    459 	}
    460 
    461 	if (os_strcmp(txt, "random") == 0) {
    462 		if (pos)
    463 			timeout = atoi(pos);
    464 		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
    465 		if (pin_txt == NULL)
    466 			return -1;
    467 		return os_snprintf(buf, buflen, "%s", pin_txt);
    468 	}
    469 
    470 	if (os_strcmp(txt, "get") == 0) {
    471 		pin_txt = hostapd_wps_ap_pin_get(hapd);
    472 		if (pin_txt == NULL)
    473 			return -1;
    474 		return os_snprintf(buf, buflen, "%s", pin_txt);
    475 	}
    476 
    477 	if (os_strcmp(txt, "set") == 0) {
    478 		char *pin;
    479 		if (pos == NULL)
    480 			return -1;
    481 		pin = pos;
    482 		pos = os_strchr(pos, ' ');
    483 		if (pos) {
    484 			*pos++ = '\0';
    485 			timeout = atoi(pos);
    486 		}
    487 		if (os_strlen(pin) > buflen)
    488 			return -1;
    489 		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
    490 			return -1;
    491 		return os_snprintf(buf, buflen, "%s", pin);
    492 	}
    493 
    494 	return -1;
    495 }
    496 
    497 
    498 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
    499 {
    500 	char *pos;
    501 	char *ssid, *auth, *encr = NULL, *key = NULL;
    502 
    503 	ssid = txt;
    504 	pos = os_strchr(txt, ' ');
    505 	if (!pos)
    506 		return -1;
    507 	*pos++ = '\0';
    508 
    509 	auth = pos;
    510 	pos = os_strchr(pos, ' ');
    511 	if (pos) {
    512 		*pos++ = '\0';
    513 		encr = pos;
    514 		pos = os_strchr(pos, ' ');
    515 		if (pos) {
    516 			*pos++ = '\0';
    517 			key = pos;
    518 		}
    519 	}
    520 
    521 	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
    522 }
    523 
    524 
    525 static const char * pbc_status_str(enum pbc_status status)
    526 {
    527 	switch (status) {
    528 	case WPS_PBC_STATUS_DISABLE:
    529 		return "Disabled";
    530 	case WPS_PBC_STATUS_ACTIVE:
    531 		return "Active";
    532 	case WPS_PBC_STATUS_TIMEOUT:
    533 		return "Timed-out";
    534 	case WPS_PBC_STATUS_OVERLAP:
    535 		return "Overlap";
    536 	default:
    537 		return "Unknown";
    538 	}
    539 }
    540 
    541 
    542 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
    543 					     char *buf, size_t buflen)
    544 {
    545 	int ret;
    546 	char *pos, *end;
    547 
    548 	pos = buf;
    549 	end = buf + buflen;
    550 
    551 	ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
    552 			  pbc_status_str(hapd->wps_stats.pbc_status));
    553 
    554 	if (os_snprintf_error(end - pos, ret))
    555 		return pos - buf;
    556 	pos += ret;
    557 
    558 	ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
    559 			  (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
    560 			   "Success":
    561 			   (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
    562 			    "Failed" : "None")));
    563 
    564 	if (os_snprintf_error(end - pos, ret))
    565 		return pos - buf;
    566 	pos += ret;
    567 
    568 	/* If status == Failure - Add possible Reasons */
    569 	if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
    570 	   hapd->wps_stats.failure_reason > 0) {
    571 		ret = os_snprintf(pos, end - pos,
    572 				  "Failure Reason: %s\n",
    573 				  wps_ei_str(hapd->wps_stats.failure_reason));
    574 
    575 		if (os_snprintf_error(end - pos, ret))
    576 			return pos - buf;
    577 		pos += ret;
    578 	}
    579 
    580 	if (hapd->wps_stats.status) {
    581 		ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
    582 				  MAC2STR(hapd->wps_stats.peer_addr));
    583 
    584 		if (os_snprintf_error(end - pos, ret))
    585 			return pos - buf;
    586 		pos += ret;
    587 	}
    588 
    589 	return pos - buf;
    590 }
    591 
    592 #endif /* CONFIG_WPS */
    593 
    594 #ifdef CONFIG_HS20
    595 
    596 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
    597 					     const char *cmd)
    598 {
    599 	u8 addr[ETH_ALEN];
    600 	const char *url;
    601 
    602 	if (hwaddr_aton(cmd, addr))
    603 		return -1;
    604 	url = cmd + 17;
    605 	if (*url == '\0') {
    606 		url = NULL;
    607 	} else {
    608 		if (*url != ' ')
    609 			return -1;
    610 		url++;
    611 		if (*url == '\0')
    612 			url = NULL;
    613 	}
    614 
    615 	return hs20_send_wnm_notification(hapd, addr, 1, url);
    616 }
    617 
    618 
    619 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
    620 					      const char *cmd)
    621 {
    622 	u8 addr[ETH_ALEN];
    623 	int code, reauth_delay, ret;
    624 	const char *pos;
    625 	size_t url_len;
    626 	struct wpabuf *req;
    627 
    628 	/* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
    629 	if (hwaddr_aton(cmd, addr))
    630 		return -1;
    631 
    632 	pos = os_strchr(cmd, ' ');
    633 	if (pos == NULL)
    634 		return -1;
    635 	pos++;
    636 	code = atoi(pos);
    637 
    638 	pos = os_strchr(pos, ' ');
    639 	if (pos == NULL)
    640 		return -1;
    641 	pos++;
    642 	reauth_delay = atoi(pos);
    643 
    644 	url_len = 0;
    645 	pos = os_strchr(pos, ' ');
    646 	if (pos) {
    647 		pos++;
    648 		url_len = os_strlen(pos);
    649 	}
    650 
    651 	req = wpabuf_alloc(4 + url_len);
    652 	if (req == NULL)
    653 		return -1;
    654 	wpabuf_put_u8(req, code);
    655 	wpabuf_put_le16(req, reauth_delay);
    656 	wpabuf_put_u8(req, url_len);
    657 	if (pos)
    658 		wpabuf_put_data(req, pos, url_len);
    659 
    660 	wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
    661 		   " to indicate imminent deauthentication (code=%d "
    662 		   "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
    663 	ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
    664 	wpabuf_free(req);
    665 	return ret;
    666 }
    667 
    668 #endif /* CONFIG_HS20 */
    669 
    670 
    671 #ifdef CONFIG_INTERWORKING
    672 
    673 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
    674 					      const char *cmd)
    675 {
    676 	u8 qos_map_set[16 + 2 * 21], count = 0;
    677 	const char *pos = cmd;
    678 	int val, ret;
    679 
    680 	for (;;) {
    681 		if (count == sizeof(qos_map_set)) {
    682 			wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
    683 			return -1;
    684 		}
    685 
    686 		val = atoi(pos);
    687 		if (val < 0 || val > 255) {
    688 			wpa_printf(MSG_INFO, "Invalid QoS Map Set");
    689 			return -1;
    690 		}
    691 
    692 		qos_map_set[count++] = val;
    693 		pos = os_strchr(pos, ',');
    694 		if (!pos)
    695 			break;
    696 		pos++;
    697 	}
    698 
    699 	if (count < 16 || count & 1) {
    700 		wpa_printf(MSG_INFO, "Invalid QoS Map Set");
    701 		return -1;
    702 	}
    703 
    704 	ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
    705 	if (ret) {
    706 		wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
    707 		return -1;
    708 	}
    709 
    710 	os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
    711 	hapd->conf->qos_map_set_len = count;
    712 
    713 	return 0;
    714 }
    715 
    716 
    717 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
    718 						const char *cmd)
    719 {
    720 	u8 addr[ETH_ALEN];
    721 	struct sta_info *sta;
    722 	struct wpabuf *buf;
    723 	u8 *qos_map_set = hapd->conf->qos_map_set;
    724 	u8 qos_map_set_len = hapd->conf->qos_map_set_len;
    725 	int ret;
    726 
    727 	if (!qos_map_set_len) {
    728 		wpa_printf(MSG_INFO, "QoS Map Set is not set");
    729 		return -1;
    730 	}
    731 
    732 	if (hwaddr_aton(cmd, addr))
    733 		return -1;
    734 
    735 	sta = ap_get_sta(hapd, addr);
    736 	if (sta == NULL) {
    737 		wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
    738 			   "for QoS Map Configuration message",
    739 			   MAC2STR(addr));
    740 		return -1;
    741 	}
    742 
    743 	if (!sta->qos_map_enabled) {
    744 		wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
    745 			   "support for QoS Map", MAC2STR(addr));
    746 		return -1;
    747 	}
    748 
    749 	buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
    750 	if (buf == NULL)
    751 		return -1;
    752 
    753 	wpabuf_put_u8(buf, WLAN_ACTION_QOS);
    754 	wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
    755 
    756 	/* QoS Map Set Element */
    757 	wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
    758 	wpabuf_put_u8(buf, qos_map_set_len);
    759 	wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
    760 
    761 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
    762 				      wpabuf_head(buf), wpabuf_len(buf));
    763 	wpabuf_free(buf);
    764 
    765 	return ret;
    766 }
    767 
    768 #endif /* CONFIG_INTERWORKING */
    769 
    770 
    771 #ifdef CONFIG_WNM_AP
    772 
    773 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
    774 						const char *cmd)
    775 {
    776 	u8 addr[ETH_ALEN];
    777 	int disassoc_timer;
    778 	struct sta_info *sta;
    779 
    780 	if (hwaddr_aton(cmd, addr))
    781 		return -1;
    782 	if (cmd[17] != ' ')
    783 		return -1;
    784 	disassoc_timer = atoi(cmd + 17);
    785 
    786 	sta = ap_get_sta(hapd, addr);
    787 	if (sta == NULL) {
    788 		wpa_printf(MSG_DEBUG, "Station " MACSTR
    789 			   " not found for disassociation imminent message",
    790 			   MAC2STR(addr));
    791 		return -1;
    792 	}
    793 
    794 	return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
    795 }
    796 
    797 
    798 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
    799 					   const char *cmd)
    800 {
    801 	u8 addr[ETH_ALEN];
    802 	const char *url, *timerstr;
    803 	int disassoc_timer;
    804 	struct sta_info *sta;
    805 
    806 	if (hwaddr_aton(cmd, addr))
    807 		return -1;
    808 
    809 	sta = ap_get_sta(hapd, addr);
    810 	if (sta == NULL) {
    811 		wpa_printf(MSG_DEBUG, "Station " MACSTR
    812 			   " not found for ESS disassociation imminent message",
    813 			   MAC2STR(addr));
    814 		return -1;
    815 	}
    816 
    817 	timerstr = cmd + 17;
    818 	if (*timerstr != ' ')
    819 		return -1;
    820 	timerstr++;
    821 	disassoc_timer = atoi(timerstr);
    822 	if (disassoc_timer < 0 || disassoc_timer > 65535)
    823 		return -1;
    824 
    825 	url = os_strchr(timerstr, ' ');
    826 	if (url == NULL)
    827 		return -1;
    828 	url++;
    829 
    830 	return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
    831 }
    832 
    833 
    834 static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
    835 					 const char *cmd)
    836 {
    837 	u8 addr[ETH_ALEN];
    838 	const char *pos, *end;
    839 	int disassoc_timer = 0;
    840 	struct sta_info *sta;
    841 	u8 req_mode = 0, valid_int = 0x01;
    842 	u8 bss_term_dur[12];
    843 	char *url = NULL;
    844 	int ret;
    845 	u8 nei_rep[1000];
    846 	int nei_len;
    847 	u8 mbo[10];
    848 	size_t mbo_len = 0;
    849 
    850 	if (hwaddr_aton(cmd, addr)) {
    851 		wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
    852 		return -1;
    853 	}
    854 
    855 	sta = ap_get_sta(hapd, addr);
    856 	if (sta == NULL) {
    857 		wpa_printf(MSG_DEBUG, "Station " MACSTR
    858 			   " not found for BSS TM Request message",
    859 			   MAC2STR(addr));
    860 		return -1;
    861 	}
    862 
    863 	pos = os_strstr(cmd, " disassoc_timer=");
    864 	if (pos) {
    865 		pos += 16;
    866 		disassoc_timer = atoi(pos);
    867 		if (disassoc_timer < 0 || disassoc_timer > 65535) {
    868 			wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
    869 			return -1;
    870 		}
    871 	}
    872 
    873 	pos = os_strstr(cmd, " valid_int=");
    874 	if (pos) {
    875 		pos += 11;
    876 		valid_int = atoi(pos);
    877 	}
    878 
    879 	pos = os_strstr(cmd, " bss_term=");
    880 	if (pos) {
    881 		pos += 10;
    882 		req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
    883 		/* TODO: TSF configurable/learnable */
    884 		bss_term_dur[0] = 4; /* Subelement ID */
    885 		bss_term_dur[1] = 10; /* Length */
    886 		os_memset(&bss_term_dur[2], 0, 8);
    887 		end = os_strchr(pos, ',');
    888 		if (end == NULL) {
    889 			wpa_printf(MSG_DEBUG, "Invalid bss_term data");
    890 			return -1;
    891 		}
    892 		end++;
    893 		WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
    894 	}
    895 
    896 	nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep,
    897 						  sizeof(nei_rep));
    898 	if (nei_len < 0)
    899 		return -1;
    900 
    901 	pos = os_strstr(cmd, " url=");
    902 	if (pos) {
    903 		size_t len;
    904 		pos += 5;
    905 		end = os_strchr(pos, ' ');
    906 		if (end)
    907 			len = end - pos;
    908 		else
    909 			len = os_strlen(pos);
    910 		url = os_malloc(len + 1);
    911 		if (url == NULL)
    912 			return -1;
    913 		os_memcpy(url, pos, len);
    914 		url[len] = '\0';
    915 		req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
    916 	}
    917 
    918 	if (os_strstr(cmd, " pref=1"))
    919 		req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
    920 	if (os_strstr(cmd, " abridged=1"))
    921 		req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
    922 	if (os_strstr(cmd, " disassoc_imminent=1"))
    923 		req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
    924 
    925 #ifdef CONFIG_MBO
    926 	pos = os_strstr(cmd, "mbo=");
    927 	if (pos) {
    928 		unsigned int mbo_reason, cell_pref, reassoc_delay;
    929 		u8 *mbo_pos = mbo;
    930 
    931 		ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
    932 			     &reassoc_delay, &cell_pref);
    933 		if (ret != 3) {
    934 			wpa_printf(MSG_DEBUG,
    935 				   "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
    936 			ret = -1;
    937 			goto fail;
    938 		}
    939 
    940 		if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
    941 			wpa_printf(MSG_DEBUG,
    942 				   "Invalid MBO transition reason code %u",
    943 				   mbo_reason);
    944 			ret = -1;
    945 			goto fail;
    946 		}
    947 
    948 		/* Valid values for Cellular preference are: 0, 1, 255 */
    949 		if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
    950 			wpa_printf(MSG_DEBUG,
    951 				   "Invalid MBO cellular capability %u",
    952 				   cell_pref);
    953 			ret = -1;
    954 			goto fail;
    955 		}
    956 
    957 		if (reassoc_delay > 65535 ||
    958 		    (reassoc_delay &&
    959 		     !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
    960 			wpa_printf(MSG_DEBUG,
    961 				   "MBO: Assoc retry delay is only valid in disassoc imminent mode");
    962 			ret = -1;
    963 			goto fail;
    964 		}
    965 
    966 		*mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
    967 		*mbo_pos++ = 1;
    968 		*mbo_pos++ = mbo_reason;
    969 		*mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
    970 		*mbo_pos++ = 1;
    971 		*mbo_pos++ = cell_pref;
    972 
    973 		if (reassoc_delay) {
    974 			*mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
    975 			*mbo_pos++ = 2;
    976 			WPA_PUT_LE16(mbo_pos, reassoc_delay);
    977 			mbo_pos += 2;
    978 		}
    979 
    980 		mbo_len = mbo_pos - mbo;
    981 	}
    982 #endif /* CONFIG_MBO */
    983 
    984 	ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
    985 				  valid_int, bss_term_dur, url,
    986 				  nei_len ? nei_rep : NULL, nei_len,
    987 				  mbo_len ? mbo : NULL, mbo_len);
    988 #ifdef CONFIG_MBO
    989 fail:
    990 #endif /* CONFIG_MBO */
    991 	os_free(url);
    992 	return ret;
    993 }
    994 
    995 
    996 static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd,
    997 					     const char *cmd)
    998 {
    999 	u8 addr[ETH_ALEN];
   1000 	struct sta_info *sta;
   1001 	const char *pos;
   1002 	unsigned int auto_report, timeout;
   1003 
   1004 	if (hwaddr_aton(cmd, addr)) {
   1005 		wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
   1006 		return -1;
   1007 	}
   1008 
   1009 	sta = ap_get_sta(hapd, addr);
   1010 	if (!sta) {
   1011 		wpa_printf(MSG_DEBUG, "Station " MACSTR
   1012 			   " not found for Collocated Interference Request",
   1013 			   MAC2STR(addr));
   1014 		return -1;
   1015 	}
   1016 
   1017 	pos = cmd + 17;
   1018 	if (*pos != ' ')
   1019 		return -1;
   1020 	pos++;
   1021 	auto_report = atoi(pos);
   1022 	pos = os_strchr(pos, ' ');
   1023 	if (!pos)
   1024 		return -1;
   1025 	pos++;
   1026 	timeout = atoi(pos);
   1027 
   1028 	return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout);
   1029 }
   1030 
   1031 #endif /* CONFIG_WNM_AP */
   1032 
   1033 
   1034 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
   1035 					   char *buf, size_t buflen)
   1036 {
   1037 	int ret = 0;
   1038 	char *pos, *end;
   1039 
   1040 	pos = buf;
   1041 	end = buf + buflen;
   1042 
   1043 	WPA_ASSERT(hapd->conf->wpa_key_mgmt);
   1044 
   1045 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
   1046 		ret = os_snprintf(pos, end - pos, "WPA-PSK ");
   1047 		if (os_snprintf_error(end - pos, ret))
   1048 			return pos - buf;
   1049 		pos += ret;
   1050 	}
   1051 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
   1052 		ret = os_snprintf(pos, end - pos, "WPA-EAP ");
   1053 		if (os_snprintf_error(end - pos, ret))
   1054 			return pos - buf;
   1055 		pos += ret;
   1056 	}
   1057 #ifdef CONFIG_IEEE80211R_AP
   1058 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
   1059 		ret = os_snprintf(pos, end - pos, "FT-PSK ");
   1060 		if (os_snprintf_error(end - pos, ret))
   1061 			return pos - buf;
   1062 		pos += ret;
   1063 	}
   1064 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
   1065 		ret = os_snprintf(pos, end - pos, "FT-EAP ");
   1066 		if (os_snprintf_error(end - pos, ret))
   1067 			return pos - buf;
   1068 		pos += ret;
   1069 	}
   1070 #ifdef CONFIG_SHA384
   1071 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
   1072 		ret = os_snprintf(pos, end - pos, "FT-EAP-SHA384 ");
   1073 		if (os_snprintf_error(end - pos, ret))
   1074 			return pos - buf;
   1075 		pos += ret;
   1076 	}
   1077 #endif /* CONFIG_SHA384 */
   1078 #ifdef CONFIG_SAE
   1079 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
   1080 		ret = os_snprintf(pos, end - pos, "FT-SAE ");
   1081 		if (os_snprintf_error(end - pos, ret))
   1082 			return pos - buf;
   1083 		pos += ret;
   1084 	}
   1085 #endif /* CONFIG_SAE */
   1086 #ifdef CONFIG_FILS
   1087 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
   1088 		ret = os_snprintf(pos, end - pos, "FT-FILS-SHA256 ");
   1089 		if (os_snprintf_error(end - pos, ret))
   1090 			return pos - buf;
   1091 		pos += ret;
   1092 	}
   1093 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
   1094 		ret = os_snprintf(pos, end - pos, "FT-FILS-SHA384 ");
   1095 		if (os_snprintf_error(end - pos, ret))
   1096 			return pos - buf;
   1097 		pos += ret;
   1098 	}
   1099 #endif /* CONFIG_FILS */
   1100 #endif /* CONFIG_IEEE80211R_AP */
   1101 #ifdef CONFIG_IEEE80211W
   1102 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
   1103 		ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
   1104 		if (os_snprintf_error(end - pos, ret))
   1105 			return pos - buf;
   1106 		pos += ret;
   1107 	}
   1108 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
   1109 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
   1110 		if (os_snprintf_error(end - pos, ret))
   1111 			return pos - buf;
   1112 		pos += ret;
   1113 	}
   1114 #endif /* CONFIG_IEEE80211W */
   1115 #ifdef CONFIG_SAE
   1116 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
   1117 		ret = os_snprintf(pos, end - pos, "SAE ");
   1118 		if (os_snprintf_error(end - pos, ret))
   1119 			return pos - buf;
   1120 		pos += ret;
   1121 	}
   1122 #endif /* CONFIG_SAE */
   1123 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
   1124 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
   1125 		if (os_snprintf_error(end - pos, ret))
   1126 			return pos - buf;
   1127 		pos += ret;
   1128 	}
   1129 	if (hapd->conf->wpa_key_mgmt &
   1130 	    WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
   1131 		ret = os_snprintf(pos, end - pos,
   1132 				  "WPA-EAP-SUITE-B-192 ");
   1133 		if (os_snprintf_error(end - pos, ret))
   1134 			return pos - buf;
   1135 		pos += ret;
   1136 	}
   1137 #ifdef CONFIG_FILS
   1138 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
   1139 		ret = os_snprintf(pos, end - pos, "FILS-SHA256 ");
   1140 		if (os_snprintf_error(end - pos, ret))
   1141 			return pos - buf;
   1142 		pos += ret;
   1143 	}
   1144 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
   1145 		ret = os_snprintf(pos, end - pos, "FILS-SHA384 ");
   1146 		if (os_snprintf_error(end - pos, ret))
   1147 			return pos - buf;
   1148 		pos += ret;
   1149 	}
   1150 #endif /* CONFIG_FILS */
   1151 
   1152 #ifdef CONFIG_OWE
   1153 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) {
   1154 		ret = os_snprintf(pos, end - pos, "OWE ");
   1155 		if (os_snprintf_error(end - pos, ret))
   1156 			return pos - buf;
   1157 		pos += ret;
   1158 	}
   1159 #endif /* CONFIG_OWE */
   1160 
   1161 #ifdef CONFIG_DPP
   1162 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
   1163 		ret = os_snprintf(pos, end - pos, "DPP ");
   1164 		if (os_snprintf_error(end - pos, ret))
   1165 			return pos - buf;
   1166 		pos += ret;
   1167 	}
   1168 #endif /* CONFIG_DPP */
   1169 
   1170 	if (pos > buf && *(pos - 1) == ' ') {
   1171 		*(pos - 1) = '\0';
   1172 		pos--;
   1173 	}
   1174 
   1175 	return pos - buf;
   1176 }
   1177 
   1178 
   1179 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
   1180 					 char *buf, size_t buflen)
   1181 {
   1182 	int ret;
   1183 	char *pos, *end;
   1184 
   1185 	pos = buf;
   1186 	end = buf + buflen;
   1187 
   1188 	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
   1189 			  "ssid=%s\n",
   1190 			  MAC2STR(hapd->own_addr),
   1191 			  wpa_ssid_txt(hapd->conf->ssid.ssid,
   1192 				       hapd->conf->ssid.ssid_len));
   1193 	if (os_snprintf_error(end - pos, ret))
   1194 		return pos - buf;
   1195 	pos += ret;
   1196 
   1197 #ifdef CONFIG_WPS
   1198 	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
   1199 			  hapd->conf->wps_state == 0 ? "disabled" :
   1200 			  (hapd->conf->wps_state == 1 ? "not configured" :
   1201 			   "configured"));
   1202 	if (os_snprintf_error(end - pos, ret))
   1203 		return pos - buf;
   1204 	pos += ret;
   1205 
   1206 	if (hapd->conf->wps_state && hapd->conf->wpa &&
   1207 	    hapd->conf->ssid.wpa_passphrase) {
   1208 		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
   1209 				  hapd->conf->ssid.wpa_passphrase);
   1210 		if (os_snprintf_error(end - pos, ret))
   1211 			return pos - buf;
   1212 		pos += ret;
   1213 	}
   1214 
   1215 	if (hapd->conf->wps_state && hapd->conf->wpa &&
   1216 	    hapd->conf->ssid.wpa_psk &&
   1217 	    hapd->conf->ssid.wpa_psk->group) {
   1218 		char hex[PMK_LEN * 2 + 1];
   1219 		wpa_snprintf_hex(hex, sizeof(hex),
   1220 				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
   1221 		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
   1222 		if (os_snprintf_error(end - pos, ret))
   1223 			return pos - buf;
   1224 		pos += ret;
   1225 	}
   1226 #endif /* CONFIG_WPS */
   1227 
   1228 	if (hapd->conf->wpa) {
   1229 		ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
   1230 		if (os_snprintf_error(end - pos, ret))
   1231 			return pos - buf;
   1232 		pos += ret;
   1233 	}
   1234 
   1235 	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
   1236 		ret = os_snprintf(pos, end - pos, "key_mgmt=");
   1237 		if (os_snprintf_error(end - pos, ret))
   1238 			return pos - buf;
   1239 		pos += ret;
   1240 
   1241 		pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
   1242 
   1243 		ret = os_snprintf(pos, end - pos, "\n");
   1244 		if (os_snprintf_error(end - pos, ret))
   1245 			return pos - buf;
   1246 		pos += ret;
   1247 	}
   1248 
   1249 	if (hapd->conf->wpa) {
   1250 		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
   1251 				  wpa_cipher_txt(hapd->conf->wpa_group));
   1252 		if (os_snprintf_error(end - pos, ret))
   1253 			return pos - buf;
   1254 		pos += ret;
   1255 	}
   1256 
   1257 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
   1258 		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
   1259 		if (os_snprintf_error(end - pos, ret))
   1260 			return pos - buf;
   1261 		pos += ret;
   1262 
   1263 		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
   1264 					" ");
   1265 		if (ret < 0)
   1266 			return pos - buf;
   1267 		pos += ret;
   1268 
   1269 		ret = os_snprintf(pos, end - pos, "\n");
   1270 		if (os_snprintf_error(end - pos, ret))
   1271 			return pos - buf;
   1272 		pos += ret;
   1273 	}
   1274 
   1275 	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
   1276 		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
   1277 		if (os_snprintf_error(end - pos, ret))
   1278 			return pos - buf;
   1279 		pos += ret;
   1280 
   1281 		ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
   1282 					" ");
   1283 		if (ret < 0)
   1284 			return pos - buf;
   1285 		pos += ret;
   1286 
   1287 		ret = os_snprintf(pos, end - pos, "\n");
   1288 		if (os_snprintf_error(end - pos, ret))
   1289 			return pos - buf;
   1290 		pos += ret;
   1291 	}
   1292 
   1293 	return pos - buf;
   1294 }
   1295 
   1296 
   1297 static void hostapd_disassoc_accept_mac(struct hostapd_data *hapd)
   1298 {
   1299 	struct sta_info *sta;
   1300 	struct vlan_description vlan_id;
   1301 
   1302 	if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED)
   1303 		return;
   1304 
   1305 	for (sta = hapd->sta_list; sta; sta = sta->next) {
   1306 		if (!hostapd_maclist_found(hapd->conf->accept_mac,
   1307 					   hapd->conf->num_accept_mac,
   1308 					   sta->addr, &vlan_id) ||
   1309 		    (vlan_id.notempty &&
   1310 		     vlan_compare(&vlan_id, sta->vlan_desc)))
   1311 			ap_sta_disconnect(hapd, sta, sta->addr,
   1312 					  WLAN_REASON_UNSPECIFIED);
   1313 	}
   1314 }
   1315 
   1316 
   1317 static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
   1318 {
   1319 	struct sta_info *sta;
   1320 	struct vlan_description vlan_id;
   1321 
   1322 	for (sta = hapd->sta_list; sta; sta = sta->next) {
   1323 		if (hostapd_maclist_found(hapd->conf->deny_mac,
   1324 					  hapd->conf->num_deny_mac, sta->addr,
   1325 					  &vlan_id) &&
   1326 		    (!vlan_id.notempty ||
   1327 		     !vlan_compare(&vlan_id, sta->vlan_desc)))
   1328 			ap_sta_disconnect(hapd, sta, sta->addr,
   1329 					  WLAN_REASON_UNSPECIFIED);
   1330 	}
   1331 }
   1332 
   1333 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
   1334 {
   1335 	char *value;
   1336 	int ret = 0;
   1337 
   1338 	value = os_strchr(cmd, ' ');
   1339 	if (value == NULL)
   1340 		return -1;
   1341 	*value++ = '\0';
   1342 
   1343 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
   1344 	if (0) {
   1345 #ifdef CONFIG_WPS_TESTING
   1346 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
   1347 		long int val;
   1348 		val = strtol(value, NULL, 0);
   1349 		if (val < 0 || val > 0xff) {
   1350 			ret = -1;
   1351 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
   1352 				   "wps_version_number %ld", val);
   1353 		} else {
   1354 			wps_version_number = val;
   1355 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
   1356 				   "version %u.%u",
   1357 				   (wps_version_number & 0xf0) >> 4,
   1358 				   wps_version_number & 0x0f);
   1359 			hostapd_wps_update_ie(hapd);
   1360 		}
   1361 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
   1362 		wps_testing_dummy_cred = atoi(value);
   1363 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
   1364 			   wps_testing_dummy_cred);
   1365 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
   1366 		wps_corrupt_pkhash = atoi(value);
   1367 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
   1368 			   wps_corrupt_pkhash);
   1369 #endif /* CONFIG_WPS_TESTING */
   1370 #ifdef CONFIG_TESTING_OPTIONS
   1371 	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
   1372 		hapd->ext_mgmt_frame_handling = atoi(value);
   1373 	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
   1374 		hapd->ext_eapol_frame_io = atoi(value);
   1375 #ifdef CONFIG_DPP
   1376 	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
   1377 		os_free(hapd->dpp_config_obj_override);
   1378 		hapd->dpp_config_obj_override = os_strdup(value);
   1379 	} else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
   1380 		os_free(hapd->dpp_discovery_override);
   1381 		hapd->dpp_discovery_override = os_strdup(value);
   1382 	} else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
   1383 		os_free(hapd->dpp_groups_override);
   1384 		hapd->dpp_groups_override = os_strdup(value);
   1385 	} else if (os_strcasecmp(cmd,
   1386 				 "dpp_ignore_netaccesskey_mismatch") == 0) {
   1387 		hapd->dpp_ignore_netaccesskey_mismatch = atoi(value);
   1388 	} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
   1389 		dpp_test = atoi(value);
   1390 #endif /* CONFIG_DPP */
   1391 #endif /* CONFIG_TESTING_OPTIONS */
   1392 #ifdef CONFIG_MBO
   1393 	} else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
   1394 		int val;
   1395 
   1396 		if (!hapd->conf->mbo_enabled)
   1397 			return -1;
   1398 
   1399 		val = atoi(value);
   1400 		if (val < 0 || val > 1)
   1401 			return -1;
   1402 
   1403 		hapd->mbo_assoc_disallow = val;
   1404 		ieee802_11_update_beacons(hapd->iface);
   1405 
   1406 		/*
   1407 		 * TODO: Need to configure drivers that do AP MLME offload with
   1408 		 * disallowing station logic.
   1409 		 */
   1410 #endif /* CONFIG_MBO */
   1411 #ifdef CONFIG_DPP
   1412 	} else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
   1413 		os_free(hapd->dpp_configurator_params);
   1414 		hapd->dpp_configurator_params = os_strdup(value);
   1415 #endif /* CONFIG_DPP */
   1416 	} else {
   1417 		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
   1418 		if (ret)
   1419 			return ret;
   1420 
   1421 		if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
   1422 			hostapd_disassoc_deny_mac(hapd);
   1423 		} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
   1424 			hostapd_disassoc_accept_mac(hapd);
   1425 		} else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
   1426 			   os_strncmp(cmd, "wmm_ac_", 7) == 0) {
   1427 			hapd->parameter_set_count++;
   1428 			if (ieee802_11_update_beacons(hapd->iface))
   1429 				wpa_printf(MSG_DEBUG,
   1430 					   "Failed to update beacons with WMM parameters");
   1431 		}
   1432 	}
   1433 
   1434 	return ret;
   1435 }
   1436 
   1437 
   1438 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
   1439 				  char *buf, size_t buflen)
   1440 {
   1441 	int res;
   1442 
   1443 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
   1444 
   1445 	if (os_strcmp(cmd, "version") == 0) {
   1446 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
   1447 		if (os_snprintf_error(buflen, res))
   1448 			return -1;
   1449 		return res;
   1450 	} else if (os_strcmp(cmd, "tls_library") == 0) {
   1451 		res = tls_get_library_version(buf, buflen);
   1452 		if (os_snprintf_error(buflen, res))
   1453 			return -1;
   1454 		return res;
   1455 	}
   1456 
   1457 	return -1;
   1458 }
   1459 
   1460 
   1461 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
   1462 {
   1463 	if (hostapd_enable_iface(iface) < 0) {
   1464 		wpa_printf(MSG_ERROR, "Enabling of interface failed");
   1465 		return -1;
   1466 	}
   1467 	return 0;
   1468 }
   1469 
   1470 
   1471 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
   1472 {
   1473 	if (hostapd_reload_iface(iface) < 0) {
   1474 		wpa_printf(MSG_ERROR, "Reloading of interface failed");
   1475 		return -1;
   1476 	}
   1477 	return 0;
   1478 }
   1479 
   1480 
   1481 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
   1482 {
   1483 	if (hostapd_disable_iface(iface) < 0) {
   1484 		wpa_printf(MSG_ERROR, "Disabling of interface failed");
   1485 		return -1;
   1486 	}
   1487 	return 0;
   1488 }
   1489 
   1490 
   1491 static int
   1492 hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd,
   1493 					      struct sta_info *sta, void *ctx)
   1494 {
   1495 	struct hostapd_wpa_psk *psk;
   1496 	const u8 *pmk;
   1497 	int pmk_len;
   1498 	int pmk_match;
   1499 	int sta_match;
   1500 	int bss_match;
   1501 	int reason;
   1502 
   1503 	pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
   1504 
   1505 	for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) {
   1506 		pmk_match = PMK_LEN == pmk_len &&
   1507 			os_memcmp(psk->psk, pmk, pmk_len) == 0;
   1508 		sta_match = psk->group == 0 &&
   1509 			os_memcmp(sta->addr, psk->addr, ETH_ALEN) == 0;
   1510 		bss_match = psk->group == 1;
   1511 
   1512 		if (pmk_match && (sta_match || bss_match))
   1513 			return 0;
   1514 	}
   1515 
   1516 	wpa_printf(MSG_INFO, "STA " MACSTR
   1517 		   " PSK/passphrase no longer valid - disconnect",
   1518 		   MAC2STR(sta->addr));
   1519 	reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
   1520 	hostapd_drv_sta_deauth(hapd, sta->addr, reason);
   1521 	ap_sta_deauthenticate(hapd, sta, reason);
   1522 
   1523 	return 0;
   1524 }
   1525 
   1526 
   1527 static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd)
   1528 {
   1529 	struct hostapd_bss_config *conf = hapd->conf;
   1530 	int err;
   1531 
   1532 	hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
   1533 
   1534 	err = hostapd_setup_wpa_psk(conf);
   1535 	if (err < 0) {
   1536 		wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d",
   1537 			   err);
   1538 		return -1;
   1539 	}
   1540 
   1541 	ap_for_each_sta(hapd, hostapd_ctrl_iface_kick_mismatch_psk_sta_iter,
   1542 			NULL);
   1543 
   1544 	return 0;
   1545 }
   1546 
   1547 
   1548 #ifdef CONFIG_TESTING_OPTIONS
   1549 
   1550 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
   1551 {
   1552 	union wpa_event_data data;
   1553 	char *pos, *param;
   1554 	enum wpa_event_type event;
   1555 
   1556 	wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
   1557 
   1558 	os_memset(&data, 0, sizeof(data));
   1559 
   1560 	param = os_strchr(cmd, ' ');
   1561 	if (param == NULL)
   1562 		return -1;
   1563 	*param++ = '\0';
   1564 
   1565 	if (os_strcmp(cmd, "DETECTED") == 0)
   1566 		event = EVENT_DFS_RADAR_DETECTED;
   1567 	else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
   1568 		event = EVENT_DFS_CAC_FINISHED;
   1569 	else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
   1570 		event = EVENT_DFS_CAC_ABORTED;
   1571 	else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
   1572 		event = EVENT_DFS_NOP_FINISHED;
   1573 	else {
   1574 		wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
   1575 			   cmd);
   1576 		return -1;
   1577 	}
   1578 
   1579 	pos = os_strstr(param, "freq=");
   1580 	if (pos)
   1581 		data.dfs_event.freq = atoi(pos + 5);
   1582 
   1583 	pos = os_strstr(param, "ht_enabled=1");
   1584 	if (pos)
   1585 		data.dfs_event.ht_enabled = 1;
   1586 
   1587 	pos = os_strstr(param, "chan_offset=");
   1588 	if (pos)
   1589 		data.dfs_event.chan_offset = atoi(pos + 12);
   1590 
   1591 	pos = os_strstr(param, "chan_width=");
   1592 	if (pos)
   1593 		data.dfs_event.chan_width = atoi(pos + 11);
   1594 
   1595 	pos = os_strstr(param, "cf1=");
   1596 	if (pos)
   1597 		data.dfs_event.cf1 = atoi(pos + 4);
   1598 
   1599 	pos = os_strstr(param, "cf2=");
   1600 	if (pos)
   1601 		data.dfs_event.cf2 = atoi(pos + 4);
   1602 
   1603 	wpa_supplicant_event(hapd, event, &data);
   1604 
   1605 	return 0;
   1606 }
   1607 
   1608 
   1609 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
   1610 {
   1611 	size_t len;
   1612 	u8 *buf;
   1613 	int res;
   1614 
   1615 	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
   1616 
   1617 	len = os_strlen(cmd);
   1618 	if (len & 1)
   1619 		return -1;
   1620 	len /= 2;
   1621 
   1622 	buf = os_malloc(len);
   1623 	if (buf == NULL)
   1624 		return -1;
   1625 
   1626 	if (hexstr2bin(cmd, buf, len) < 0) {
   1627 		os_free(buf);
   1628 		return -1;
   1629 	}
   1630 
   1631 	res = hostapd_drv_send_mlme(hapd, buf, len, 0);
   1632 	os_free(buf);
   1633 	return res;
   1634 }
   1635 
   1636 
   1637 static int hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data *hapd,
   1638 						     char *cmd)
   1639 {
   1640 	char *pos, *param;
   1641 	size_t len;
   1642 	u8 *buf;
   1643 	int stype = 0, ok = 0;
   1644 	union wpa_event_data event;
   1645 
   1646 	if (!hapd->ext_mgmt_frame_handling)
   1647 		return -1;
   1648 
   1649 	/* stype=<val> ok=<0/1> buf=<frame hexdump> */
   1650 
   1651 	wpa_printf(MSG_DEBUG, "External MGMT TX status process: %s", cmd);
   1652 
   1653 	pos = cmd;
   1654 	param = os_strstr(pos, "stype=");
   1655 	if (param) {
   1656 		param += 6;
   1657 		stype = atoi(param);
   1658 	}
   1659 
   1660 	param = os_strstr(pos, " ok=");
   1661 	if (param) {
   1662 		param += 4;
   1663 		ok = atoi(param);
   1664 	}
   1665 
   1666 	param = os_strstr(pos, " buf=");
   1667 	if (!param)
   1668 		return -1;
   1669 	param += 5;
   1670 
   1671 	len = os_strlen(param);
   1672 	if (len & 1)
   1673 		return -1;
   1674 	len /= 2;
   1675 
   1676 	buf = os_malloc(len);
   1677 	if (!buf || hexstr2bin(param, buf, len) < 0) {
   1678 		os_free(buf);
   1679 		return -1;
   1680 	}
   1681 
   1682 	os_memset(&event, 0, sizeof(event));
   1683 	event.tx_status.type = WLAN_FC_TYPE_MGMT;
   1684 	event.tx_status.data = buf;
   1685 	event.tx_status.data_len = len;
   1686 	event.tx_status.stype = stype;
   1687 	event.tx_status.ack = ok;
   1688 	hapd->ext_mgmt_frame_handling = 0;
   1689 	wpa_supplicant_event(hapd, EVENT_TX_STATUS, &event);
   1690 	hapd->ext_mgmt_frame_handling = 1;
   1691 
   1692 	os_free(buf);
   1693 
   1694 	return 0;
   1695 }
   1696 
   1697 
   1698 static int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd,
   1699 					      char *cmd)
   1700 {
   1701 	char *pos, *param;
   1702 	size_t len;
   1703 	u8 *buf;
   1704 	int freq = 0, datarate = 0, ssi_signal = 0;
   1705 	union wpa_event_data event;
   1706 
   1707 	if (!hapd->ext_mgmt_frame_handling)
   1708 		return -1;
   1709 
   1710 	/* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
   1711 
   1712 	wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
   1713 
   1714 	pos = cmd;
   1715 	param = os_strstr(pos, "freq=");
   1716 	if (param) {
   1717 		param += 5;
   1718 		freq = atoi(param);
   1719 	}
   1720 
   1721 	param = os_strstr(pos, " datarate=");
   1722 	if (param) {
   1723 		param += 10;
   1724 		datarate = atoi(param);
   1725 	}
   1726 
   1727 	param = os_strstr(pos, " ssi_signal=");
   1728 	if (param) {
   1729 		param += 12;
   1730 		ssi_signal = atoi(param);
   1731 	}
   1732 
   1733 	param = os_strstr(pos, " frame=");
   1734 	if (param == NULL)
   1735 		return -1;
   1736 	param += 7;
   1737 
   1738 	len = os_strlen(param);
   1739 	if (len & 1)
   1740 		return -1;
   1741 	len /= 2;
   1742 
   1743 	buf = os_malloc(len);
   1744 	if (buf == NULL)
   1745 		return -1;
   1746 
   1747 	if (hexstr2bin(param, buf, len) < 0) {
   1748 		os_free(buf);
   1749 		return -1;
   1750 	}
   1751 
   1752 	os_memset(&event, 0, sizeof(event));
   1753 	event.rx_mgmt.freq = freq;
   1754 	event.rx_mgmt.frame = buf;
   1755 	event.rx_mgmt.frame_len = len;
   1756 	event.rx_mgmt.ssi_signal = ssi_signal;
   1757 	event.rx_mgmt.datarate = datarate;
   1758 	hapd->ext_mgmt_frame_handling = 0;
   1759 	wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event);
   1760 	hapd->ext_mgmt_frame_handling = 1;
   1761 
   1762 	os_free(buf);
   1763 
   1764 	return 0;
   1765 }
   1766 
   1767 
   1768 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
   1769 {
   1770 	char *pos;
   1771 	u8 src[ETH_ALEN], *buf;
   1772 	int used;
   1773 	size_t len;
   1774 
   1775 	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
   1776 
   1777 	pos = cmd;
   1778 	used = hwaddr_aton2(pos, src);
   1779 	if (used < 0)
   1780 		return -1;
   1781 	pos += used;
   1782 	while (*pos == ' ')
   1783 		pos++;
   1784 
   1785 	len = os_strlen(pos);
   1786 	if (len & 1)
   1787 		return -1;
   1788 	len /= 2;
   1789 
   1790 	buf = os_malloc(len);
   1791 	if (buf == NULL)
   1792 		return -1;
   1793 
   1794 	if (hexstr2bin(pos, buf, len) < 0) {
   1795 		os_free(buf);
   1796 		return -1;
   1797 	}
   1798 
   1799 	ieee802_1x_receive(hapd, src, buf, len);
   1800 	os_free(buf);
   1801 
   1802 	return 0;
   1803 }
   1804 
   1805 
   1806 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
   1807 {
   1808 	size_t i;
   1809 	u32 sum = 0;
   1810 	const u16 *pos = buf;
   1811 
   1812 	for (i = 0; i < len / 2; i++)
   1813 		sum += *pos++;
   1814 
   1815 	while (sum >> 16)
   1816 		sum = (sum & 0xffff) + (sum >> 16);
   1817 
   1818 	return sum ^ 0xffff;
   1819 }
   1820 
   1821 
   1822 #define HWSIM_PACKETLEN 1500
   1823 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
   1824 
   1825 static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
   1826 				 size_t len)
   1827 {
   1828 	struct hostapd_data *hapd = ctx;
   1829 	const struct ether_header *eth;
   1830 	struct iphdr ip;
   1831 	const u8 *pos;
   1832 	unsigned int i;
   1833 
   1834 	if (len != HWSIM_PACKETLEN)
   1835 		return;
   1836 
   1837 	eth = (const struct ether_header *) buf;
   1838 	os_memcpy(&ip, eth + 1, sizeof(ip));
   1839 	pos = &buf[sizeof(*eth) + sizeof(ip)];
   1840 
   1841 	if (ip.ihl != 5 || ip.version != 4 ||
   1842 	    ntohs(ip.tot_len) != HWSIM_IP_LEN)
   1843 		return;
   1844 
   1845 	for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
   1846 		if (*pos != (u8) i)
   1847 			return;
   1848 		pos++;
   1849 	}
   1850 
   1851 	wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
   1852 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
   1853 }
   1854 
   1855 
   1856 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
   1857 					       char *cmd)
   1858 {
   1859 	int enabled = atoi(cmd);
   1860 	char *pos;
   1861 	const char *ifname;
   1862 
   1863 	if (!enabled) {
   1864 		if (hapd->l2_test) {
   1865 			l2_packet_deinit(hapd->l2_test);
   1866 			hapd->l2_test = NULL;
   1867 			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
   1868 				"test data: Disabled");
   1869 		}
   1870 		return 0;
   1871 	}
   1872 
   1873 	if (hapd->l2_test)
   1874 		return 0;
   1875 
   1876 	pos = os_strstr(cmd, " ifname=");
   1877 	if (pos)
   1878 		ifname = pos + 8;
   1879 	else
   1880 		ifname = hapd->conf->iface;
   1881 
   1882 	hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
   1883 					ETHERTYPE_IP, hostapd_data_test_rx,
   1884 					hapd, 1);
   1885 	if (hapd->l2_test == NULL)
   1886 		return -1;
   1887 
   1888 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
   1889 
   1890 	return 0;
   1891 }
   1892 
   1893 
   1894 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
   1895 {
   1896 	u8 dst[ETH_ALEN], src[ETH_ALEN];
   1897 	char *pos;
   1898 	int used;
   1899 	long int val;
   1900 	u8 tos;
   1901 	u8 buf[2 + HWSIM_PACKETLEN];
   1902 	struct ether_header *eth;
   1903 	struct iphdr *ip;
   1904 	u8 *dpos;
   1905 	unsigned int i;
   1906 
   1907 	if (hapd->l2_test == NULL)
   1908 		return -1;
   1909 
   1910 	/* format: <dst> <src> <tos> */
   1911 
   1912 	pos = cmd;
   1913 	used = hwaddr_aton2(pos, dst);
   1914 	if (used < 0)
   1915 		return -1;
   1916 	pos += used;
   1917 	while (*pos == ' ')
   1918 		pos++;
   1919 	used = hwaddr_aton2(pos, src);
   1920 	if (used < 0)
   1921 		return -1;
   1922 	pos += used;
   1923 
   1924 	val = strtol(pos, NULL, 0);
   1925 	if (val < 0 || val > 0xff)
   1926 		return -1;
   1927 	tos = val;
   1928 
   1929 	eth = (struct ether_header *) &buf[2];
   1930 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
   1931 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
   1932 	eth->ether_type = htons(ETHERTYPE_IP);
   1933 	ip = (struct iphdr *) (eth + 1);
   1934 	os_memset(ip, 0, sizeof(*ip));
   1935 	ip->ihl = 5;
   1936 	ip->version = 4;
   1937 	ip->ttl = 64;
   1938 	ip->tos = tos;
   1939 	ip->tot_len = htons(HWSIM_IP_LEN);
   1940 	ip->protocol = 1;
   1941 	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
   1942 	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
   1943 	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
   1944 	dpos = (u8 *) (ip + 1);
   1945 	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
   1946 		*dpos++ = i;
   1947 
   1948 	if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
   1949 			   HWSIM_PACKETLEN) < 0)
   1950 		return -1;
   1951 
   1952 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
   1953 		" src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
   1954 
   1955 	return 0;
   1956 }
   1957 
   1958 
   1959 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
   1960 					      char *cmd)
   1961 {
   1962 	u8 *buf;
   1963 	struct ether_header *eth;
   1964 	struct l2_packet_data *l2 = NULL;
   1965 	size_t len;
   1966 	u16 ethertype;
   1967 	int res = -1;
   1968 	const char *ifname = hapd->conf->iface;
   1969 
   1970 	if (os_strncmp(cmd, "ifname=", 7) == 0) {
   1971 		cmd += 7;
   1972 		ifname = cmd;
   1973 		cmd = os_strchr(cmd, ' ');
   1974 		if (cmd == NULL)
   1975 			return -1;
   1976 		*cmd++ = '\0';
   1977 	}
   1978 
   1979 	len = os_strlen(cmd);
   1980 	if (len & 1 || len < ETH_HLEN * 2)
   1981 		return -1;
   1982 	len /= 2;
   1983 
   1984 	buf = os_malloc(len);
   1985 	if (buf == NULL)
   1986 		return -1;
   1987 
   1988 	if (hexstr2bin(cmd, buf, len) < 0)
   1989 		goto done;
   1990 
   1991 	eth = (struct ether_header *) buf;
   1992 	ethertype = ntohs(eth->ether_type);
   1993 
   1994 	l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
   1995 			    hostapd_data_test_rx, hapd, 1);
   1996 	if (l2 == NULL)
   1997 		goto done;
   1998 
   1999 	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
   2000 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
   2001 done:
   2002 	if (l2)
   2003 		l2_packet_deinit(l2);
   2004 	os_free(buf);
   2005 
   2006 	return res < 0 ? -1 : 0;
   2007 }
   2008 
   2009 
   2010 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
   2011 {
   2012 #ifdef WPA_TRACE_BFD
   2013 	char *pos;
   2014 
   2015 	wpa_trace_fail_after = atoi(cmd);
   2016 	pos = os_strchr(cmd, ':');
   2017 	if (pos) {
   2018 		pos++;
   2019 		os_strlcpy(wpa_trace_fail_func, pos,
   2020 			   sizeof(wpa_trace_fail_func));
   2021 	} else {
   2022 		wpa_trace_fail_after = 0;
   2023 	}
   2024 
   2025 	return 0;
   2026 #else /* WPA_TRACE_BFD */
   2027 	return -1;
   2028 #endif /* WPA_TRACE_BFD */
   2029 }
   2030 
   2031 
   2032 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
   2033 				       char *buf, size_t buflen)
   2034 {
   2035 #ifdef WPA_TRACE_BFD
   2036 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
   2037 			   wpa_trace_fail_func);
   2038 #else /* WPA_TRACE_BFD */
   2039 	return -1;
   2040 #endif /* WPA_TRACE_BFD */
   2041 }
   2042 
   2043 
   2044 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
   2045 {
   2046 #ifdef WPA_TRACE_BFD
   2047 	char *pos;
   2048 
   2049 	wpa_trace_test_fail_after = atoi(cmd);
   2050 	pos = os_strchr(cmd, ':');
   2051 	if (pos) {
   2052 		pos++;
   2053 		os_strlcpy(wpa_trace_test_fail_func, pos,
   2054 			   sizeof(wpa_trace_test_fail_func));
   2055 	} else {
   2056 		wpa_trace_test_fail_after = 0;
   2057 	}
   2058 
   2059 	return 0;
   2060 #else /* WPA_TRACE_BFD */
   2061 	return -1;
   2062 #endif /* WPA_TRACE_BFD */
   2063 }
   2064 
   2065 
   2066 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
   2067 				 char *buf, size_t buflen)
   2068 {
   2069 #ifdef WPA_TRACE_BFD
   2070 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
   2071 			   wpa_trace_test_fail_func);
   2072 #else /* WPA_TRACE_BFD */
   2073 	return -1;
   2074 #endif /* WPA_TRACE_BFD */
   2075 }
   2076 
   2077 
   2078 static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
   2079 {
   2080 	struct sta_info *sta;
   2081 	u8 addr[ETH_ALEN];
   2082 	u8 zero[WPA_TK_MAX_LEN];
   2083 
   2084 	os_memset(zero, 0, sizeof(zero));
   2085 
   2086 	if (hwaddr_aton(cmd, addr))
   2087 		return -1;
   2088 
   2089 #ifdef CONFIG_IEEE80211W
   2090 	if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
   2091 		if (hapd->last_igtk_alg == WPA_ALG_NONE)
   2092 			return -1;
   2093 
   2094 		wpa_printf(MSG_INFO, "TESTING: Reset IPN for IGTK");
   2095 
   2096 		/* First, use a zero key to avoid any possible duplicate key
   2097 		 * avoidance in the driver. */
   2098 		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
   2099 					hapd->last_igtk_alg,
   2100 					broadcast_ether_addr,
   2101 					hapd->last_igtk_key_idx, 1, NULL, 0,
   2102 					zero, hapd->last_igtk_len) < 0)
   2103 			return -1;
   2104 
   2105 		/* Set the previously configured key to reset its TSC */
   2106 		return hostapd_drv_set_key(hapd->conf->iface, hapd,
   2107 					   hapd->last_igtk_alg,
   2108 					   broadcast_ether_addr,
   2109 					   hapd->last_igtk_key_idx, 1, NULL, 0,
   2110 					   hapd->last_igtk,
   2111 					   hapd->last_igtk_len);
   2112 	}
   2113 #endif /* CONFIG_IEEE80211W */
   2114 
   2115 	if (is_broadcast_ether_addr(addr)) {
   2116 		if (hapd->last_gtk_alg == WPA_ALG_NONE)
   2117 			return -1;
   2118 
   2119 		wpa_printf(MSG_INFO, "TESTING: Reset PN for GTK");
   2120 
   2121 		/* First, use a zero key to avoid any possible duplicate key
   2122 		 * avoidance in the driver. */
   2123 		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
   2124 					hapd->last_gtk_alg,
   2125 					broadcast_ether_addr,
   2126 					hapd->last_gtk_key_idx, 1, NULL, 0,
   2127 					zero, hapd->last_gtk_len) < 0)
   2128 			return -1;
   2129 
   2130 		/* Set the previously configured key to reset its TSC */
   2131 		return hostapd_drv_set_key(hapd->conf->iface, hapd,
   2132 					   hapd->last_gtk_alg,
   2133 					   broadcast_ether_addr,
   2134 					   hapd->last_gtk_key_idx, 1, NULL, 0,
   2135 					   hapd->last_gtk, hapd->last_gtk_len);
   2136 	}
   2137 
   2138 	sta = ap_get_sta(hapd, addr);
   2139 	if (!sta)
   2140 		return -1;
   2141 
   2142 	if (sta->last_tk_alg == WPA_ALG_NONE)
   2143 		return -1;
   2144 
   2145 	wpa_printf(MSG_INFO, "TESTING: Reset PN for " MACSTR,
   2146 		   MAC2STR(sta->addr));
   2147 
   2148 	/* First, use a zero key to avoid any possible duplicate key avoidance
   2149 	 * in the driver. */
   2150 	if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
   2151 				sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
   2152 				zero, sta->last_tk_len) < 0)
   2153 		return -1;
   2154 
   2155 	/* Set the previously configured key to reset its TSC/RSC */
   2156 	return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
   2157 				   sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
   2158 				   sta->last_tk, sta->last_tk_len);
   2159 }
   2160 
   2161 
   2162 static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
   2163 {
   2164 	u8 addr[ETH_ALEN];
   2165 	const char *pos = cmd;
   2166 	enum wpa_alg alg;
   2167 	int idx, set_tx;
   2168 	u8 seq[6], key[WPA_TK_MAX_LEN];
   2169 	size_t key_len;
   2170 
   2171 	/* parameters: alg addr idx set_tx seq key */
   2172 
   2173 	alg = atoi(pos);
   2174 	pos = os_strchr(pos, ' ');
   2175 	if (!pos)
   2176 		return -1;
   2177 	pos++;
   2178 	if (hwaddr_aton(pos, addr))
   2179 		return -1;
   2180 	pos += 17;
   2181 	if (*pos != ' ')
   2182 		return -1;
   2183 	pos++;
   2184 	idx = atoi(pos);
   2185 	pos = os_strchr(pos, ' ');
   2186 	if (!pos)
   2187 		return -1;
   2188 	pos++;
   2189 	set_tx = atoi(pos);
   2190 	pos = os_strchr(pos, ' ');
   2191 	if (!pos)
   2192 		return -1;
   2193 	pos++;
   2194 	if (hexstr2bin(pos, seq, sizeof(seq)) < 0)
   2195 		return -1;
   2196 	pos += 2 * 6;
   2197 	if (*pos != ' ')
   2198 		return -1;
   2199 	pos++;
   2200 	key_len = os_strlen(pos) / 2;
   2201 	if (hexstr2bin(pos, key, key_len) < 0)
   2202 		return -1;
   2203 
   2204 	wpa_printf(MSG_INFO, "TESTING: Set key");
   2205 	return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx,
   2206 				   set_tx, seq, 6, key, key_len);
   2207 }
   2208 
   2209 
   2210 static void restore_tk(void *ctx1, void *ctx2)
   2211 {
   2212 	struct hostapd_data *hapd = ctx1;
   2213 	struct sta_info *sta = ctx2;
   2214 
   2215 	wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR,
   2216 		   MAC2STR(sta->addr));
   2217 	/* This does not really restore the TSC properly, so this will result
   2218 	 * in replay protection issues for now since there is no clean way of
   2219 	 * preventing encryption of a single EAPOL frame. */
   2220 	hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
   2221 			    sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
   2222 			    sta->last_tk, sta->last_tk_len);
   2223 }
   2224 
   2225 
   2226 static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
   2227 {
   2228 	struct sta_info *sta;
   2229 	u8 addr[ETH_ALEN];
   2230 	int plain = os_strstr(cmd, "plaintext") != NULL;
   2231 
   2232 	if (hwaddr_aton(cmd, addr))
   2233 		return -1;
   2234 
   2235 	sta = ap_get_sta(hapd, addr);
   2236 	if (!sta || !sta->wpa_sm)
   2237 		return -1;
   2238 
   2239 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
   2240 		plain = 0; /* no need for special processing */
   2241 	if (plain) {
   2242 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
   2243 			   MAC2STR(sta->addr));
   2244 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
   2245 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
   2246 				    NULL, 0);
   2247 	}
   2248 
   2249 	wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
   2250 	return wpa_auth_resend_m1(sta->wpa_sm,
   2251 				  os_strstr(cmd, "change-anonce") != NULL,
   2252 				  plain ? restore_tk : NULL, hapd, sta);
   2253 }
   2254 
   2255 
   2256 static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
   2257 {
   2258 	struct sta_info *sta;
   2259 	u8 addr[ETH_ALEN];
   2260 	int plain = os_strstr(cmd, "plaintext") != NULL;
   2261 
   2262 	if (hwaddr_aton(cmd, addr))
   2263 		return -1;
   2264 
   2265 	sta = ap_get_sta(hapd, addr);
   2266 	if (!sta || !sta->wpa_sm)
   2267 		return -1;
   2268 
   2269 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
   2270 		plain = 0; /* no need for special processing */
   2271 	if (plain) {
   2272 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
   2273 			   MAC2STR(sta->addr));
   2274 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
   2275 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
   2276 				    NULL, 0);
   2277 	}
   2278 
   2279 	wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
   2280 	return wpa_auth_resend_m3(sta->wpa_sm,
   2281 				  plain ? restore_tk : NULL, hapd, sta);
   2282 }
   2283 
   2284 
   2285 static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
   2286 					const char *cmd)
   2287 {
   2288 	struct sta_info *sta;
   2289 	u8 addr[ETH_ALEN];
   2290 	int plain = os_strstr(cmd, "plaintext") != NULL;
   2291 
   2292 	if (hwaddr_aton(cmd, addr))
   2293 		return -1;
   2294 
   2295 	sta = ap_get_sta(hapd, addr);
   2296 	if (!sta || !sta->wpa_sm)
   2297 		return -1;
   2298 
   2299 	if (plain && sta->last_tk_alg == WPA_ALG_NONE)
   2300 		plain = 0; /* no need for special processing */
   2301 	if (plain) {
   2302 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
   2303 			   MAC2STR(sta->addr));
   2304 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
   2305 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
   2306 				    NULL, 0);
   2307 	}
   2308 
   2309 	wpa_printf(MSG_INFO,
   2310 		   "TESTING: Send group M1 for the same GTK and zero RSC to "
   2311 		   MACSTR, MAC2STR(sta->addr));
   2312 	return wpa_auth_resend_group_m1(sta->wpa_sm,
   2313 					plain ? restore_tk : NULL, hapd, sta);
   2314 }
   2315 
   2316 #endif /* CONFIG_TESTING_OPTIONS */
   2317 
   2318 
   2319 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
   2320 					  char *pos)
   2321 {
   2322 #ifdef NEED_AP_MLME
   2323 	struct csa_settings settings;
   2324 	int ret;
   2325 	unsigned int i;
   2326 
   2327 	ret = hostapd_parse_csa_settings(pos, &settings);
   2328 	if (ret)
   2329 		return ret;
   2330 
   2331 	for (i = 0; i < iface->num_bss; i++) {
   2332 
   2333 		/* Save CHAN_SWITCH VHT config */
   2334 		hostapd_chan_switch_vht_config(
   2335 			iface->bss[i], settings.freq_params.vht_enabled);
   2336 
   2337 		ret = hostapd_switch_channel(iface->bss[i], &settings);
   2338 		if (ret) {
   2339 			/* FIX: What do we do if CSA fails in the middle of
   2340 			 * submitting multi-BSS CSA requests? */
   2341 			return ret;
   2342 		}
   2343 	}
   2344 
   2345 	return 0;
   2346 #else /* NEED_AP_MLME */
   2347 	return -1;
   2348 #endif /* NEED_AP_MLME */
   2349 }
   2350 
   2351 
   2352 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
   2353 				  int reply_size, const char *param)
   2354 {
   2355 #ifdef RADIUS_SERVER
   2356 	if (os_strcmp(param, "radius_server") == 0) {
   2357 		return radius_server_get_mib(hapd->radius_srv, reply,
   2358 					     reply_size);
   2359 	}
   2360 #endif /* RADIUS_SERVER */
   2361 	return -1;
   2362 }
   2363 
   2364 
   2365 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
   2366 				     char *buf, size_t buflen)
   2367 {
   2368 	int ret;
   2369 	char *pos;
   2370 	u8 *data = NULL;
   2371 	unsigned int vendor_id, subcmd;
   2372 	struct wpabuf *reply;
   2373 	size_t data_len = 0;
   2374 
   2375 	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
   2376 	vendor_id = strtoul(cmd, &pos, 16);
   2377 	if (!isblank((unsigned char) *pos))
   2378 		return -EINVAL;
   2379 
   2380 	subcmd = strtoul(pos, &pos, 10);
   2381 
   2382 	if (*pos != '\0') {
   2383 		if (!isblank((unsigned char) *pos++))
   2384 			return -EINVAL;
   2385 		data_len = os_strlen(pos);
   2386 	}
   2387 
   2388 	if (data_len) {
   2389 		data_len /= 2;
   2390 		data = os_malloc(data_len);
   2391 		if (!data)
   2392 			return -ENOBUFS;
   2393 
   2394 		if (hexstr2bin(pos, data, data_len)) {
   2395 			wpa_printf(MSG_DEBUG,
   2396 				   "Vendor command: wrong parameter format");
   2397 			os_free(data);
   2398 			return -EINVAL;
   2399 		}
   2400 	}
   2401 
   2402 	reply = wpabuf_alloc((buflen - 1) / 2);
   2403 	if (!reply) {
   2404 		os_free(data);
   2405 		return -ENOBUFS;
   2406 	}
   2407 
   2408 	ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
   2409 				     reply);
   2410 
   2411 	if (ret == 0)
   2412 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
   2413 				       wpabuf_len(reply));
   2414 
   2415 	wpabuf_free(reply);
   2416 	os_free(data);
   2417 
   2418 	return ret;
   2419 }
   2420 
   2421 
   2422 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
   2423 					   const char *cmd)
   2424 {
   2425 	u8 addr[ETH_ALEN];
   2426 	struct sta_info *sta;
   2427 
   2428 	if (hwaddr_aton(cmd, addr))
   2429 		return -1;
   2430 
   2431 	sta = ap_get_sta(hapd, addr);
   2432 	if (!sta || !sta->eapol_sm)
   2433 		return -1;
   2434 
   2435 	eapol_auth_reauthenticate(sta->eapol_sm);
   2436 	return 0;
   2437 }
   2438 
   2439 
   2440 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
   2441 {
   2442 	u8 addr[ETH_ALEN];
   2443 	struct sta_info *sta;
   2444 	char *pos = cmd, *param;
   2445 
   2446 	if (hwaddr_aton(pos, addr) || pos[17] != ' ')
   2447 		return -1;
   2448 	pos += 18;
   2449 	param = pos;
   2450 	pos = os_strchr(pos, ' ');
   2451 	if (!pos)
   2452 		return -1;
   2453 	*pos++ = '\0';
   2454 
   2455 	sta = ap_get_sta(hapd, addr);
   2456 	if (!sta || !sta->eapol_sm)
   2457 		return -1;
   2458 
   2459 	return eapol_auth_set_conf(sta->eapol_sm, param, pos);
   2460 }
   2461 
   2462 
   2463 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
   2464 					char *buf, size_t buflen)
   2465 {
   2466 	char *pos, *end, *stamp;
   2467 	int ret;
   2468 
   2469 	/* cmd: "LOG_LEVEL [<level>]" */
   2470 	if (*cmd == '\0') {
   2471 		pos = buf;
   2472 		end = buf + buflen;
   2473 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
   2474 				  "Timestamp: %d\n",
   2475 				  debug_level_str(wpa_debug_level),
   2476 				  wpa_debug_timestamp);
   2477 		if (os_snprintf_error(end - pos, ret))
   2478 			ret = 0;
   2479 
   2480 		return ret;
   2481 	}
   2482 
   2483 	while (*cmd == ' ')
   2484 		cmd++;
   2485 
   2486 	stamp = os_strchr(cmd, ' ');
   2487 	if (stamp) {
   2488 		*stamp++ = '\0';
   2489 		while (*stamp == ' ') {
   2490 			stamp++;
   2491 		}
   2492 	}
   2493 
   2494 	if (os_strlen(cmd)) {
   2495 		int level = str_to_debug_level(cmd);
   2496 		if (level < 0)
   2497 			return -1;
   2498 		wpa_debug_level = level;
   2499 	}
   2500 
   2501 	if (stamp && os_strlen(stamp))
   2502 		wpa_debug_timestamp = atoi(stamp);
   2503 
   2504 	os_memcpy(buf, "OK\n", 3);
   2505 	return 3;
   2506 }
   2507 
   2508 
   2509 #ifdef NEED_AP_MLME
   2510 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
   2511 					     char *buf, size_t buflen)
   2512 {
   2513 	struct hostapd_iface *iface = hapd->iface;
   2514 	char *pos, *end;
   2515 	struct hostapd_sta_info *info;
   2516 	struct os_reltime now;
   2517 
   2518 	if (!iface->num_sta_seen)
   2519 		return 0;
   2520 
   2521 	sta_track_expire(iface, 0);
   2522 
   2523 	pos = buf;
   2524 	end = buf + buflen;
   2525 
   2526 	os_get_reltime(&now);
   2527 	dl_list_for_each_reverse(info, &iface->sta_seen,
   2528 				 struct hostapd_sta_info, list) {
   2529 		struct os_reltime age;
   2530 		int ret;
   2531 
   2532 		os_reltime_sub(&now, &info->last_seen, &age);
   2533 		ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n",
   2534 				  MAC2STR(info->addr), (unsigned int) age.sec,
   2535 				  info->ssi_signal);
   2536 		if (os_snprintf_error(end - pos, ret))
   2537 			break;
   2538 		pos += ret;
   2539 	}
   2540 
   2541 	return pos - buf;
   2542 }
   2543 #endif /* NEED_AP_MLME */
   2544 
   2545 
   2546 static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd,
   2547 				      const char *cmd)
   2548 {
   2549 	u8 addr[ETH_ALEN];
   2550 
   2551 	if (hwaddr_aton(cmd, addr)) {
   2552 		wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address");
   2553 		return -1;
   2554 	}
   2555 
   2556 	return hostapd_send_lci_req(hapd, addr);
   2557 }
   2558 
   2559 
   2560 static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd)
   2561 {
   2562 	u8 addr[ETH_ALEN];
   2563 	char *token, *context = NULL;
   2564 	int random_interval, min_ap;
   2565 	u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS];
   2566 	unsigned int n_responders;
   2567 
   2568 	token = str_token(cmd, " ", &context);
   2569 	if (!token || hwaddr_aton(token, addr)) {
   2570 		wpa_printf(MSG_INFO,
   2571 			   "CTRL: REQ_RANGE - Bad destination address");
   2572 		return -1;
   2573 	}
   2574 
   2575 	token = str_token(cmd, " ", &context);
   2576 	if (!token)
   2577 		return -1;
   2578 
   2579 	random_interval = atoi(token);
   2580 	if (random_interval < 0 || random_interval > 0xffff)
   2581 		return -1;
   2582 
   2583 	token = str_token(cmd, " ", &context);
   2584 	if (!token)
   2585 		return -1;
   2586 
   2587 	min_ap = atoi(token);
   2588 	if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP)
   2589 		return -1;
   2590 
   2591 	n_responders = 0;
   2592 	while ((token = str_token(cmd, " ", &context))) {
   2593 		if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) {
   2594 			wpa_printf(MSG_INFO,
   2595 				   "CTRL: REQ_RANGE: Too many responders");
   2596 			return -1;
   2597 		}
   2598 
   2599 		if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) {
   2600 			wpa_printf(MSG_INFO,
   2601 				   "CTRL: REQ_RANGE: Bad responder address");
   2602 			return -1;
   2603 		}
   2604 
   2605 		n_responders++;
   2606 	}
   2607 
   2608 	if (!n_responders) {
   2609 		wpa_printf(MSG_INFO,
   2610 			   "CTRL: REQ_RANGE - No FTM responder address");
   2611 		return -1;
   2612 	}
   2613 
   2614 	return hostapd_send_range_req(hapd, addr, random_interval, min_ap,
   2615 				      responders, n_responders);
   2616 }
   2617 
   2618 
   2619 static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
   2620 					 const char *cmd, char *reply,
   2621 					 size_t reply_size)
   2622 {
   2623 	u8 addr[ETH_ALEN];
   2624 	const char *pos;
   2625 	struct wpabuf *req;
   2626 	int ret;
   2627 	u8 req_mode = 0;
   2628 
   2629 	if (hwaddr_aton(cmd, addr))
   2630 		return -1;
   2631 	pos = os_strchr(cmd, ' ');
   2632 	if (!pos)
   2633 		return -1;
   2634 	pos++;
   2635 	if (os_strncmp(pos, "req_mode=", 9) == 0) {
   2636 		int val = hex2byte(pos + 9);
   2637 
   2638 		if (val < 0)
   2639 			return -1;
   2640 		req_mode = val;
   2641 		pos += 11;
   2642 		pos = os_strchr(pos, ' ');
   2643 		if (!pos)
   2644 			return -1;
   2645 		pos++;
   2646 	}
   2647 	req = wpabuf_parse_bin(pos);
   2648 	if (!req)
   2649 		return -1;
   2650 
   2651 	ret = hostapd_send_beacon_req(hapd, addr, req_mode, req);
   2652 	wpabuf_free(req);
   2653 	if (ret >= 0)
   2654 		ret = os_snprintf(reply, reply_size, "%d", ret);
   2655 	return ret;
   2656 }
   2657 
   2658 
   2659 static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
   2660 {
   2661 	struct wpa_ssid_value ssid;
   2662 	u8 bssid[ETH_ALEN];
   2663 	struct wpabuf *nr, *lci = NULL, *civic = NULL;
   2664 	int stationary = 0;
   2665 	char *tmp;
   2666 	int ret;
   2667 
   2668 	if (!(hapd->conf->radio_measurements[0] &
   2669 	      WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
   2670 		wpa_printf(MSG_ERROR,
   2671 			   "CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
   2672 		return -1;
   2673 	}
   2674 
   2675 	if (hwaddr_aton(buf, bssid)) {
   2676 		wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
   2677 		return -1;
   2678 	}
   2679 
   2680 	tmp = os_strstr(buf, "ssid=");
   2681 	if (!tmp || ssid_parse(tmp + 5, &ssid)) {
   2682 		wpa_printf(MSG_ERROR,
   2683 			   "CTRL: SET_NEIGHBOR: Bad or missing SSID");
   2684 		return -1;
   2685 	}
   2686 	buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
   2687 	if (!buf)
   2688 		return -1;
   2689 
   2690 	tmp = os_strstr(buf, "nr=");
   2691 	if (!tmp) {
   2692 		wpa_printf(MSG_ERROR,
   2693 			   "CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
   2694 		return -1;
   2695 	}
   2696 
   2697 	buf = os_strchr(tmp, ' ');
   2698 	if (buf)
   2699 		*buf++ = '\0';
   2700 
   2701 	nr = wpabuf_parse_bin(tmp + 3);
   2702 	if (!nr) {
   2703 		wpa_printf(MSG_ERROR,
   2704 			   "CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
   2705 		return -1;
   2706 	}
   2707 
   2708 	if (!buf)
   2709 		goto set;
   2710 
   2711 	tmp = os_strstr(buf, "lci=");
   2712 	if (tmp) {
   2713 		buf = os_strchr(tmp, ' ');
   2714 		if (buf)
   2715 			*buf++ = '\0';
   2716 		lci = wpabuf_parse_bin(tmp + 4);
   2717 		if (!lci) {
   2718 			wpa_printf(MSG_ERROR,
   2719 				   "CTRL: SET_NEIGHBOR: Bad LCI subelement");
   2720 			wpabuf_free(nr);
   2721 			return -1;
   2722 		}
   2723 	}
   2724 
   2725 	if (!buf)
   2726 		goto set;
   2727 
   2728 	tmp = os_strstr(buf, "civic=");
   2729 	if (tmp) {
   2730 		buf = os_strchr(tmp, ' ');
   2731 		if (buf)
   2732 			*buf++ = '\0';
   2733 		civic = wpabuf_parse_bin(tmp + 6);
   2734 		if (!civic) {
   2735 			wpa_printf(MSG_ERROR,
   2736 				   "CTRL: SET_NEIGHBOR: Bad civic subelement");
   2737 			wpabuf_free(nr);
   2738 			wpabuf_free(lci);
   2739 			return -1;
   2740 		}
   2741 	}
   2742 
   2743 	if (!buf)
   2744 		goto set;
   2745 
   2746 	if (os_strstr(buf, "stat"))
   2747 		stationary = 1;
   2748 
   2749 set:
   2750 	ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic,
   2751 				   stationary);
   2752 
   2753 	wpabuf_free(nr);
   2754 	wpabuf_free(lci);
   2755 	wpabuf_free(civic);
   2756 
   2757 	return ret;
   2758 }
   2759 
   2760 
   2761 static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
   2762 					      char *buf)
   2763 {
   2764 	struct wpa_ssid_value ssid;
   2765 	u8 bssid[ETH_ALEN];
   2766 	char *tmp;
   2767 
   2768 	if (hwaddr_aton(buf, bssid)) {
   2769 		wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
   2770 		return -1;
   2771 	}
   2772 
   2773 	tmp = os_strstr(buf, "ssid=");
   2774 	if (!tmp || ssid_parse(tmp + 5, &ssid)) {
   2775 		wpa_printf(MSG_ERROR,
   2776 			   "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
   2777 		return -1;
   2778 	}
   2779 
   2780 	return hostapd_neighbor_remove(hapd, bssid, &ssid);
   2781 }
   2782 
   2783 
   2784 static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
   2785 				     size_t buflen)
   2786 {
   2787 	int ret, i;
   2788 	char *pos, *end;
   2789 
   2790 	ret = os_snprintf(buf, buflen, "%016llX:\n",
   2791 			  (long long unsigned) iface->drv_flags);
   2792 	if (os_snprintf_error(buflen, ret))
   2793 		return -1;
   2794 
   2795 	pos = buf + ret;
   2796 	end = buf + buflen;
   2797 
   2798 	for (i = 0; i < 64; i++) {
   2799 		if (iface->drv_flags & (1LLU << i)) {
   2800 			ret = os_snprintf(pos, end - pos, "%s\n",
   2801 					  driver_flag_to_string(1LLU << i));
   2802 			if (os_snprintf_error(end - pos, ret))
   2803 				return -1;
   2804 			pos += ret;
   2805 		}
   2806 	}
   2807 
   2808 	return pos - buf;
   2809 }
   2810 
   2811 
   2812 static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num,
   2813 					  const char *txtaddr)
   2814 {
   2815 	u8 addr[ETH_ALEN];
   2816 	struct vlan_description vlan_id;
   2817 
   2818 	if (!(*num))
   2819 		return 0;
   2820 
   2821 	if (hwaddr_aton(txtaddr, addr))
   2822 		return -1;
   2823 
   2824 	if (hostapd_maclist_found(*acl, *num, addr, &vlan_id))
   2825 		hostapd_remove_acl_mac(acl, num, addr);
   2826 
   2827 	return 0;
   2828 }
   2829 
   2830 
   2831 static void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl,
   2832 					      int *num)
   2833 {
   2834 	while (*num)
   2835 		hostapd_remove_acl_mac(acl, num, (*acl)[0].addr);
   2836 }
   2837 
   2838 
   2839 static int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num,
   2840 					   char *buf, size_t buflen)
   2841 {
   2842 	int i = 0, len = 0, ret = 0;
   2843 
   2844 	if (!acl)
   2845 		return 0;
   2846 
   2847 	while (i < num) {
   2848 		ret = os_snprintf(buf + len, buflen - len,
   2849 				  MACSTR " VLAN_ID=%d\n",
   2850 				  MAC2STR(acl[i].addr),
   2851 				  acl[i].vlan_id.untagged);
   2852 		if (ret < 0 || (size_t) ret >= buflen - len)
   2853 			return len;
   2854 		i++;
   2855 		len += ret;
   2856 	}
   2857 	return len;
   2858 }
   2859 
   2860 
   2861 static int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num,
   2862 					  const char *cmd)
   2863 {
   2864 	u8 addr[ETH_ALEN];
   2865 	struct vlan_description vlan_id;
   2866 	int ret = 0, vlanid = 0;
   2867 	const char *pos;
   2868 
   2869 	if (hwaddr_aton(cmd, addr))
   2870 		return -1;
   2871 
   2872 	pos = os_strstr(cmd, "VLAN_ID=");
   2873 	if (pos)
   2874 		vlanid = atoi(pos + 8);
   2875 
   2876 	if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) {
   2877 		ret = hostapd_add_acl_maclist(acl, num, vlanid, addr);
   2878 		if (ret != -1 && *acl)
   2879 			qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
   2880 	}
   2881 
   2882 	return ret < 0 ? -1 : 0;
   2883 }
   2884 
   2885 
   2886 static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd,
   2887 					     const char *field, char *buf,
   2888 					     size_t buflen)
   2889 {
   2890 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
   2891 
   2892 #ifdef CONFIG_DPP
   2893 	if (os_strcmp(field, "dpp") == 0) {
   2894 		int res;
   2895 
   2896 #ifdef CONFIG_DPP2
   2897 		res = os_snprintf(buf, buflen, "DPP=2");
   2898 #else /* CONFIG_DPP2 */
   2899 		res = os_snprintf(buf, buflen, "DPP=1");
   2900 #endif /* CONFIG_DPP2 */
   2901 		if (os_snprintf_error(buflen, res))
   2902 			return -1;
   2903 		return res;
   2904 	}
   2905 #endif /* CONFIG_DPP */
   2906 
   2907 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
   2908 		   field);
   2909 
   2910 	return -1;
   2911 }
   2912 
   2913 
   2914 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
   2915 					      char *buf, char *reply,
   2916 					      int reply_size,
   2917 					      struct sockaddr_storage *from,
   2918 					      socklen_t fromlen)
   2919 {
   2920 	int reply_len, res;
   2921 
   2922 	os_memcpy(reply, "OK\n", 3);
   2923 	reply_len = 3;
   2924 
   2925 	if (os_strcmp(buf, "PING") == 0) {
   2926 		os_memcpy(reply, "PONG\n", 5);
   2927 		reply_len = 5;
   2928 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
   2929 		if (wpa_debug_reopen_file() < 0)
   2930 			reply_len = -1;
   2931 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
   2932 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
   2933 	} else if (os_strcmp(buf, "STATUS") == 0) {
   2934 		reply_len = hostapd_ctrl_iface_status(hapd, reply,
   2935 						      reply_size);
   2936 	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
   2937 		reply_len = hostapd_drv_status(hapd, reply, reply_size);
   2938 	} else if (os_strcmp(buf, "MIB") == 0) {
   2939 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
   2940 		if (reply_len >= 0) {
   2941 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
   2942 					  reply_size - reply_len);
   2943 			if (res < 0)
   2944 				reply_len = -1;
   2945 			else
   2946 				reply_len += res;
   2947 		}
   2948 		if (reply_len >= 0) {
   2949 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
   2950 						 reply_size - reply_len);
   2951 			if (res < 0)
   2952 				reply_len = -1;
   2953 			else
   2954 				reply_len += res;
   2955 		}
   2956 #ifndef CONFIG_NO_RADIUS
   2957 		if (reply_len >= 0) {
   2958 			res = radius_client_get_mib(hapd->radius,
   2959 						    reply + reply_len,
   2960 						    reply_size - reply_len);
   2961 			if (res < 0)
   2962 				reply_len = -1;
   2963 			else
   2964 				reply_len += res;
   2965 		}
   2966 #endif /* CONFIG_NO_RADIUS */
   2967 	} else if (os_strncmp(buf, "MIB ", 4) == 0) {
   2968 		reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
   2969 						   buf + 4);
   2970 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
   2971 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
   2972 							 reply_size);
   2973 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
   2974 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
   2975 						   reply_size);
   2976 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
   2977 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
   2978 							reply_size);
   2979 	} else if (os_strcmp(buf, "ATTACH") == 0) {
   2980 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL))
   2981 			reply_len = -1;
   2982 	} else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
   2983 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen, buf + 7))
   2984 			reply_len = -1;
   2985 	} else if (os_strcmp(buf, "DETACH") == 0) {
   2986 		if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
   2987 			reply_len = -1;
   2988 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
   2989 		if (hostapd_ctrl_iface_level(hapd, from, fromlen,
   2990 						    buf + 6))
   2991 			reply_len = -1;
   2992 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
   2993 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
   2994 			reply_len = -1;
   2995 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
   2996 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
   2997 			reply_len = -1;
   2998 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
   2999 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
   3000 			reply_len = -1;
   3001 #ifdef CONFIG_TAXONOMY
   3002 	} else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) {
   3003 		reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10,
   3004 							 reply, reply_size);
   3005 #endif /* CONFIG_TAXONOMY */
   3006 	} else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
   3007 		if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
   3008 			reply_len = -1;
   3009 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
   3010 		if (hostapd_ctrl_iface_stop_ap(hapd))
   3011 			reply_len = -1;
   3012 #ifdef CONFIG_IEEE80211W
   3013 #ifdef NEED_AP_MLME
   3014 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
   3015 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
   3016 			reply_len = -1;
   3017 #endif /* NEED_AP_MLME */
   3018 #endif /* CONFIG_IEEE80211W */
   3019 #ifdef CONFIG_WPS
   3020 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
   3021 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
   3022 			reply_len = -1;
   3023 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
   3024 		reply_len = hostapd_ctrl_iface_wps_check_pin(
   3025 			hapd, buf + 14, reply, reply_size);
   3026 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
   3027 		if (hostapd_wps_button_pushed(hapd, NULL))
   3028 			reply_len = -1;
   3029 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
   3030 		if (hostapd_wps_cancel(hapd))
   3031 			reply_len = -1;
   3032 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
   3033 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
   3034 							  reply, reply_size);
   3035 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
   3036 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
   3037 			reply_len = -1;
   3038 	} else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
   3039 		reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
   3040 							      reply_size);
   3041 #ifdef CONFIG_WPS_NFC
   3042 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
   3043 		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
   3044 			reply_len = -1;
   3045 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
   3046 		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
   3047 			hapd, buf + 21, reply, reply_size);
   3048 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
   3049 		reply_len = hostapd_ctrl_iface_wps_nfc_token(
   3050 			hapd, buf + 14, reply, reply_size);
   3051 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
   3052 		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
   3053 			hapd, buf + 21, reply, reply_size);
   3054 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
   3055 		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
   3056 			reply_len = -1;
   3057 #endif /* CONFIG_WPS_NFC */
   3058 #endif /* CONFIG_WPS */
   3059 #ifdef CONFIG_INTERWORKING
   3060 	} else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
   3061 		if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
   3062 			reply_len = -1;
   3063 	} else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
   3064 		if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
   3065 			reply_len = -1;
   3066 #endif /* CONFIG_INTERWORKING */
   3067 #ifdef CONFIG_HS20
   3068 	} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
   3069 		if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
   3070 			reply_len = -1;
   3071 	} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
   3072 		if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
   3073 			reply_len = -1;
   3074 #endif /* CONFIG_HS20 */
   3075 #ifdef CONFIG_WNM_AP
   3076 	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
   3077 		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
   3078 			reply_len = -1;
   3079 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
   3080 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
   3081 			reply_len = -1;
   3082 	} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
   3083 		if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
   3084 			reply_len = -1;
   3085 	} else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) {
   3086 		if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
   3087 			reply_len = -1;
   3088 #endif /* CONFIG_WNM_AP */
   3089 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
   3090 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
   3091 							  reply_size);
   3092 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
   3093 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
   3094 			reply_len = -1;
   3095 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
   3096 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
   3097 						   reply_size);
   3098 	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
   3099 		if (hostapd_ctrl_iface_enable(hapd->iface))
   3100 			reply_len = -1;
   3101 	} else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) {
   3102 		if (hostapd_ctrl_iface_reload_wpa_psk(hapd))
   3103 			reply_len = -1;
   3104 	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
   3105 		if (hostapd_ctrl_iface_reload(hapd->iface))
   3106 			reply_len = -1;
   3107 	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
   3108 		if (hostapd_ctrl_iface_disable(hapd->iface))
   3109 			reply_len = -1;
   3110 	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
   3111 		if (ieee802_11_set_beacon(hapd))
   3112 			reply_len = -1;
   3113 #ifdef CONFIG_TESTING_OPTIONS
   3114 	} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
   3115 		if (hostapd_ctrl_iface_radar(hapd, buf + 6))
   3116 			reply_len = -1;
   3117 	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
   3118 		if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
   3119 			reply_len = -1;
   3120 	} else if (os_strncmp(buf, "MGMT_TX_STATUS_PROCESS ", 23) == 0) {
   3121 		if (hostapd_ctrl_iface_mgmt_tx_status_process(hapd,
   3122 							      buf + 23) < 0)
   3123 			reply_len = -1;
   3124 	} else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
   3125 		if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0)
   3126 			reply_len = -1;
   3127 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
   3128 		if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
   3129 			reply_len = -1;
   3130 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
   3131 		if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
   3132 			reply_len = -1;
   3133 	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
   3134 		if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
   3135 			reply_len = -1;
   3136 	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
   3137 		if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
   3138 			reply_len = -1;
   3139 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
   3140 		if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
   3141 			reply_len = -1;
   3142 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
   3143 		reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
   3144 							reply_size);
   3145 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
   3146 		if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
   3147 			reply_len = -1;
   3148 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
   3149 		reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
   3150 	} else if (os_strncmp(buf, "RESET_PN ", 9) == 0) {
   3151 		if (hostapd_ctrl_reset_pn(hapd, buf + 9) < 0)
   3152 			reply_len = -1;
   3153 	} else if (os_strncmp(buf, "SET_KEY ", 8) == 0) {
   3154 		if (hostapd_ctrl_set_key(hapd, buf + 8) < 0)
   3155 			reply_len = -1;
   3156 	} else if (os_strncmp(buf, "RESEND_M1 ", 10) == 0) {
   3157 		if (hostapd_ctrl_resend_m1(hapd, buf + 10) < 0)
   3158 			reply_len = -1;
   3159 	} else if (os_strncmp(buf, "RESEND_M3 ", 10) == 0) {
   3160 		if (hostapd_ctrl_resend_m3(hapd, buf + 10) < 0)
   3161 			reply_len = -1;
   3162 	} else if (os_strncmp(buf, "RESEND_GROUP_M1 ", 16) == 0) {
   3163 		if (hostapd_ctrl_resend_group_m1(hapd, buf + 16) < 0)
   3164 			reply_len = -1;
   3165 	} else if (os_strcmp(buf, "REKEY_GTK") == 0) {
   3166 		if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0)
   3167 			reply_len = -1;
   3168 #endif /* CONFIG_TESTING_OPTIONS */
   3169 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
   3170 		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
   3171 			reply_len = -1;
   3172 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
   3173 		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
   3174 						      reply_size);
   3175 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
   3176 		ieee802_1x_erp_flush(hapd);
   3177 #ifdef RADIUS_SERVER
   3178 		radius_server_erp_flush(hapd->radius_srv);
   3179 #endif /* RADIUS_SERVER */
   3180 	} else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
   3181 		if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
   3182 			reply_len = -1;
   3183 	} else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
   3184 		if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
   3185 			reply_len = -1;
   3186 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
   3187 		reply_len = hostapd_ctrl_iface_log_level(
   3188 			hapd, buf + 9, reply, reply_size);
   3189 #ifdef NEED_AP_MLME
   3190 	} else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
   3191 		reply_len = hostapd_ctrl_iface_track_sta_list(
   3192 			hapd, reply, reply_size);
   3193 #endif /* NEED_AP_MLME */
   3194 	} else if (os_strcmp(buf, "PMKSA") == 0) {
   3195 		reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
   3196 							  reply_size);
   3197 	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
   3198 		hostapd_ctrl_iface_pmksa_flush(hapd);
   3199 	} else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
   3200 		if (hostapd_ctrl_iface_pmksa_add(hapd, buf + 10) < 0)
   3201 			reply_len = -1;
   3202 	} else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
   3203 		if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
   3204 			reply_len = -1;
   3205 	} else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
   3206 		if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
   3207 			reply_len = -1;
   3208 	} else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) {
   3209 		if (hostapd_ctrl_iface_req_lci(hapd, buf + 8))
   3210 			reply_len = -1;
   3211 	} else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
   3212 		if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
   3213 			reply_len = -1;
   3214 	} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
   3215 		reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
   3216 							  reply, reply_size);
   3217 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
   3218 		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
   3219 						      reply_size);
   3220 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   3221 		eloop_terminate();
   3222 	} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
   3223 		if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
   3224 			if (!hostapd_ctrl_iface_acl_add_mac(
   3225 				    &hapd->conf->accept_mac,
   3226 				    &hapd->conf->num_accept_mac, buf + 19))
   3227 				hostapd_disassoc_accept_mac(hapd);
   3228 			else
   3229 				reply_len = -1;
   3230 		} else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
   3231 			hostapd_ctrl_iface_acl_del_mac(
   3232 				&hapd->conf->accept_mac,
   3233 				&hapd->conf->num_accept_mac, buf + 19);
   3234 		} else if (os_strcmp(buf + 11, "SHOW") == 0) {
   3235 			reply_len = hostapd_ctrl_iface_acl_show_mac(
   3236 				hapd->conf->accept_mac,
   3237 				hapd->conf->num_accept_mac, reply, reply_size);
   3238 		} else if (os_strcmp(buf + 11, "CLEAR") == 0) {
   3239 			hostapd_ctrl_iface_acl_clear_list(
   3240 				&hapd->conf->accept_mac,
   3241 				&hapd->conf->num_accept_mac);
   3242 		}
   3243 	} else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
   3244 		if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
   3245 			if (!hostapd_ctrl_iface_acl_add_mac(
   3246 				    &hapd->conf->deny_mac,
   3247 				    &hapd->conf->num_deny_mac, buf + 17))
   3248 				hostapd_disassoc_deny_mac(hapd);
   3249 		} else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
   3250 			hostapd_ctrl_iface_acl_del_mac(
   3251 				&hapd->conf->deny_mac,
   3252 				&hapd->conf->num_deny_mac, buf + 17);
   3253 		} else if (os_strcmp(buf + 9, "SHOW") == 0) {
   3254 			reply_len = hostapd_ctrl_iface_acl_show_mac(
   3255 				hapd->conf->deny_mac,
   3256 				hapd->conf->num_deny_mac, reply, reply_size);
   3257 		} else if (os_strcmp(buf + 9, "CLEAR") == 0) {
   3258 			hostapd_ctrl_iface_acl_clear_list(
   3259 				&hapd->conf->deny_mac,
   3260 				&hapd->conf->num_deny_mac);
   3261 		}
   3262 #ifdef CONFIG_DPP
   3263 	} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
   3264 		res = hostapd_dpp_qr_code(hapd, buf + 12);
   3265 		if (res < 0) {
   3266 			reply_len = -1;
   3267 		} else {
   3268 			reply_len = os_snprintf(reply, reply_size, "%d", res);
   3269 			if (os_snprintf_error(reply_size, reply_len))
   3270 				reply_len = -1;
   3271 		}
   3272 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
   3273 		res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
   3274 		if (res < 0) {
   3275 			reply_len = -1;
   3276 		} else {
   3277 			reply_len = os_snprintf(reply, reply_size, "%d", res);
   3278 			if (os_snprintf_error(reply_size, reply_len))
   3279 				reply_len = -1;
   3280 		}
   3281 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
   3282 		if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp,
   3283 					 buf + 21) < 0)
   3284 			reply_len = -1;
   3285 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
   3286 		const char *uri;
   3287 
   3288 		uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp,
   3289 					    atoi(buf + 22));
   3290 		if (!uri) {
   3291 			reply_len = -1;
   3292 		} else {
   3293 			reply_len = os_snprintf(reply, reply_size, "%s", uri);
   3294 			if (os_snprintf_error(reply_size, reply_len))
   3295 				reply_len = -1;
   3296 		}
   3297 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
   3298 		reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
   3299 					       atoi(buf + 19),
   3300 			reply, reply_size);
   3301 	} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
   3302 		if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
   3303 			reply_len = -1;
   3304 	} else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
   3305 		if (hostapd_dpp_listen(hapd, buf + 11) < 0)
   3306 			reply_len = -1;
   3307 	} else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
   3308 		hostapd_dpp_stop(hapd);
   3309 		hostapd_dpp_listen_stop(hapd);
   3310 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
   3311 		res = dpp_configurator_add(hapd->iface->interfaces->dpp,
   3312 					   buf + 20);
   3313 		if (res < 0) {
   3314 			reply_len = -1;
   3315 		} else {
   3316 			reply_len = os_snprintf(reply, reply_size, "%d", res);
   3317 			if (os_snprintf_error(reply_size, reply_len))
   3318 				reply_len = -1;
   3319 		}
   3320 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
   3321 		if (dpp_configurator_remove(hapd->iface->interfaces->dpp,
   3322 					    buf + 24) < 0)
   3323 			reply_len = -1;
   3324 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
   3325 		if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0)
   3326 			reply_len = -1;
   3327 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
   3328 		reply_len = dpp_configurator_get_key_id(
   3329 			hapd->iface->interfaces->dpp,
   3330 			atoi(buf + 25),
   3331 			reply, reply_size);
   3332 	} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
   3333 		res = hostapd_dpp_pkex_add(hapd, buf + 12);
   3334 		if (res < 0) {
   3335 			reply_len = -1;
   3336 		} else {
   3337 			reply_len = os_snprintf(reply, reply_size, "%d", res);
   3338 			if (os_snprintf_error(reply_size, reply_len))
   3339 				reply_len = -1;
   3340 		}
   3341 	} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
   3342 		if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0)
   3343 			reply_len = -1;
   3344 #endif /* CONFIG_DPP */
   3345 #ifdef RADIUS_SERVER
   3346 	} else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
   3347 		if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0)
   3348 			reply_len = -1;
   3349 #endif /* RADIUS_SERVER */
   3350 	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
   3351 		reply_len = hostapd_ctrl_iface_get_capability(
   3352 			hapd, buf + 15, reply, reply_size);
   3353 	} else {
   3354 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   3355 		reply_len = 16;
   3356 	}
   3357 
   3358 	if (reply_len < 0) {
   3359 		os_memcpy(reply, "FAIL\n", 5);
   3360 		reply_len = 5;
   3361 	}
   3362 
   3363 	return reply_len;
   3364 }
   3365 
   3366 
   3367 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
   3368 				       void *sock_ctx)
   3369 {
   3370 	struct hostapd_data *hapd = eloop_ctx;
   3371 	char buf[4096];
   3372 	int res;
   3373 	struct sockaddr_storage from;
   3374 	socklen_t fromlen = sizeof(from);
   3375 	char *reply, *pos = buf;
   3376 	const int reply_size = 4096;
   3377 	int reply_len;
   3378 	int level = MSG_DEBUG;
   3379 #ifdef CONFIG_CTRL_IFACE_UDP
   3380 	unsigned char lcookie[COOKIE_LEN];
   3381 #endif /* CONFIG_CTRL_IFACE_UDP */
   3382 
   3383 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
   3384 		       (struct sockaddr *) &from, &fromlen);
   3385 	if (res < 0) {
   3386 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
   3387 			   strerror(errno));
   3388 		return;
   3389 	}
   3390 	buf[res] = '\0';
   3391 
   3392 	reply = os_malloc(reply_size);
   3393 	if (reply == NULL) {
   3394 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
   3395 			   fromlen) < 0) {
   3396 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   3397 				   strerror(errno));
   3398 		}
   3399 		return;
   3400 	}
   3401 
   3402 #ifdef CONFIG_CTRL_IFACE_UDP
   3403 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
   3404 		os_memcpy(reply, "COOKIE=", 7);
   3405 		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
   3406 				 cookie, COOKIE_LEN);
   3407 		reply_len = 7 + 2 * COOKIE_LEN;
   3408 		goto done;
   3409 	}
   3410 
   3411 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
   3412 	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
   3413 		wpa_printf(MSG_DEBUG,
   3414 			   "CTRL: No cookie in the request - drop request");
   3415 		os_free(reply);
   3416 		return;
   3417 	}
   3418 
   3419 	if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
   3420 		wpa_printf(MSG_DEBUG,
   3421 			   "CTRL: Invalid cookie in the request - drop request");
   3422 		os_free(reply);
   3423 		return;
   3424 	}
   3425 
   3426 	pos = buf + 7 + 2 * COOKIE_LEN;
   3427 	while (*pos == ' ')
   3428 		pos++;
   3429 #endif /* CONFIG_CTRL_IFACE_UDP */
   3430 
   3431 	if (os_strcmp(pos, "PING") == 0)
   3432 		level = MSG_EXCESSIVE;
   3433 	wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
   3434 
   3435 	reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
   3436 						       reply, reply_size,
   3437 						       &from, fromlen);
   3438 
   3439 #ifdef CONFIG_CTRL_IFACE_UDP
   3440 done:
   3441 #endif /* CONFIG_CTRL_IFACE_UDP */
   3442 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
   3443 		   fromlen) < 0) {
   3444 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   3445 			   strerror(errno));
   3446 	}
   3447 	os_free(reply);
   3448 }
   3449 
   3450 
   3451 #ifndef CONFIG_CTRL_IFACE_UDP
   3452 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
   3453 {
   3454 	char *buf;
   3455 	size_t len;
   3456 
   3457 	if (hapd->conf->ctrl_interface == NULL)
   3458 		return NULL;
   3459 
   3460 	len = os_strlen(hapd->conf->ctrl_interface) +
   3461 		os_strlen(hapd->conf->iface) + 2;
   3462 	buf = os_malloc(len);
   3463 	if (buf == NULL)
   3464 		return NULL;
   3465 
   3466 	os_snprintf(buf, len, "%s/%s",
   3467 		    hapd->conf->ctrl_interface, hapd->conf->iface);
   3468 	buf[len - 1] = '\0';
   3469 	return buf;
   3470 }
   3471 #endif /* CONFIG_CTRL_IFACE_UDP */
   3472 
   3473 
   3474 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
   3475 				      enum wpa_msg_type type,
   3476 				      const char *txt, size_t len)
   3477 {
   3478 	struct hostapd_data *hapd = ctx;
   3479 	if (hapd == NULL)
   3480 		return;
   3481 	hostapd_ctrl_iface_send(hapd, level, type, txt, len);
   3482 }
   3483 
   3484 
   3485 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
   3486 {
   3487 #ifdef CONFIG_CTRL_IFACE_UDP
   3488 	int port = HOSTAPD_CTRL_IFACE_PORT;
   3489 	char p[32] = { 0 };
   3490 	char port_str[40], *tmp;
   3491 	char *pos;
   3492 	struct addrinfo hints = { 0 }, *res, *saveres;
   3493 	int n;
   3494 
   3495 	if (hapd->ctrl_sock > -1) {
   3496 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   3497 		return 0;
   3498 	}
   3499 
   3500 	if (hapd->conf->ctrl_interface == NULL)
   3501 		return 0;
   3502 
   3503 	pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
   3504 	if (pos) {
   3505 		pos += 4;
   3506 		port = atoi(pos);
   3507 		if (port <= 0) {
   3508 			wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
   3509 			goto fail;
   3510 		}
   3511 	}
   3512 
   3513 	dl_list_init(&hapd->ctrl_dst);
   3514 	hapd->ctrl_sock = -1;
   3515 	os_get_random(cookie, COOKIE_LEN);
   3516 
   3517 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
   3518 	hints.ai_flags = AI_PASSIVE;
   3519 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
   3520 
   3521 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
   3522 	hints.ai_family = AF_INET6;
   3523 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   3524 	hints.ai_family = AF_INET;
   3525 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   3526 	hints.ai_socktype = SOCK_DGRAM;
   3527 
   3528 try_again:
   3529 	os_snprintf(p, sizeof(p), "%d", port);
   3530 	n = getaddrinfo(NULL, p, &hints, &res);
   3531 	if (n) {
   3532 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
   3533 		goto fail;
   3534 	}
   3535 
   3536 	saveres = res;
   3537 	hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
   3538 				 res->ai_protocol);
   3539 	if (hapd->ctrl_sock < 0) {
   3540 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
   3541 		goto fail;
   3542 	}
   3543 
   3544 	if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
   3545 		port--;
   3546 		if ((HOSTAPD_CTRL_IFACE_PORT - port) <
   3547 		    HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
   3548 			goto try_again;
   3549 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
   3550 		goto fail;
   3551 	}
   3552 
   3553 	freeaddrinfo(saveres);
   3554 
   3555 	os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
   3556 	tmp = os_strdup(port_str);
   3557 	if (tmp) {
   3558 		os_free(hapd->conf->ctrl_interface);
   3559 		hapd->conf->ctrl_interface = tmp;
   3560 	}
   3561 	wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
   3562 
   3563 	if (eloop_register_read_sock(hapd->ctrl_sock,
   3564 				     hostapd_ctrl_iface_receive, hapd, NULL) <
   3565 	    0) {
   3566 		hostapd_ctrl_iface_deinit(hapd);
   3567 		return -1;
   3568 	}
   3569 
   3570 	hapd->msg_ctx = hapd;
   3571 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
   3572 
   3573 	return 0;
   3574 
   3575 fail:
   3576 	if (hapd->ctrl_sock >= 0)
   3577 		close(hapd->ctrl_sock);
   3578 	return -1;
   3579 #else /* CONFIG_CTRL_IFACE_UDP */
   3580 	struct sockaddr_un addr;
   3581 	int s = -1;
   3582 	char *fname = NULL;
   3583 
   3584 	if (hapd->ctrl_sock > -1) {
   3585 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   3586 		return 0;
   3587 	}
   3588 
   3589 	dl_list_init(&hapd->ctrl_dst);
   3590 
   3591 	if (hapd->conf->ctrl_interface == NULL)
   3592 		return 0;
   3593 
   3594 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
   3595 		if (errno == EEXIST) {
   3596 			wpa_printf(MSG_DEBUG, "Using existing control "
   3597 				   "interface directory.");
   3598 		} else {
   3599 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
   3600 				   strerror(errno));
   3601 			goto fail;
   3602 		}
   3603 	}
   3604 
   3605 	if (hapd->conf->ctrl_interface_gid_set &&
   3606 	    lchown(hapd->conf->ctrl_interface, -1,
   3607 		   hapd->conf->ctrl_interface_gid) < 0) {
   3608 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
   3609 			   strerror(errno));
   3610 		return -1;
   3611 	}
   3612 
   3613 	if (!hapd->conf->ctrl_interface_gid_set &&
   3614 	    hapd->iface->interfaces->ctrl_iface_group &&
   3615 	    lchown(hapd->conf->ctrl_interface, -1,
   3616 		   hapd->iface->interfaces->ctrl_iface_group) < 0) {
   3617 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
   3618 			   strerror(errno));
   3619 		return -1;
   3620 	}
   3621 
   3622 #ifdef ANDROID
   3623 	/*
   3624 	 * Android is using umask 0077 which would leave the control interface
   3625 	 * directory without group access. This breaks things since Wi-Fi
   3626 	 * framework assumes that this directory can be accessed by other
   3627 	 * applications in the wifi group. Fix this by adding group access even
   3628 	 * if umask value would prevent this.
   3629 	 */
   3630 	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
   3631 		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
   3632 			   strerror(errno));
   3633 		/* Try to continue anyway */
   3634 	}
   3635 #endif /* ANDROID */
   3636 
   3637 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
   3638 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
   3639 		goto fail;
   3640 
   3641 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   3642 	if (s < 0) {
   3643 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
   3644 		goto fail;
   3645 	}
   3646 
   3647 	os_memset(&addr, 0, sizeof(addr));
   3648 #ifdef __FreeBSD__
   3649 	addr.sun_len = sizeof(addr);
   3650 #endif /* __FreeBSD__ */
   3651 	addr.sun_family = AF_UNIX;
   3652 	fname = hostapd_ctrl_iface_path(hapd);
   3653 	if (fname == NULL)
   3654 		goto fail;
   3655 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   3656 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   3657 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   3658 			   strerror(errno));
   3659 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   3660 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   3661 				   " allow connections - assuming it was left"
   3662 				   "over from forced program termination");
   3663 			if (unlink(fname) < 0) {
   3664 				wpa_printf(MSG_ERROR,
   3665 					   "Could not unlink existing ctrl_iface socket '%s': %s",
   3666 					   fname, strerror(errno));
   3667 				goto fail;
   3668 			}
   3669 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   3670 			    0) {
   3671 				wpa_printf(MSG_ERROR,
   3672 					   "hostapd-ctrl-iface: bind(PF_UNIX): %s",
   3673 					   strerror(errno));
   3674 				goto fail;
   3675 			}
   3676 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   3677 				   "ctrl_iface socket '%s'", fname);
   3678 		} else {
   3679 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   3680 				   "be in use - cannot override it");
   3681 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   3682 				   "not used anymore", fname);
   3683 			os_free(fname);
   3684 			fname = NULL;
   3685 			goto fail;
   3686 		}
   3687 	}
   3688 
   3689 	if (hapd->conf->ctrl_interface_gid_set &&
   3690 	    lchown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
   3691 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
   3692 			   strerror(errno));
   3693 		goto fail;
   3694 	}
   3695 
   3696 	if (!hapd->conf->ctrl_interface_gid_set &&
   3697 	    hapd->iface->interfaces->ctrl_iface_group &&
   3698 	    lchown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
   3699 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
   3700 			   strerror(errno));
   3701 		goto fail;
   3702 	}
   3703 
   3704 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   3705 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
   3706 			   strerror(errno));
   3707 		goto fail;
   3708 	}
   3709 	os_free(fname);
   3710 
   3711 	hapd->ctrl_sock = s;
   3712 	if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
   3713 				     NULL) < 0) {
   3714 		hostapd_ctrl_iface_deinit(hapd);
   3715 		return -1;
   3716 	}
   3717 	hapd->msg_ctx = hapd;
   3718 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
   3719 
   3720 	return 0;
   3721 
   3722 fail:
   3723 	if (s >= 0)
   3724 		close(s);
   3725 	if (fname) {
   3726 		unlink(fname);
   3727 		os_free(fname);
   3728 	}
   3729 	return -1;
   3730 #endif /* CONFIG_CTRL_IFACE_UDP */
   3731 }
   3732 
   3733 
   3734 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
   3735 {
   3736 	struct wpa_ctrl_dst *dst, *prev;
   3737 
   3738 	if (hapd->ctrl_sock > -1) {
   3739 #ifndef CONFIG_CTRL_IFACE_UDP
   3740 		char *fname;
   3741 #endif /* !CONFIG_CTRL_IFACE_UDP */
   3742 
   3743 		eloop_unregister_read_sock(hapd->ctrl_sock);
   3744 		close(hapd->ctrl_sock);
   3745 		hapd->ctrl_sock = -1;
   3746 #ifndef CONFIG_CTRL_IFACE_UDP
   3747 		fname = hostapd_ctrl_iface_path(hapd);
   3748 		if (fname)
   3749 			unlink(fname);
   3750 		os_free(fname);
   3751 
   3752 		if (hapd->conf->ctrl_interface &&
   3753 		    rmdir(hapd->conf->ctrl_interface) < 0) {
   3754 			if (errno == ENOTEMPTY) {
   3755 				wpa_printf(MSG_DEBUG, "Control interface "
   3756 					   "directory not empty - leaving it "
   3757 					   "behind");
   3758 			} else {
   3759 				wpa_printf(MSG_ERROR,
   3760 					   "rmdir[ctrl_interface=%s]: %s",
   3761 					   hapd->conf->ctrl_interface,
   3762 					   strerror(errno));
   3763 			}
   3764 		}
   3765 #endif /* !CONFIG_CTRL_IFACE_UDP */
   3766 	}
   3767 
   3768 	dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
   3769 			      list)
   3770 		os_free(dst);
   3771 
   3772 #ifdef CONFIG_TESTING_OPTIONS
   3773 	l2_packet_deinit(hapd->l2_test);
   3774 	hapd->l2_test = NULL;
   3775 #endif /* CONFIG_TESTING_OPTIONS */
   3776 }
   3777 
   3778 
   3779 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
   3780 				  char *buf)
   3781 {
   3782 	if (hostapd_add_iface(interfaces, buf) < 0) {
   3783 		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
   3784 		return -1;
   3785 	}
   3786 	return 0;
   3787 }
   3788 
   3789 
   3790 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
   3791 				     char *buf)
   3792 {
   3793 	if (hostapd_remove_iface(interfaces, buf) < 0) {
   3794 		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
   3795 		return -1;
   3796 	}
   3797 	return 0;
   3798 }
   3799 
   3800 
   3801 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
   3802 					    struct sockaddr_storage *from,
   3803 					    socklen_t fromlen, char *input)
   3804 {
   3805 	return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen,
   3806 				 input);
   3807 }
   3808 
   3809 
   3810 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
   3811 					    struct sockaddr_storage *from,
   3812 					    socklen_t fromlen)
   3813 {
   3814 	return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
   3815 }
   3816 
   3817 
   3818 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
   3819 {
   3820 #ifdef CONFIG_WPS_TESTING
   3821 	wps_version_number = 0x20;
   3822 	wps_testing_dummy_cred = 0;
   3823 	wps_corrupt_pkhash = 0;
   3824 #endif /* CONFIG_WPS_TESTING */
   3825 
   3826 #ifdef CONFIG_TESTING_OPTIONS
   3827 #ifdef CONFIG_DPP
   3828 	dpp_test = DPP_TEST_DISABLED;
   3829 #endif /* CONFIG_DPP */
   3830 #endif /* CONFIG_TESTING_OPTIONS */
   3831 
   3832 #ifdef CONFIG_DPP
   3833 	dpp_global_clear(interfaces->dpp);
   3834 #endif /* CONFIG_DPP */
   3835 }
   3836 
   3837 
   3838 #ifdef CONFIG_FST
   3839 
   3840 static int
   3841 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
   3842 				     const char *cmd)
   3843 {
   3844 	char ifname[IFNAMSIZ + 1];
   3845 	struct fst_iface_cfg cfg;
   3846 	struct hostapd_data *hapd;
   3847 	struct fst_wpa_obj iface_obj;
   3848 
   3849 	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
   3850 		hapd = hostapd_get_iface(interfaces, ifname);
   3851 		if (hapd) {
   3852 			if (hapd->iface->fst) {
   3853 				wpa_printf(MSG_INFO, "FST: Already attached");
   3854 				return -1;
   3855 			}
   3856 			fst_hostapd_fill_iface_obj(hapd, &iface_obj);
   3857 			hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
   3858 						      &iface_obj, &cfg);
   3859 			if (hapd->iface->fst)
   3860 				return 0;
   3861 		}
   3862 	}
   3863 
   3864 	return -EINVAL;
   3865 }
   3866 
   3867 
   3868 static int
   3869 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
   3870 				     const char *cmd)
   3871 {
   3872 	char ifname[IFNAMSIZ + 1];
   3873 	struct hostapd_data * hapd;
   3874 
   3875 	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
   3876 		hapd = hostapd_get_iface(interfaces, ifname);
   3877 		if (hapd) {
   3878 			if (!fst_iface_detach(ifname)) {
   3879 				hapd->iface->fst = NULL;
   3880 				hapd->iface->fst_ies = NULL;
   3881 				return 0;
   3882 			}
   3883 		}
   3884 	}
   3885 
   3886 	return -EINVAL;
   3887 }
   3888 
   3889 #endif /* CONFIG_FST */
   3890 
   3891 
   3892 static struct hostapd_data *
   3893 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
   3894 			    const char *ifname)
   3895 {
   3896 	size_t i, j;
   3897 
   3898 	for (i = 0; i < interfaces->count; i++) {
   3899 		struct hostapd_iface *iface = interfaces->iface[i];
   3900 
   3901 		for (j = 0; j < iface->num_bss; j++) {
   3902 			struct hostapd_data *hapd;
   3903 
   3904 			hapd = iface->bss[j];
   3905 			if (os_strcmp(ifname, hapd->conf->iface) == 0)
   3906 				return hapd;
   3907 		}
   3908 	}
   3909 
   3910 	return NULL;
   3911 }
   3912 
   3913 
   3914 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
   3915 					struct hostapd_data *dst_hapd,
   3916 					const char *param)
   3917 {
   3918 	int res;
   3919 	char *value;
   3920 
   3921 	value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
   3922 	if (!value) {
   3923 		wpa_printf(MSG_ERROR,
   3924 			   "DUP: cannot allocate buffer to stringify %s",
   3925 			   param);
   3926 		goto error_return;
   3927 	}
   3928 
   3929 	if (os_strcmp(param, "wpa") == 0) {
   3930 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
   3931 			    src_hapd->conf->wpa);
   3932 	} else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
   3933 		   src_hapd->conf->wpa_key_mgmt) {
   3934 		res = hostapd_ctrl_iface_get_key_mgmt(
   3935 			src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
   3936 		if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
   3937 			goto error_stringify;
   3938 	} else if (os_strcmp(param, "wpa_pairwise") == 0 &&
   3939 		   src_hapd->conf->wpa_pairwise) {
   3940 		res = wpa_write_ciphers(value,
   3941 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
   3942 					src_hapd->conf->wpa_pairwise, " ");
   3943 		if (res < 0)
   3944 			goto error_stringify;
   3945 	} else if (os_strcmp(param, "rsn_pairwise") == 0 &&
   3946 		   src_hapd->conf->rsn_pairwise) {
   3947 		res = wpa_write_ciphers(value,
   3948 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
   3949 					src_hapd->conf->rsn_pairwise, " ");
   3950 		if (res < 0)
   3951 			goto error_stringify;
   3952 	} else if (os_strcmp(param, "wpa_passphrase") == 0 &&
   3953 		   src_hapd->conf->ssid.wpa_passphrase) {
   3954 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
   3955 			    src_hapd->conf->ssid.wpa_passphrase);
   3956 	} else if (os_strcmp(param, "wpa_psk") == 0 &&
   3957 		   src_hapd->conf->ssid.wpa_psk_set) {
   3958 		wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
   3959 			src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
   3960 	} else {
   3961 		wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
   3962 		goto error_return;
   3963 	}
   3964 
   3965 	res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
   3966 	os_free(value);
   3967 	return res;
   3968 
   3969 error_stringify:
   3970 	wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
   3971 error_return:
   3972 	os_free(value);
   3973 	return -1;
   3974 }
   3975 
   3976 
   3977 static int
   3978 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
   3979 				     const char *input,
   3980 				     char *reply, int reply_size)
   3981 {
   3982 	size_t i, j;
   3983 	int res;
   3984 	char *pos, *end;
   3985 	struct hostapd_iface *iface;
   3986 	int show_ctrl = 0;
   3987 
   3988 	if (input)
   3989 		show_ctrl = !!os_strstr(input, "ctrl");
   3990 
   3991 	pos = reply;
   3992 	end = reply + reply_size;
   3993 
   3994 	for (i = 0; i < interfaces->count; i++) {
   3995 		iface = interfaces->iface[i];
   3996 
   3997 		for (j = 0; j < iface->num_bss; j++) {
   3998 			struct hostapd_bss_config *conf;
   3999 
   4000 			conf = iface->conf->bss[j];
   4001 			if (show_ctrl)
   4002 				res = os_snprintf(pos, end - pos,
   4003 						  "%s ctrl_iface=%s\n",
   4004 						  conf->iface,
   4005 						  conf->ctrl_interface ?
   4006 						  conf->ctrl_interface : "N/A");
   4007 			else
   4008 				res = os_snprintf(pos, end - pos, "%s\n",
   4009 						  conf->iface);
   4010 			if (os_snprintf_error(end - pos, res)) {
   4011 				*pos = '\0';
   4012 				return pos - reply;
   4013 			}
   4014 			pos += res;
   4015 		}
   4016 	}
   4017 
   4018 	return pos - reply;
   4019 }
   4020 
   4021 
   4022 static int
   4023 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
   4024 				      char *cmd)
   4025 {
   4026 	char *p_start = cmd, *p_end;
   4027 	struct hostapd_data *src_hapd, *dst_hapd;
   4028 
   4029 	/* cmd: "<src ifname> <dst ifname> <variable name> */
   4030 
   4031 	p_end = os_strchr(p_start, ' ');
   4032 	if (!p_end) {
   4033 		wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
   4034 			   cmd);
   4035 		return -1;
   4036 	}
   4037 
   4038 	*p_end = '\0';
   4039 	src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
   4040 	if (!src_hapd) {
   4041 		wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
   4042 			   p_start);
   4043 		return -1;
   4044 	}
   4045 
   4046 	p_start = p_end + 1;
   4047 	p_end = os_strchr(p_start, ' ');
   4048 	if (!p_end) {
   4049 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
   4050 			   cmd);
   4051 		return -1;
   4052 	}
   4053 
   4054 	*p_end = '\0';
   4055 	dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
   4056 	if (!dst_hapd) {
   4057 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
   4058 			   p_start);
   4059 		return -1;
   4060 	}
   4061 
   4062 	p_start = p_end + 1;
   4063 	return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
   4064 }
   4065 
   4066 
   4067 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
   4068 					    const char *ifname,
   4069 					    char *buf, char *reply,
   4070 					    int reply_size,
   4071 					    struct sockaddr_storage *from,
   4072 					    socklen_t fromlen)
   4073 {
   4074 	struct hostapd_data *hapd;
   4075 
   4076 	hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
   4077 	if (hapd == NULL) {
   4078 		int res;
   4079 
   4080 		res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
   4081 		if (os_snprintf_error(reply_size, res))
   4082 			return -1;
   4083 		return res;
   4084 	}
   4085 
   4086 	return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
   4087 						  from, fromlen);
   4088 }
   4089 
   4090 
   4091 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
   4092 					      void *sock_ctx)
   4093 {
   4094 	void *interfaces = eloop_ctx;
   4095 	char buffer[256], *buf = buffer;
   4096 	int res;
   4097 	struct sockaddr_storage from;
   4098 	socklen_t fromlen = sizeof(from);
   4099 	char *reply;
   4100 	int reply_len;
   4101 	const int reply_size = 4096;
   4102 #ifdef CONFIG_CTRL_IFACE_UDP
   4103 	unsigned char lcookie[COOKIE_LEN];
   4104 #endif /* CONFIG_CTRL_IFACE_UDP */
   4105 
   4106 	res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
   4107 		       (struct sockaddr *) &from, &fromlen);
   4108 	if (res < 0) {
   4109 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
   4110 			   strerror(errno));
   4111 		return;
   4112 	}
   4113 	buf[res] = '\0';
   4114 	wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
   4115 
   4116 	reply = os_malloc(reply_size);
   4117 	if (reply == NULL) {
   4118 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
   4119 			   fromlen) < 0) {
   4120 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   4121 				   strerror(errno));
   4122 		}
   4123 		return;
   4124 	}
   4125 
   4126 	os_memcpy(reply, "OK\n", 3);
   4127 	reply_len = 3;
   4128 
   4129 #ifdef CONFIG_CTRL_IFACE_UDP
   4130 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
   4131 		os_memcpy(reply, "COOKIE=", 7);
   4132 		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
   4133 				 gcookie, COOKIE_LEN);
   4134 		reply_len = 7 + 2 * COOKIE_LEN;
   4135 		goto send_reply;
   4136 	}
   4137 
   4138 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
   4139 	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
   4140 		wpa_printf(MSG_DEBUG,
   4141 			   "CTRL: No cookie in the request - drop request");
   4142 		os_free(reply);
   4143 		return;
   4144 	}
   4145 
   4146 	if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
   4147 		wpa_printf(MSG_DEBUG,
   4148 			   "CTRL: Invalid cookie in the request - drop request");
   4149 		os_free(reply);
   4150 		return;
   4151 	}
   4152 
   4153 	buf += 7 + 2 * COOKIE_LEN;
   4154 	while (*buf == ' ')
   4155 		buf++;
   4156 #endif /* CONFIG_CTRL_IFACE_UDP */
   4157 
   4158 	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
   4159 		char *pos = os_strchr(buf + 7, ' ');
   4160 
   4161 		if (pos) {
   4162 			*pos++ = '\0';
   4163 			reply_len = hostapd_global_ctrl_iface_ifname(
   4164 				interfaces, buf + 7, pos, reply, reply_size,
   4165 				&from, fromlen);
   4166 			goto send_reply;
   4167 		}
   4168 	}
   4169 
   4170 	if (os_strcmp(buf, "PING") == 0) {
   4171 		os_memcpy(reply, "PONG\n", 5);
   4172 		reply_len = 5;
   4173 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
   4174 		if (wpa_debug_reopen_file() < 0)
   4175 			reply_len = -1;
   4176 	} else if (os_strcmp(buf, "FLUSH") == 0) {
   4177 		hostapd_ctrl_iface_flush(interfaces);
   4178 	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
   4179 		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
   4180 			reply_len = -1;
   4181 	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
   4182 		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
   4183 			reply_len = -1;
   4184 	} else if (os_strcmp(buf, "ATTACH") == 0) {
   4185 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
   4186 						     fromlen, NULL))
   4187 			reply_len = -1;
   4188 	} else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
   4189 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
   4190 						     fromlen, buf + 7))
   4191 			reply_len = -1;
   4192 	} else if (os_strcmp(buf, "DETACH") == 0) {
   4193 		if (hostapd_global_ctrl_iface_detach(interfaces, &from,
   4194 			fromlen))
   4195 			reply_len = -1;
   4196 #ifdef CONFIG_MODULE_TESTS
   4197 	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
   4198 		if (hapd_module_tests() < 0)
   4199 			reply_len = -1;
   4200 #endif /* CONFIG_MODULE_TESTS */
   4201 #ifdef CONFIG_FST
   4202 	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
   4203 		if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
   4204 			reply_len = os_snprintf(reply, reply_size, "OK\n");
   4205 		else
   4206 			reply_len = -1;
   4207 	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
   4208 		if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
   4209 			reply_len = os_snprintf(reply, reply_size, "OK\n");
   4210 		else
   4211 			reply_len = -1;
   4212 	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
   4213 		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
   4214 #endif /* CONFIG_FST */
   4215 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
   4216 		if (!hostapd_global_ctrl_iface_dup_network(interfaces,
   4217 							   buf + 12))
   4218 			reply_len = os_snprintf(reply, reply_size, "OK\n");
   4219 		else
   4220 			reply_len = -1;
   4221 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
   4222 		reply_len = hostapd_global_ctrl_iface_interfaces(
   4223 			interfaces, buf + 10, reply, sizeof(buffer));
   4224 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   4225 		eloop_terminate();
   4226 	} else {
   4227 		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
   4228 			   "ignored");
   4229 		reply_len = -1;
   4230 	}
   4231 
   4232 send_reply:
   4233 	if (reply_len < 0) {
   4234 		os_memcpy(reply, "FAIL\n", 5);
   4235 		reply_len = 5;
   4236 	}
   4237 
   4238 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
   4239 		   fromlen) < 0) {
   4240 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   4241 			   strerror(errno));
   4242 	}
   4243 	os_free(reply);
   4244 }
   4245 
   4246 
   4247 #ifndef CONFIG_CTRL_IFACE_UDP
   4248 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
   4249 {
   4250 	char *buf;
   4251 	size_t len;
   4252 
   4253 	if (interface->global_iface_path == NULL)
   4254 		return NULL;
   4255 
   4256 	len = os_strlen(interface->global_iface_path) +
   4257 		os_strlen(interface->global_iface_name) + 2;
   4258 	buf = os_malloc(len);
   4259 	if (buf == NULL)
   4260 		return NULL;
   4261 
   4262 	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
   4263 		    interface->global_iface_name);
   4264 	buf[len - 1] = '\0';
   4265 	return buf;
   4266 }
   4267 #endif /* CONFIG_CTRL_IFACE_UDP */
   4268 
   4269 
   4270 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
   4271 {
   4272 #ifdef CONFIG_CTRL_IFACE_UDP
   4273 	int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
   4274 	char p[32] = { 0 };
   4275 	char *pos;
   4276 	struct addrinfo hints = { 0 }, *res, *saveres;
   4277 	int n;
   4278 
   4279 	if (interface->global_ctrl_sock > -1) {
   4280 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   4281 		return 0;
   4282 	}
   4283 
   4284 	if (interface->global_iface_path == NULL)
   4285 		return 0;
   4286 
   4287 	pos = os_strstr(interface->global_iface_path, "udp:");
   4288 	if (pos) {
   4289 		pos += 4;
   4290 		port = atoi(pos);
   4291 		if (port <= 0) {
   4292 			wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
   4293 			goto fail;
   4294 		}
   4295 	}
   4296 
   4297 	os_get_random(gcookie, COOKIE_LEN);
   4298 
   4299 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
   4300 	hints.ai_flags = AI_PASSIVE;
   4301 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
   4302 
   4303 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
   4304 	hints.ai_family = AF_INET6;
   4305 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   4306 	hints.ai_family = AF_INET;
   4307 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   4308 	hints.ai_socktype = SOCK_DGRAM;
   4309 
   4310 try_again:
   4311 	os_snprintf(p, sizeof(p), "%d", port);
   4312 	n = getaddrinfo(NULL, p, &hints, &res);
   4313 	if (n) {
   4314 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
   4315 		goto fail;
   4316 	}
   4317 
   4318 	saveres = res;
   4319 	interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
   4320 					     res->ai_protocol);
   4321 	if (interface->global_ctrl_sock < 0) {
   4322 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
   4323 		goto fail;
   4324 	}
   4325 
   4326 	if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
   4327 	    0) {
   4328 		port++;
   4329 		if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
   4330 		    HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
   4331 			goto try_again;
   4332 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
   4333 		goto fail;
   4334 	}
   4335 
   4336 	freeaddrinfo(saveres);
   4337 
   4338 	wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
   4339 
   4340 	if (eloop_register_read_sock(interface->global_ctrl_sock,
   4341 				     hostapd_global_ctrl_iface_receive,
   4342 				     interface, NULL) < 0) {
   4343 		hostapd_global_ctrl_iface_deinit(interface);
   4344 		return -1;
   4345 	}
   4346 
   4347 	return 0;
   4348 
   4349 fail:
   4350 	if (interface->global_ctrl_sock >= 0)
   4351 		close(interface->global_ctrl_sock);
   4352 	return -1;
   4353 #else /* CONFIG_CTRL_IFACE_UDP */
   4354 	struct sockaddr_un addr;
   4355 	int s = -1;
   4356 	char *fname = NULL;
   4357 
   4358 	if (interface->global_iface_path == NULL) {
   4359 		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
   4360 		return 0;
   4361 	}
   4362 
   4363 	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
   4364 		if (errno == EEXIST) {
   4365 			wpa_printf(MSG_DEBUG, "Using existing control "
   4366 				   "interface directory.");
   4367 		} else {
   4368 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
   4369 				   strerror(errno));
   4370 			goto fail;
   4371 		}
   4372 	} else if (interface->ctrl_iface_group &&
   4373 		   lchown(interface->global_iface_path, -1,
   4374 			  interface->ctrl_iface_group) < 0) {
   4375 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
   4376 			   strerror(errno));
   4377 		goto fail;
   4378 	}
   4379 
   4380 	if (os_strlen(interface->global_iface_path) + 1 +
   4381 	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
   4382 		goto fail;
   4383 
   4384 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   4385 	if (s < 0) {
   4386 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
   4387 		goto fail;
   4388 	}
   4389 
   4390 	os_memset(&addr, 0, sizeof(addr));
   4391 #ifdef __FreeBSD__
   4392 	addr.sun_len = sizeof(addr);
   4393 #endif /* __FreeBSD__ */
   4394 	addr.sun_family = AF_UNIX;
   4395 	fname = hostapd_global_ctrl_iface_path(interface);
   4396 	if (fname == NULL)
   4397 		goto fail;
   4398 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   4399 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   4400 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   4401 			   strerror(errno));
   4402 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   4403 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   4404 				   " allow connections - assuming it was left"
   4405 				   "over from forced program termination");
   4406 			if (unlink(fname) < 0) {
   4407 				wpa_printf(MSG_ERROR,
   4408 					   "Could not unlink existing ctrl_iface socket '%s': %s",
   4409 					   fname, strerror(errno));
   4410 				goto fail;
   4411 			}
   4412 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   4413 			    0) {
   4414 				wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
   4415 					   strerror(errno));
   4416 				goto fail;
   4417 			}
   4418 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   4419 				   "ctrl_iface socket '%s'", fname);
   4420 		} else {
   4421 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   4422 				   "be in use - cannot override it");
   4423 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   4424 				   "not used anymore", fname);
   4425 			os_free(fname);
   4426 			fname = NULL;
   4427 			goto fail;
   4428 		}
   4429 	}
   4430 
   4431 	if (interface->ctrl_iface_group &&
   4432 	    lchown(fname, -1, interface->ctrl_iface_group) < 0) {
   4433 		wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
   4434 			   strerror(errno));
   4435 		goto fail;
   4436 	}
   4437 
   4438 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   4439 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
   4440 			   strerror(errno));
   4441 		goto fail;
   4442 	}
   4443 	os_free(fname);
   4444 
   4445 	interface->global_ctrl_sock = s;
   4446 	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
   4447 				 interface, NULL);
   4448 
   4449 	return 0;
   4450 
   4451 fail:
   4452 	if (s >= 0)
   4453 		close(s);
   4454 	if (fname) {
   4455 		unlink(fname);
   4456 		os_free(fname);
   4457 	}
   4458 	return -1;
   4459 #endif /* CONFIG_CTRL_IFACE_UDP */
   4460 }
   4461 
   4462 
   4463 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
   4464 {
   4465 #ifndef CONFIG_CTRL_IFACE_UDP
   4466 	char *fname = NULL;
   4467 #endif /* CONFIG_CTRL_IFACE_UDP */
   4468 	struct wpa_ctrl_dst *dst, *prev;
   4469 
   4470 	if (interfaces->global_ctrl_sock > -1) {
   4471 		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
   4472 		close(interfaces->global_ctrl_sock);
   4473 		interfaces->global_ctrl_sock = -1;
   4474 #ifndef CONFIG_CTRL_IFACE_UDP
   4475 		fname = hostapd_global_ctrl_iface_path(interfaces);
   4476 		if (fname) {
   4477 			unlink(fname);
   4478 			os_free(fname);
   4479 		}
   4480 
   4481 		if (interfaces->global_iface_path &&
   4482 		    rmdir(interfaces->global_iface_path) < 0) {
   4483 			if (errno == ENOTEMPTY) {
   4484 				wpa_printf(MSG_DEBUG, "Control interface "
   4485 					   "directory not empty - leaving it "
   4486 					   "behind");
   4487 			} else {
   4488 				wpa_printf(MSG_ERROR,
   4489 					   "rmdir[ctrl_interface=%s]: %s",
   4490 					   interfaces->global_iface_path,
   4491 					   strerror(errno));
   4492 			}
   4493 		}
   4494 #endif /* CONFIG_CTRL_IFACE_UDP */
   4495 	}
   4496 
   4497 	os_free(interfaces->global_iface_path);
   4498 	interfaces->global_iface_path = NULL;
   4499 
   4500 	dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
   4501 			      struct wpa_ctrl_dst, list)
   4502 		os_free(dst);
   4503 }
   4504 
   4505 
   4506 static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst,
   4507 					    const char *buf)
   4508 {
   4509 	/* Enable Probe Request events based on explicit request.
   4510 	 * Other events are enabled by default.
   4511 	 */
   4512 	if (str_starts(buf, RX_PROBE_REQUEST))
   4513 		return !!(dst->events & WPA_EVENT_RX_PROBE_REQUEST);
   4514 	return 1;
   4515 }
   4516 
   4517 
   4518 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
   4519 				    enum wpa_msg_type type,
   4520 				    const char *buf, size_t len)
   4521 {
   4522 	struct wpa_ctrl_dst *dst, *next;
   4523 	struct dl_list *ctrl_dst;
   4524 	struct msghdr msg;
   4525 	int idx;
   4526 	struct iovec io[2];
   4527 	char levelstr[10];
   4528 	int s;
   4529 
   4530 	if (type != WPA_MSG_ONLY_GLOBAL) {
   4531 		s = hapd->ctrl_sock;
   4532 		ctrl_dst = &hapd->ctrl_dst;
   4533 	} else {
   4534 		s = hapd->iface->interfaces->global_ctrl_sock;
   4535 		ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
   4536 	}
   4537 
   4538 	if (s < 0 || dl_list_empty(ctrl_dst))
   4539 		return;
   4540 
   4541 	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
   4542 	io[0].iov_base = levelstr;
   4543 	io[0].iov_len = os_strlen(levelstr);
   4544 	io[1].iov_base = (char *) buf;
   4545 	io[1].iov_len = len;
   4546 	os_memset(&msg, 0, sizeof(msg));
   4547 	msg.msg_iov = io;
   4548 	msg.msg_iovlen = 2;
   4549 
   4550 	idx = 0;
   4551 	dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
   4552 		if ((level >= dst->debug_level) &&
   4553 		     hostapd_ctrl_check_event_enabled(dst, buf)) {
   4554 			sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
   4555 				       &dst->addr, dst->addrlen);
   4556 			msg.msg_name = &dst->addr;
   4557 			msg.msg_namelen = dst->addrlen;
   4558 			if (sendmsg(s, &msg, 0) < 0) {
   4559 				int _errno = errno;
   4560 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
   4561 					   "%d - %s",
   4562 					   idx, errno, strerror(errno));
   4563 				dst->errors++;
   4564 				if (dst->errors > 10 || _errno == ENOENT) {
   4565 					if (type != WPA_MSG_ONLY_GLOBAL)
   4566 						hostapd_ctrl_iface_detach(
   4567 							hapd, &dst->addr,
   4568 							dst->addrlen);
   4569 					else
   4570 						hostapd_global_ctrl_iface_detach(
   4571 							hapd->iface->interfaces,
   4572 							&dst->addr,
   4573 							dst->addrlen);
   4574 				}
   4575 			} else
   4576 				dst->errors = 0;
   4577 		}
   4578 		idx++;
   4579 	}
   4580 }
   4581 
   4582 #endif /* CONFIG_NATIVE_WINDOWS */
   4583