Home | History | Annotate | Download | only in hostapd
      1 /*
      2  * hostapd / UNIX domain socket -based control interface
      3  * Copyright (c) 2004-2015, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "utils/includes.h"
     10 
     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 "common/version.h"
     29 #include "common/ieee802_11_defs.h"
     30 #include "common/ctrl_iface_common.h"
     31 #include "crypto/tls.h"
     32 #include "drivers/driver.h"
     33 #include "eapol_auth/eapol_auth_sm.h"
     34 #include "radius/radius_client.h"
     35 #include "radius/radius_server.h"
     36 #include "l2_packet/l2_packet.h"
     37 #include "ap/hostapd.h"
     38 #include "ap/ap_config.h"
     39 #include "ap/ieee802_1x.h"
     40 #include "ap/wpa_auth.h"
     41 #include "ap/ieee802_11.h"
     42 #include "ap/sta_info.h"
     43 #include "ap/wps_hostapd.h"
     44 #include "ap/ctrl_iface_ap.h"
     45 #include "ap/ap_drv_ops.h"
     46 #include "ap/hs20.h"
     47 #include "ap/wnm_ap.h"
     48 #include "ap/wpa_auth.h"
     49 #include "ap/beacon.h"
     50 #include "wps/wps_defs.h"
     51 #include "wps/wps.h"
     52 #include "fst/fst_ctrl_iface.h"
     53 #include "config_file.h"
     54 #include "ctrl_iface.h"
     55 
     56 
     57 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
     58 
     59 #ifdef CONFIG_CTRL_IFACE_UDP
     60 #define COOKIE_LEN 8
     61 static unsigned char cookie[COOKIE_LEN];
     62 static unsigned char gcookie[COOKIE_LEN];
     63 #define HOSTAPD_CTRL_IFACE_PORT		8877
     64 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT	50
     65 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT		8878
     66 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT	50
     67 #endif /* CONFIG_CTRL_IFACE_UDP */
     68 
     69 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
     70 				    enum wpa_msg_type type,
     71 				    const char *buf, size_t len);
     72 
     73 
     74 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
     75 				     struct sockaddr_storage *from,
     76 				     socklen_t fromlen)
     77 {
     78 	return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen);
     79 }
     80 
     81 
     82 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
     83 				     struct sockaddr_storage *from,
     84 				     socklen_t fromlen)
     85 {
     86 	return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
     87 }
     88 
     89 
     90 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
     91 				    struct sockaddr_storage *from,
     92 				    socklen_t fromlen,
     93 				    char *level)
     94 {
     95 	return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
     96 }
     97 
     98 
     99 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
    100 				      const char *txtaddr)
    101 {
    102 	u8 addr[ETH_ALEN];
    103 	struct sta_info *sta;
    104 
    105 	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
    106 
    107 	if (hwaddr_aton(txtaddr, addr))
    108 		return -1;
    109 
    110 	sta = ap_get_sta(hapd, addr);
    111 	if (sta)
    112 		return 0;
    113 
    114 	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
    115 		   "notification", MAC2STR(addr));
    116 	sta = ap_sta_add(hapd, addr);
    117 	if (sta == NULL)
    118 		return -1;
    119 
    120 	hostapd_new_assoc_sta(hapd, sta, 0);
    121 	return 0;
    122 }
    123 
    124 
    125 #ifdef CONFIG_IEEE80211W
    126 #ifdef NEED_AP_MLME
    127 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
    128 				       const char *txtaddr)
    129 {
    130 	u8 addr[ETH_ALEN];
    131 	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
    132 
    133 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
    134 
    135 	if (hwaddr_aton(txtaddr, addr) ||
    136 	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
    137 		return -1;
    138 
    139 	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
    140 
    141 	return 0;
    142 }
    143 #endif /* NEED_AP_MLME */
    144 #endif /* CONFIG_IEEE80211W */
    145 
    146 
    147 #ifdef CONFIG_WPS
    148 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
    149 {
    150 	char *pin = os_strchr(txt, ' ');
    151 	char *timeout_txt;
    152 	int timeout;
    153 	u8 addr_buf[ETH_ALEN], *addr = NULL;
    154 	char *pos;
    155 
    156 	if (pin == NULL)
    157 		return -1;
    158 	*pin++ = '\0';
    159 
    160 	timeout_txt = os_strchr(pin, ' ');
    161 	if (timeout_txt) {
    162 		*timeout_txt++ = '\0';
    163 		timeout = atoi(timeout_txt);
    164 		pos = os_strchr(timeout_txt, ' ');
    165 		if (pos) {
    166 			*pos++ = '\0';
    167 			if (hwaddr_aton(pos, addr_buf) == 0)
    168 				addr = addr_buf;
    169 		}
    170 	} else
    171 		timeout = 0;
    172 
    173 	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
    174 }
    175 
    176 
    177 static int hostapd_ctrl_iface_wps_check_pin(
    178 	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
    179 {
    180 	char pin[9];
    181 	size_t len;
    182 	char *pos;
    183 	int ret;
    184 
    185 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
    186 			      (u8 *) cmd, os_strlen(cmd));
    187 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
    188 		if (*pos < '0' || *pos > '9')
    189 			continue;
    190 		pin[len++] = *pos;
    191 		if (len == 9) {
    192 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
    193 			return -1;
    194 		}
    195 	}
    196 	if (len != 4 && len != 8) {
    197 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
    198 		return -1;
    199 	}
    200 	pin[len] = '\0';
    201 
    202 	if (len == 8) {
    203 		unsigned int pin_val;
    204 		pin_val = atoi(pin);
    205 		if (!wps_pin_valid(pin_val)) {
    206 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
    207 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
    208 			if (os_snprintf_error(buflen, ret))
    209 				return -1;
    210 			return ret;
    211 		}
    212 	}
    213 
    214 	ret = os_snprintf(buf, buflen, "%s", pin);
    215 	if (os_snprintf_error(buflen, ret))
    216 		return -1;
    217 
    218 	return ret;
    219 }
    220 
    221 
    222 #ifdef CONFIG_WPS_NFC
    223 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
    224 					       char *pos)
    225 {
    226 	size_t len;
    227 	struct wpabuf *buf;
    228 	int ret;
    229 
    230 	len = os_strlen(pos);
    231 	if (len & 0x01)
    232 		return -1;
    233 	len /= 2;
    234 
    235 	buf = wpabuf_alloc(len);
    236 	if (buf == NULL)
    237 		return -1;
    238 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
    239 		wpabuf_free(buf);
    240 		return -1;
    241 	}
    242 
    243 	ret = hostapd_wps_nfc_tag_read(hapd, buf);
    244 	wpabuf_free(buf);
    245 
    246 	return ret;
    247 }
    248 
    249 
    250 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
    251 						   char *cmd, char *reply,
    252 						   size_t max_len)
    253 {
    254 	int ndef;
    255 	struct wpabuf *buf;
    256 	int res;
    257 
    258 	if (os_strcmp(cmd, "WPS") == 0)
    259 		ndef = 0;
    260 	else if (os_strcmp(cmd, "NDEF") == 0)
    261 		ndef = 1;
    262 	else
    263 		return -1;
    264 
    265 	buf = hostapd_wps_nfc_config_token(hapd, ndef);
    266 	if (buf == NULL)
    267 		return -1;
    268 
    269 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    270 					 wpabuf_len(buf));
    271 	reply[res++] = '\n';
    272 	reply[res] = '\0';
    273 
    274 	wpabuf_free(buf);
    275 
    276 	return res;
    277 }
    278 
    279 
    280 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
    281 						char *reply, size_t max_len,
    282 						int ndef)
    283 {
    284 	struct wpabuf *buf;
    285 	int res;
    286 
    287 	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
    288 	if (buf == NULL)
    289 		return -1;
    290 
    291 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    292 					 wpabuf_len(buf));
    293 	reply[res++] = '\n';
    294 	reply[res] = '\0';
    295 
    296 	wpabuf_free(buf);
    297 
    298 	return res;
    299 }
    300 
    301 
    302 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
    303 					    char *cmd, char *reply,
    304 					    size_t max_len)
    305 {
    306 	if (os_strcmp(cmd, "WPS") == 0)
    307 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    308 							    max_len, 0);
    309 
    310 	if (os_strcmp(cmd, "NDEF") == 0)
    311 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    312 							    max_len, 1);
    313 
    314 	if (os_strcmp(cmd, "enable") == 0)
    315 		return hostapd_wps_nfc_token_enable(hapd);
    316 
    317 	if (os_strcmp(cmd, "disable") == 0) {
    318 		hostapd_wps_nfc_token_disable(hapd);
    319 		return 0;
    320 	}
    321 
    322 	return -1;
    323 }
    324 
    325 
    326 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
    327 						   char *cmd, char *reply,
    328 						   size_t max_len)
    329 {
    330 	struct wpabuf *buf;
    331 	int res;
    332 	char *pos;
    333 	int ndef;
    334 
    335 	pos = os_strchr(cmd, ' ');
    336 	if (pos == NULL)
    337 		return -1;
    338 	*pos++ = '\0';
    339 
    340 	if (os_strcmp(cmd, "WPS") == 0)
    341 		ndef = 0;
    342 	else if (os_strcmp(cmd, "NDEF") == 0)
    343 		ndef = 1;
    344 	else
    345 		return -1;
    346 
    347 	if (os_strcmp(pos, "WPS-CR") == 0)
    348 		buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
    349 	else
    350 		buf = NULL;
    351 	if (buf == NULL)
    352 		return -1;
    353 
    354 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    355 					 wpabuf_len(buf));
    356 	reply[res++] = '\n';
    357 	reply[res] = '\0';
    358 
    359 	wpabuf_free(buf);
    360 
    361 	return res;
    362 }
    363 
    364 
    365 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
    366 						  char *cmd)
    367 {
    368 	size_t len;
    369 	struct wpabuf *req, *sel;
    370 	int ret;
    371 	char *pos, *role, *type, *pos2;
    372 
    373 	role = cmd;
    374 	pos = os_strchr(role, ' ');
    375 	if (pos == NULL)
    376 		return -1;
    377 	*pos++ = '\0';
    378 
    379 	type = pos;
    380 	pos = os_strchr(type, ' ');
    381 	if (pos == NULL)
    382 		return -1;
    383 	*pos++ = '\0';
    384 
    385 	pos2 = os_strchr(pos, ' ');
    386 	if (pos2 == NULL)
    387 		return -1;
    388 	*pos2++ = '\0';
    389 
    390 	len = os_strlen(pos);
    391 	if (len & 0x01)
    392 		return -1;
    393 	len /= 2;
    394 
    395 	req = wpabuf_alloc(len);
    396 	if (req == NULL)
    397 		return -1;
    398 	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
    399 		wpabuf_free(req);
    400 		return -1;
    401 	}
    402 
    403 	len = os_strlen(pos2);
    404 	if (len & 0x01) {
    405 		wpabuf_free(req);
    406 		return -1;
    407 	}
    408 	len /= 2;
    409 
    410 	sel = wpabuf_alloc(len);
    411 	if (sel == NULL) {
    412 		wpabuf_free(req);
    413 		return -1;
    414 	}
    415 	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
    416 		wpabuf_free(req);
    417 		wpabuf_free(sel);
    418 		return -1;
    419 	}
    420 
    421 	if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
    422 		ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
    423 	} else {
    424 		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
    425 			   "reported: role=%s type=%s", role, type);
    426 		ret = -1;
    427 	}
    428 	wpabuf_free(req);
    429 	wpabuf_free(sel);
    430 
    431 	return ret;
    432 }
    433 
    434 #endif /* CONFIG_WPS_NFC */
    435 
    436 
    437 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
    438 					 char *buf, size_t buflen)
    439 {
    440 	int timeout = 300;
    441 	char *pos;
    442 	const char *pin_txt;
    443 
    444 	pos = os_strchr(txt, ' ');
    445 	if (pos)
    446 		*pos++ = '\0';
    447 
    448 	if (os_strcmp(txt, "disable") == 0) {
    449 		hostapd_wps_ap_pin_disable(hapd);
    450 		return os_snprintf(buf, buflen, "OK\n");
    451 	}
    452 
    453 	if (os_strcmp(txt, "random") == 0) {
    454 		if (pos)
    455 			timeout = atoi(pos);
    456 		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
    457 		if (pin_txt == NULL)
    458 			return -1;
    459 		return os_snprintf(buf, buflen, "%s", pin_txt);
    460 	}
    461 
    462 	if (os_strcmp(txt, "get") == 0) {
    463 		pin_txt = hostapd_wps_ap_pin_get(hapd);
    464 		if (pin_txt == NULL)
    465 			return -1;
    466 		return os_snprintf(buf, buflen, "%s", pin_txt);
    467 	}
    468 
    469 	if (os_strcmp(txt, "set") == 0) {
    470 		char *pin;
    471 		if (pos == NULL)
    472 			return -1;
    473 		pin = pos;
    474 		pos = os_strchr(pos, ' ');
    475 		if (pos) {
    476 			*pos++ = '\0';
    477 			timeout = atoi(pos);
    478 		}
    479 		if (os_strlen(pin) > buflen)
    480 			return -1;
    481 		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
    482 			return -1;
    483 		return os_snprintf(buf, buflen, "%s", pin);
    484 	}
    485 
    486 	return -1;
    487 }
    488 
    489 
    490 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
    491 {
    492 	char *pos;
    493 	char *ssid, *auth, *encr = NULL, *key = NULL;
    494 
    495 	ssid = txt;
    496 	pos = os_strchr(txt, ' ');
    497 	if (!pos)
    498 		return -1;
    499 	*pos++ = '\0';
    500 
    501 	auth = pos;
    502 	pos = os_strchr(pos, ' ');
    503 	if (pos) {
    504 		*pos++ = '\0';
    505 		encr = pos;
    506 		pos = os_strchr(pos, ' ');
    507 		if (pos) {
    508 			*pos++ = '\0';
    509 			key = pos;
    510 		}
    511 	}
    512 
    513 	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
    514 }
    515 
    516 
    517 static const char * pbc_status_str(enum pbc_status status)
    518 {
    519 	switch (status) {
    520 	case WPS_PBC_STATUS_DISABLE:
    521 		return "Disabled";
    522 	case WPS_PBC_STATUS_ACTIVE:
    523 		return "Active";
    524 	case WPS_PBC_STATUS_TIMEOUT:
    525 		return "Timed-out";
    526 	case WPS_PBC_STATUS_OVERLAP:
    527 		return "Overlap";
    528 	default:
    529 		return "Unknown";
    530 	}
    531 }
    532 
    533 
    534 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
    535 					     char *buf, size_t buflen)
    536 {
    537 	int ret;
    538 	char *pos, *end;
    539 
    540 	pos = buf;
    541 	end = buf + buflen;
    542 
    543 	ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
    544 			  pbc_status_str(hapd->wps_stats.pbc_status));
    545 
    546 	if (os_snprintf_error(end - pos, ret))
    547 		return pos - buf;
    548 	pos += ret;
    549 
    550 	ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
    551 			  (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
    552 			   "Success":
    553 			   (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
    554 			    "Failed" : "None")));
    555 
    556 	if (os_snprintf_error(end - pos, ret))
    557 		return pos - buf;
    558 	pos += ret;
    559 
    560 	/* If status == Failure - Add possible Reasons */
    561 	if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
    562 	   hapd->wps_stats.failure_reason > 0) {
    563 		ret = os_snprintf(pos, end - pos,
    564 				  "Failure Reason: %s\n",
    565 				  wps_ei_str(hapd->wps_stats.failure_reason));
    566 
    567 		if (os_snprintf_error(end - pos, ret))
    568 			return pos - buf;
    569 		pos += ret;
    570 	}
    571 
    572 	if (hapd->wps_stats.status) {
    573 		ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
    574 				  MAC2STR(hapd->wps_stats.peer_addr));
    575 
    576 		if (os_snprintf_error(end - pos, ret))
    577 			return pos - buf;
    578 		pos += ret;
    579 	}
    580 
    581 	return pos - buf;
    582 }
    583 
    584 #endif /* CONFIG_WPS */
    585 
    586 #ifdef CONFIG_HS20
    587 
    588 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
    589 					     const char *cmd)
    590 {
    591 	u8 addr[ETH_ALEN];
    592 	const char *url;
    593 
    594 	if (hwaddr_aton(cmd, addr))
    595 		return -1;
    596 	url = cmd + 17;
    597 	if (*url == '\0') {
    598 		url = NULL;
    599 	} else {
    600 		if (*url != ' ')
    601 			return -1;
    602 		url++;
    603 		if (*url == '\0')
    604 			url = NULL;
    605 	}
    606 
    607 	return hs20_send_wnm_notification(hapd, addr, 1, url);
    608 }
    609 
    610 
    611 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
    612 					      const char *cmd)
    613 {
    614 	u8 addr[ETH_ALEN];
    615 	int code, reauth_delay, ret;
    616 	const char *pos;
    617 	size_t url_len;
    618 	struct wpabuf *req;
    619 
    620 	/* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
    621 	if (hwaddr_aton(cmd, addr))
    622 		return -1;
    623 
    624 	pos = os_strchr(cmd, ' ');
    625 	if (pos == NULL)
    626 		return -1;
    627 	pos++;
    628 	code = atoi(pos);
    629 
    630 	pos = os_strchr(pos, ' ');
    631 	if (pos == NULL)
    632 		return -1;
    633 	pos++;
    634 	reauth_delay = atoi(pos);
    635 
    636 	url_len = 0;
    637 	pos = os_strchr(pos, ' ');
    638 	if (pos) {
    639 		pos++;
    640 		url_len = os_strlen(pos);
    641 	}
    642 
    643 	req = wpabuf_alloc(4 + url_len);
    644 	if (req == NULL)
    645 		return -1;
    646 	wpabuf_put_u8(req, code);
    647 	wpabuf_put_le16(req, reauth_delay);
    648 	wpabuf_put_u8(req, url_len);
    649 	if (pos)
    650 		wpabuf_put_data(req, pos, url_len);
    651 
    652 	wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
    653 		   " to indicate imminent deauthentication (code=%d "
    654 		   "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
    655 	ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
    656 	wpabuf_free(req);
    657 	return ret;
    658 }
    659 
    660 #endif /* CONFIG_HS20 */
    661 
    662 
    663 #ifdef CONFIG_INTERWORKING
    664 
    665 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
    666 					      const char *cmd)
    667 {
    668 	u8 qos_map_set[16 + 2 * 21], count = 0;
    669 	const char *pos = cmd;
    670 	int val, ret;
    671 
    672 	for (;;) {
    673 		if (count == sizeof(qos_map_set)) {
    674 			wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
    675 			return -1;
    676 		}
    677 
    678 		val = atoi(pos);
    679 		if (val < 0 || val > 255) {
    680 			wpa_printf(MSG_INFO, "Invalid QoS Map Set");
    681 			return -1;
    682 		}
    683 
    684 		qos_map_set[count++] = val;
    685 		pos = os_strchr(pos, ',');
    686 		if (!pos)
    687 			break;
    688 		pos++;
    689 	}
    690 
    691 	if (count < 16 || count & 1) {
    692 		wpa_printf(MSG_INFO, "Invalid QoS Map Set");
    693 		return -1;
    694 	}
    695 
    696 	ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
    697 	if (ret) {
    698 		wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
    699 		return -1;
    700 	}
    701 
    702 	os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
    703 	hapd->conf->qos_map_set_len = count;
    704 
    705 	return 0;
    706 }
    707 
    708 
    709 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
    710 						const char *cmd)
    711 {
    712 	u8 addr[ETH_ALEN];
    713 	struct sta_info *sta;
    714 	struct wpabuf *buf;
    715 	u8 *qos_map_set = hapd->conf->qos_map_set;
    716 	u8 qos_map_set_len = hapd->conf->qos_map_set_len;
    717 	int ret;
    718 
    719 	if (!qos_map_set_len) {
    720 		wpa_printf(MSG_INFO, "QoS Map Set is not set");
    721 		return -1;
    722 	}
    723 
    724 	if (hwaddr_aton(cmd, addr))
    725 		return -1;
    726 
    727 	sta = ap_get_sta(hapd, addr);
    728 	if (sta == NULL) {
    729 		wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
    730 			   "for QoS Map Configuration message",
    731 			   MAC2STR(addr));
    732 		return -1;
    733 	}
    734 
    735 	if (!sta->qos_map_enabled) {
    736 		wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
    737 			   "support for QoS Map", MAC2STR(addr));
    738 		return -1;
    739 	}
    740 
    741 	buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
    742 	if (buf == NULL)
    743 		return -1;
    744 
    745 	wpabuf_put_u8(buf, WLAN_ACTION_QOS);
    746 	wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
    747 
    748 	/* QoS Map Set Element */
    749 	wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
    750 	wpabuf_put_u8(buf, qos_map_set_len);
    751 	wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
    752 
    753 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
    754 				      wpabuf_head(buf), wpabuf_len(buf));
    755 	wpabuf_free(buf);
    756 
    757 	return ret;
    758 }
    759 
    760 #endif /* CONFIG_INTERWORKING */
    761 
    762 
    763 #ifdef CONFIG_WNM
    764 
    765 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
    766 						const char *cmd)
    767 {
    768 	u8 addr[ETH_ALEN];
    769 	int disassoc_timer;
    770 	struct sta_info *sta;
    771 
    772 	if (hwaddr_aton(cmd, addr))
    773 		return -1;
    774 	if (cmd[17] != ' ')
    775 		return -1;
    776 	disassoc_timer = atoi(cmd + 17);
    777 
    778 	sta = ap_get_sta(hapd, addr);
    779 	if (sta == NULL) {
    780 		wpa_printf(MSG_DEBUG, "Station " MACSTR
    781 			   " not found for disassociation imminent message",
    782 			   MAC2STR(addr));
    783 		return -1;
    784 	}
    785 
    786 	return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
    787 }
    788 
    789 
    790 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
    791 					   const char *cmd)
    792 {
    793 	u8 addr[ETH_ALEN];
    794 	const char *url, *timerstr;
    795 	int disassoc_timer;
    796 	struct sta_info *sta;
    797 
    798 	if (hwaddr_aton(cmd, addr))
    799 		return -1;
    800 
    801 	sta = ap_get_sta(hapd, addr);
    802 	if (sta == NULL) {
    803 		wpa_printf(MSG_DEBUG, "Station " MACSTR
    804 			   " not found for ESS disassociation imminent message",
    805 			   MAC2STR(addr));
    806 		return -1;
    807 	}
    808 
    809 	timerstr = cmd + 17;
    810 	if (*timerstr != ' ')
    811 		return -1;
    812 	timerstr++;
    813 	disassoc_timer = atoi(timerstr);
    814 	if (disassoc_timer < 0 || disassoc_timer > 65535)
    815 		return -1;
    816 
    817 	url = os_strchr(timerstr, ' ');
    818 	if (url == NULL)
    819 		return -1;
    820 	url++;
    821 
    822 	return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
    823 }
    824 
    825 
    826 static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
    827 					 const char *cmd)
    828 {
    829 	u8 addr[ETH_ALEN];
    830 	const char *pos, *end;
    831 	int disassoc_timer = 0;
    832 	struct sta_info *sta;
    833 	u8 req_mode = 0, valid_int = 0x01;
    834 	u8 bss_term_dur[12];
    835 	char *url = NULL;
    836 	int ret;
    837 	u8 nei_rep[1000];
    838 	u8 *nei_pos = nei_rep;
    839 	u8 mbo[10];
    840 	size_t mbo_len = 0;
    841 
    842 	if (hwaddr_aton(cmd, addr)) {
    843 		wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
    844 		return -1;
    845 	}
    846 
    847 	sta = ap_get_sta(hapd, addr);
    848 	if (sta == NULL) {
    849 		wpa_printf(MSG_DEBUG, "Station " MACSTR
    850 			   " not found for BSS TM Request message",
    851 			   MAC2STR(addr));
    852 		return -1;
    853 	}
    854 
    855 	pos = os_strstr(cmd, " disassoc_timer=");
    856 	if (pos) {
    857 		pos += 16;
    858 		disassoc_timer = atoi(pos);
    859 		if (disassoc_timer < 0 || disassoc_timer > 65535) {
    860 			wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
    861 			return -1;
    862 		}
    863 	}
    864 
    865 	pos = os_strstr(cmd, " valid_int=");
    866 	if (pos) {
    867 		pos += 11;
    868 		valid_int = atoi(pos);
    869 	}
    870 
    871 	pos = os_strstr(cmd, " bss_term=");
    872 	if (pos) {
    873 		pos += 10;
    874 		req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
    875 		/* TODO: TSF configurable/learnable */
    876 		bss_term_dur[0] = 4; /* Subelement ID */
    877 		bss_term_dur[1] = 10; /* Length */
    878 		os_memset(bss_term_dur, 2, 8);
    879 		end = os_strchr(pos, ',');
    880 		if (end == NULL) {
    881 			wpa_printf(MSG_DEBUG, "Invalid bss_term data");
    882 			return -1;
    883 		}
    884 		end++;
    885 		WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
    886 	}
    887 
    888 
    889 	/*
    890 	 * BSS Transition Candidate List Entries - Neighbor Report elements
    891 	 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
    892 	 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
    893 	 */
    894 	pos = cmd;
    895 	while (pos) {
    896 		u8 *nei_start;
    897 		long int val;
    898 		char *endptr, *tmp;
    899 
    900 		pos = os_strstr(pos, " neighbor=");
    901 		if (!pos)
    902 			break;
    903 		if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
    904 			wpa_printf(MSG_DEBUG,
    905 				   "Not enough room for additional neighbor");
    906 			return -1;
    907 		}
    908 		pos += 10;
    909 
    910 		nei_start = nei_pos;
    911 		*nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
    912 		nei_pos++; /* length to be filled in */
    913 
    914 		if (hwaddr_aton(pos, nei_pos)) {
    915 			wpa_printf(MSG_DEBUG, "Invalid BSSID");
    916 			return -1;
    917 		}
    918 		nei_pos += ETH_ALEN;
    919 		pos += 17;
    920 		if (*pos != ',') {
    921 			wpa_printf(MSG_DEBUG, "Missing BSSID Information");
    922 			return -1;
    923 		}
    924 		pos++;
    925 
    926 		val = strtol(pos, &endptr, 0);
    927 		WPA_PUT_LE32(nei_pos, val);
    928 		nei_pos += 4;
    929 		if (*endptr != ',') {
    930 			wpa_printf(MSG_DEBUG, "Missing Operating Class");
    931 			return -1;
    932 		}
    933 		pos = endptr + 1;
    934 
    935 		*nei_pos++ = atoi(pos); /* Operating Class */
    936 		pos = os_strchr(pos, ',');
    937 		if (pos == NULL) {
    938 			wpa_printf(MSG_DEBUG, "Missing Channel Number");
    939 			return -1;
    940 		}
    941 		pos++;
    942 
    943 		*nei_pos++ = atoi(pos); /* Channel Number */
    944 		pos = os_strchr(pos, ',');
    945 		if (pos == NULL) {
    946 			wpa_printf(MSG_DEBUG, "Missing PHY Type");
    947 			return -1;
    948 		}
    949 		pos++;
    950 
    951 		*nei_pos++ = atoi(pos); /* PHY Type */
    952 		end = os_strchr(pos, ' ');
    953 		tmp = os_strchr(pos, ',');
    954 		if (tmp && (!end || tmp < end)) {
    955 			/* Optional Subelements (hexdump) */
    956 			size_t len;
    957 
    958 			pos = tmp + 1;
    959 			end = os_strchr(pos, ' ');
    960 			if (end)
    961 				len = end - pos;
    962 			else
    963 				len = os_strlen(pos);
    964 			if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
    965 				wpa_printf(MSG_DEBUG,
    966 					   "Not enough room for neighbor subelements");
    967 				return -1;
    968 			}
    969 			if (len & 0x01 ||
    970 			    hexstr2bin(pos, nei_pos, len / 2) < 0) {
    971 				wpa_printf(MSG_DEBUG,
    972 					   "Invalid neighbor subelement info");
    973 				return -1;
    974 			}
    975 			nei_pos += len / 2;
    976 			pos = end;
    977 		}
    978 
    979 		nei_start[1] = nei_pos - nei_start - 2;
    980 	}
    981 
    982 	pos = os_strstr(cmd, " url=");
    983 	if (pos) {
    984 		size_t len;
    985 		pos += 5;
    986 		end = os_strchr(pos, ' ');
    987 		if (end)
    988 			len = end - pos;
    989 		else
    990 			len = os_strlen(pos);
    991 		url = os_malloc(len + 1);
    992 		if (url == NULL)
    993 			return -1;
    994 		os_memcpy(url, pos, len);
    995 		url[len] = '\0';
    996 		req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
    997 	}
    998 
    999 	if (os_strstr(cmd, " pref=1"))
   1000 		req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
   1001 	if (os_strstr(cmd, " abridged=1"))
   1002 		req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
   1003 	if (os_strstr(cmd, " disassoc_imminent=1"))
   1004 		req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
   1005 
   1006 #ifdef CONFIG_MBO
   1007 	pos = os_strstr(cmd, "mbo=");
   1008 	if (pos) {
   1009 		unsigned int mbo_reason, cell_pref, reassoc_delay;
   1010 		u8 *mbo_pos = mbo;
   1011 
   1012 		ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
   1013 			     &reassoc_delay, &cell_pref);
   1014 		if (ret != 3) {
   1015 			wpa_printf(MSG_DEBUG,
   1016 				   "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
   1017 			return -1;
   1018 		}
   1019 
   1020 		if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
   1021 			wpa_printf(MSG_DEBUG,
   1022 				   "Invalid MBO transition reason code %u",
   1023 				   mbo_reason);
   1024 			return -1;
   1025 		}
   1026 
   1027 		/* Valid values for Cellular preference are: 0, 1, 255 */
   1028 		if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
   1029 			wpa_printf(MSG_DEBUG,
   1030 				   "Invalid MBO cellular capability %u",
   1031 				   cell_pref);
   1032 			return -1;
   1033 		}
   1034 
   1035 		if (reassoc_delay > 65535 ||
   1036 		    (reassoc_delay &&
   1037 		     !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
   1038 			wpa_printf(MSG_DEBUG,
   1039 				   "MBO: Assoc retry delay is only valid in disassoc imminent mode");
   1040 			return -1;
   1041 		}
   1042 
   1043 		*mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
   1044 		*mbo_pos++ = 1;
   1045 		*mbo_pos++ = mbo_reason;
   1046 		*mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
   1047 		*mbo_pos++ = 1;
   1048 		*mbo_pos++ = cell_pref;
   1049 
   1050 		if (reassoc_delay) {
   1051 			*mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
   1052 			*mbo_pos++ = 2;
   1053 			WPA_PUT_LE16(mbo_pos, reassoc_delay);
   1054 			mbo_pos += 2;
   1055 		}
   1056 
   1057 		mbo_len = mbo_pos - mbo;
   1058 	}
   1059 #endif /* CONFIG_MBO */
   1060 
   1061 	ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
   1062 				  valid_int, bss_term_dur, url,
   1063 				  nei_pos > nei_rep ? nei_rep : NULL,
   1064 				  nei_pos - nei_rep, mbo_len ? mbo : NULL,
   1065 				  mbo_len);
   1066 	os_free(url);
   1067 	return ret;
   1068 }
   1069 
   1070 #endif /* CONFIG_WNM */
   1071 
   1072 
   1073 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
   1074 					   char *buf, size_t buflen)
   1075 {
   1076 	int ret = 0;
   1077 	char *pos, *end;
   1078 
   1079 	pos = buf;
   1080 	end = buf + buflen;
   1081 
   1082 	WPA_ASSERT(hapd->conf->wpa_key_mgmt);
   1083 
   1084 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
   1085 		ret = os_snprintf(pos, end - pos, "WPA-PSK ");
   1086 		if (os_snprintf_error(end - pos, ret))
   1087 			return pos - buf;
   1088 		pos += ret;
   1089 	}
   1090 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
   1091 		ret = os_snprintf(pos, end - pos, "WPA-EAP ");
   1092 		if (os_snprintf_error(end - pos, ret))
   1093 			return pos - buf;
   1094 		pos += ret;
   1095 	}
   1096 #ifdef CONFIG_IEEE80211R
   1097 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
   1098 		ret = os_snprintf(pos, end - pos, "FT-PSK ");
   1099 		if (os_snprintf_error(end - pos, ret))
   1100 			return pos - buf;
   1101 		pos += ret;
   1102 	}
   1103 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
   1104 		ret = os_snprintf(pos, end - pos, "FT-EAP ");
   1105 		if (os_snprintf_error(end - pos, ret))
   1106 			return pos - buf;
   1107 		pos += ret;
   1108 	}
   1109 #ifdef CONFIG_SAE
   1110 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
   1111 		ret = os_snprintf(pos, end - pos, "FT-SAE ");
   1112 		if (os_snprintf_error(end - pos, ret))
   1113 			return pos - buf;
   1114 		pos += ret;
   1115 	}
   1116 #endif /* CONFIG_SAE */
   1117 #endif /* CONFIG_IEEE80211R */
   1118 #ifdef CONFIG_IEEE80211W
   1119 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
   1120 		ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
   1121 		if (os_snprintf_error(end - pos, ret))
   1122 			return pos - buf;
   1123 		pos += ret;
   1124 	}
   1125 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
   1126 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
   1127 		if (os_snprintf_error(end - pos, ret))
   1128 			return pos - buf;
   1129 		pos += ret;
   1130 	}
   1131 #endif /* CONFIG_IEEE80211W */
   1132 #ifdef CONFIG_SAE
   1133 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
   1134 		ret = os_snprintf(pos, end - pos, "SAE ");
   1135 		if (os_snprintf_error(end - pos, ret))
   1136 			return pos - buf;
   1137 		pos += ret;
   1138 	}
   1139 #endif /* CONFIG_SAE */
   1140 	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
   1141 		ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
   1142 		if (os_snprintf_error(end - pos, ret))
   1143 			return pos - buf;
   1144 		pos += ret;
   1145 	}
   1146 	if (hapd->conf->wpa_key_mgmt &
   1147 	    WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
   1148 		ret = os_snprintf(pos, end - pos,
   1149 				  "WPA-EAP-SUITE-B-192 ");
   1150 		if (os_snprintf_error(end - pos, ret))
   1151 			return pos - buf;
   1152 		pos += ret;
   1153 	}
   1154 
   1155 	if (pos > buf && *(pos - 1) == ' ') {
   1156 		*(pos - 1) = '\0';
   1157 		pos--;
   1158 	}
   1159 
   1160 	return pos - buf;
   1161 }
   1162 
   1163 
   1164 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
   1165 					 char *buf, size_t buflen)
   1166 {
   1167 	int ret;
   1168 	char *pos, *end;
   1169 
   1170 	pos = buf;
   1171 	end = buf + buflen;
   1172 
   1173 	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
   1174 			  "ssid=%s\n",
   1175 			  MAC2STR(hapd->own_addr),
   1176 			  wpa_ssid_txt(hapd->conf->ssid.ssid,
   1177 				       hapd->conf->ssid.ssid_len));
   1178 	if (os_snprintf_error(end - pos, ret))
   1179 		return pos - buf;
   1180 	pos += ret;
   1181 
   1182 #ifdef CONFIG_WPS
   1183 	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
   1184 			  hapd->conf->wps_state == 0 ? "disabled" :
   1185 			  (hapd->conf->wps_state == 1 ? "not configured" :
   1186 			   "configured"));
   1187 	if (os_snprintf_error(end - pos, ret))
   1188 		return pos - buf;
   1189 	pos += ret;
   1190 
   1191 	if (hapd->conf->wps_state && hapd->conf->wpa &&
   1192 	    hapd->conf->ssid.wpa_passphrase) {
   1193 		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
   1194 				  hapd->conf->ssid.wpa_passphrase);
   1195 		if (os_snprintf_error(end - pos, ret))
   1196 			return pos - buf;
   1197 		pos += ret;
   1198 	}
   1199 
   1200 	if (hapd->conf->wps_state && hapd->conf->wpa &&
   1201 	    hapd->conf->ssid.wpa_psk &&
   1202 	    hapd->conf->ssid.wpa_psk->group) {
   1203 		char hex[PMK_LEN * 2 + 1];
   1204 		wpa_snprintf_hex(hex, sizeof(hex),
   1205 				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
   1206 		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
   1207 		if (os_snprintf_error(end - pos, ret))
   1208 			return pos - buf;
   1209 		pos += ret;
   1210 	}
   1211 #endif /* CONFIG_WPS */
   1212 
   1213 	if (hapd->conf->wpa) {
   1214 		ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
   1215 		if (os_snprintf_error(end - pos, ret))
   1216 			return pos - buf;
   1217 		pos += ret;
   1218 	}
   1219 
   1220 	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
   1221 		ret = os_snprintf(pos, end - pos, "key_mgmt=");
   1222 		if (os_snprintf_error(end - pos, ret))
   1223 			return pos - buf;
   1224 		pos += ret;
   1225 
   1226 		pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
   1227 
   1228 		ret = os_snprintf(pos, end - pos, "\n");
   1229 		if (os_snprintf_error(end - pos, ret))
   1230 			return pos - buf;
   1231 		pos += ret;
   1232 	}
   1233 
   1234 	if (hapd->conf->wpa) {
   1235 		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
   1236 				  wpa_cipher_txt(hapd->conf->wpa_group));
   1237 		if (os_snprintf_error(end - pos, ret))
   1238 			return pos - buf;
   1239 		pos += ret;
   1240 	}
   1241 
   1242 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
   1243 		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
   1244 		if (os_snprintf_error(end - pos, ret))
   1245 			return pos - buf;
   1246 		pos += ret;
   1247 
   1248 		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
   1249 					" ");
   1250 		if (ret < 0)
   1251 			return pos - buf;
   1252 		pos += ret;
   1253 
   1254 		ret = os_snprintf(pos, end - pos, "\n");
   1255 		if (os_snprintf_error(end - pos, ret))
   1256 			return pos - buf;
   1257 		pos += ret;
   1258 	}
   1259 
   1260 	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
   1261 		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
   1262 		if (os_snprintf_error(end - pos, ret))
   1263 			return pos - buf;
   1264 		pos += ret;
   1265 
   1266 		ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
   1267 					" ");
   1268 		if (ret < 0)
   1269 			return pos - buf;
   1270 		pos += ret;
   1271 
   1272 		ret = os_snprintf(pos, end - pos, "\n");
   1273 		if (os_snprintf_error(end - pos, ret))
   1274 			return pos - buf;
   1275 		pos += ret;
   1276 	}
   1277 
   1278 	return pos - buf;
   1279 }
   1280 
   1281 
   1282 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
   1283 {
   1284 	char *value;
   1285 	int ret = 0;
   1286 
   1287 	value = os_strchr(cmd, ' ');
   1288 	if (value == NULL)
   1289 		return -1;
   1290 	*value++ = '\0';
   1291 
   1292 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
   1293 	if (0) {
   1294 #ifdef CONFIG_WPS_TESTING
   1295 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
   1296 		long int val;
   1297 		val = strtol(value, NULL, 0);
   1298 		if (val < 0 || val > 0xff) {
   1299 			ret = -1;
   1300 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
   1301 				   "wps_version_number %ld", val);
   1302 		} else {
   1303 			wps_version_number = val;
   1304 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
   1305 				   "version %u.%u",
   1306 				   (wps_version_number & 0xf0) >> 4,
   1307 				   wps_version_number & 0x0f);
   1308 			hostapd_wps_update_ie(hapd);
   1309 		}
   1310 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
   1311 		wps_testing_dummy_cred = atoi(value);
   1312 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
   1313 			   wps_testing_dummy_cred);
   1314 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
   1315 		wps_corrupt_pkhash = atoi(value);
   1316 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
   1317 			   wps_corrupt_pkhash);
   1318 #endif /* CONFIG_WPS_TESTING */
   1319 #ifdef CONFIG_INTERWORKING
   1320 	} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
   1321 		int val = atoi(value);
   1322 		if (val <= 0)
   1323 			ret = -1;
   1324 		else
   1325 			hapd->gas_frag_limit = val;
   1326 #endif /* CONFIG_INTERWORKING */
   1327 #ifdef CONFIG_TESTING_OPTIONS
   1328 	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
   1329 		hapd->ext_mgmt_frame_handling = atoi(value);
   1330 	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
   1331 		hapd->ext_eapol_frame_io = atoi(value);
   1332 #endif /* CONFIG_TESTING_OPTIONS */
   1333 #ifdef CONFIG_MBO
   1334 	} else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
   1335 		int val;
   1336 
   1337 		if (!hapd->conf->mbo_enabled)
   1338 			return -1;
   1339 
   1340 		val = atoi(value);
   1341 		if (val < 0 || val > 1)
   1342 			return -1;
   1343 
   1344 		hapd->mbo_assoc_disallow = val;
   1345 		ieee802_11_update_beacons(hapd->iface);
   1346 
   1347 		/*
   1348 		 * TODO: Need to configure drivers that do AP MLME offload with
   1349 		 * disallowing station logic.
   1350 		 */
   1351 #endif /* CONFIG_MBO */
   1352 	} else {
   1353 		struct sta_info *sta;
   1354 		struct vlan_description vlan_id;
   1355 
   1356 		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
   1357 		if (ret)
   1358 			return ret;
   1359 
   1360 		if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
   1361 			for (sta = hapd->sta_list; sta; sta = sta->next) {
   1362 				if (hostapd_maclist_found(
   1363 					    hapd->conf->deny_mac,
   1364 					    hapd->conf->num_deny_mac, sta->addr,
   1365 					    &vlan_id) &&
   1366 				    (!vlan_id.notempty ||
   1367 				     !vlan_compare(&vlan_id, sta->vlan_desc)))
   1368 					ap_sta_disconnect(
   1369 						hapd, sta, sta->addr,
   1370 						WLAN_REASON_UNSPECIFIED);
   1371 			}
   1372 		} else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
   1373 			   os_strcasecmp(cmd, "accept_mac_file") == 0) {
   1374 			for (sta = hapd->sta_list; sta; sta = sta->next) {
   1375 				if (!hostapd_maclist_found(
   1376 					    hapd->conf->accept_mac,
   1377 					    hapd->conf->num_accept_mac,
   1378 					    sta->addr, &vlan_id) ||
   1379 				    (vlan_id.notempty &&
   1380 				     vlan_compare(&vlan_id, sta->vlan_desc)))
   1381 					ap_sta_disconnect(
   1382 						hapd, sta, sta->addr,
   1383 						WLAN_REASON_UNSPECIFIED);
   1384 			}
   1385 		}
   1386 	}
   1387 
   1388 	return ret;
   1389 }
   1390 
   1391 
   1392 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
   1393 				  char *buf, size_t buflen)
   1394 {
   1395 	int res;
   1396 
   1397 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
   1398 
   1399 	if (os_strcmp(cmd, "version") == 0) {
   1400 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
   1401 		if (os_snprintf_error(buflen, res))
   1402 			return -1;
   1403 		return res;
   1404 	} else if (os_strcmp(cmd, "tls_library") == 0) {
   1405 		res = tls_get_library_version(buf, buflen);
   1406 		if (os_snprintf_error(buflen, res))
   1407 			return -1;
   1408 		return res;
   1409 	}
   1410 
   1411 	return -1;
   1412 }
   1413 
   1414 
   1415 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
   1416 {
   1417 	if (hostapd_enable_iface(iface) < 0) {
   1418 		wpa_printf(MSG_ERROR, "Enabling of interface failed");
   1419 		return -1;
   1420 	}
   1421 	return 0;
   1422 }
   1423 
   1424 
   1425 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
   1426 {
   1427 	if (hostapd_reload_iface(iface) < 0) {
   1428 		wpa_printf(MSG_ERROR, "Reloading of interface failed");
   1429 		return -1;
   1430 	}
   1431 	return 0;
   1432 }
   1433 
   1434 
   1435 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
   1436 {
   1437 	if (hostapd_disable_iface(iface) < 0) {
   1438 		wpa_printf(MSG_ERROR, "Disabling of interface failed");
   1439 		return -1;
   1440 	}
   1441 	return 0;
   1442 }
   1443 
   1444 
   1445 #ifdef CONFIG_TESTING_OPTIONS
   1446 
   1447 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
   1448 {
   1449 	union wpa_event_data data;
   1450 	char *pos, *param;
   1451 	enum wpa_event_type event;
   1452 
   1453 	wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
   1454 
   1455 	os_memset(&data, 0, sizeof(data));
   1456 
   1457 	param = os_strchr(cmd, ' ');
   1458 	if (param == NULL)
   1459 		return -1;
   1460 	*param++ = '\0';
   1461 
   1462 	if (os_strcmp(cmd, "DETECTED") == 0)
   1463 		event = EVENT_DFS_RADAR_DETECTED;
   1464 	else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
   1465 		event = EVENT_DFS_CAC_FINISHED;
   1466 	else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
   1467 		event = EVENT_DFS_CAC_ABORTED;
   1468 	else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
   1469 		event = EVENT_DFS_NOP_FINISHED;
   1470 	else {
   1471 		wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
   1472 			   cmd);
   1473 		return -1;
   1474 	}
   1475 
   1476 	pos = os_strstr(param, "freq=");
   1477 	if (pos)
   1478 		data.dfs_event.freq = atoi(pos + 5);
   1479 
   1480 	pos = os_strstr(param, "ht_enabled=1");
   1481 	if (pos)
   1482 		data.dfs_event.ht_enabled = 1;
   1483 
   1484 	pos = os_strstr(param, "chan_offset=");
   1485 	if (pos)
   1486 		data.dfs_event.chan_offset = atoi(pos + 12);
   1487 
   1488 	pos = os_strstr(param, "chan_width=");
   1489 	if (pos)
   1490 		data.dfs_event.chan_width = atoi(pos + 11);
   1491 
   1492 	pos = os_strstr(param, "cf1=");
   1493 	if (pos)
   1494 		data.dfs_event.cf1 = atoi(pos + 4);
   1495 
   1496 	pos = os_strstr(param, "cf2=");
   1497 	if (pos)
   1498 		data.dfs_event.cf2 = atoi(pos + 4);
   1499 
   1500 	wpa_supplicant_event(hapd, event, &data);
   1501 
   1502 	return 0;
   1503 }
   1504 
   1505 
   1506 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
   1507 {
   1508 	size_t len;
   1509 	u8 *buf;
   1510 	int res;
   1511 
   1512 	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
   1513 
   1514 	len = os_strlen(cmd);
   1515 	if (len & 1)
   1516 		return -1;
   1517 	len /= 2;
   1518 
   1519 	buf = os_malloc(len);
   1520 	if (buf == NULL)
   1521 		return -1;
   1522 
   1523 	if (hexstr2bin(cmd, buf, len) < 0) {
   1524 		os_free(buf);
   1525 		return -1;
   1526 	}
   1527 
   1528 	res = hostapd_drv_send_mlme(hapd, buf, len, 0);
   1529 	os_free(buf);
   1530 	return res;
   1531 }
   1532 
   1533 
   1534 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
   1535 {
   1536 	char *pos;
   1537 	u8 src[ETH_ALEN], *buf;
   1538 	int used;
   1539 	size_t len;
   1540 
   1541 	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
   1542 
   1543 	pos = cmd;
   1544 	used = hwaddr_aton2(pos, src);
   1545 	if (used < 0)
   1546 		return -1;
   1547 	pos += used;
   1548 	while (*pos == ' ')
   1549 		pos++;
   1550 
   1551 	len = os_strlen(pos);
   1552 	if (len & 1)
   1553 		return -1;
   1554 	len /= 2;
   1555 
   1556 	buf = os_malloc(len);
   1557 	if (buf == NULL)
   1558 		return -1;
   1559 
   1560 	if (hexstr2bin(pos, buf, len) < 0) {
   1561 		os_free(buf);
   1562 		return -1;
   1563 	}
   1564 
   1565 	ieee802_1x_receive(hapd, src, buf, len);
   1566 	os_free(buf);
   1567 
   1568 	return 0;
   1569 }
   1570 
   1571 
   1572 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
   1573 {
   1574 	size_t i;
   1575 	u32 sum = 0;
   1576 	const u16 *pos = buf;
   1577 
   1578 	for (i = 0; i < len / 2; i++)
   1579 		sum += *pos++;
   1580 
   1581 	while (sum >> 16)
   1582 		sum = (sum & 0xffff) + (sum >> 16);
   1583 
   1584 	return sum ^ 0xffff;
   1585 }
   1586 
   1587 
   1588 #define HWSIM_PACKETLEN 1500
   1589 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
   1590 
   1591 void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
   1592 			  size_t len)
   1593 {
   1594 	struct hostapd_data *hapd = ctx;
   1595 	const struct ether_header *eth;
   1596 	struct iphdr ip;
   1597 	const u8 *pos;
   1598 	unsigned int i;
   1599 
   1600 	if (len != HWSIM_PACKETLEN)
   1601 		return;
   1602 
   1603 	eth = (const struct ether_header *) buf;
   1604 	os_memcpy(&ip, eth + 1, sizeof(ip));
   1605 	pos = &buf[sizeof(*eth) + sizeof(ip)];
   1606 
   1607 	if (ip.ihl != 5 || ip.version != 4 ||
   1608 	    ntohs(ip.tot_len) != HWSIM_IP_LEN)
   1609 		return;
   1610 
   1611 	for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
   1612 		if (*pos != (u8) i)
   1613 			return;
   1614 		pos++;
   1615 	}
   1616 
   1617 	wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
   1618 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
   1619 }
   1620 
   1621 
   1622 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
   1623 					       char *cmd)
   1624 {
   1625 	int enabled = atoi(cmd);
   1626 	char *pos;
   1627 	const char *ifname;
   1628 
   1629 	if (!enabled) {
   1630 		if (hapd->l2_test) {
   1631 			l2_packet_deinit(hapd->l2_test);
   1632 			hapd->l2_test = NULL;
   1633 			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
   1634 				"test data: Disabled");
   1635 		}
   1636 		return 0;
   1637 	}
   1638 
   1639 	if (hapd->l2_test)
   1640 		return 0;
   1641 
   1642 	pos = os_strstr(cmd, " ifname=");
   1643 	if (pos)
   1644 		ifname = pos + 8;
   1645 	else
   1646 		ifname = hapd->conf->iface;
   1647 
   1648 	hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
   1649 					ETHERTYPE_IP, hostapd_data_test_rx,
   1650 					hapd, 1);
   1651 	if (hapd->l2_test == NULL)
   1652 		return -1;
   1653 
   1654 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
   1655 
   1656 	return 0;
   1657 }
   1658 
   1659 
   1660 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
   1661 {
   1662 	u8 dst[ETH_ALEN], src[ETH_ALEN];
   1663 	char *pos;
   1664 	int used;
   1665 	long int val;
   1666 	u8 tos;
   1667 	u8 buf[2 + HWSIM_PACKETLEN];
   1668 	struct ether_header *eth;
   1669 	struct iphdr *ip;
   1670 	u8 *dpos;
   1671 	unsigned int i;
   1672 
   1673 	if (hapd->l2_test == NULL)
   1674 		return -1;
   1675 
   1676 	/* format: <dst> <src> <tos> */
   1677 
   1678 	pos = cmd;
   1679 	used = hwaddr_aton2(pos, dst);
   1680 	if (used < 0)
   1681 		return -1;
   1682 	pos += used;
   1683 	while (*pos == ' ')
   1684 		pos++;
   1685 	used = hwaddr_aton2(pos, src);
   1686 	if (used < 0)
   1687 		return -1;
   1688 	pos += used;
   1689 
   1690 	val = strtol(pos, NULL, 0);
   1691 	if (val < 0 || val > 0xff)
   1692 		return -1;
   1693 	tos = val;
   1694 
   1695 	eth = (struct ether_header *) &buf[2];
   1696 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
   1697 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
   1698 	eth->ether_type = htons(ETHERTYPE_IP);
   1699 	ip = (struct iphdr *) (eth + 1);
   1700 	os_memset(ip, 0, sizeof(*ip));
   1701 	ip->ihl = 5;
   1702 	ip->version = 4;
   1703 	ip->ttl = 64;
   1704 	ip->tos = tos;
   1705 	ip->tot_len = htons(HWSIM_IP_LEN);
   1706 	ip->protocol = 1;
   1707 	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
   1708 	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
   1709 	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
   1710 	dpos = (u8 *) (ip + 1);
   1711 	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
   1712 		*dpos++ = i;
   1713 
   1714 	if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
   1715 			   HWSIM_PACKETLEN) < 0)
   1716 		return -1;
   1717 
   1718 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
   1719 		" src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
   1720 
   1721 	return 0;
   1722 }
   1723 
   1724 
   1725 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
   1726 					      char *cmd)
   1727 {
   1728 	u8 *buf;
   1729 	struct ether_header *eth;
   1730 	struct l2_packet_data *l2 = NULL;
   1731 	size_t len;
   1732 	u16 ethertype;
   1733 	int res = -1;
   1734 	const char *ifname = hapd->conf->iface;
   1735 
   1736 	if (os_strncmp(cmd, "ifname=", 7) == 0) {
   1737 		cmd += 7;
   1738 		ifname = cmd;
   1739 		cmd = os_strchr(cmd, ' ');
   1740 		if (cmd == NULL)
   1741 			return -1;
   1742 		*cmd++ = '\0';
   1743 	}
   1744 
   1745 	len = os_strlen(cmd);
   1746 	if (len & 1 || len < ETH_HLEN * 2)
   1747 		return -1;
   1748 	len /= 2;
   1749 
   1750 	buf = os_malloc(len);
   1751 	if (buf == NULL)
   1752 		return -1;
   1753 
   1754 	if (hexstr2bin(cmd, buf, len) < 0)
   1755 		goto done;
   1756 
   1757 	eth = (struct ether_header *) buf;
   1758 	ethertype = ntohs(eth->ether_type);
   1759 
   1760 	l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
   1761 			    hostapd_data_test_rx, hapd, 1);
   1762 	if (l2 == NULL)
   1763 		goto done;
   1764 
   1765 	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
   1766 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
   1767 done:
   1768 	if (l2)
   1769 		l2_packet_deinit(l2);
   1770 	os_free(buf);
   1771 
   1772 	return res < 0 ? -1 : 0;
   1773 }
   1774 
   1775 
   1776 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
   1777 {
   1778 #ifdef WPA_TRACE_BFD
   1779 	extern char wpa_trace_fail_func[256];
   1780 	extern unsigned int wpa_trace_fail_after;
   1781 	char *pos;
   1782 
   1783 	wpa_trace_fail_after = atoi(cmd);
   1784 	pos = os_strchr(cmd, ':');
   1785 	if (pos) {
   1786 		pos++;
   1787 		os_strlcpy(wpa_trace_fail_func, pos,
   1788 			   sizeof(wpa_trace_fail_func));
   1789 	} else {
   1790 		wpa_trace_fail_after = 0;
   1791 	}
   1792 
   1793 	return 0;
   1794 #else /* WPA_TRACE_BFD */
   1795 	return -1;
   1796 #endif /* WPA_TRACE_BFD */
   1797 }
   1798 
   1799 
   1800 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
   1801 				       char *buf, size_t buflen)
   1802 {
   1803 #ifdef WPA_TRACE_BFD
   1804 	extern char wpa_trace_fail_func[256];
   1805 	extern unsigned int wpa_trace_fail_after;
   1806 
   1807 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
   1808 			   wpa_trace_fail_func);
   1809 #else /* WPA_TRACE_BFD */
   1810 	return -1;
   1811 #endif /* WPA_TRACE_BFD */
   1812 }
   1813 
   1814 
   1815 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
   1816 {
   1817 #ifdef WPA_TRACE_BFD
   1818 	extern char wpa_trace_test_fail_func[256];
   1819 	extern unsigned int wpa_trace_test_fail_after;
   1820 	char *pos;
   1821 
   1822 	wpa_trace_test_fail_after = atoi(cmd);
   1823 	pos = os_strchr(cmd, ':');
   1824 	if (pos) {
   1825 		pos++;
   1826 		os_strlcpy(wpa_trace_test_fail_func, pos,
   1827 			   sizeof(wpa_trace_test_fail_func));
   1828 	} else {
   1829 		wpa_trace_test_fail_after = 0;
   1830 	}
   1831 
   1832 	return 0;
   1833 #else /* WPA_TRACE_BFD */
   1834 	return -1;
   1835 #endif /* WPA_TRACE_BFD */
   1836 }
   1837 
   1838 
   1839 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
   1840 				 char *buf, size_t buflen)
   1841 {
   1842 #ifdef WPA_TRACE_BFD
   1843 	extern char wpa_trace_test_fail_func[256];
   1844 	extern unsigned int wpa_trace_test_fail_after;
   1845 
   1846 	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
   1847 			   wpa_trace_test_fail_func);
   1848 #else /* WPA_TRACE_BFD */
   1849 	return -1;
   1850 #endif /* WPA_TRACE_BFD */
   1851 }
   1852 
   1853 #endif /* CONFIG_TESTING_OPTIONS */
   1854 
   1855 
   1856 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
   1857 					  char *pos)
   1858 {
   1859 #ifdef NEED_AP_MLME
   1860 	struct csa_settings settings;
   1861 	int ret;
   1862 	unsigned int i;
   1863 
   1864 	ret = hostapd_parse_csa_settings(pos, &settings);
   1865 	if (ret)
   1866 		return ret;
   1867 
   1868 	for (i = 0; i < iface->num_bss; i++) {
   1869 		ret = hostapd_switch_channel(iface->bss[i], &settings);
   1870 		if (ret) {
   1871 			/* FIX: What do we do if CSA fails in the middle of
   1872 			 * submitting multi-BSS CSA requests? */
   1873 			return ret;
   1874 		}
   1875 	}
   1876 
   1877 	return 0;
   1878 #else /* NEED_AP_MLME */
   1879 	return -1;
   1880 #endif /* NEED_AP_MLME */
   1881 }
   1882 
   1883 
   1884 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
   1885 				  int reply_size, const char *param)
   1886 {
   1887 #ifdef RADIUS_SERVER
   1888 	if (os_strcmp(param, "radius_server") == 0) {
   1889 		return radius_server_get_mib(hapd->radius_srv, reply,
   1890 					     reply_size);
   1891 	}
   1892 #endif /* RADIUS_SERVER */
   1893 	return -1;
   1894 }
   1895 
   1896 
   1897 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
   1898 				     char *buf, size_t buflen)
   1899 {
   1900 	int ret;
   1901 	char *pos;
   1902 	u8 *data = NULL;
   1903 	unsigned int vendor_id, subcmd;
   1904 	struct wpabuf *reply;
   1905 	size_t data_len = 0;
   1906 
   1907 	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
   1908 	vendor_id = strtoul(cmd, &pos, 16);
   1909 	if (!isblank((unsigned char) *pos))
   1910 		return -EINVAL;
   1911 
   1912 	subcmd = strtoul(pos, &pos, 10);
   1913 
   1914 	if (*pos != '\0') {
   1915 		if (!isblank((unsigned char) *pos++))
   1916 			return -EINVAL;
   1917 		data_len = os_strlen(pos);
   1918 	}
   1919 
   1920 	if (data_len) {
   1921 		data_len /= 2;
   1922 		data = os_malloc(data_len);
   1923 		if (!data)
   1924 			return -ENOBUFS;
   1925 
   1926 		if (hexstr2bin(pos, data, data_len)) {
   1927 			wpa_printf(MSG_DEBUG,
   1928 				   "Vendor command: wrong parameter format");
   1929 			os_free(data);
   1930 			return -EINVAL;
   1931 		}
   1932 	}
   1933 
   1934 	reply = wpabuf_alloc((buflen - 1) / 2);
   1935 	if (!reply) {
   1936 		os_free(data);
   1937 		return -ENOBUFS;
   1938 	}
   1939 
   1940 	ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
   1941 				     reply);
   1942 
   1943 	if (ret == 0)
   1944 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
   1945 				       wpabuf_len(reply));
   1946 
   1947 	wpabuf_free(reply);
   1948 	os_free(data);
   1949 
   1950 	return ret;
   1951 }
   1952 
   1953 
   1954 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
   1955 					   const char *cmd)
   1956 {
   1957 	u8 addr[ETH_ALEN];
   1958 	struct sta_info *sta;
   1959 
   1960 	if (hwaddr_aton(cmd, addr))
   1961 		return -1;
   1962 
   1963 	sta = ap_get_sta(hapd, addr);
   1964 	if (!sta || !sta->eapol_sm)
   1965 		return -1;
   1966 
   1967 	eapol_auth_reauthenticate(sta->eapol_sm);
   1968 	return 0;
   1969 }
   1970 
   1971 
   1972 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
   1973 {
   1974 	u8 addr[ETH_ALEN];
   1975 	struct sta_info *sta;
   1976 	char *pos = cmd, *param;
   1977 
   1978 	if (hwaddr_aton(pos, addr) || pos[17] != ' ')
   1979 		return -1;
   1980 	pos += 18;
   1981 	param = pos;
   1982 	pos = os_strchr(pos, ' ');
   1983 	if (!pos)
   1984 		return -1;
   1985 	*pos++ = '\0';
   1986 
   1987 	sta = ap_get_sta(hapd, addr);
   1988 	if (!sta || !sta->eapol_sm)
   1989 		return -1;
   1990 
   1991 	return eapol_auth_set_conf(sta->eapol_sm, param, pos);
   1992 }
   1993 
   1994 
   1995 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
   1996 					char *buf, size_t buflen)
   1997 {
   1998 	char *pos, *end, *stamp;
   1999 	int ret;
   2000 
   2001 	/* cmd: "LOG_LEVEL [<level>]" */
   2002 	if (*cmd == '\0') {
   2003 		pos = buf;
   2004 		end = buf + buflen;
   2005 		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
   2006 				  "Timestamp: %d\n",
   2007 				  debug_level_str(wpa_debug_level),
   2008 				  wpa_debug_timestamp);
   2009 		if (os_snprintf_error(end - pos, ret))
   2010 			ret = 0;
   2011 
   2012 		return ret;
   2013 	}
   2014 
   2015 	while (*cmd == ' ')
   2016 		cmd++;
   2017 
   2018 	stamp = os_strchr(cmd, ' ');
   2019 	if (stamp) {
   2020 		*stamp++ = '\0';
   2021 		while (*stamp == ' ') {
   2022 			stamp++;
   2023 		}
   2024 	}
   2025 
   2026 	if (os_strlen(cmd)) {
   2027 		int level = str_to_debug_level(cmd);
   2028 		if (level < 0)
   2029 			return -1;
   2030 		wpa_debug_level = level;
   2031 	}
   2032 
   2033 	if (stamp && os_strlen(stamp))
   2034 		wpa_debug_timestamp = atoi(stamp);
   2035 
   2036 	os_memcpy(buf, "OK\n", 3);
   2037 	return 3;
   2038 }
   2039 
   2040 
   2041 #ifdef NEED_AP_MLME
   2042 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
   2043 					     char *buf, size_t buflen)
   2044 {
   2045 	struct hostapd_iface *iface = hapd->iface;
   2046 	char *pos, *end;
   2047 	struct hostapd_sta_info *info;
   2048 	struct os_reltime now;
   2049 
   2050 	sta_track_expire(iface, 0);
   2051 
   2052 	pos = buf;
   2053 	end = buf + buflen;
   2054 
   2055 	os_get_reltime(&now);
   2056 	dl_list_for_each_reverse(info, &iface->sta_seen,
   2057 				 struct hostapd_sta_info, list) {
   2058 		struct os_reltime age;
   2059 		int ret;
   2060 
   2061 		os_reltime_sub(&now, &info->last_seen, &age);
   2062 		ret = os_snprintf(pos, end - pos, MACSTR " %u\n",
   2063 				  MAC2STR(info->addr), (unsigned int) age.sec);
   2064 		if (os_snprintf_error(end - pos, ret))
   2065 			break;
   2066 		pos += ret;
   2067 	}
   2068 
   2069 	return pos - buf;
   2070 }
   2071 #endif /* NEED_AP_MLME */
   2072 
   2073 
   2074 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
   2075 					      char *buf, char *reply,
   2076 					      int reply_size,
   2077 					      struct sockaddr_storage *from,
   2078 					      socklen_t fromlen)
   2079 {
   2080 	int reply_len, res;
   2081 
   2082 	os_memcpy(reply, "OK\n", 3);
   2083 	reply_len = 3;
   2084 
   2085 	if (os_strcmp(buf, "PING") == 0) {
   2086 		os_memcpy(reply, "PONG\n", 5);
   2087 		reply_len = 5;
   2088 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
   2089 		if (wpa_debug_reopen_file() < 0)
   2090 			reply_len = -1;
   2091 	} else if (os_strcmp(buf, "STATUS") == 0) {
   2092 		reply_len = hostapd_ctrl_iface_status(hapd, reply,
   2093 						      reply_size);
   2094 	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
   2095 		reply_len = hostapd_drv_status(hapd, reply, reply_size);
   2096 	} else if (os_strcmp(buf, "MIB") == 0) {
   2097 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
   2098 		if (reply_len >= 0) {
   2099 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
   2100 					  reply_size - reply_len);
   2101 			if (res < 0)
   2102 				reply_len = -1;
   2103 			else
   2104 				reply_len += res;
   2105 		}
   2106 		if (reply_len >= 0) {
   2107 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
   2108 						 reply_size - reply_len);
   2109 			if (res < 0)
   2110 				reply_len = -1;
   2111 			else
   2112 				reply_len += res;
   2113 		}
   2114 #ifndef CONFIG_NO_RADIUS
   2115 		if (reply_len >= 0) {
   2116 			res = radius_client_get_mib(hapd->radius,
   2117 						    reply + reply_len,
   2118 						    reply_size - reply_len);
   2119 			if (res < 0)
   2120 				reply_len = -1;
   2121 			else
   2122 				reply_len += res;
   2123 		}
   2124 #endif /* CONFIG_NO_RADIUS */
   2125 	} else if (os_strncmp(buf, "MIB ", 4) == 0) {
   2126 		reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
   2127 						   buf + 4);
   2128 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
   2129 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
   2130 							 reply_size);
   2131 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
   2132 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
   2133 						   reply_size);
   2134 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
   2135 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
   2136 							reply_size);
   2137 	} else if (os_strcmp(buf, "ATTACH") == 0) {
   2138 		if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
   2139 			reply_len = -1;
   2140 	} else if (os_strcmp(buf, "DETACH") == 0) {
   2141 		if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
   2142 			reply_len = -1;
   2143 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
   2144 		if (hostapd_ctrl_iface_level(hapd, from, fromlen,
   2145 						    buf + 6))
   2146 			reply_len = -1;
   2147 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
   2148 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
   2149 			reply_len = -1;
   2150 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
   2151 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
   2152 			reply_len = -1;
   2153 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
   2154 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
   2155 			reply_len = -1;
   2156 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
   2157 		if (hostapd_ctrl_iface_stop_ap(hapd))
   2158 			reply_len = -1;
   2159 #ifdef CONFIG_IEEE80211W
   2160 #ifdef NEED_AP_MLME
   2161 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
   2162 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
   2163 			reply_len = -1;
   2164 #endif /* NEED_AP_MLME */
   2165 #endif /* CONFIG_IEEE80211W */
   2166 #ifdef CONFIG_WPS
   2167 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
   2168 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
   2169 			reply_len = -1;
   2170 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
   2171 		reply_len = hostapd_ctrl_iface_wps_check_pin(
   2172 			hapd, buf + 14, reply, reply_size);
   2173 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
   2174 		if (hostapd_wps_button_pushed(hapd, NULL))
   2175 			reply_len = -1;
   2176 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
   2177 		if (hostapd_wps_cancel(hapd))
   2178 			reply_len = -1;
   2179 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
   2180 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
   2181 							  reply, reply_size);
   2182 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
   2183 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
   2184 			reply_len = -1;
   2185 	} else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
   2186 		reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
   2187 							      reply_size);
   2188 #ifdef CONFIG_WPS_NFC
   2189 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
   2190 		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
   2191 			reply_len = -1;
   2192 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
   2193 		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
   2194 			hapd, buf + 21, reply, reply_size);
   2195 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
   2196 		reply_len = hostapd_ctrl_iface_wps_nfc_token(
   2197 			hapd, buf + 14, reply, reply_size);
   2198 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
   2199 		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
   2200 			hapd, buf + 21, reply, reply_size);
   2201 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
   2202 		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
   2203 			reply_len = -1;
   2204 #endif /* CONFIG_WPS_NFC */
   2205 #endif /* CONFIG_WPS */
   2206 #ifdef CONFIG_INTERWORKING
   2207 	} else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
   2208 		if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
   2209 			reply_len = -1;
   2210 	} else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
   2211 		if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
   2212 			reply_len = -1;
   2213 #endif /* CONFIG_INTERWORKING */
   2214 #ifdef CONFIG_HS20
   2215 	} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
   2216 		if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
   2217 			reply_len = -1;
   2218 	} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
   2219 		if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
   2220 			reply_len = -1;
   2221 #endif /* CONFIG_HS20 */
   2222 #ifdef CONFIG_WNM
   2223 	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
   2224 		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
   2225 			reply_len = -1;
   2226 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
   2227 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
   2228 			reply_len = -1;
   2229 	} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
   2230 		if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
   2231 			reply_len = -1;
   2232 #endif /* CONFIG_WNM */
   2233 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
   2234 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
   2235 							  reply_size);
   2236 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
   2237 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
   2238 			reply_len = -1;
   2239 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
   2240 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
   2241 						   reply_size);
   2242 	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
   2243 		if (hostapd_ctrl_iface_enable(hapd->iface))
   2244 			reply_len = -1;
   2245 	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
   2246 		if (hostapd_ctrl_iface_reload(hapd->iface))
   2247 			reply_len = -1;
   2248 	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
   2249 		if (hostapd_ctrl_iface_disable(hapd->iface))
   2250 			reply_len = -1;
   2251 	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
   2252 		if (ieee802_11_set_beacon(hapd))
   2253 			reply_len = -1;
   2254 #ifdef CONFIG_TESTING_OPTIONS
   2255 	} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
   2256 		if (hostapd_ctrl_iface_radar(hapd, buf + 6))
   2257 			reply_len = -1;
   2258 	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
   2259 		if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
   2260 			reply_len = -1;
   2261 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
   2262 		if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
   2263 			reply_len = -1;
   2264 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
   2265 		if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
   2266 			reply_len = -1;
   2267 	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
   2268 		if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
   2269 			reply_len = -1;
   2270 	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
   2271 		if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
   2272 			reply_len = -1;
   2273 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
   2274 		if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
   2275 			reply_len = -1;
   2276 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
   2277 		reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
   2278 							reply_size);
   2279 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
   2280 		if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
   2281 			reply_len = -1;
   2282 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
   2283 		reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
   2284 #endif /* CONFIG_TESTING_OPTIONS */
   2285 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
   2286 		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
   2287 			reply_len = -1;
   2288 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
   2289 		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
   2290 						      reply_size);
   2291 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
   2292 		ieee802_1x_erp_flush(hapd);
   2293 #ifdef RADIUS_SERVER
   2294 		radius_server_erp_flush(hapd->radius_srv);
   2295 #endif /* RADIUS_SERVER */
   2296 	} else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
   2297 		if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
   2298 			reply_len = -1;
   2299 	} else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
   2300 		if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
   2301 			reply_len = -1;
   2302 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
   2303 		reply_len = hostapd_ctrl_iface_log_level(
   2304 			hapd, buf + 9, reply, reply_size);
   2305 #ifdef NEED_AP_MLME
   2306 	} else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
   2307 		reply_len = hostapd_ctrl_iface_track_sta_list(
   2308 			hapd, reply, reply_size);
   2309 #endif /* NEED_AP_MLME */
   2310 	} else if (os_strcmp(buf, "PMKSA") == 0) {
   2311 		reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
   2312 							  reply_size);
   2313 	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
   2314 		hostapd_ctrl_iface_pmksa_flush(hapd);
   2315 	} else {
   2316 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   2317 		reply_len = 16;
   2318 	}
   2319 
   2320 	if (reply_len < 0) {
   2321 		os_memcpy(reply, "FAIL\n", 5);
   2322 		reply_len = 5;
   2323 	}
   2324 
   2325 	return reply_len;
   2326 }
   2327 
   2328 
   2329 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
   2330 				       void *sock_ctx)
   2331 {
   2332 	struct hostapd_data *hapd = eloop_ctx;
   2333 	char buf[4096];
   2334 	int res;
   2335 	struct sockaddr_storage from;
   2336 	socklen_t fromlen = sizeof(from);
   2337 	char *reply, *pos = buf;
   2338 	const int reply_size = 4096;
   2339 	int reply_len;
   2340 	int level = MSG_DEBUG;
   2341 #ifdef CONFIG_CTRL_IFACE_UDP
   2342 	unsigned char lcookie[COOKIE_LEN];
   2343 #endif /* CONFIG_CTRL_IFACE_UDP */
   2344 
   2345 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
   2346 		       (struct sockaddr *) &from, &fromlen);
   2347 	if (res < 0) {
   2348 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
   2349 			   strerror(errno));
   2350 		return;
   2351 	}
   2352 	buf[res] = '\0';
   2353 
   2354 	reply = os_malloc(reply_size);
   2355 	if (reply == NULL) {
   2356 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
   2357 			   fromlen) < 0) {
   2358 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   2359 				   strerror(errno));
   2360 		}
   2361 		return;
   2362 	}
   2363 
   2364 #ifdef CONFIG_CTRL_IFACE_UDP
   2365 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
   2366 		os_memcpy(reply, "COOKIE=", 7);
   2367 		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
   2368 				 cookie, COOKIE_LEN);
   2369 		reply_len = 7 + 2 * COOKIE_LEN;
   2370 		goto done;
   2371 	}
   2372 
   2373 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
   2374 	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
   2375 		wpa_printf(MSG_DEBUG,
   2376 			   "CTRL: No cookie in the request - drop request");
   2377 		os_free(reply);
   2378 		return;
   2379 	}
   2380 
   2381 	if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
   2382 		wpa_printf(MSG_DEBUG,
   2383 			   "CTRL: Invalid cookie in the request - drop request");
   2384 		os_free(reply);
   2385 		return;
   2386 	}
   2387 
   2388 	pos = buf + 7 + 2 * COOKIE_LEN;
   2389 	while (*pos == ' ')
   2390 		pos++;
   2391 #endif /* CONFIG_CTRL_IFACE_UDP */
   2392 
   2393 	if (os_strcmp(pos, "PING") == 0)
   2394 		level = MSG_EXCESSIVE;
   2395 	wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
   2396 
   2397 	reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
   2398 						       reply, reply_size,
   2399 						       &from, fromlen);
   2400 
   2401 #ifdef CONFIG_CTRL_IFACE_UDP
   2402 done:
   2403 #endif /* CONFIG_CTRL_IFACE_UDP */
   2404 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
   2405 		   fromlen) < 0) {
   2406 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   2407 			   strerror(errno));
   2408 	}
   2409 	os_free(reply);
   2410 }
   2411 
   2412 
   2413 #ifndef CONFIG_CTRL_IFACE_UDP
   2414 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
   2415 {
   2416 	char *buf;
   2417 	size_t len;
   2418 
   2419 	if (hapd->conf->ctrl_interface == NULL)
   2420 		return NULL;
   2421 
   2422 	len = os_strlen(hapd->conf->ctrl_interface) +
   2423 		os_strlen(hapd->conf->iface) + 2;
   2424 	buf = os_malloc(len);
   2425 	if (buf == NULL)
   2426 		return NULL;
   2427 
   2428 	os_snprintf(buf, len, "%s/%s",
   2429 		    hapd->conf->ctrl_interface, hapd->conf->iface);
   2430 	buf[len - 1] = '\0';
   2431 	return buf;
   2432 }
   2433 #endif /* CONFIG_CTRL_IFACE_UDP */
   2434 
   2435 
   2436 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
   2437 				      enum wpa_msg_type type,
   2438 				      const char *txt, size_t len)
   2439 {
   2440 	struct hostapd_data *hapd = ctx;
   2441 	if (hapd == NULL)
   2442 		return;
   2443 	hostapd_ctrl_iface_send(hapd, level, type, txt, len);
   2444 }
   2445 
   2446 
   2447 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
   2448 {
   2449 #ifdef CONFIG_CTRL_IFACE_UDP
   2450 	int port = HOSTAPD_CTRL_IFACE_PORT;
   2451 	char p[32] = { 0 };
   2452 	char port_str[40], *tmp;
   2453 	char *pos;
   2454 	struct addrinfo hints = { 0 }, *res, *saveres;
   2455 	int n;
   2456 
   2457 	if (hapd->ctrl_sock > -1) {
   2458 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   2459 		return 0;
   2460 	}
   2461 
   2462 	if (hapd->conf->ctrl_interface == NULL)
   2463 		return 0;
   2464 
   2465 	pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
   2466 	if (pos) {
   2467 		pos += 4;
   2468 		port = atoi(pos);
   2469 		if (port <= 0) {
   2470 			wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
   2471 			goto fail;
   2472 		}
   2473 	}
   2474 
   2475 	dl_list_init(&hapd->ctrl_dst);
   2476 	hapd->ctrl_sock = -1;
   2477 	os_get_random(cookie, COOKIE_LEN);
   2478 
   2479 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
   2480 	hints.ai_flags = AI_PASSIVE;
   2481 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
   2482 
   2483 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
   2484 	hints.ai_family = AF_INET6;
   2485 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   2486 	hints.ai_family = AF_INET;
   2487 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   2488 	hints.ai_socktype = SOCK_DGRAM;
   2489 
   2490 try_again:
   2491 	os_snprintf(p, sizeof(p), "%d", port);
   2492 	n = getaddrinfo(NULL, p, &hints, &res);
   2493 	if (n) {
   2494 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
   2495 		goto fail;
   2496 	}
   2497 
   2498 	saveres = res;
   2499 	hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
   2500 				 res->ai_protocol);
   2501 	if (hapd->ctrl_sock < 0) {
   2502 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
   2503 		goto fail;
   2504 	}
   2505 
   2506 	if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
   2507 		port--;
   2508 		if ((HOSTAPD_CTRL_IFACE_PORT - port) <
   2509 		    HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
   2510 			goto try_again;
   2511 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
   2512 		goto fail;
   2513 	}
   2514 
   2515 	freeaddrinfo(saveres);
   2516 
   2517 	os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
   2518 	tmp = os_strdup(port_str);
   2519 	if (tmp) {
   2520 		os_free(hapd->conf->ctrl_interface);
   2521 		hapd->conf->ctrl_interface = tmp;
   2522 	}
   2523 	wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
   2524 
   2525 	if (eloop_register_read_sock(hapd->ctrl_sock,
   2526 				     hostapd_ctrl_iface_receive, hapd, NULL) <
   2527 	    0) {
   2528 		hostapd_ctrl_iface_deinit(hapd);
   2529 		return -1;
   2530 	}
   2531 
   2532 	hapd->msg_ctx = hapd;
   2533 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
   2534 
   2535 	return 0;
   2536 
   2537 fail:
   2538 	if (hapd->ctrl_sock >= 0)
   2539 		close(hapd->ctrl_sock);
   2540 	return -1;
   2541 #else /* CONFIG_CTRL_IFACE_UDP */
   2542 	struct sockaddr_un addr;
   2543 	int s = -1;
   2544 	char *fname = NULL;
   2545 
   2546 	if (hapd->ctrl_sock > -1) {
   2547 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   2548 		return 0;
   2549 	}
   2550 
   2551 	dl_list_init(&hapd->ctrl_dst);
   2552 
   2553 	if (hapd->conf->ctrl_interface == NULL)
   2554 		return 0;
   2555 
   2556 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
   2557 		if (errno == EEXIST) {
   2558 			wpa_printf(MSG_DEBUG, "Using existing control "
   2559 				   "interface directory.");
   2560 		} else {
   2561 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
   2562 				   strerror(errno));
   2563 			goto fail;
   2564 		}
   2565 	}
   2566 
   2567 	if (hapd->conf->ctrl_interface_gid_set &&
   2568 	    chown(hapd->conf->ctrl_interface, -1,
   2569 		  hapd->conf->ctrl_interface_gid) < 0) {
   2570 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
   2571 			   strerror(errno));
   2572 		return -1;
   2573 	}
   2574 
   2575 	if (!hapd->conf->ctrl_interface_gid_set &&
   2576 	    hapd->iface->interfaces->ctrl_iface_group &&
   2577 	    chown(hapd->conf->ctrl_interface, -1,
   2578 		  hapd->iface->interfaces->ctrl_iface_group) < 0) {
   2579 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
   2580 			   strerror(errno));
   2581 		return -1;
   2582 	}
   2583 
   2584 #ifdef ANDROID
   2585 	/*
   2586 	 * Android is using umask 0077 which would leave the control interface
   2587 	 * directory without group access. This breaks things since Wi-Fi
   2588 	 * framework assumes that this directory can be accessed by other
   2589 	 * applications in the wifi group. Fix this by adding group access even
   2590 	 * if umask value would prevent this.
   2591 	 */
   2592 	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
   2593 		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
   2594 			   strerror(errno));
   2595 		/* Try to continue anyway */
   2596 	}
   2597 #endif /* ANDROID */
   2598 
   2599 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
   2600 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
   2601 		goto fail;
   2602 
   2603 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   2604 	if (s < 0) {
   2605 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
   2606 		goto fail;
   2607 	}
   2608 
   2609 	os_memset(&addr, 0, sizeof(addr));
   2610 #ifdef __FreeBSD__
   2611 	addr.sun_len = sizeof(addr);
   2612 #endif /* __FreeBSD__ */
   2613 	addr.sun_family = AF_UNIX;
   2614 	fname = hostapd_ctrl_iface_path(hapd);
   2615 	if (fname == NULL)
   2616 		goto fail;
   2617 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   2618 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   2619 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   2620 			   strerror(errno));
   2621 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   2622 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   2623 				   " allow connections - assuming it was left"
   2624 				   "over from forced program termination");
   2625 			if (unlink(fname) < 0) {
   2626 				wpa_printf(MSG_ERROR,
   2627 					   "Could not unlink existing ctrl_iface socket '%s': %s",
   2628 					   fname, strerror(errno));
   2629 				goto fail;
   2630 			}
   2631 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   2632 			    0) {
   2633 				wpa_printf(MSG_ERROR,
   2634 					   "hostapd-ctrl-iface: bind(PF_UNIX): %s",
   2635 					   strerror(errno));
   2636 				goto fail;
   2637 			}
   2638 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   2639 				   "ctrl_iface socket '%s'", fname);
   2640 		} else {
   2641 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   2642 				   "be in use - cannot override it");
   2643 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   2644 				   "not used anymore", fname);
   2645 			os_free(fname);
   2646 			fname = NULL;
   2647 			goto fail;
   2648 		}
   2649 	}
   2650 
   2651 	if (hapd->conf->ctrl_interface_gid_set &&
   2652 	    chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
   2653 		wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
   2654 			   strerror(errno));
   2655 		goto fail;
   2656 	}
   2657 
   2658 	if (!hapd->conf->ctrl_interface_gid_set &&
   2659 	    hapd->iface->interfaces->ctrl_iface_group &&
   2660 	    chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
   2661 		wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
   2662 			   strerror(errno));
   2663 		goto fail;
   2664 	}
   2665 
   2666 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   2667 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
   2668 			   strerror(errno));
   2669 		goto fail;
   2670 	}
   2671 	os_free(fname);
   2672 
   2673 	hapd->ctrl_sock = s;
   2674 	if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
   2675 				     NULL) < 0) {
   2676 		hostapd_ctrl_iface_deinit(hapd);
   2677 		return -1;
   2678 	}
   2679 	hapd->msg_ctx = hapd;
   2680 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
   2681 
   2682 	return 0;
   2683 
   2684 fail:
   2685 	if (s >= 0)
   2686 		close(s);
   2687 	if (fname) {
   2688 		unlink(fname);
   2689 		os_free(fname);
   2690 	}
   2691 	return -1;
   2692 #endif /* CONFIG_CTRL_IFACE_UDP */
   2693 }
   2694 
   2695 
   2696 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
   2697 {
   2698 	struct wpa_ctrl_dst *dst, *prev;
   2699 
   2700 	if (hapd->ctrl_sock > -1) {
   2701 #ifndef CONFIG_CTRL_IFACE_UDP
   2702 		char *fname;
   2703 #endif /* !CONFIG_CTRL_IFACE_UDP */
   2704 
   2705 		eloop_unregister_read_sock(hapd->ctrl_sock);
   2706 		close(hapd->ctrl_sock);
   2707 		hapd->ctrl_sock = -1;
   2708 #ifndef CONFIG_CTRL_IFACE_UDP
   2709 		fname = hostapd_ctrl_iface_path(hapd);
   2710 		if (fname)
   2711 			unlink(fname);
   2712 		os_free(fname);
   2713 
   2714 		if (hapd->conf->ctrl_interface &&
   2715 		    rmdir(hapd->conf->ctrl_interface) < 0) {
   2716 			if (errno == ENOTEMPTY) {
   2717 				wpa_printf(MSG_DEBUG, "Control interface "
   2718 					   "directory not empty - leaving it "
   2719 					   "behind");
   2720 			} else {
   2721 				wpa_printf(MSG_ERROR,
   2722 					   "rmdir[ctrl_interface=%s]: %s",
   2723 					   hapd->conf->ctrl_interface,
   2724 					   strerror(errno));
   2725 			}
   2726 		}
   2727 #endif /* !CONFIG_CTRL_IFACE_UDP */
   2728 	}
   2729 
   2730 	dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
   2731 			      list)
   2732 		os_free(dst);
   2733 
   2734 #ifdef CONFIG_TESTING_OPTIONS
   2735 	l2_packet_deinit(hapd->l2_test);
   2736 	hapd->l2_test = NULL;
   2737 #endif /* CONFIG_TESTING_OPTIONS */
   2738 }
   2739 
   2740 
   2741 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
   2742 				  char *buf)
   2743 {
   2744 	if (hostapd_add_iface(interfaces, buf) < 0) {
   2745 		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
   2746 		return -1;
   2747 	}
   2748 	return 0;
   2749 }
   2750 
   2751 
   2752 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
   2753 				     char *buf)
   2754 {
   2755 	if (hostapd_remove_iface(interfaces, buf) < 0) {
   2756 		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
   2757 		return -1;
   2758 	}
   2759 	return 0;
   2760 }
   2761 
   2762 
   2763 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
   2764 					    struct sockaddr_storage *from,
   2765 					    socklen_t fromlen)
   2766 {
   2767 	return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen);
   2768 }
   2769 
   2770 
   2771 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
   2772 					    struct sockaddr_storage *from,
   2773 					    socklen_t fromlen)
   2774 {
   2775 	return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
   2776 }
   2777 
   2778 
   2779 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
   2780 {
   2781 #ifdef CONFIG_WPS_TESTING
   2782 	wps_version_number = 0x20;
   2783 	wps_testing_dummy_cred = 0;
   2784 	wps_corrupt_pkhash = 0;
   2785 #endif /* CONFIG_WPS_TESTING */
   2786 }
   2787 
   2788 
   2789 #ifdef CONFIG_FST
   2790 
   2791 static int
   2792 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
   2793 				     const char *cmd)
   2794 {
   2795 	char ifname[IFNAMSIZ + 1];
   2796 	struct fst_iface_cfg cfg;
   2797 	struct hostapd_data *hapd;
   2798 	struct fst_wpa_obj iface_obj;
   2799 
   2800 	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
   2801 		hapd = hostapd_get_iface(interfaces, ifname);
   2802 		if (hapd) {
   2803 			if (hapd->iface->fst) {
   2804 				wpa_printf(MSG_INFO, "FST: Already attached");
   2805 				return -1;
   2806 			}
   2807 			fst_hostapd_fill_iface_obj(hapd, &iface_obj);
   2808 			hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
   2809 						      &iface_obj, &cfg);
   2810 			if (hapd->iface->fst)
   2811 				return 0;
   2812 		}
   2813 	}
   2814 
   2815 	return -EINVAL;
   2816 }
   2817 
   2818 
   2819 static int
   2820 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
   2821 				     const char *cmd)
   2822 {
   2823 	char ifname[IFNAMSIZ + 1];
   2824 	struct hostapd_data * hapd;
   2825 
   2826 	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
   2827 		hapd = hostapd_get_iface(interfaces, ifname);
   2828 		if (hapd) {
   2829 			if (!fst_iface_detach(ifname)) {
   2830 				hapd->iface->fst = NULL;
   2831 				hapd->iface->fst_ies = NULL;
   2832 				return 0;
   2833 			}
   2834 		}
   2835 	}
   2836 
   2837 	return -EINVAL;
   2838 }
   2839 
   2840 #endif /* CONFIG_FST */
   2841 
   2842 
   2843 static struct hostapd_data *
   2844 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
   2845 			    const char *ifname)
   2846 {
   2847 	size_t i, j;
   2848 
   2849 	for (i = 0; i < interfaces->count; i++) {
   2850 		struct hostapd_iface *iface = interfaces->iface[i];
   2851 
   2852 		for (j = 0; j < iface->num_bss; j++) {
   2853 			struct hostapd_data *hapd;
   2854 
   2855 			hapd = iface->bss[j];
   2856 			if (os_strcmp(ifname, hapd->conf->iface) == 0)
   2857 				return hapd;
   2858 		}
   2859 	}
   2860 
   2861 	return NULL;
   2862 }
   2863 
   2864 
   2865 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
   2866 					struct hostapd_data *dst_hapd,
   2867 					const char *param)
   2868 {
   2869 	int res;
   2870 	char *value;
   2871 
   2872 	value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
   2873 	if (!value) {
   2874 		wpa_printf(MSG_ERROR,
   2875 			   "DUP: cannot allocate buffer to stringify %s",
   2876 			   param);
   2877 		goto error_return;
   2878 	}
   2879 
   2880 	if (os_strcmp(param, "wpa") == 0) {
   2881 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
   2882 			    src_hapd->conf->wpa);
   2883 	} else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
   2884 		   src_hapd->conf->wpa_key_mgmt) {
   2885 		res = hostapd_ctrl_iface_get_key_mgmt(
   2886 			src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
   2887 		if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
   2888 			goto error_stringify;
   2889 	} else if (os_strcmp(param, "wpa_pairwise") == 0 &&
   2890 		   src_hapd->conf->wpa_pairwise) {
   2891 		res = wpa_write_ciphers(value,
   2892 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
   2893 					src_hapd->conf->wpa_pairwise, " ");
   2894 		if (res < 0)
   2895 			goto error_stringify;
   2896 	} else if (os_strcmp(param, "rsn_pairwise") == 0 &&
   2897 		   src_hapd->conf->rsn_pairwise) {
   2898 		res = wpa_write_ciphers(value,
   2899 					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
   2900 					src_hapd->conf->rsn_pairwise, " ");
   2901 		if (res < 0)
   2902 			goto error_stringify;
   2903 	} else if (os_strcmp(param, "wpa_passphrase") == 0 &&
   2904 		   src_hapd->conf->ssid.wpa_passphrase) {
   2905 		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
   2906 			    src_hapd->conf->ssid.wpa_passphrase);
   2907 	} else if (os_strcmp(param, "wpa_psk") == 0 &&
   2908 		   src_hapd->conf->ssid.wpa_psk_set) {
   2909 		wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
   2910 			src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
   2911 	} else {
   2912 		wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
   2913 		goto error_return;
   2914 	}
   2915 
   2916 	res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
   2917 	os_free(value);
   2918 	return res;
   2919 
   2920 error_stringify:
   2921 	wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
   2922 error_return:
   2923 	os_free(value);
   2924 	return -1;
   2925 }
   2926 
   2927 
   2928 static int
   2929 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
   2930 				     const char *input,
   2931 				     char *reply, int reply_size)
   2932 {
   2933 	size_t i, j;
   2934 	int res;
   2935 	char *pos, *end;
   2936 	struct hostapd_iface *iface;
   2937 	int show_ctrl = 0;
   2938 
   2939 	if (input)
   2940 		show_ctrl = !!os_strstr(input, "ctrl");
   2941 
   2942 	pos = reply;
   2943 	end = reply + reply_size;
   2944 
   2945 	for (i = 0; i < interfaces->count; i++) {
   2946 		iface = interfaces->iface[i];
   2947 
   2948 		for (j = 0; j < iface->num_bss; j++) {
   2949 			struct hostapd_bss_config *conf;
   2950 
   2951 			conf = iface->conf->bss[j];
   2952 			if (show_ctrl)
   2953 				res = os_snprintf(pos, end - pos,
   2954 						  "%s ctrl_iface=%s\n",
   2955 						  conf->iface,
   2956 						  conf->ctrl_interface ?
   2957 						  conf->ctrl_interface : "N/A");
   2958 			else
   2959 				res = os_snprintf(pos, end - pos, "%s\n",
   2960 						  conf->iface);
   2961 			if (os_snprintf_error(end - pos, res)) {
   2962 				*pos = '\0';
   2963 				return pos - reply;
   2964 			}
   2965 			pos += res;
   2966 		}
   2967 	}
   2968 
   2969 	return pos - reply;
   2970 }
   2971 
   2972 
   2973 static int
   2974 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
   2975 				      char *cmd)
   2976 {
   2977 	char *p_start = cmd, *p_end;
   2978 	struct hostapd_data *src_hapd, *dst_hapd;
   2979 
   2980 	/* cmd: "<src ifname> <dst ifname> <variable name> */
   2981 
   2982 	p_end = os_strchr(p_start, ' ');
   2983 	if (!p_end) {
   2984 		wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
   2985 			   cmd);
   2986 		return -1;
   2987 	}
   2988 
   2989 	*p_end = '\0';
   2990 	src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
   2991 	if (!src_hapd) {
   2992 		wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
   2993 			   p_start);
   2994 		return -1;
   2995 	}
   2996 
   2997 	p_start = p_end + 1;
   2998 	p_end = os_strchr(p_start, ' ');
   2999 	if (!p_end) {
   3000 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
   3001 			   cmd);
   3002 		return -1;
   3003 	}
   3004 
   3005 	*p_end = '\0';
   3006 	dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
   3007 	if (!dst_hapd) {
   3008 		wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
   3009 			   p_start);
   3010 		return -1;
   3011 	}
   3012 
   3013 	p_start = p_end + 1;
   3014 	return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
   3015 }
   3016 
   3017 
   3018 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
   3019 					    const char *ifname,
   3020 					    char *buf, char *reply,
   3021 					    int reply_size,
   3022 					    struct sockaddr_storage *from,
   3023 					    socklen_t fromlen)
   3024 {
   3025 	struct hostapd_data *hapd;
   3026 
   3027 	hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
   3028 	if (hapd == NULL) {
   3029 		int res;
   3030 
   3031 		res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
   3032 		if (os_snprintf_error(reply_size, res))
   3033 			return -1;
   3034 		return res;
   3035 	}
   3036 
   3037 	return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
   3038 						  from, fromlen);
   3039 }
   3040 
   3041 
   3042 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
   3043 					      void *sock_ctx)
   3044 {
   3045 	void *interfaces = eloop_ctx;
   3046 	char buffer[256], *buf = buffer;
   3047 	int res;
   3048 	struct sockaddr_storage from;
   3049 	socklen_t fromlen = sizeof(from);
   3050 	char *reply;
   3051 	int reply_len;
   3052 	const int reply_size = 4096;
   3053 #ifdef CONFIG_CTRL_IFACE_UDP
   3054 	unsigned char lcookie[COOKIE_LEN];
   3055 #endif /* CONFIG_CTRL_IFACE_UDP */
   3056 
   3057 	res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
   3058 		       (struct sockaddr *) &from, &fromlen);
   3059 	if (res < 0) {
   3060 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
   3061 			   strerror(errno));
   3062 		return;
   3063 	}
   3064 	buf[res] = '\0';
   3065 	wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
   3066 
   3067 	reply = os_malloc(reply_size);
   3068 	if (reply == NULL) {
   3069 		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
   3070 			   fromlen) < 0) {
   3071 			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   3072 				   strerror(errno));
   3073 		}
   3074 		return;
   3075 	}
   3076 
   3077 	os_memcpy(reply, "OK\n", 3);
   3078 	reply_len = 3;
   3079 
   3080 #ifdef CONFIG_CTRL_IFACE_UDP
   3081 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
   3082 		os_memcpy(reply, "COOKIE=", 7);
   3083 		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
   3084 				 gcookie, COOKIE_LEN);
   3085 		reply_len = 7 + 2 * COOKIE_LEN;
   3086 		goto send_reply;
   3087 	}
   3088 
   3089 	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
   3090 	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
   3091 		wpa_printf(MSG_DEBUG,
   3092 			   "CTRL: No cookie in the request - drop request");
   3093 		os_free(reply);
   3094 		return;
   3095 	}
   3096 
   3097 	if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
   3098 		wpa_printf(MSG_DEBUG,
   3099 			   "CTRL: Invalid cookie in the request - drop request");
   3100 		os_free(reply);
   3101 		return;
   3102 	}
   3103 
   3104 	buf += 7 + 2 * COOKIE_LEN;
   3105 	while (*buf == ' ')
   3106 		buf++;
   3107 #endif /* CONFIG_CTRL_IFACE_UDP */
   3108 
   3109 	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
   3110 		char *pos = os_strchr(buf + 7, ' ');
   3111 
   3112 		if (pos) {
   3113 			*pos++ = '\0';
   3114 			reply_len = hostapd_global_ctrl_iface_ifname(
   3115 				interfaces, buf + 7, pos, reply, reply_size,
   3116 				&from, fromlen);
   3117 			goto send_reply;
   3118 		}
   3119 	}
   3120 
   3121 	if (os_strcmp(buf, "PING") == 0) {
   3122 		os_memcpy(reply, "PONG\n", 5);
   3123 		reply_len = 5;
   3124 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
   3125 		if (wpa_debug_reopen_file() < 0)
   3126 			reply_len = -1;
   3127 	} else if (os_strcmp(buf, "FLUSH") == 0) {
   3128 		hostapd_ctrl_iface_flush(interfaces);
   3129 	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
   3130 		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
   3131 			reply_len = -1;
   3132 	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
   3133 		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
   3134 			reply_len = -1;
   3135 	} else if (os_strcmp(buf, "ATTACH") == 0) {
   3136 		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
   3137 						     fromlen))
   3138 			reply_len = -1;
   3139 	} else if (os_strcmp(buf, "DETACH") == 0) {
   3140 		if (hostapd_global_ctrl_iface_detach(interfaces, &from,
   3141 			fromlen))
   3142 			reply_len = -1;
   3143 #ifdef CONFIG_MODULE_TESTS
   3144 	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
   3145 		int hapd_module_tests(void);
   3146 		if (hapd_module_tests() < 0)
   3147 			reply_len = -1;
   3148 #endif /* CONFIG_MODULE_TESTS */
   3149 #ifdef CONFIG_FST
   3150 	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
   3151 		if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
   3152 			reply_len = os_snprintf(reply, reply_size, "OK\n");
   3153 		else
   3154 			reply_len = -1;
   3155 	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
   3156 		if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
   3157 			reply_len = os_snprintf(reply, reply_size, "OK\n");
   3158 		else
   3159 			reply_len = -1;
   3160 	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
   3161 		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
   3162 #endif /* CONFIG_FST */
   3163 	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
   3164 		if (!hostapd_global_ctrl_iface_dup_network(interfaces,
   3165 							   buf + 12))
   3166 			reply_len = os_snprintf(reply, reply_size, "OK\n");
   3167 		else
   3168 			reply_len = -1;
   3169 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
   3170 		reply_len = hostapd_global_ctrl_iface_interfaces(
   3171 			interfaces, buf + 10, reply, sizeof(buffer));
   3172 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
   3173 		eloop_terminate();
   3174 	} else {
   3175 		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
   3176 			   "ignored");
   3177 		reply_len = -1;
   3178 	}
   3179 
   3180 send_reply:
   3181 	if (reply_len < 0) {
   3182 		os_memcpy(reply, "FAIL\n", 5);
   3183 		reply_len = 5;
   3184 	}
   3185 
   3186 	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
   3187 		   fromlen) < 0) {
   3188 		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
   3189 			   strerror(errno));
   3190 	}
   3191 	os_free(reply);
   3192 }
   3193 
   3194 
   3195 #ifndef CONFIG_CTRL_IFACE_UDP
   3196 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
   3197 {
   3198 	char *buf;
   3199 	size_t len;
   3200 
   3201 	if (interface->global_iface_path == NULL)
   3202 		return NULL;
   3203 
   3204 	len = os_strlen(interface->global_iface_path) +
   3205 		os_strlen(interface->global_iface_name) + 2;
   3206 	buf = os_malloc(len);
   3207 	if (buf == NULL)
   3208 		return NULL;
   3209 
   3210 	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
   3211 		    interface->global_iface_name);
   3212 	buf[len - 1] = '\0';
   3213 	return buf;
   3214 }
   3215 #endif /* CONFIG_CTRL_IFACE_UDP */
   3216 
   3217 
   3218 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
   3219 {
   3220 #ifdef CONFIG_CTRL_IFACE_UDP
   3221 	int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
   3222 	char p[32] = { 0 };
   3223 	char *pos;
   3224 	struct addrinfo hints = { 0 }, *res, *saveres;
   3225 	int n;
   3226 
   3227 	if (interface->global_ctrl_sock > -1) {
   3228 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   3229 		return 0;
   3230 	}
   3231 
   3232 	if (interface->global_iface_path == NULL)
   3233 		return 0;
   3234 
   3235 	pos = os_strstr(interface->global_iface_path, "udp:");
   3236 	if (pos) {
   3237 		pos += 4;
   3238 		port = atoi(pos);
   3239 		if (port <= 0) {
   3240 			wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
   3241 			goto fail;
   3242 		}
   3243 	}
   3244 
   3245 	dl_list_init(&interface->global_ctrl_dst);
   3246 	interface->global_ctrl_sock = -1;
   3247 	os_get_random(gcookie, COOKIE_LEN);
   3248 
   3249 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
   3250 	hints.ai_flags = AI_PASSIVE;
   3251 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
   3252 
   3253 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
   3254 	hints.ai_family = AF_INET6;
   3255 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   3256 	hints.ai_family = AF_INET;
   3257 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
   3258 	hints.ai_socktype = SOCK_DGRAM;
   3259 
   3260 try_again:
   3261 	os_snprintf(p, sizeof(p), "%d", port);
   3262 	n = getaddrinfo(NULL, p, &hints, &res);
   3263 	if (n) {
   3264 		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
   3265 		goto fail;
   3266 	}
   3267 
   3268 	saveres = res;
   3269 	interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
   3270 					     res->ai_protocol);
   3271 	if (interface->global_ctrl_sock < 0) {
   3272 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
   3273 		goto fail;
   3274 	}
   3275 
   3276 	if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
   3277 	    0) {
   3278 		port++;
   3279 		if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
   3280 		    HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
   3281 			goto try_again;
   3282 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
   3283 		goto fail;
   3284 	}
   3285 
   3286 	freeaddrinfo(saveres);
   3287 
   3288 	wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
   3289 
   3290 	if (eloop_register_read_sock(interface->global_ctrl_sock,
   3291 				     hostapd_global_ctrl_iface_receive,
   3292 				     interface, NULL) < 0) {
   3293 		hostapd_global_ctrl_iface_deinit(interface);
   3294 		return -1;
   3295 	}
   3296 
   3297 	return 0;
   3298 
   3299 fail:
   3300 	if (interface->global_ctrl_sock >= 0)
   3301 		close(interface->global_ctrl_sock);
   3302 	return -1;
   3303 #else /* CONFIG_CTRL_IFACE_UDP */
   3304 	struct sockaddr_un addr;
   3305 	int s = -1;
   3306 	char *fname = NULL;
   3307 
   3308 	if (interface->global_iface_path == NULL) {
   3309 		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
   3310 		return 0;
   3311 	}
   3312 
   3313 	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
   3314 		if (errno == EEXIST) {
   3315 			wpa_printf(MSG_DEBUG, "Using existing control "
   3316 				   "interface directory.");
   3317 		} else {
   3318 			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
   3319 				   strerror(errno));
   3320 			goto fail;
   3321 		}
   3322 	} else if (interface->ctrl_iface_group &&
   3323 		   chown(interface->global_iface_path, -1,
   3324 			 interface->ctrl_iface_group) < 0) {
   3325 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
   3326 			   strerror(errno));
   3327 		goto fail;
   3328 	}
   3329 
   3330 	if (os_strlen(interface->global_iface_path) + 1 +
   3331 	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
   3332 		goto fail;
   3333 
   3334 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   3335 	if (s < 0) {
   3336 		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
   3337 		goto fail;
   3338 	}
   3339 
   3340 	os_memset(&addr, 0, sizeof(addr));
   3341 #ifdef __FreeBSD__
   3342 	addr.sun_len = sizeof(addr);
   3343 #endif /* __FreeBSD__ */
   3344 	addr.sun_family = AF_UNIX;
   3345 	fname = hostapd_global_ctrl_iface_path(interface);
   3346 	if (fname == NULL)
   3347 		goto fail;
   3348 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   3349 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   3350 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   3351 			   strerror(errno));
   3352 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   3353 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   3354 				   " allow connections - assuming it was left"
   3355 				   "over from forced program termination");
   3356 			if (unlink(fname) < 0) {
   3357 				wpa_printf(MSG_ERROR,
   3358 					   "Could not unlink existing ctrl_iface socket '%s': %s",
   3359 					   fname, strerror(errno));
   3360 				goto fail;
   3361 			}
   3362 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   3363 			    0) {
   3364 				wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
   3365 					   strerror(errno));
   3366 				goto fail;
   3367 			}
   3368 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   3369 				   "ctrl_iface socket '%s'", fname);
   3370 		} else {
   3371 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   3372 				   "be in use - cannot override it");
   3373 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   3374 				   "not used anymore", fname);
   3375 			os_free(fname);
   3376 			fname = NULL;
   3377 			goto fail;
   3378 		}
   3379 	}
   3380 
   3381 	if (interface->ctrl_iface_group &&
   3382 	    chown(fname, -1, interface->ctrl_iface_group) < 0) {
   3383 		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
   3384 			   strerror(errno));
   3385 		goto fail;
   3386 	}
   3387 
   3388 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   3389 		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
   3390 			   strerror(errno));
   3391 		goto fail;
   3392 	}
   3393 	os_free(fname);
   3394 
   3395 	interface->global_ctrl_sock = s;
   3396 	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
   3397 				 interface, NULL);
   3398 
   3399 	return 0;
   3400 
   3401 fail:
   3402 	if (s >= 0)
   3403 		close(s);
   3404 	if (fname) {
   3405 		unlink(fname);
   3406 		os_free(fname);
   3407 	}
   3408 	return -1;
   3409 #endif /* CONFIG_CTRL_IFACE_UDP */
   3410 }
   3411 
   3412 
   3413 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
   3414 {
   3415 #ifndef CONFIG_CTRL_IFACE_UDP
   3416 	char *fname = NULL;
   3417 #endif /* CONFIG_CTRL_IFACE_UDP */
   3418 	struct wpa_ctrl_dst *dst, *prev;
   3419 
   3420 	if (interfaces->global_ctrl_sock > -1) {
   3421 		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
   3422 		close(interfaces->global_ctrl_sock);
   3423 		interfaces->global_ctrl_sock = -1;
   3424 #ifndef CONFIG_CTRL_IFACE_UDP
   3425 		fname = hostapd_global_ctrl_iface_path(interfaces);
   3426 		if (fname) {
   3427 			unlink(fname);
   3428 			os_free(fname);
   3429 		}
   3430 
   3431 		if (interfaces->global_iface_path &&
   3432 		    rmdir(interfaces->global_iface_path) < 0) {
   3433 			if (errno == ENOTEMPTY) {
   3434 				wpa_printf(MSG_DEBUG, "Control interface "
   3435 					   "directory not empty - leaving it "
   3436 					   "behind");
   3437 			} else {
   3438 				wpa_printf(MSG_ERROR,
   3439 					   "rmdir[ctrl_interface=%s]: %s",
   3440 					   interfaces->global_iface_path,
   3441 					   strerror(errno));
   3442 			}
   3443 		}
   3444 #endif /* CONFIG_CTRL_IFACE_UDP */
   3445 	}
   3446 
   3447 	os_free(interfaces->global_iface_path);
   3448 	interfaces->global_iface_path = NULL;
   3449 
   3450 	dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
   3451 			      struct wpa_ctrl_dst, list)
   3452 		os_free(dst);
   3453 }
   3454 
   3455 
   3456 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
   3457 				    enum wpa_msg_type type,
   3458 				    const char *buf, size_t len)
   3459 {
   3460 	struct wpa_ctrl_dst *dst, *next;
   3461 	struct dl_list *ctrl_dst;
   3462 	struct msghdr msg;
   3463 	int idx;
   3464 	struct iovec io[2];
   3465 	char levelstr[10];
   3466 	int s;
   3467 
   3468 	if (type != WPA_MSG_ONLY_GLOBAL) {
   3469 		s = hapd->ctrl_sock;
   3470 		ctrl_dst = &hapd->ctrl_dst;
   3471 	} else {
   3472 		s = hapd->iface->interfaces->global_ctrl_sock;
   3473 		ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
   3474 	}
   3475 
   3476 	if (s < 0 || dl_list_empty(ctrl_dst))
   3477 		return;
   3478 
   3479 	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
   3480 	io[0].iov_base = levelstr;
   3481 	io[0].iov_len = os_strlen(levelstr);
   3482 	io[1].iov_base = (char *) buf;
   3483 	io[1].iov_len = len;
   3484 	os_memset(&msg, 0, sizeof(msg));
   3485 	msg.msg_iov = io;
   3486 	msg.msg_iovlen = 2;
   3487 
   3488 	idx = 0;
   3489 	dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
   3490 		if (level >= dst->debug_level) {
   3491 			sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
   3492 				       &dst->addr, dst->addrlen);
   3493 			msg.msg_name = &dst->addr;
   3494 			msg.msg_namelen = dst->addrlen;
   3495 			if (sendmsg(s, &msg, 0) < 0) {
   3496 				int _errno = errno;
   3497 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
   3498 					   "%d - %s",
   3499 					   idx, errno, strerror(errno));
   3500 				dst->errors++;
   3501 				if (dst->errors > 10 || _errno == ENOENT) {
   3502 					if (type != WPA_MSG_ONLY_GLOBAL)
   3503 						hostapd_ctrl_iface_detach(
   3504 							hapd, &dst->addr,
   3505 							dst->addrlen);
   3506 					else
   3507 						hostapd_global_ctrl_iface_detach(
   3508 							hapd->iface->interfaces,
   3509 							&dst->addr,
   3510 							dst->addrlen);
   3511 				}
   3512 			} else
   3513 				dst->errors = 0;
   3514 		}
   3515 		idx++;
   3516 	}
   3517 }
   3518 
   3519 #endif /* CONFIG_NATIVE_WINDOWS */
   3520