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