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_OOB
    254 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
    255 {
    256 	char *path, *method, *name;
    257 
    258 	path = os_strchr(txt, ' ');
    259 	if (path == NULL)
    260 		return -1;
    261 	*path++ = '\0';
    262 
    263 	method = os_strchr(path, ' ');
    264 	if (method == NULL)
    265 		return -1;
    266 	*method++ = '\0';
    267 
    268 	name = os_strchr(method, ' ');
    269 	if (name != NULL)
    270 		*name++ = '\0';
    271 
    272 	return hostapd_wps_start_oob(hapd, txt, path, method, name);
    273 }
    274 #endif /* CONFIG_WPS_OOB */
    275 
    276 
    277 #ifdef CONFIG_WPS_NFC
    278 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
    279 					       char *pos)
    280 {
    281 	size_t len;
    282 	struct wpabuf *buf;
    283 	int ret;
    284 
    285 	len = os_strlen(pos);
    286 	if (len & 0x01)
    287 		return -1;
    288 	len /= 2;
    289 
    290 	buf = wpabuf_alloc(len);
    291 	if (buf == NULL)
    292 		return -1;
    293 	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
    294 		wpabuf_free(buf);
    295 		return -1;
    296 	}
    297 
    298 	ret = hostapd_wps_nfc_tag_read(hapd, buf);
    299 	wpabuf_free(buf);
    300 
    301 	return ret;
    302 }
    303 
    304 
    305 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
    306 						   char *cmd, char *reply,
    307 						   size_t max_len)
    308 {
    309 	int ndef;
    310 	struct wpabuf *buf;
    311 	int res;
    312 
    313 	if (os_strcmp(cmd, "WPS") == 0)
    314 		ndef = 0;
    315 	else if (os_strcmp(cmd, "NDEF") == 0)
    316 		ndef = 1;
    317 	else
    318 		return -1;
    319 
    320 	buf = hostapd_wps_nfc_config_token(hapd, ndef);
    321 	if (buf == NULL)
    322 		return -1;
    323 
    324 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    325 					 wpabuf_len(buf));
    326 	reply[res++] = '\n';
    327 	reply[res] = '\0';
    328 
    329 	wpabuf_free(buf);
    330 
    331 	return res;
    332 }
    333 
    334 
    335 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
    336 						char *reply, size_t max_len,
    337 						int ndef)
    338 {
    339 	struct wpabuf *buf;
    340 	int res;
    341 
    342 	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
    343 	if (buf == NULL)
    344 		return -1;
    345 
    346 	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    347 					 wpabuf_len(buf));
    348 	reply[res++] = '\n';
    349 	reply[res] = '\0';
    350 
    351 	wpabuf_free(buf);
    352 
    353 	return res;
    354 }
    355 
    356 
    357 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
    358 					    char *cmd, char *reply,
    359 					    size_t max_len)
    360 {
    361 	if (os_strcmp(cmd, "WPS") == 0)
    362 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    363 							    max_len, 0);
    364 
    365 	if (os_strcmp(cmd, "NDEF") == 0)
    366 		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
    367 							    max_len, 1);
    368 
    369 	if (os_strcmp(cmd, "enable") == 0)
    370 		return hostapd_wps_nfc_token_enable(hapd);
    371 
    372 	if (os_strcmp(cmd, "disable") == 0) {
    373 		hostapd_wps_nfc_token_disable(hapd);
    374 		return 0;
    375 	}
    376 
    377 	return -1;
    378 }
    379 #endif /* CONFIG_WPS_NFC */
    380 
    381 
    382 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
    383 					 char *buf, size_t buflen)
    384 {
    385 	int timeout = 300;
    386 	char *pos;
    387 	const char *pin_txt;
    388 
    389 	pos = os_strchr(txt, ' ');
    390 	if (pos)
    391 		*pos++ = '\0';
    392 
    393 	if (os_strcmp(txt, "disable") == 0) {
    394 		hostapd_wps_ap_pin_disable(hapd);
    395 		return os_snprintf(buf, buflen, "OK\n");
    396 	}
    397 
    398 	if (os_strcmp(txt, "random") == 0) {
    399 		if (pos)
    400 			timeout = atoi(pos);
    401 		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
    402 		if (pin_txt == NULL)
    403 			return -1;
    404 		return os_snprintf(buf, buflen, "%s", pin_txt);
    405 	}
    406 
    407 	if (os_strcmp(txt, "get") == 0) {
    408 		pin_txt = hostapd_wps_ap_pin_get(hapd);
    409 		if (pin_txt == NULL)
    410 			return -1;
    411 		return os_snprintf(buf, buflen, "%s", pin_txt);
    412 	}
    413 
    414 	if (os_strcmp(txt, "set") == 0) {
    415 		char *pin;
    416 		if (pos == NULL)
    417 			return -1;
    418 		pin = pos;
    419 		pos = os_strchr(pos, ' ');
    420 		if (pos) {
    421 			*pos++ = '\0';
    422 			timeout = atoi(pos);
    423 		}
    424 		if (os_strlen(pin) > buflen)
    425 			return -1;
    426 		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
    427 			return -1;
    428 		return os_snprintf(buf, buflen, "%s", pin);
    429 	}
    430 
    431 	return -1;
    432 }
    433 
    434 
    435 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
    436 {
    437 	char *pos;
    438 	char *ssid, *auth, *encr = NULL, *key = NULL;
    439 
    440 	ssid = txt;
    441 	pos = os_strchr(txt, ' ');
    442 	if (!pos)
    443 		return -1;
    444 	*pos++ = '\0';
    445 
    446 	auth = pos;
    447 	pos = os_strchr(pos, ' ');
    448 	if (pos) {
    449 		*pos++ = '\0';
    450 		encr = pos;
    451 		pos = os_strchr(pos, ' ');
    452 		if (pos) {
    453 			*pos++ = '\0';
    454 			key = pos;
    455 		}
    456 	}
    457 
    458 	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
    459 }
    460 #endif /* CONFIG_WPS */
    461 
    462 
    463 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
    464 					   const char *cmd)
    465 {
    466 	u8 addr[ETH_ALEN];
    467 	const char *url;
    468 	u8 buf[1000], *pos;
    469 	struct ieee80211_mgmt *mgmt;
    470 	size_t url_len;
    471 
    472 	if (hwaddr_aton(cmd, addr))
    473 		return -1;
    474 	url = cmd + 17;
    475 	if (*url != ' ')
    476 		return -1;
    477 	url++;
    478 	url_len = os_strlen(url);
    479 	if (url_len > 255)
    480 		return -1;
    481 
    482 	os_memset(buf, 0, sizeof(buf));
    483 	mgmt = (struct ieee80211_mgmt *) buf;
    484 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    485 					   WLAN_FC_STYPE_ACTION);
    486 	os_memcpy(mgmt->da, addr, ETH_ALEN);
    487 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
    488 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
    489 	mgmt->u.action.category = WLAN_ACTION_WNM;
    490 	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
    491 	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
    492 	mgmt->u.action.u.bss_tm_req.req_mode =
    493 		WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
    494 	mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
    495 	mgmt->u.action.u.bss_tm_req.validity_interval = 0;
    496 
    497 	pos = mgmt->u.action.u.bss_tm_req.variable;
    498 
    499 	/* Session Information URL */
    500 	*pos++ = url_len;
    501 	os_memcpy(pos, url, url_len);
    502 	pos += url_len;
    503 
    504 	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
    505 		wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
    506 			   "Management Request frame");
    507 		return -1;
    508 	}
    509 
    510 	return 0;
    511 }
    512 
    513 
    514 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
    515 					 char *buf, size_t buflen)
    516 {
    517 	int ret;
    518 	char *pos, *end;
    519 
    520 	pos = buf;
    521 	end = buf + buflen;
    522 
    523 	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
    524 			  "ssid=%s\n",
    525 			  MAC2STR(hapd->own_addr),
    526 			  wpa_ssid_txt(hapd->conf->ssid.ssid,
    527 				       hapd->conf->ssid.ssid_len));
    528 	if (ret < 0 || ret >= end - pos)
    529 		return pos - buf;
    530 	pos += ret;
    531 
    532 #ifdef CONFIG_WPS
    533 	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
    534 			  hapd->conf->wps_state == 0 ? "disabled" :
    535 			  (hapd->conf->wps_state == 1 ? "not configured" :
    536 			   "configured"));
    537 	if (ret < 0 || ret >= end - pos)
    538 		return pos - buf;
    539 	pos += ret;
    540 
    541 	if (hapd->conf->wps_state && hapd->conf->wpa &&
    542 	    hapd->conf->ssid.wpa_passphrase) {
    543 		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
    544 				  hapd->conf->ssid.wpa_passphrase);
    545 		if (ret < 0 || ret >= end - pos)
    546 			return pos - buf;
    547 		pos += ret;
    548 	}
    549 
    550 	if (hapd->conf->wps_state && hapd->conf->wpa &&
    551 	    hapd->conf->ssid.wpa_psk &&
    552 	    hapd->conf->ssid.wpa_psk->group) {
    553 		char hex[PMK_LEN * 2 + 1];
    554 		wpa_snprintf_hex(hex, sizeof(hex),
    555 				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
    556 		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
    557 		if (ret < 0 || ret >= end - pos)
    558 			return pos - buf;
    559 		pos += ret;
    560 	}
    561 #endif /* CONFIG_WPS */
    562 
    563 	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
    564 		ret = os_snprintf(pos, end - pos, "key_mgmt=");
    565 		if (ret < 0 || ret >= end - pos)
    566 			return pos - buf;
    567 		pos += ret;
    568 
    569 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
    570 			ret = os_snprintf(pos, end - pos, "WPA-PSK ");
    571 			if (ret < 0 || ret >= end - pos)
    572 				return pos - buf;
    573 			pos += ret;
    574 		}
    575 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    576 			ret = os_snprintf(pos, end - pos, "WPA-EAP ");
    577 			if (ret < 0 || ret >= end - pos)
    578 				return pos - buf;
    579 			pos += ret;
    580 		}
    581 #ifdef CONFIG_IEEE80211R
    582 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    583 			ret = os_snprintf(pos, end - pos, "FT-PSK ");
    584 			if (ret < 0 || ret >= end - pos)
    585 				return pos - buf;
    586 			pos += ret;
    587 		}
    588 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    589 			ret = os_snprintf(pos, end - pos, "FT-EAP ");
    590 			if (ret < 0 || ret >= end - pos)
    591 				return pos - buf;
    592 			pos += ret;
    593 		}
    594 #endif /* CONFIG_IEEE80211R */
    595 #ifdef CONFIG_IEEE80211W
    596 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    597 			ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
    598 			if (ret < 0 || ret >= end - pos)
    599 				return pos - buf;
    600 			pos += ret;
    601 		}
    602 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    603 			ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
    604 			if (ret < 0 || ret >= end - pos)
    605 				return pos - buf;
    606 			pos += ret;
    607 		}
    608 #endif /* CONFIG_IEEE80211W */
    609 
    610 		ret = os_snprintf(pos, end - pos, "\n");
    611 		if (ret < 0 || ret >= end - pos)
    612 			return pos - buf;
    613 		pos += ret;
    614 	}
    615 
    616 	if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) {
    617 		ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n");
    618 		if (ret < 0 || ret >= end - pos)
    619 			return pos - buf;
    620 		pos += ret;
    621 	} else if (hapd->conf->wpa &&
    622 		   hapd->conf->wpa_group == WPA_CIPHER_GCMP) {
    623 		ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n");
    624 		if (ret < 0 || ret >= end - pos)
    625 			return pos - buf;
    626 		pos += ret;
    627 	} else if (hapd->conf->wpa &&
    628 		   hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
    629 		ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
    630 		if (ret < 0 || ret >= end - pos)
    631 			return pos - buf;
    632 		pos += ret;
    633 	}
    634 
    635 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
    636 		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
    637 		if (ret < 0 || ret >= end - pos)
    638 			return pos - buf;
    639 		pos += ret;
    640 
    641 		if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) {
    642 			ret = os_snprintf(pos, end - pos, "CCMP ");
    643 			if (ret < 0 || ret >= end - pos)
    644 				return pos - buf;
    645 			pos += ret;
    646 		}
    647 		if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) {
    648 			ret = os_snprintf(pos, end - pos, "GCMP ");
    649 			if (ret < 0 || ret >= end - pos)
    650 				return pos - buf;
    651 			pos += ret;
    652 		}
    653 		if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
    654 			ret = os_snprintf(pos, end - pos, "TKIP ");
    655 			if (ret < 0 || ret >= end - pos)
    656 				return pos - buf;
    657 			pos += ret;
    658 		}
    659 
    660 		ret = os_snprintf(pos, end - pos, "\n");
    661 		if (ret < 0 || ret >= end - pos)
    662 			return pos - buf;
    663 		pos += ret;
    664 	}
    665 
    666 	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
    667 		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
    668 		if (ret < 0 || ret >= end - pos)
    669 			return pos - buf;
    670 		pos += ret;
    671 
    672 		if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {
    673 			ret = os_snprintf(pos, end - pos, "CCMP ");
    674 			if (ret < 0 || ret >= end - pos)
    675 				return pos - buf;
    676 			pos += ret;
    677 		}
    678 		if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) {
    679 			ret = os_snprintf(pos, end - pos, "GCMP ");
    680 			if (ret < 0 || ret >= end - pos)
    681 				return pos - buf;
    682 			pos += ret;
    683 		}
    684 		if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
    685 			ret = os_snprintf(pos, end - pos, "TKIP ");
    686 			if (ret < 0 || ret >= end - pos)
    687 				return pos - buf;
    688 			pos += ret;
    689 		}
    690 
    691 		ret = os_snprintf(pos, end - pos, "\n");
    692 		if (ret < 0 || ret >= end - pos)
    693 			return pos - buf;
    694 		pos += ret;
    695 	}
    696 
    697 	return pos - buf;
    698 }
    699 
    700 
    701 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
    702 {
    703 	char *value;
    704 	int ret = 0;
    705 
    706 	value = os_strchr(cmd, ' ');
    707 	if (value == NULL)
    708 		return -1;
    709 	*value++ = '\0';
    710 
    711 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    712 	if (0) {
    713 #ifdef CONFIG_WPS_TESTING
    714 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
    715 		long int val;
    716 		val = strtol(value, NULL, 0);
    717 		if (val < 0 || val > 0xff) {
    718 			ret = -1;
    719 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
    720 				   "wps_version_number %ld", val);
    721 		} else {
    722 			wps_version_number = val;
    723 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
    724 				   "version %u.%u",
    725 				   (wps_version_number & 0xf0) >> 4,
    726 				   wps_version_number & 0x0f);
    727 			hostapd_wps_update_ie(hapd);
    728 		}
    729 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
    730 		wps_testing_dummy_cred = atoi(value);
    731 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
    732 			   wps_testing_dummy_cred);
    733 #endif /* CONFIG_WPS_TESTING */
    734 #ifdef CONFIG_INTERWORKING
    735 	} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
    736 		int val = atoi(value);
    737 		if (val <= 0)
    738 			ret = -1;
    739 		else
    740 			hapd->gas_frag_limit = val;
    741 #endif /* CONFIG_INTERWORKING */
    742 	} else {
    743 		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
    744 	}
    745 
    746 	return ret;
    747 }
    748 
    749 
    750 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
    751 				  char *buf, size_t buflen)
    752 {
    753 	int res;
    754 
    755 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
    756 
    757 	if (os_strcmp(cmd, "version") == 0) {
    758 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
    759 		if (res < 0 || (unsigned int) res >= buflen)
    760 			return -1;
    761 		return res;
    762 	}
    763 
    764 	return -1;
    765 }
    766 
    767 
    768 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
    769 {
    770 	if (hostapd_enable_iface(iface) < 0) {
    771 		wpa_printf(MSG_ERROR, "Enabling of interface failed");
    772 		return -1;
    773 	}
    774 	return 0;
    775 }
    776 
    777 
    778 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
    779 {
    780 	if (hostapd_reload_iface(iface) < 0) {
    781 		wpa_printf(MSG_ERROR, "Reloading of interface failed");
    782 		return -1;
    783 	}
    784 	return 0;
    785 }
    786 
    787 
    788 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
    789 {
    790 	if (hostapd_disable_iface(iface) < 0) {
    791 		wpa_printf(MSG_ERROR, "Disabling of interface failed");
    792 		return -1;
    793 	}
    794 	return 0;
    795 }
    796 
    797 
    798 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
    799 				       void *sock_ctx)
    800 {
    801 	struct hostapd_data *hapd = eloop_ctx;
    802 	char buf[256];
    803 	int res;
    804 	struct sockaddr_un from;
    805 	socklen_t fromlen = sizeof(from);
    806 	char *reply;
    807 	const int reply_size = 4096;
    808 	int reply_len;
    809 	int level = MSG_DEBUG;
    810 
    811 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    812 		       (struct sockaddr *) &from, &fromlen);
    813 	if (res < 0) {
    814 		perror("recvfrom(ctrl_iface)");
    815 		return;
    816 	}
    817 	buf[res] = '\0';
    818 	if (os_strcmp(buf, "PING") == 0)
    819 		level = MSG_EXCESSIVE;
    820 	wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
    821 
    822 	reply = os_malloc(reply_size);
    823 	if (reply == NULL) {
    824 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    825 		       fromlen);
    826 		return;
    827 	}
    828 
    829 	os_memcpy(reply, "OK\n", 3);
    830 	reply_len = 3;
    831 
    832 	if (os_strcmp(buf, "PING") == 0) {
    833 		os_memcpy(reply, "PONG\n", 5);
    834 		reply_len = 5;
    835 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
    836 		if (wpa_debug_reopen_file() < 0)
    837 			reply_len = -1;
    838 	} else if (os_strcmp(buf, "MIB") == 0) {
    839 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
    840 		if (reply_len >= 0) {
    841 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
    842 					  reply_size - reply_len);
    843 			if (res < 0)
    844 				reply_len = -1;
    845 			else
    846 				reply_len += res;
    847 		}
    848 		if (reply_len >= 0) {
    849 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
    850 						 reply_size - reply_len);
    851 			if (res < 0)
    852 				reply_len = -1;
    853 			else
    854 				reply_len += res;
    855 		}
    856 #ifndef CONFIG_NO_RADIUS
    857 		if (reply_len >= 0) {
    858 			res = radius_client_get_mib(hapd->radius,
    859 						    reply + reply_len,
    860 						    reply_size - reply_len);
    861 			if (res < 0)
    862 				reply_len = -1;
    863 			else
    864 				reply_len += res;
    865 		}
    866 #endif /* CONFIG_NO_RADIUS */
    867 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
    868 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
    869 							 reply_size);
    870 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
    871 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
    872 						   reply_size);
    873 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    874 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
    875 							reply_size);
    876 	} else if (os_strcmp(buf, "ATTACH") == 0) {
    877 		if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
    878 			reply_len = -1;
    879 	} else if (os_strcmp(buf, "DETACH") == 0) {
    880 		if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
    881 			reply_len = -1;
    882 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
    883 		if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
    884 						    buf + 6))
    885 			reply_len = -1;
    886 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
    887 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
    888 			reply_len = -1;
    889 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    890 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
    891 			reply_len = -1;
    892 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    893 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
    894 			reply_len = -1;
    895 #ifdef CONFIG_IEEE80211W
    896 #ifdef NEED_AP_MLME
    897 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
    898 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
    899 			reply_len = -1;
    900 #endif /* NEED_AP_MLME */
    901 #endif /* CONFIG_IEEE80211W */
    902 #ifdef CONFIG_WPS
    903 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    904 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
    905 			reply_len = -1;
    906 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    907 		reply_len = hostapd_ctrl_iface_wps_check_pin(
    908 			hapd, buf + 14, reply, reply_size);
    909 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
    910 		if (hostapd_wps_button_pushed(hapd, NULL))
    911 			reply_len = -1;
    912 	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
    913 		if (hostapd_wps_cancel(hapd))
    914 			reply_len = -1;
    915 #ifdef CONFIG_WPS_OOB
    916 	} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
    917 		if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
    918 			reply_len = -1;
    919 #endif /* CONFIG_WPS_OOB */
    920 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    921 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
    922 							  reply, reply_size);
    923 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
    924 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
    925 			reply_len = -1;
    926 #ifdef CONFIG_WPS_NFC
    927 	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
    928 		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
    929 			reply_len = -1;
    930 	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
    931 		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
    932 			hapd, buf + 21, reply, reply_size);
    933 	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
    934 		reply_len = hostapd_ctrl_iface_wps_nfc_token(
    935 			hapd, buf + 14, reply, reply_size);
    936 #endif /* CONFIG_WPS_NFC */
    937 #endif /* CONFIG_WPS */
    938 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
    939 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
    940 			reply_len = -1;
    941 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
    942 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
    943 							  reply_size);
    944 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
    945 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
    946 			reply_len = -1;
    947 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
    948 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
    949 						   reply_size);
    950 	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
    951 		if (hostapd_ctrl_iface_enable(hapd->iface))
    952 			reply_len = -1;
    953 	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
    954 		if (hostapd_ctrl_iface_reload(hapd->iface))
    955 			reply_len = -1;
    956 	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
    957 		if (hostapd_ctrl_iface_disable(hapd->iface))
    958 			reply_len = -1;
    959 	} else {
    960 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    961 		reply_len = 16;
    962 	}
    963 
    964 	if (reply_len < 0) {
    965 		os_memcpy(reply, "FAIL\n", 5);
    966 		reply_len = 5;
    967 	}
    968 	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
    969 	os_free(reply);
    970 }
    971 
    972 
    973 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
    974 {
    975 	char *buf;
    976 	size_t len;
    977 
    978 	if (hapd->conf->ctrl_interface == NULL)
    979 		return NULL;
    980 
    981 	len = os_strlen(hapd->conf->ctrl_interface) +
    982 		os_strlen(hapd->conf->iface) + 2;
    983 	buf = os_malloc(len);
    984 	if (buf == NULL)
    985 		return NULL;
    986 
    987 	os_snprintf(buf, len, "%s/%s",
    988 		    hapd->conf->ctrl_interface, hapd->conf->iface);
    989 	buf[len - 1] = '\0';
    990 	return buf;
    991 }
    992 
    993 
    994 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
    995 				      const char *txt, size_t len)
    996 {
    997 	struct hostapd_data *hapd = ctx;
    998 	if (hapd == NULL)
    999 		return;
   1000 	hostapd_ctrl_iface_send(hapd, level, txt, len);
   1001 }
   1002 
   1003 
   1004 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
   1005 {
   1006 	struct sockaddr_un addr;
   1007 	int s = -1;
   1008 	char *fname = NULL;
   1009 
   1010 	if (hapd->ctrl_sock > -1) {
   1011 		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
   1012 		return 0;
   1013 	}
   1014 
   1015 	if (hapd->conf->ctrl_interface == NULL)
   1016 		return 0;
   1017 
   1018 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
   1019 		if (errno == EEXIST) {
   1020 			wpa_printf(MSG_DEBUG, "Using existing control "
   1021 				   "interface directory.");
   1022 		} else {
   1023 			perror("mkdir[ctrl_interface]");
   1024 			goto fail;
   1025 		}
   1026 	}
   1027 
   1028 	if (hapd->conf->ctrl_interface_gid_set &&
   1029 	    chown(hapd->conf->ctrl_interface, 0,
   1030 		  hapd->conf->ctrl_interface_gid) < 0) {
   1031 		perror("chown[ctrl_interface]");
   1032 		return -1;
   1033 	}
   1034 
   1035 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
   1036 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
   1037 		goto fail;
   1038 
   1039 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   1040 	if (s < 0) {
   1041 		perror("socket(PF_UNIX)");
   1042 		goto fail;
   1043 	}
   1044 
   1045 	os_memset(&addr, 0, sizeof(addr));
   1046 #ifdef __FreeBSD__
   1047 	addr.sun_len = sizeof(addr);
   1048 #endif /* __FreeBSD__ */
   1049 	addr.sun_family = AF_UNIX;
   1050 	fname = hostapd_ctrl_iface_path(hapd);
   1051 	if (fname == NULL)
   1052 		goto fail;
   1053 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   1054 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1055 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   1056 			   strerror(errno));
   1057 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1058 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   1059 				   " allow connections - assuming it was left"
   1060 				   "over from forced program termination");
   1061 			if (unlink(fname) < 0) {
   1062 				perror("unlink[ctrl_iface]");
   1063 				wpa_printf(MSG_ERROR, "Could not unlink "
   1064 					   "existing ctrl_iface socket '%s'",
   1065 					   fname);
   1066 				goto fail;
   1067 			}
   1068 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   1069 			    0) {
   1070 				perror("hostapd-ctrl-iface: bind(PF_UNIX)");
   1071 				goto fail;
   1072 			}
   1073 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   1074 				   "ctrl_iface socket '%s'", fname);
   1075 		} else {
   1076 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   1077 				   "be in use - cannot override it");
   1078 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   1079 				   "not used anymore", fname);
   1080 			os_free(fname);
   1081 			fname = NULL;
   1082 			goto fail;
   1083 		}
   1084 	}
   1085 
   1086 	if (hapd->conf->ctrl_interface_gid_set &&
   1087 	    chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) {
   1088 		perror("chown[ctrl_interface/ifname]");
   1089 		goto fail;
   1090 	}
   1091 
   1092 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   1093 		perror("chmod[ctrl_interface/ifname]");
   1094 		goto fail;
   1095 	}
   1096 	os_free(fname);
   1097 
   1098 	hapd->ctrl_sock = s;
   1099 	eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
   1100 				 NULL);
   1101 	hapd->msg_ctx = hapd;
   1102 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
   1103 
   1104 	return 0;
   1105 
   1106 fail:
   1107 	if (s >= 0)
   1108 		close(s);
   1109 	if (fname) {
   1110 		unlink(fname);
   1111 		os_free(fname);
   1112 	}
   1113 	return -1;
   1114 }
   1115 
   1116 
   1117 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
   1118 {
   1119 	struct wpa_ctrl_dst *dst, *prev;
   1120 
   1121 	if (hapd->ctrl_sock > -1) {
   1122 		char *fname;
   1123 		eloop_unregister_read_sock(hapd->ctrl_sock);
   1124 		close(hapd->ctrl_sock);
   1125 		hapd->ctrl_sock = -1;
   1126 		fname = hostapd_ctrl_iface_path(hapd);
   1127 		if (fname)
   1128 			unlink(fname);
   1129 		os_free(fname);
   1130 
   1131 		if (hapd->conf->ctrl_interface &&
   1132 		    rmdir(hapd->conf->ctrl_interface) < 0) {
   1133 			if (errno == ENOTEMPTY) {
   1134 				wpa_printf(MSG_DEBUG, "Control interface "
   1135 					   "directory not empty - leaving it "
   1136 					   "behind");
   1137 			} else {
   1138 				perror("rmdir[ctrl_interface]");
   1139 			}
   1140 		}
   1141 	}
   1142 
   1143 	dst = hapd->ctrl_dst;
   1144 	while (dst) {
   1145 		prev = dst;
   1146 		dst = dst->next;
   1147 		os_free(prev);
   1148 	}
   1149 }
   1150 
   1151 
   1152 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
   1153 				  char *buf)
   1154 {
   1155 	if (hostapd_add_iface(interfaces, buf) < 0) {
   1156 		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
   1157 		return -1;
   1158 	}
   1159 	return 0;
   1160 }
   1161 
   1162 
   1163 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
   1164 				     char *buf)
   1165 {
   1166 	if (hostapd_remove_iface(interfaces, buf) < 0) {
   1167 		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
   1168 		return -1;
   1169 	}
   1170 	return 0;
   1171 }
   1172 
   1173 
   1174 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
   1175 					      void *sock_ctx)
   1176 {
   1177 	void *interfaces = eloop_ctx;
   1178 	char buf[256];
   1179 	int res;
   1180 	struct sockaddr_un from;
   1181 	socklen_t fromlen = sizeof(from);
   1182 	char reply[24];
   1183 	int reply_len;
   1184 
   1185 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
   1186 		       (struct sockaddr *) &from, &fromlen);
   1187 	if (res < 0) {
   1188 		perror("recvfrom(ctrl_iface)");
   1189 		return;
   1190 	}
   1191 	buf[res] = '\0';
   1192 
   1193 	os_memcpy(reply, "OK\n", 3);
   1194 	reply_len = 3;
   1195 
   1196 	if (os_strcmp(buf, "PING") == 0) {
   1197 		os_memcpy(reply, "PONG\n", 5);
   1198 		reply_len = 5;
   1199 	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
   1200 		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
   1201 			reply_len = -1;
   1202 	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
   1203 		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
   1204 			reply_len = -1;
   1205 	} else {
   1206 		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
   1207 			   "ignored");
   1208 		reply_len = -1;
   1209 	}
   1210 
   1211 	if (reply_len < 0) {
   1212 		os_memcpy(reply, "FAIL\n", 5);
   1213 		reply_len = 5;
   1214 	}
   1215 
   1216 	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
   1217 }
   1218 
   1219 
   1220 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
   1221 {
   1222 	char *buf;
   1223 	size_t len;
   1224 
   1225 	if (interface->global_iface_path == NULL)
   1226 		return NULL;
   1227 
   1228 	len = os_strlen(interface->global_iface_path) +
   1229 		os_strlen(interface->global_iface_name) + 2;
   1230 	buf = os_malloc(len);
   1231 	if (buf == NULL)
   1232 		return NULL;
   1233 
   1234 	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
   1235 		    interface->global_iface_name);
   1236 	buf[len - 1] = '\0';
   1237 	return buf;
   1238 }
   1239 
   1240 
   1241 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
   1242 {
   1243 	struct sockaddr_un addr;
   1244 	int s = -1;
   1245 	char *fname = NULL;
   1246 
   1247 	if (interface->global_iface_path == NULL) {
   1248 		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
   1249 		return 0;
   1250 	}
   1251 
   1252 	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
   1253 		if (errno == EEXIST) {
   1254 			wpa_printf(MSG_DEBUG, "Using existing control "
   1255 				   "interface directory.");
   1256 		} else {
   1257 			perror("mkdir[ctrl_interface]");
   1258 			goto fail;
   1259 		}
   1260 	}
   1261 
   1262 	if (os_strlen(interface->global_iface_path) + 1 +
   1263 	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
   1264 		goto fail;
   1265 
   1266 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
   1267 	if (s < 0) {
   1268 		perror("socket(PF_UNIX)");
   1269 		goto fail;
   1270 	}
   1271 
   1272 	os_memset(&addr, 0, sizeof(addr));
   1273 #ifdef __FreeBSD__
   1274 	addr.sun_len = sizeof(addr);
   1275 #endif /* __FreeBSD__ */
   1276 	addr.sun_family = AF_UNIX;
   1277 	fname = hostapd_global_ctrl_iface_path(interface);
   1278 	if (fname == NULL)
   1279 		goto fail;
   1280 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
   1281 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1282 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
   1283 			   strerror(errno));
   1284 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1285 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
   1286 				   " allow connections - assuming it was left"
   1287 				   "over from forced program termination");
   1288 			if (unlink(fname) < 0) {
   1289 				perror("unlink[ctrl_iface]");
   1290 				wpa_printf(MSG_ERROR, "Could not unlink "
   1291 					   "existing ctrl_iface socket '%s'",
   1292 					   fname);
   1293 				goto fail;
   1294 			}
   1295 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
   1296 			    0) {
   1297 				perror("bind(PF_UNIX)");
   1298 				goto fail;
   1299 			}
   1300 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   1301 				   "ctrl_iface socket '%s'", fname);
   1302 		} else {
   1303 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   1304 				   "be in use - cannot override it");
   1305 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   1306 				   "not used anymore", fname);
   1307 			os_free(fname);
   1308 			fname = NULL;
   1309 			goto fail;
   1310 		}
   1311 	}
   1312 
   1313 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   1314 		perror("chmod[ctrl_interface/ifname]");
   1315 		goto fail;
   1316 	}
   1317 	os_free(fname);
   1318 
   1319 	interface->global_ctrl_sock = s;
   1320 	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
   1321 				 interface, NULL);
   1322 
   1323 	return 0;
   1324 
   1325 fail:
   1326 	if (s >= 0)
   1327 		close(s);
   1328 	if (fname) {
   1329 		unlink(fname);
   1330 		os_free(fname);
   1331 	}
   1332 	return -1;
   1333 }
   1334 
   1335 
   1336 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
   1337 {
   1338 	char *fname = NULL;
   1339 
   1340 	if (interfaces->global_ctrl_sock > -1) {
   1341 		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
   1342 		close(interfaces->global_ctrl_sock);
   1343 		interfaces->global_ctrl_sock = -1;
   1344 		fname = hostapd_global_ctrl_iface_path(interfaces);
   1345 		if (fname) {
   1346 			unlink(fname);
   1347 			os_free(fname);
   1348 		}
   1349 
   1350 		if (interfaces->global_iface_path &&
   1351 		    rmdir(interfaces->global_iface_path) < 0) {
   1352 			if (errno == ENOTEMPTY) {
   1353 				wpa_printf(MSG_DEBUG, "Control interface "
   1354 					   "directory not empty - leaving it "
   1355 					   "behind");
   1356 			} else {
   1357 				perror("rmdir[ctrl_interface]");
   1358 			}
   1359 		}
   1360 		os_free(interfaces->global_iface_path);
   1361 		interfaces->global_iface_path = NULL;
   1362 	}
   1363 }
   1364 
   1365 
   1366 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
   1367 				    const char *buf, size_t len)
   1368 {
   1369 	struct wpa_ctrl_dst *dst, *next;
   1370 	struct msghdr msg;
   1371 	int idx;
   1372 	struct iovec io[2];
   1373 	char levelstr[10];
   1374 
   1375 	dst = hapd->ctrl_dst;
   1376 	if (hapd->ctrl_sock < 0 || dst == NULL)
   1377 		return;
   1378 
   1379 	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
   1380 	io[0].iov_base = levelstr;
   1381 	io[0].iov_len = os_strlen(levelstr);
   1382 	io[1].iov_base = (char *) buf;
   1383 	io[1].iov_len = len;
   1384 	os_memset(&msg, 0, sizeof(msg));
   1385 	msg.msg_iov = io;
   1386 	msg.msg_iovlen = 2;
   1387 
   1388 	idx = 0;
   1389 	while (dst) {
   1390 		next = dst->next;
   1391 		if (level >= dst->debug_level) {
   1392 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
   1393 				    (u8 *) dst->addr.sun_path, dst->addrlen -
   1394 				    offsetof(struct sockaddr_un, sun_path));
   1395 			msg.msg_name = &dst->addr;
   1396 			msg.msg_namelen = dst->addrlen;
   1397 			if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
   1398 				int _errno = errno;
   1399 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
   1400 					   "%d - %s",
   1401 					   idx, errno, strerror(errno));
   1402 				dst->errors++;
   1403 				if (dst->errors > 10 || _errno == ENOENT) {
   1404 					hostapd_ctrl_iface_detach(
   1405 						hapd, &dst->addr,
   1406 						dst->addrlen);
   1407 				}
   1408 			} else
   1409 				dst->errors = 0;
   1410 		}
   1411 		idx++;
   1412 		dst = next;
   1413 	}
   1414 }
   1415 
   1416 #endif /* CONFIG_NATIVE_WINDOWS */
   1417