Home | History | Annotate | Download | only in hostapd
      1 /*
      2  * hostapd / UNIX domain socket -based control interface
      3  * Copyright (c) 2004-2012, 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 #include <sys/un.h>
     14 #include <sys/stat.h>
     15 #include <stddef.h>
     16 
     17 #include "utils/common.h"
     18 #include "utils/eloop.h"
     19 #include "common/version.h"
     20 #include "common/ieee802_11_defs.h"
     21 #include "drivers/driver.h"
     22 #include "radius/radius_client.h"
     23 #include "ap/hostapd.h"
     24 #include "ap/ap_config.h"
     25 #include "ap/ieee802_1x.h"
     26 #include "ap/wpa_auth.h"
     27 #include "ap/ieee802_11.h"
     28 #include "ap/sta_info.h"
     29 #include "ap/wps_hostapd.h"
     30 #include "ap/ctrl_iface_ap.h"
     31 #include "ap/ap_drv_ops.h"
     32 #include "wps/wps_defs.h"
     33 #include "wps/wps.h"
     34 #include "config_file.h"
     35 #include "ctrl_iface.h"
     36 
     37 
     38 struct wpa_ctrl_dst {
     39 	struct wpa_ctrl_dst *next;
     40 	struct sockaddr_un addr;
     41 	socklen_t addrlen;
     42 	int debug_level;
     43 	int errors;
     44 };
     45 
     46 
     47 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
     48 				    const char *buf, size_t len);
     49 
     50 
     51 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
     52 				     struct sockaddr_un *from,
     53 				     socklen_t fromlen)
     54 {
     55 	struct wpa_ctrl_dst *dst;
     56 
     57 	dst = os_zalloc(sizeof(*dst));
     58 	if (dst == NULL)
     59 		return -1;
     60 	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
     61 	dst->addrlen = fromlen;
     62 	dst->debug_level = MSG_INFO;
     63 	dst->next = hapd->ctrl_dst;
     64 	hapd->ctrl_dst = dst;
     65 	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
     66 		    (u8 *) from->sun_path,
     67 		    fromlen - offsetof(struct sockaddr_un, sun_path));
     68 	return 0;
     69 }
     70 
     71 
     72 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
     73 				     struct sockaddr_un *from,
     74 				     socklen_t fromlen)
     75 {
     76 	struct wpa_ctrl_dst *dst, *prev = NULL;
     77 
     78 	dst = hapd->ctrl_dst;
     79 	while (dst) {
     80 		if (fromlen == dst->addrlen &&
     81 		    os_memcmp(from->sun_path, dst->addr.sun_path,
     82 			      fromlen - offsetof(struct sockaddr_un, sun_path))
     83 		    == 0) {
     84 			if (prev == NULL)
     85 				hapd->ctrl_dst = dst->next;
     86 			else
     87 				prev->next = dst->next;
     88 			os_free(dst);
     89 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
     90 				    (u8 *) from->sun_path,
     91 				    fromlen -
     92 				    offsetof(struct sockaddr_un, sun_path));
     93 			return 0;
     94 		}
     95 		prev = dst;
     96 		dst = dst->next;
     97 	}
     98 	return -1;
     99 }
    100 
    101 
    102 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
    103 				    struct sockaddr_un *from,
    104 				    socklen_t fromlen,
    105 				    char *level)
    106 {
    107 	struct wpa_ctrl_dst *dst;
    108 
    109 	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
    110 
    111 	dst = hapd->ctrl_dst;
    112 	while (dst) {
    113 		if (fromlen == dst->addrlen &&
    114 		    os_memcmp(from->sun_path, dst->addr.sun_path,
    115 			      fromlen - offsetof(struct sockaddr_un, sun_path))
    116 		    == 0) {
    117 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
    118 				    "level", (u8 *) from->sun_path, fromlen -
    119 				    offsetof(struct sockaddr_un, sun_path));
    120 			dst->debug_level = atoi(level);
    121 			return 0;
    122 		}
    123 		dst = dst->next;
    124 	}
    125 
    126 	return -1;
    127 }
    128 
    129 
    130 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
    131 				      const char *txtaddr)
    132 {
    133 	u8 addr[ETH_ALEN];
    134 	struct sta_info *sta;
    135 
    136 	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
    137 
    138 	if (hwaddr_aton(txtaddr, addr))
    139 		return -1;
    140 
    141 	sta = ap_get_sta(hapd, addr);
    142 	if (sta)
    143 		return 0;
    144 
    145 	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
    146 		   "notification", MAC2STR(addr));
    147 	sta = ap_sta_add(hapd, addr);
    148 	if (sta == NULL)
    149 		return -1;
    150 
    151 	hostapd_new_assoc_sta(hapd, sta, 0);
    152 	return 0;
    153 }
    154 
    155 
    156 #ifdef CONFIG_IEEE80211W
    157 #ifdef NEED_AP_MLME
    158 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
    159 				       const char *txtaddr)
    160 {
    161 	u8 addr[ETH_ALEN];
    162 	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
    163 
    164 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
    165 
    166 	if (hwaddr_aton(txtaddr, addr) ||
    167 	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
    168 		return -1;
    169 
    170 	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
    171 
    172 	return 0;
    173 }
    174 #endif /* NEED_AP_MLME */
    175 #endif /* CONFIG_IEEE80211W */
    176 
    177 
    178 #ifdef CONFIG_WPS
    179 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
    180 {
    181 	char *pin = os_strchr(txt, ' ');
    182 	char *timeout_txt;
    183 	int timeout;
    184 	u8 addr_buf[ETH_ALEN], *addr = NULL;
    185 	char *pos;
    186 
    187 	if (pin == NULL)
    188 		return -1;
    189 	*pin++ = '\0';
    190 
    191 	timeout_txt = os_strchr(pin, ' ');
    192 	if (timeout_txt) {
    193 		*timeout_txt++ = '\0';
    194 		timeout = atoi(timeout_txt);
    195 		pos = os_strchr(timeout_txt, ' ');
    196 		if (pos) {
    197 			*pos++ = '\0';
    198 			if (hwaddr_aton(pos, addr_buf) == 0)
    199 				addr = addr_buf;
    200 		}
    201 	} else
    202 		timeout = 0;
    203 
    204 	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
    205 }
    206 
    207 
    208 static int hostapd_ctrl_iface_wps_check_pin(
    209 	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
    210 {
    211 	char pin[9];
    212 	size_t len;
    213 	char *pos;
    214 	int ret;
    215 
    216 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
    217 			      (u8 *) cmd, os_strlen(cmd));
    218 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
    219 		if (*pos < '0' || *pos > '9')
    220 			continue;
    221 		pin[len++] = *pos;
    222 		if (len == 9) {
    223 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
    224 			return -1;
    225 		}
    226 	}
    227 	if (len != 4 && len != 8) {
    228 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
    229 		return -1;
    230 	}
    231 	pin[len] = '\0';
    232 
    233 	if (len == 8) {
    234 		unsigned int pin_val;
    235 		pin_val = atoi(pin);
    236 		if (!wps_pin_valid(pin_val)) {
    237 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
    238 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
    239 			if (ret < 0 || (size_t) ret >= buflen)
    240 				return -1;
    241 			return ret;
    242 		}
    243 	}
    244 
    245 	ret = os_snprintf(buf, buflen, "%s", pin);
    246 	if (ret < 0 || (size_t) ret >= buflen)
    247 		return -1;
    248 
    249 	return ret;
    250 }
    251 
    252 
    253 #ifdef CONFIG_WPS_NFC
    254 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
    255 					       char *pos)
    256 {
    257 	size_t len;
    258 	struct wpabuf *buf;
    259 	int ret;
    260 
    261 	len = os_strlen(pos);
    262 	if (len & 0x01)
    263 		return -1;
    264 	len /= 2;
    265 
    266 	buf = wpabuf_alloc(len);
    267 	if (buf == NULL)
    268 		return -1;
    269 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
    270 		wpabuf_free(buf);
    271 		return -1;
    272 	}
    273 
    274 	ret = hostapd_wps_nfc_tag_read(hapd, buf);
    275 	wpabuf_free(buf);
    276 
    277 	return ret;
    278 }
    279 
    280 
    281 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
    282 						   char *cmd, char *reply,
    283 						   size_t max_len)
    284 {
    285 	int ndef;
    286 	struct wpabuf *buf;
    287 	int res;
    288 
    289 	if (os_strcmp(cmd, "WPS") == 0)
    290 		ndef = 0;
    291 	else if (os_strcmp(cmd, "NDEF") == 0)
    292 		ndef = 1;
    293 	else
    294 		return -1;
    295 
    296 	buf = hostapd_wps_nfc_config_token(hapd, ndef);
    297 	if (buf == NULL)
    298 		return -1;
    299 
    300 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    301 					 wpabuf_len(buf));
    302 	reply[res++] = '\n';
    303 	reply[res] = '\0';
    304 
    305 	wpabuf_free(buf);
    306 
    307 	return res;
    308 }
    309 
    310 
    311 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
    312 						char *reply, size_t max_len,
    313 						int ndef)
    314 {
    315 	struct wpabuf *buf;
    316 	int res;
    317 
    318 	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
    319 	if (buf == NULL)
    320 		return -1;
    321 
    322 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    323 					 wpabuf_len(buf));
    324 	reply[res++] = '\n';
    325 	reply[res] = '\0';
    326 
    327 	wpabuf_free(buf);
    328 
    329 	return res;
    330 }
    331 
    332 
    333 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
    334 					    char *cmd, char *reply,
    335 					    size_t max_len)
    336 {
    337 	if (os_strcmp(cmd, "WPS") == 0)
    338 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    339 							    max_len, 0);
    340 
    341 	if (os_strcmp(cmd, "NDEF") == 0)
    342 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    343 							    max_len, 1);
    344 
    345 	if (os_strcmp(cmd, "enable") == 0)
    346 		return hostapd_wps_nfc_token_enable(hapd);
    347 
    348 	if (os_strcmp(cmd, "disable") == 0) {
    349 		hostapd_wps_nfc_token_disable(hapd);
    350 		return 0;
    351 	}
    352 
    353 	return -1;
    354 }
    355 
    356 
    357 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
    358 						   char *cmd, char *reply,
    359 						   size_t max_len)
    360 {
    361 	struct wpabuf *buf;
    362 	int res;
    363 	char *pos;
    364 	int ndef;
    365 
    366 	pos = os_strchr(cmd, ' ');
    367 	if (pos == NULL)
    368 		return -1;
    369 	*pos++ = '\0';
    370 
    371 	if (os_strcmp(cmd, "WPS") == 0)
    372 		ndef = 0;
    373 	else if (os_strcmp(cmd, "NDEF") == 0)
    374 		ndef = 1;
    375 	else
    376 		return -1;
    377 
    378 	if (os_strcmp(pos, "WPS-CR") == 0)
    379 		buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
    380 	else
    381 		buf = NULL;
    382 	if (buf == NULL)
    383 		return -1;
    384 
    385 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    386 					 wpabuf_len(buf));
    387 	reply[res++] = '\n';
    388 	reply[res] = '\0';
    389 
    390 	wpabuf_free(buf);
    391 
    392 	return res;
    393 }
    394 
    395 
    396 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
    397 						  char *cmd)
    398 {
    399 	/*
    400 	 * Since NFC connection handover provided full WPS Credential, there is
    401 	 * no need for additional operations within hostapd. Just report this in
    402 	 * debug log.
    403 	 */
    404 	wpa_printf(MSG_DEBUG, "NFC: Connection handover reported: %s", cmd);
    405 	return 0;
    406 }
    407 
    408 #endif /* CONFIG_WPS_NFC */
    409 
    410 
    411 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
    412 					 char *buf, size_t buflen)
    413 {
    414 	int timeout = 300;
    415 	char *pos;
    416 	const char *pin_txt;
    417 
    418 	pos = os_strchr(txt, ' ');
    419 	if (pos)
    420 		*pos++ = '\0';
    421 
    422 	if (os_strcmp(txt, "disable") == 0) {
    423 		hostapd_wps_ap_pin_disable(hapd);
    424 		return os_snprintf(buf, buflen, "OK\n");
    425 	}
    426 
    427 	if (os_strcmp(txt, "random") == 0) {
    428 		if (pos)
    429 			timeout = atoi(pos);
    430 		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
    431 		if (pin_txt == NULL)
    432 			return -1;
    433 		return os_snprintf(buf, buflen, "%s", pin_txt);
    434 	}
    435 
    436 	if (os_strcmp(txt, "get") == 0) {
    437 		pin_txt = hostapd_wps_ap_pin_get(hapd);
    438 		if (pin_txt == NULL)
    439 			return -1;
    440 		return os_snprintf(buf, buflen, "%s", pin_txt);
    441 	}
    442 
    443 	if (os_strcmp(txt, "set") == 0) {
    444 		char *pin;
    445 		if (pos == NULL)
    446 			return -1;
    447 		pin = pos;
    448 		pos = os_strchr(pos, ' ');
    449 		if (pos) {
    450 			*pos++ = '\0';
    451 			timeout = atoi(pos);
    452 		}
    453 		if (os_strlen(pin) > buflen)
    454 			return -1;
    455 		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
    456 			return -1;
    457 		return os_snprintf(buf, buflen, "%s", pin);
    458 	}
    459 
    460 	return -1;
    461 }
    462 
    463 
    464 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
    465 {
    466 	char *pos;
    467 	char *ssid, *auth, *encr = NULL, *key = NULL;
    468 
    469 	ssid = txt;
    470 	pos = os_strchr(txt, ' ');
    471 	if (!pos)
    472 		return -1;
    473 	*pos++ = '\0';
    474 
    475 	auth = pos;
    476 	pos = os_strchr(pos, ' ');
    477 	if (pos) {
    478 		*pos++ = '\0';
    479 		encr = pos;
    480 		pos = os_strchr(pos, ' ');
    481 		if (pos) {
    482 			*pos++ = '\0';
    483 			key = pos;
    484 		}
    485 	}
    486 
    487 	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
    488 }
    489 #endif /* CONFIG_WPS */
    490 
    491 
    492 #ifdef CONFIG_WNM
    493 
    494 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
    495 						const char *cmd)
    496 {
    497 	u8 addr[ETH_ALEN];
    498 	u8 buf[1000], *pos;
    499 	struct ieee80211_mgmt *mgmt;
    500 	int disassoc_timer;
    501 
    502 	if (hwaddr_aton(cmd, addr))
    503 		return -1;
    504 	if (cmd[17] != ' ')
    505 		return -1;
    506 	disassoc_timer = atoi(cmd + 17);
    507 
    508 	os_memset(buf, 0, sizeof(buf));
    509 	mgmt = (struct ieee80211_mgmt *) buf;
    510 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    511 					   WLAN_FC_STYPE_ACTION);
    512 	os_memcpy(mgmt->da, addr, ETH_ALEN);
    513 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
    514 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
    515 	mgmt->u.action.category = WLAN_ACTION_WNM;
    516 	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
    517 	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
    518 	mgmt->u.action.u.bss_tm_req.req_mode =
    519 		WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
    520 	mgmt->u.action.u.bss_tm_req.disassoc_timer =
    521 		host_to_le16(disassoc_timer);
    522 	mgmt->u.action.u.bss_tm_req.validity_interval = 0;
    523 
    524 	pos = mgmt->u.action.u.bss_tm_req.variable;
    525 
    526 	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
    527 		wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
    528 			   "Management Request frame");
    529 		return -1;
    530 	}
    531 
    532 	return 0;
    533 }
    534 
    535 
    536 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
    537 					   const char *cmd)
    538 {
    539 	u8 addr[ETH_ALEN];
    540 	const char *url;
    541 	u8 buf[1000], *pos;
    542 	struct ieee80211_mgmt *mgmt;
    543 	size_t url_len;
    544 
    545 	if (hwaddr_aton(cmd, addr))
    546 		return -1;
    547 	url = cmd + 17;
    548 	if (*url != ' ')
    549 		return -1;
    550 	url++;
    551 	url_len = os_strlen(url);
    552 	if (url_len > 255)
    553 		return -1;
    554 
    555 	os_memset(buf, 0, sizeof(buf));
    556 	mgmt = (struct ieee80211_mgmt *) buf;
    557 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    558 					   WLAN_FC_STYPE_ACTION);
    559 	os_memcpy(mgmt->da, addr, ETH_ALEN);
    560 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
    561 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
    562 	mgmt->u.action.category = WLAN_ACTION_WNM;
    563 	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
    564 	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
    565 	mgmt->u.action.u.bss_tm_req.req_mode =
    566 		WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
    567 	mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
    568 	mgmt->u.action.u.bss_tm_req.validity_interval = 0;
    569 
    570 	pos = mgmt->u.action.u.bss_tm_req.variable;
    571 
    572 	/* Session Information URL */
    573 	*pos++ = url_len;
    574 	os_memcpy(pos, url, url_len);
    575 	pos += url_len;
    576 
    577 	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
    578 		wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
    579 			   "Management Request frame");
    580 		return -1;
    581 	}
    582 
    583 	return 0;
    584 }
    585 
    586 #endif /* CONFIG_WNM */
    587 
    588 
    589 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
    590 					 char *buf, size_t buflen)
    591 {
    592 	int ret;
    593 	char *pos, *end;
    594 
    595 	pos = buf;
    596 	end = buf + buflen;
    597 
    598 	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
    599 			  "ssid=%s\n",
    600 			  MAC2STR(hapd->own_addr),
    601 			  wpa_ssid_txt(hapd->conf->ssid.ssid,
    602 				       hapd->conf->ssid.ssid_len));
    603 	if (ret < 0 || ret >= end - pos)
    604 		return pos - buf;
    605 	pos += ret;
    606 
    607 #ifdef CONFIG_WPS
    608 	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
    609 			  hapd->conf->wps_state == 0 ? "disabled" :
    610 			  (hapd->conf->wps_state == 1 ? "not configured" :
    611 			   "configured"));
    612 	if (ret < 0 || ret >= end - pos)
    613 		return pos - buf;
    614 	pos += ret;
    615 
    616 	if (hapd->conf->wps_state && hapd->conf->wpa &&
    617 	    hapd->conf->ssid.wpa_passphrase) {
    618 		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
    619 				  hapd->conf->ssid.wpa_passphrase);
    620 		if (ret < 0 || ret >= end - pos)
    621 			return pos - buf;
    622 		pos += ret;
    623 	}
    624 
    625 	if (hapd->conf->wps_state && hapd->conf->wpa &&
    626 	    hapd->conf->ssid.wpa_psk &&
    627 	    hapd->conf->ssid.wpa_psk->group) {
    628 		char hex[PMK_LEN * 2 + 1];
    629 		wpa_snprintf_hex(hex, sizeof(hex),
    630 				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
    631 		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
    632 		if (ret < 0 || ret >= end - pos)
    633 			return pos - buf;
    634 		pos += ret;
    635 	}
    636 #endif /* CONFIG_WPS */
    637 
    638 	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
    639 		ret = os_snprintf(pos, end - pos, "key_mgmt=");
    640 		if (ret < 0 || ret >= end - pos)
    641 			return pos - buf;
    642 		pos += ret;
    643 
    644 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
    645 			ret = os_snprintf(pos, end - pos, "WPA-PSK ");
    646 			if (ret < 0 || ret >= end - pos)
    647 				return pos - buf;
    648 			pos += ret;
    649 		}
    650 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    651 			ret = os_snprintf(pos, end - pos, "WPA-EAP ");
    652 			if (ret < 0 || ret >= end - pos)
    653 				return pos - buf;
    654 			pos += ret;
    655 		}
    656 #ifdef CONFIG_IEEE80211R
    657 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    658 			ret = os_snprintf(pos, end - pos, "FT-PSK ");
    659 			if (ret < 0 || ret >= end - pos)
    660 				return pos - buf;
    661 			pos += ret;
    662 		}
    663 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    664 			ret = os_snprintf(pos, end - pos, "FT-EAP ");
    665 			if (ret < 0 || ret >= end - pos)
    666 				return pos - buf;
    667 			pos += ret;
    668 		}
    669 #endif /* CONFIG_IEEE80211R */
    670 #ifdef CONFIG_IEEE80211W
    671 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    672 			ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
    673 			if (ret < 0 || ret >= end - pos)
    674 				return pos - buf;
    675 			pos += ret;
    676 		}
    677 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    678 			ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
    679 			if (ret < 0 || ret >= end - pos)
    680 				return pos - buf;
    681 			pos += ret;
    682 		}
    683 #endif /* CONFIG_IEEE80211W */
    684 
    685 		ret = os_snprintf(pos, end - pos, "\n");
    686 		if (ret < 0 || ret >= end - pos)
    687 			return pos - buf;
    688 		pos += ret;
    689 	}
    690 
    691 	if (hapd->conf->wpa) {
    692 		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
    693 				  wpa_cipher_txt(hapd->conf->wpa_group));
    694 		if (ret < 0 || ret >= end - pos)
    695 			return pos - buf;
    696 		pos += ret;
    697 	}
    698 
    699 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
    700 		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
    701 		if (ret < 0 || ret >= end - pos)
    702 			return pos - buf;
    703 		pos += ret;
    704 
    705 		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
    706 					" ");
    707 		if (ret < 0)
    708 			return pos - buf;
    709 		pos += ret;
    710 
    711 		ret = os_snprintf(pos, end - pos, "\n");
    712 		if (ret < 0 || ret >= end - pos)
    713 			return pos - buf;
    714 		pos += ret;
    715 	}
    716 
    717 	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
    718 		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
    719 		if (ret < 0 || ret >= end - pos)
    720 			return pos - buf;
    721 		pos += ret;
    722 
    723 		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
    724 					" ");
    725 		if (ret < 0)
    726 			return pos - buf;
    727 		pos += ret;
    728 
    729 		ret = os_snprintf(pos, end - pos, "\n");
    730 		if (ret < 0 || ret >= end - pos)
    731 			return pos - buf;
    732 		pos += ret;
    733 	}
    734 
    735 	return pos - buf;
    736 }
    737 
    738 
    739 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
    740 {
    741 	char *value;
    742 	int ret = 0;
    743 
    744 	value = os_strchr(cmd, ' ');
    745 	if (value == NULL)
    746 		return -1;
    747 	*value++ = '\0';
    748 
    749 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    750 	if (0) {
    751 #ifdef CONFIG_WPS_TESTING
    752 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
    753 		long int val;
    754 		val = strtol(value, NULL, 0);
    755 		if (val < 0 || val > 0xff) {
    756 			ret = -1;
    757 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
    758 				   "wps_version_number %ld", val);
    759 		} else {
    760 			wps_version_number = val;
    761 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
    762 				   "version %u.%u",
    763 				   (wps_version_number & 0xf0) >> 4,
    764 				   wps_version_number & 0x0f);
    765 			hostapd_wps_update_ie(hapd);
    766 		}
    767 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
    768 		wps_testing_dummy_cred = atoi(value);
    769 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
    770 			   wps_testing_dummy_cred);
    771 #endif /* CONFIG_WPS_TESTING */
    772 #ifdef CONFIG_INTERWORKING
    773 	} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
    774 		int val = atoi(value);
    775 		if (val <= 0)
    776 			ret = -1;
    777 		else
    778 			hapd->gas_frag_limit = val;
    779 #endif /* CONFIG_INTERWORKING */
    780 	} else {
    781 		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
    782 	}
    783 
    784 	return ret;
    785 }
    786 
    787 
    788 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
    789 				  char *buf, size_t buflen)
    790 {
    791 	int res;
    792 
    793 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
    794 
    795 	if (os_strcmp(cmd, "version") == 0) {
    796 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
    797 		if (res < 0 || (unsigned int) res >= buflen)
    798 			return -1;
    799 		return res;
    800 	}
    801 
    802 	return -1;
    803 }
    804 
    805 
    806 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
    807 {
    808 	if (hostapd_enable_iface(iface) < 0) {
    809 		wpa_printf(MSG_ERROR, "Enabling of interface failed");
    810 		return -1;
    811 	}
    812 	return 0;
    813 }
    814 
    815 
    816 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
    817 {
    818 	if (hostapd_reload_iface(iface) < 0) {
    819 		wpa_printf(MSG_ERROR, "Reloading of interface failed");
    820 		return -1;
    821 	}
    822 	return 0;
    823 }
    824 
    825 
    826 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
    827 {
    828 	if (hostapd_disable_iface(iface) < 0) {
    829 		wpa_printf(MSG_ERROR, "Disabling of interface failed");
    830 		return -1;
    831 	}
    832 	return 0;
    833 }
    834 
    835 
    836 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
    837 				       void *sock_ctx)
    838 {
    839 	struct hostapd_data *hapd = eloop_ctx;
    840 	char buf[256];
    841 	int res;
    842 	struct sockaddr_un from;
    843 	socklen_t fromlen = sizeof(from);
    844 	char *reply;
    845 	const int reply_size = 4096;
    846 	int reply_len;
    847 	int level = MSG_DEBUG;
    848 
    849 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    850 		       (struct sockaddr *) &from, &fromlen);
    851 	if (res < 0) {
    852 		perror("recvfrom(ctrl_iface)");
    853 		return;
    854 	}
    855 	buf[res] = '\0';
    856 	if (os_strcmp(buf, "PING") == 0)
    857 		level = MSG_EXCESSIVE;
    858 	wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
    859 
    860 	reply = os_malloc(reply_size);
    861 	if (reply == NULL) {
    862 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    863 		       fromlen);
    864 		return;
    865 	}
    866 
    867 	os_memcpy(reply, "OK\n", 3);
    868 	reply_len = 3;
    869 
    870 	if (os_strcmp(buf, "PING") == 0) {
    871 		os_memcpy(reply, "PONG\n", 5);
    872 		reply_len = 5;
    873 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
    874 		if (wpa_debug_reopen_file() < 0)
    875 			reply_len = -1;
    876 	} else if (os_strcmp(buf, "MIB") == 0) {
    877 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
    878 		if (reply_len >= 0) {
    879 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
    880 					  reply_size - reply_len);
    881 			if (res < 0)
    882 				reply_len = -1;
    883 			else
    884 				reply_len += res;
    885 		}
    886 		if (reply_len >= 0) {
    887 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
    888 						 reply_size - reply_len);
    889 			if (res < 0)
    890 				reply_len = -1;
    891 			else
    892 				reply_len += res;
    893 		}
    894 #ifndef CONFIG_NO_RADIUS
    895 		if (reply_len >= 0) {
    896 			res = radius_client_get_mib(hapd->radius,
    897 						    reply + reply_len,
    898 						    reply_size - reply_len);
    899 			if (res < 0)
    900 				reply_len = -1;
    901 			else
    902 				reply_len += res;
    903 		}
    904 #endif /* CONFIG_NO_RADIUS */
    905 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
    906 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
    907 							 reply_size);
    908 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
    909 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
    910 						   reply_size);
    911 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    912 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
    913 							reply_size);
    914 	} else if (os_strcmp(buf, "ATTACH") == 0) {
    915 		if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
    916 			reply_len = -1;
    917 	} else if (os_strcmp(buf, "DETACH") == 0) {
    918 		if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
    919 			reply_len = -1;
    920 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
    921 		if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
    922 						    buf + 6))
    923 			reply_len = -1;
    924 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
    925 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
    926 			reply_len = -1;
    927 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    928 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
    929 			reply_len = -1;
    930 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    931 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
    932 			reply_len = -1;
    933 #ifdef CONFIG_IEEE80211W
    934 #ifdef NEED_AP_MLME
    935 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
    936 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
    937 			reply_len = -1;
    938 #endif /* NEED_AP_MLME */
    939 #endif /* CONFIG_IEEE80211W */
    940 #ifdef CONFIG_WPS
    941 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    942 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
    943 			reply_len = -1;
    944 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    945 		reply_len = hostapd_ctrl_iface_wps_check_pin(
    946 			hapd, buf + 14, reply, reply_size);
    947 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
    948 		if (hostapd_wps_button_pushed(hapd, NULL))
    949 			reply_len = -1;
    950 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
    951 		if (hostapd_wps_cancel(hapd))
    952 			reply_len = -1;
    953 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    954 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
    955 							  reply, reply_size);
    956 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
    957 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
    958 			reply_len = -1;
    959 #ifdef CONFIG_WPS_NFC
    960 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
    961 		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
    962 			reply_len = -1;
    963 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
    964 		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
    965 			hapd, buf + 21, reply, reply_size);
    966 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
    967 		reply_len = hostapd_ctrl_iface_wps_nfc_token(
    968 			hapd, buf + 14, reply, reply_size);
    969 	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
    970 		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
    971 			hapd, buf + 21, reply, reply_size);
    972 	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
    973 		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
    974 			reply_len = -1;
    975 #endif /* CONFIG_WPS_NFC */
    976 #endif /* CONFIG_WPS */
    977 #ifdef CONFIG_WNM
    978 	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
    979 		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
    980 			reply_len = -1;
    981 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
    982 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
    983 			reply_len = -1;
    984 #endif /* CONFIG_WNM */
    985 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
    986 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
    987 							  reply_size);
    988 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
    989 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
    990 			reply_len = -1;
    991 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
    992 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
    993 						   reply_size);
    994 	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
    995 		if (hostapd_ctrl_iface_enable(hapd->iface))
    996 			reply_len = -1;
    997 	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
    998 		if (hostapd_ctrl_iface_reload(hapd->iface))
    999 			reply_len = -1;
   1000 	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
   1001 		if (hostapd_ctrl_iface_disable(hapd->iface))
   1002 			reply_len = -1;
   1003 	} else {
   1004 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
   1005 		reply_len = 16;
   1006 	}
   1007 
   1008 	if (reply_len < 0) {
   1009 		os_memcpy(reply, "FAIL\n", 5);
   1010 		reply_len = 5;
   1011 	}
   1012 	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
   1013 	os_free(reply);
   1014 }
   1015 
   1016 
   1017 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
   1018 {
   1019 	char *buf;
   1020 	size_t len;
   1021 
   1022 	if (hapd->conf->ctrl_interface == NULL)
   1023 		return NULL;
   1024 
   1025 	len = os_strlen(hapd->conf->ctrl_interface) +
   1026 		os_strlen(hapd->conf->iface) + 2;
   1027 	buf = os_malloc(len);
   1028 	if (buf == NULL)
   1029 		return NULL;
   1030 
   1031 	os_snprintf(buf, len, "%s/%s",
   1032 		    hapd->conf->ctrl_interface, hapd->conf->iface);
   1033 	buf[len - 1] = '\0';
   1034 	return buf;
   1035 }
   1036 
   1037 
   1038 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
   1039 				      const char *txt, size_t len)
   1040 {
   1041 	struct hostapd_data *hapd = ctx;
   1042 	if (hapd == NULL)
   1043 		return;
   1044 	hostapd_ctrl_iface_send(hapd, level, txt, len);
   1045 }
   1046 
   1047 
   1048 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
   1049 {
   1050 	struct sockaddr_un addr;
   1051 	int s = -1;
   1052 	char *fname = NULL;
   1053 
   1054 	if (hapd->ctrl_sock > -1) {
   1055 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   1056 		return 0;
   1057 	}
   1058 
   1059 	if (hapd->conf->ctrl_interface == NULL)
   1060 		return 0;
   1061 
   1062 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
   1063 		if (errno == EEXIST) {
   1064 			wpa_printf(MSG_DEBUG, "Using existing control "
   1065 				   "interface directory.");
   1066 		} else {
   1067 			perror("mkdir[ctrl_interface]");
   1068 			goto fail;
   1069 		}
   1070 	}
   1071 
   1072 	if (hapd->conf->ctrl_interface_gid_set &&
   1073 	    chown(hapd->conf->ctrl_interface, -1,
   1074 		  hapd->conf->ctrl_interface_gid) < 0) {
   1075 		perror("chown[ctrl_interface]");
   1076 		return -1;
   1077 	}
   1078 
   1079 	if (!hapd->conf->ctrl_interface_gid_set &&
   1080 	    hapd->iface->interfaces->ctrl_iface_group &&
   1081 	    chown(hapd->conf->ctrl_interface, -1,
   1082 		  hapd->iface->interfaces->ctrl_iface_group) < 0) {
   1083 		perror("chown[ctrl_interface]");
   1084 		return -1;
   1085 	}
   1086 
   1087 #ifdef ANDROID
   1088 	/*
   1089 	 * Android is using umask 0077 which would leave the control interface
   1090 	 * directory without group access. This breaks things since Wi-Fi
   1091 	 * framework assumes that this directory can be accessed by other
   1092 	 * applications in the wifi group. Fix this by adding group access even
   1093 	 * if umask value would prevent this.
   1094 	 */
   1095 	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
   1096 		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
   1097 			   strerror(errno));
   1098 		/* Try to continue anyway */
   1099 	}
   1100 #endif /* ANDROID */
   1101 
   1102 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
   1103 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
   1104 		goto fail;
   1105 
   1106 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   1107 	if (s < 0) {
   1108 		perror("socket(PF_UNIX)");
   1109 		goto fail;
   1110 	}
   1111 
   1112 	os_memset(&addr, 0, sizeof(addr));
   1113 #ifdef __FreeBSD__
   1114 	addr.sun_len = sizeof(addr);
   1115 #endif /* __FreeBSD__ */
   1116 	addr.sun_family = AF_UNIX;
   1117 	fname = hostapd_ctrl_iface_path(hapd);
   1118 	if (fname == NULL)
   1119 		goto fail;
   1120 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   1121 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1122 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   1123 			   strerror(errno));
   1124 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1125 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   1126 				   " allow connections - assuming it was left"
   1127 				   "over from forced program termination");
   1128 			if (unlink(fname) < 0) {
   1129 				perror("unlink[ctrl_iface]");
   1130 				wpa_printf(MSG_ERROR, "Could not unlink "
   1131 					   "existing ctrl_iface socket '%s'",
   1132 					   fname);
   1133 				goto fail;
   1134 			}
   1135 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   1136 			    0) {
   1137 				perror("hostapd-ctrl-iface: bind(PF_UNIX)");
   1138 				goto fail;
   1139 			}
   1140 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   1141 				   "ctrl_iface socket '%s'", fname);
   1142 		} else {
   1143 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   1144 				   "be in use - cannot override it");
   1145 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   1146 				   "not used anymore", fname);
   1147 			os_free(fname);
   1148 			fname = NULL;
   1149 			goto fail;
   1150 		}
   1151 	}
   1152 
   1153 	if (hapd->conf->ctrl_interface_gid_set &&
   1154 	    chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
   1155 		perror("chown[ctrl_interface/ifname]");
   1156 		goto fail;
   1157 	}
   1158 
   1159 	if (!hapd->conf->ctrl_interface_gid_set &&
   1160 	    hapd->iface->interfaces->ctrl_iface_group &&
   1161 	    chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
   1162 		perror("chown[ctrl_interface/ifname]");
   1163 		goto fail;
   1164 	}
   1165 
   1166 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   1167 		perror("chmod[ctrl_interface/ifname]");
   1168 		goto fail;
   1169 	}
   1170 	os_free(fname);
   1171 
   1172 	hapd->ctrl_sock = s;
   1173 	eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
   1174 				 NULL);
   1175 	hapd->msg_ctx = hapd;
   1176 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
   1177 
   1178 	return 0;
   1179 
   1180 fail:
   1181 	if (s >= 0)
   1182 		close(s);
   1183 	if (fname) {
   1184 		unlink(fname);
   1185 		os_free(fname);
   1186 	}
   1187 	return -1;
   1188 }
   1189 
   1190 
   1191 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
   1192 {
   1193 	struct wpa_ctrl_dst *dst, *prev;
   1194 
   1195 	if (hapd->ctrl_sock > -1) {
   1196 		char *fname;
   1197 		eloop_unregister_read_sock(hapd->ctrl_sock);
   1198 		close(hapd->ctrl_sock);
   1199 		hapd->ctrl_sock = -1;
   1200 		fname = hostapd_ctrl_iface_path(hapd);
   1201 		if (fname)
   1202 			unlink(fname);
   1203 		os_free(fname);
   1204 
   1205 		if (hapd->conf->ctrl_interface &&
   1206 		    rmdir(hapd->conf->ctrl_interface) < 0) {
   1207 			if (errno == ENOTEMPTY) {
   1208 				wpa_printf(MSG_DEBUG, "Control interface "
   1209 					   "directory not empty - leaving it "
   1210 					   "behind");
   1211 			} else {
   1212 				perror("rmdir[ctrl_interface]");
   1213 			}
   1214 		}
   1215 	}
   1216 
   1217 	dst = hapd->ctrl_dst;
   1218 	while (dst) {
   1219 		prev = dst;
   1220 		dst = dst->next;
   1221 		os_free(prev);
   1222 	}
   1223 }
   1224 
   1225 
   1226 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
   1227 				  char *buf)
   1228 {
   1229 	if (hostapd_add_iface(interfaces, buf) < 0) {
   1230 		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
   1231 		return -1;
   1232 	}
   1233 	return 0;
   1234 }
   1235 
   1236 
   1237 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
   1238 				     char *buf)
   1239 {
   1240 	if (hostapd_remove_iface(interfaces, buf) < 0) {
   1241 		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
   1242 		return -1;
   1243 	}
   1244 	return 0;
   1245 }
   1246 
   1247 
   1248 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
   1249 					      void *sock_ctx)
   1250 {
   1251 	void *interfaces = eloop_ctx;
   1252 	char buf[256];
   1253 	int res;
   1254 	struct sockaddr_un from;
   1255 	socklen_t fromlen = sizeof(from);
   1256 	char reply[24];
   1257 	int reply_len;
   1258 
   1259 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
   1260 		       (struct sockaddr *) &from, &fromlen);
   1261 	if (res < 0) {
   1262 		perror("recvfrom(ctrl_iface)");
   1263 		return;
   1264 	}
   1265 	buf[res] = '\0';
   1266 
   1267 	os_memcpy(reply, "OK\n", 3);
   1268 	reply_len = 3;
   1269 
   1270 	if (os_strcmp(buf, "PING") == 0) {
   1271 		os_memcpy(reply, "PONG\n", 5);
   1272 		reply_len = 5;
   1273 	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
   1274 		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
   1275 			reply_len = -1;
   1276 	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
   1277 		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
   1278 			reply_len = -1;
   1279 	} else {
   1280 		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
   1281 			   "ignored");
   1282 		reply_len = -1;
   1283 	}
   1284 
   1285 	if (reply_len < 0) {
   1286 		os_memcpy(reply, "FAIL\n", 5);
   1287 		reply_len = 5;
   1288 	}
   1289 
   1290 	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
   1291 }
   1292 
   1293 
   1294 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
   1295 {
   1296 	char *buf;
   1297 	size_t len;
   1298 
   1299 	if (interface->global_iface_path == NULL)
   1300 		return NULL;
   1301 
   1302 	len = os_strlen(interface->global_iface_path) +
   1303 		os_strlen(interface->global_iface_name) + 2;
   1304 	buf = os_malloc(len);
   1305 	if (buf == NULL)
   1306 		return NULL;
   1307 
   1308 	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
   1309 		    interface->global_iface_name);
   1310 	buf[len - 1] = '\0';
   1311 	return buf;
   1312 }
   1313 
   1314 
   1315 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
   1316 {
   1317 	struct sockaddr_un addr;
   1318 	int s = -1;
   1319 	char *fname = NULL;
   1320 
   1321 	if (interface->global_iface_path == NULL) {
   1322 		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
   1323 		return 0;
   1324 	}
   1325 
   1326 	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
   1327 		if (errno == EEXIST) {
   1328 			wpa_printf(MSG_DEBUG, "Using existing control "
   1329 				   "interface directory.");
   1330 		} else {
   1331 			perror("mkdir[ctrl_interface]");
   1332 			goto fail;
   1333 		}
   1334 	} else if (interface->ctrl_iface_group &&
   1335 		   chown(interface->global_iface_path, -1,
   1336 			 interface->ctrl_iface_group) < 0) {
   1337 		perror("chown[ctrl_interface]");
   1338 		goto fail;
   1339 	}
   1340 
   1341 	if (os_strlen(interface->global_iface_path) + 1 +
   1342 	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
   1343 		goto fail;
   1344 
   1345 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   1346 	if (s < 0) {
   1347 		perror("socket(PF_UNIX)");
   1348 		goto fail;
   1349 	}
   1350 
   1351 	os_memset(&addr, 0, sizeof(addr));
   1352 #ifdef __FreeBSD__
   1353 	addr.sun_len = sizeof(addr);
   1354 #endif /* __FreeBSD__ */
   1355 	addr.sun_family = AF_UNIX;
   1356 	fname = hostapd_global_ctrl_iface_path(interface);
   1357 	if (fname == NULL)
   1358 		goto fail;
   1359 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   1360 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1361 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   1362 			   strerror(errno));
   1363 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1364 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   1365 				   " allow connections - assuming it was left"
   1366 				   "over from forced program termination");
   1367 			if (unlink(fname) < 0) {
   1368 				perror("unlink[ctrl_iface]");
   1369 				wpa_printf(MSG_ERROR, "Could not unlink "
   1370 					   "existing ctrl_iface socket '%s'",
   1371 					   fname);
   1372 				goto fail;
   1373 			}
   1374 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   1375 			    0) {
   1376 				perror("bind(PF_UNIX)");
   1377 				goto fail;
   1378 			}
   1379 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   1380 				   "ctrl_iface socket '%s'", fname);
   1381 		} else {
   1382 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   1383 				   "be in use - cannot override it");
   1384 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   1385 				   "not used anymore", fname);
   1386 			os_free(fname);
   1387 			fname = NULL;
   1388 			goto fail;
   1389 		}
   1390 	}
   1391 
   1392 	if (interface->ctrl_iface_group &&
   1393 	    chown(fname, -1, interface->ctrl_iface_group) < 0) {
   1394 		perror("chown[ctrl_interface]");
   1395 		goto fail;
   1396 	}
   1397 
   1398 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   1399 		perror("chmod[ctrl_interface/ifname]");
   1400 		goto fail;
   1401 	}
   1402 	os_free(fname);
   1403 
   1404 	interface->global_ctrl_sock = s;
   1405 	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
   1406 				 interface, NULL);
   1407 
   1408 	return 0;
   1409 
   1410 fail:
   1411 	if (s >= 0)
   1412 		close(s);
   1413 	if (fname) {
   1414 		unlink(fname);
   1415 		os_free(fname);
   1416 	}
   1417 	return -1;
   1418 }
   1419 
   1420 
   1421 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
   1422 {
   1423 	char *fname = NULL;
   1424 
   1425 	if (interfaces->global_ctrl_sock > -1) {
   1426 		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
   1427 		close(interfaces->global_ctrl_sock);
   1428 		interfaces->global_ctrl_sock = -1;
   1429 		fname = hostapd_global_ctrl_iface_path(interfaces);
   1430 		if (fname) {
   1431 			unlink(fname);
   1432 			os_free(fname);
   1433 		}
   1434 
   1435 		if (interfaces->global_iface_path &&
   1436 		    rmdir(interfaces->global_iface_path) < 0) {
   1437 			if (errno == ENOTEMPTY) {
   1438 				wpa_printf(MSG_DEBUG, "Control interface "
   1439 					   "directory not empty - leaving it "
   1440 					   "behind");
   1441 			} else {
   1442 				perror("rmdir[ctrl_interface]");
   1443 			}
   1444 		}
   1445 		os_free(interfaces->global_iface_path);
   1446 		interfaces->global_iface_path = NULL;
   1447 	}
   1448 }
   1449 
   1450 
   1451 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
   1452 				    const char *buf, size_t len)
   1453 {
   1454 	struct wpa_ctrl_dst *dst, *next;
   1455 	struct msghdr msg;
   1456 	int idx;
   1457 	struct iovec io[2];
   1458 	char levelstr[10];
   1459 
   1460 	dst = hapd->ctrl_dst;
   1461 	if (hapd->ctrl_sock < 0 || dst == NULL)
   1462 		return;
   1463 
   1464 	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
   1465 	io[0].iov_base = levelstr;
   1466 	io[0].iov_len = os_strlen(levelstr);
   1467 	io[1].iov_base = (char *) buf;
   1468 	io[1].iov_len = len;
   1469 	os_memset(&msg, 0, sizeof(msg));
   1470 	msg.msg_iov = io;
   1471 	msg.msg_iovlen = 2;
   1472 
   1473 	idx = 0;
   1474 	while (dst) {
   1475 		next = dst->next;
   1476 		if (level >= dst->debug_level) {
   1477 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
   1478 				    (u8 *) dst->addr.sun_path, dst->addrlen -
   1479 				    offsetof(struct sockaddr_un, sun_path));
   1480 			msg.msg_name = &dst->addr;
   1481 			msg.msg_namelen = dst->addrlen;
   1482 			if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
   1483 				int _errno = errno;
   1484 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
   1485 					   "%d - %s",
   1486 					   idx, errno, strerror(errno));
   1487 				dst->errors++;
   1488 				if (dst->errors > 10 || _errno == ENOENT) {
   1489 					hostapd_ctrl_iface_detach(
   1490 						hapd, &dst->addr,
   1491 						dst->addrlen);
   1492 				}
   1493 			} else
   1494 				dst->errors = 0;
   1495 		}
   1496 		idx++;
   1497 		dst = next;
   1498 	}
   1499 }
   1500 
   1501 #endif /* CONFIG_NATIVE_WINDOWS */
   1502