Home | History | Annotate | Download | only in hostapd
      1 /*
      2  * hostapd / UNIX domain socket -based control interface
      3  * Copyright (c) 2004-2010, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "utils/includes.h"
     16 
     17 #ifndef CONFIG_NATIVE_WINDOWS
     18 
     19 #include <sys/un.h>
     20 #include <sys/stat.h>
     21 #include <stddef.h>
     22 
     23 #include "utils/common.h"
     24 #include "utils/eloop.h"
     25 #include "common/version.h"
     26 #include "common/ieee802_11_defs.h"
     27 #include "drivers/driver.h"
     28 #include "radius/radius_client.h"
     29 #include "ap/hostapd.h"
     30 #include "ap/ap_config.h"
     31 #include "ap/ieee802_1x.h"
     32 #include "ap/wpa_auth.h"
     33 #include "ap/ieee802_11.h"
     34 #include "ap/sta_info.h"
     35 #include "ap/accounting.h"
     36 #include "ap/wps_hostapd.h"
     37 #include "ap/ctrl_iface_ap.h"
     38 #include "ap/ap_drv_ops.h"
     39 #include "wps/wps_defs.h"
     40 #include "wps/wps.h"
     41 #include "ctrl_iface.h"
     42 
     43 
     44 struct wpa_ctrl_dst {
     45 	struct wpa_ctrl_dst *next;
     46 	struct sockaddr_un addr;
     47 	socklen_t addrlen;
     48 	int debug_level;
     49 	int errors;
     50 };
     51 
     52 
     53 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
     54 				    const char *buf, size_t len);
     55 
     56 
     57 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
     58 				     struct sockaddr_un *from,
     59 				     socklen_t fromlen)
     60 {
     61 	struct wpa_ctrl_dst *dst;
     62 
     63 	dst = os_zalloc(sizeof(*dst));
     64 	if (dst == NULL)
     65 		return -1;
     66 	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
     67 	dst->addrlen = fromlen;
     68 	dst->debug_level = MSG_INFO;
     69 	dst->next = hapd->ctrl_dst;
     70 	hapd->ctrl_dst = dst;
     71 	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
     72 		    (u8 *) from->sun_path,
     73 		    fromlen - offsetof(struct sockaddr_un, sun_path));
     74 	return 0;
     75 }
     76 
     77 
     78 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
     79 				     struct sockaddr_un *from,
     80 				     socklen_t fromlen)
     81 {
     82 	struct wpa_ctrl_dst *dst, *prev = NULL;
     83 
     84 	dst = hapd->ctrl_dst;
     85 	while (dst) {
     86 		if (fromlen == dst->addrlen &&
     87 		    os_memcmp(from->sun_path, dst->addr.sun_path,
     88 			      fromlen - offsetof(struct sockaddr_un, sun_path))
     89 		    == 0) {
     90 			if (prev == NULL)
     91 				hapd->ctrl_dst = dst->next;
     92 			else
     93 				prev->next = dst->next;
     94 			os_free(dst);
     95 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
     96 				    (u8 *) from->sun_path,
     97 				    fromlen -
     98 				    offsetof(struct sockaddr_un, sun_path));
     99 			return 0;
    100 		}
    101 		prev = dst;
    102 		dst = dst->next;
    103 	}
    104 	return -1;
    105 }
    106 
    107 
    108 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
    109 				    struct sockaddr_un *from,
    110 				    socklen_t fromlen,
    111 				    char *level)
    112 {
    113 	struct wpa_ctrl_dst *dst;
    114 
    115 	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
    116 
    117 	dst = hapd->ctrl_dst;
    118 	while (dst) {
    119 		if (fromlen == dst->addrlen &&
    120 		    os_memcmp(from->sun_path, dst->addr.sun_path,
    121 			      fromlen - offsetof(struct sockaddr_un, sun_path))
    122 		    == 0) {
    123 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
    124 				    "level", (u8 *) from->sun_path, fromlen -
    125 				    offsetof(struct sockaddr_un, sun_path));
    126 			dst->debug_level = atoi(level);
    127 			return 0;
    128 		}
    129 		dst = dst->next;
    130 	}
    131 
    132 	return -1;
    133 }
    134 
    135 
    136 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
    137 				      const char *txtaddr)
    138 {
    139 	u8 addr[ETH_ALEN];
    140 	struct sta_info *sta;
    141 
    142 	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
    143 
    144 	if (hwaddr_aton(txtaddr, addr))
    145 		return -1;
    146 
    147 	sta = ap_get_sta(hapd, addr);
    148 	if (sta)
    149 		return 0;
    150 
    151 	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
    152 		   "notification", MAC2STR(addr));
    153 	sta = ap_sta_add(hapd, addr);
    154 	if (sta == NULL)
    155 		return -1;
    156 
    157 	hostapd_new_assoc_sta(hapd, sta, 0);
    158 	return 0;
    159 }
    160 
    161 
    162 #ifdef CONFIG_P2P_MANAGER
    163 static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
    164 				  u8 minor_reason_code, const u8 *addr)
    165 {
    166 	struct ieee80211_mgmt *mgmt;
    167 	int ret;
    168 	u8 *pos;
    169 
    170 	if (hapd->driver->send_frame == NULL)
    171 		return -1;
    172 
    173 	mgmt = os_zalloc(sizeof(*mgmt) + 100);
    174 	if (mgmt == NULL)
    175 		return -1;
    176 
    177 	wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor "
    178 		   "reason code %u (stype=%u)",
    179 		   MAC2STR(addr), minor_reason_code, stype);
    180 
    181 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
    182 	os_memcpy(mgmt->da, addr, ETH_ALEN);
    183 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
    184 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
    185 	if (stype == WLAN_FC_STYPE_DEAUTH) {
    186 		mgmt->u.deauth.reason_code =
    187 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
    188 		pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
    189 	} else {
    190 		mgmt->u.disassoc.reason_code =
    191 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
    192 		pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
    193 	}
    194 
    195 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
    196 	*pos++ = 4 + 3 + 1;
    197 	WPA_PUT_BE24(pos, OUI_WFA);
    198 	pos += 3;
    199 	*pos++ = P2P_OUI_TYPE;
    200 
    201 	*pos++ = P2P_ATTR_MINOR_REASON_CODE;
    202 	WPA_PUT_LE16(pos, 1);
    203 	pos += 2;
    204 	*pos++ = minor_reason_code;
    205 
    206 	ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
    207 				       pos - (u8 *) mgmt, 1);
    208 	os_free(mgmt);
    209 
    210 	return ret < 0 ? -1 : 0;
    211 }
    212 #endif /* CONFIG_P2P_MANAGER */
    213 
    214 
    215 static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
    216 					     const char *txtaddr)
    217 {
    218 	u8 addr[ETH_ALEN];
    219 	struct sta_info *sta;
    220 	const char *pos;
    221 
    222 	wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr);
    223 
    224 	if (hwaddr_aton(txtaddr, addr))
    225 		return -1;
    226 
    227 	pos = os_strstr(txtaddr, " test=");
    228 	if (pos) {
    229 		struct ieee80211_mgmt mgmt;
    230 		int encrypt;
    231 		if (hapd->driver->send_frame == NULL)
    232 			return -1;
    233 		pos += 6;
    234 		encrypt = atoi(pos);
    235 		os_memset(&mgmt, 0, sizeof(mgmt));
    236 		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    237 						  WLAN_FC_STYPE_DEAUTH);
    238 		os_memcpy(mgmt.da, addr, ETH_ALEN);
    239 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
    240 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
    241 		mgmt.u.deauth.reason_code =
    242 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
    243 		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
    244 					     IEEE80211_HDRLEN +
    245 					     sizeof(mgmt.u.deauth),
    246 					     encrypt) < 0)
    247 			return -1;
    248 		return 0;
    249 	}
    250 
    251 #ifdef CONFIG_P2P_MANAGER
    252 	pos = os_strstr(txtaddr, " p2p=");
    253 	if (pos) {
    254 		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
    255 					      atoi(pos + 5), addr);
    256 	}
    257 #endif /* CONFIG_P2P_MANAGER */
    258 
    259 	hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
    260 	sta = ap_get_sta(hapd, addr);
    261 	if (sta)
    262 		ap_sta_deauthenticate(hapd, sta,
    263 				      WLAN_REASON_PREV_AUTH_NOT_VALID);
    264 	else if (addr[0] == 0xff)
    265 		hostapd_free_stas(hapd);
    266 
    267 	return 0;
    268 }
    269 
    270 
    271 static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
    272 					   const char *txtaddr)
    273 {
    274 	u8 addr[ETH_ALEN];
    275 	struct sta_info *sta;
    276 	const char *pos;
    277 
    278 	wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr);
    279 
    280 	if (hwaddr_aton(txtaddr, addr))
    281 		return -1;
    282 
    283 	pos = os_strstr(txtaddr, " test=");
    284 	if (pos) {
    285 		struct ieee80211_mgmt mgmt;
    286 		int encrypt;
    287 		if (hapd->driver->send_frame == NULL)
    288 			return -1;
    289 		pos += 6;
    290 		encrypt = atoi(pos);
    291 		os_memset(&mgmt, 0, sizeof(mgmt));
    292 		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    293 						  WLAN_FC_STYPE_DISASSOC);
    294 		os_memcpy(mgmt.da, addr, ETH_ALEN);
    295 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
    296 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
    297 		mgmt.u.disassoc.reason_code =
    298 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
    299 		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
    300 					     IEEE80211_HDRLEN +
    301 					     sizeof(mgmt.u.deauth),
    302 					     encrypt) < 0)
    303 			return -1;
    304 		return 0;
    305 	}
    306 
    307 #ifdef CONFIG_P2P_MANAGER
    308 	pos = os_strstr(txtaddr, " p2p=");
    309 	if (pos) {
    310 		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
    311 					      atoi(pos + 5), addr);
    312 	}
    313 #endif /* CONFIG_P2P_MANAGER */
    314 
    315 	hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
    316 	sta = ap_get_sta(hapd, addr);
    317 	if (sta)
    318 		ap_sta_disassociate(hapd, sta,
    319 				    WLAN_REASON_PREV_AUTH_NOT_VALID);
    320 	else if (addr[0] == 0xff)
    321 		hostapd_free_stas(hapd);
    322 
    323 	return 0;
    324 }
    325 
    326 
    327 #ifdef CONFIG_IEEE80211W
    328 #ifdef NEED_AP_MLME
    329 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
    330 				       const char *txtaddr)
    331 {
    332 	u8 addr[ETH_ALEN];
    333 	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
    334 
    335 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
    336 
    337 	if (hwaddr_aton(txtaddr, addr) ||
    338 	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
    339 		return -1;
    340 
    341 	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
    342 
    343 	return 0;
    344 }
    345 #endif /* NEED_AP_MLME */
    346 #endif /* CONFIG_IEEE80211W */
    347 
    348 
    349 #ifdef CONFIG_WPS
    350 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
    351 {
    352 	char *pin = os_strchr(txt, ' ');
    353 	char *timeout_txt;
    354 	int timeout;
    355 	u8 addr_buf[ETH_ALEN], *addr = NULL;
    356 	char *pos;
    357 
    358 	if (pin == NULL)
    359 		return -1;
    360 	*pin++ = '\0';
    361 
    362 	timeout_txt = os_strchr(pin, ' ');
    363 	if (timeout_txt) {
    364 		*timeout_txt++ = '\0';
    365 		timeout = atoi(timeout_txt);
    366 		pos = os_strchr(timeout_txt, ' ');
    367 		if (pos) {
    368 			*pos++ = '\0';
    369 			if (hwaddr_aton(pos, addr_buf) == 0)
    370 				addr = addr_buf;
    371 		}
    372 	} else
    373 		timeout = 0;
    374 
    375 	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
    376 }
    377 
    378 
    379 static int hostapd_ctrl_iface_wps_check_pin(
    380 	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
    381 {
    382 	char pin[9];
    383 	size_t len;
    384 	char *pos;
    385 	int ret;
    386 
    387 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
    388 			      (u8 *) cmd, os_strlen(cmd));
    389 	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
    390 		if (*pos < '0' || *pos > '9')
    391 			continue;
    392 		pin[len++] = *pos;
    393 		if (len == 9) {
    394 			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
    395 			return -1;
    396 		}
    397 	}
    398 	if (len != 4 && len != 8) {
    399 		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
    400 		return -1;
    401 	}
    402 	pin[len] = '\0';
    403 
    404 	if (len == 8) {
    405 		unsigned int pin_val;
    406 		pin_val = atoi(pin);
    407 		if (!wps_pin_valid(pin_val)) {
    408 			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
    409 			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
    410 			if (ret < 0 || (size_t) ret >= buflen)
    411 				return -1;
    412 			return ret;
    413 		}
    414 	}
    415 
    416 	ret = os_snprintf(buf, buflen, "%s", pin);
    417 	if (ret < 0 || (size_t) ret >= buflen)
    418 		return -1;
    419 
    420 	return ret;
    421 }
    422 
    423 
    424 #ifdef CONFIG_WPS_OOB
    425 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
    426 {
    427 	char *path, *method, *name;
    428 
    429 	path = os_strchr(txt, ' ');
    430 	if (path == NULL)
    431 		return -1;
    432 	*path++ = '\0';
    433 
    434 	method = os_strchr(path, ' ');
    435 	if (method == NULL)
    436 		return -1;
    437 	*method++ = '\0';
    438 
    439 	name = os_strchr(method, ' ');
    440 	if (name != NULL)
    441 		*name++ = '\0';
    442 
    443 	return hostapd_wps_start_oob(hapd, txt, path, method, name);
    444 }
    445 #endif /* CONFIG_WPS_OOB */
    446 
    447 
    448 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
    449 					 char *buf, size_t buflen)
    450 {
    451 	int timeout = 300;
    452 	char *pos;
    453 	const char *pin_txt;
    454 
    455 	pos = os_strchr(txt, ' ');
    456 	if (pos)
    457 		*pos++ = '\0';
    458 
    459 	if (os_strcmp(txt, "disable") == 0) {
    460 		hostapd_wps_ap_pin_disable(hapd);
    461 		return os_snprintf(buf, buflen, "OK\n");
    462 	}
    463 
    464 	if (os_strcmp(txt, "random") == 0) {
    465 		if (pos)
    466 			timeout = atoi(pos);
    467 		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
    468 		if (pin_txt == NULL)
    469 			return -1;
    470 		return os_snprintf(buf, buflen, "%s", pin_txt);
    471 	}
    472 
    473 	if (os_strcmp(txt, "get") == 0) {
    474 		pin_txt = hostapd_wps_ap_pin_get(hapd);
    475 		if (pin_txt == NULL)
    476 			return -1;
    477 		return os_snprintf(buf, buflen, "%s", pin_txt);
    478 	}
    479 
    480 	if (os_strcmp(txt, "set") == 0) {
    481 		char *pin;
    482 		if (pos == NULL)
    483 			return -1;
    484 		pin = pos;
    485 		pos = os_strchr(pos, ' ');
    486 		if (pos) {
    487 			*pos++ = '\0';
    488 			timeout = atoi(pos);
    489 		}
    490 		if (os_strlen(pin) > buflen)
    491 			return -1;
    492 		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
    493 			return -1;
    494 		return os_snprintf(buf, buflen, "%s", pin);
    495 	}
    496 
    497 	return -1;
    498 }
    499 
    500 
    501 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
    502 {
    503 	char *pos;
    504 	char *ssid, *auth, *encr = NULL, *key = NULL;
    505 
    506 	ssid = txt;
    507 	pos = os_strchr(txt, ' ');
    508 	if (!pos)
    509 		return -1;
    510 	*pos++ = '\0';
    511 
    512 	auth = pos;
    513 	pos = os_strchr(pos, ' ');
    514 	if (pos) {
    515 		*pos++ = '\0';
    516 		encr = pos;
    517 		pos = os_strchr(pos, ' ');
    518 		if (pos) {
    519 			*pos++ = '\0';
    520 			key = pos;
    521 		}
    522 	}
    523 
    524 	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
    525 }
    526 #endif /* CONFIG_WPS */
    527 
    528 
    529 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
    530 					 char *buf, size_t buflen)
    531 {
    532 	int ret;
    533 	char *pos, *end;
    534 
    535 	pos = buf;
    536 	end = buf + buflen;
    537 
    538 	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
    539 			  "ssid=%s\n",
    540 			  MAC2STR(hapd->own_addr),
    541 			  hapd->conf->ssid.ssid);
    542 	if (ret < 0 || ret >= end - pos)
    543 		return pos - buf;
    544 	pos += ret;
    545 
    546 #ifdef CONFIG_WPS
    547 	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
    548 			  hapd->conf->wps_state == 0 ? "disabled" :
    549 			  (hapd->conf->wps_state == 1 ? "not configured" :
    550 			   "configured"));
    551 	if (ret < 0 || ret >= end - pos)
    552 		return pos - buf;
    553 	pos += ret;
    554 
    555 	if (hapd->conf->wps_state && hapd->conf->wpa &&
    556 	    hapd->conf->ssid.wpa_passphrase) {
    557 		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
    558 				  hapd->conf->ssid.wpa_passphrase);
    559 		if (ret < 0 || ret >= end - pos)
    560 			return pos - buf;
    561 		pos += ret;
    562 	}
    563 
    564 	if (hapd->conf->wps_state && hapd->conf->wpa &&
    565 	    hapd->conf->ssid.wpa_psk &&
    566 	    hapd->conf->ssid.wpa_psk->group) {
    567 		char hex[PMK_LEN * 2 + 1];
    568 		wpa_snprintf_hex(hex, sizeof(hex),
    569 				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
    570 		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
    571 		if (ret < 0 || ret >= end - pos)
    572 			return pos - buf;
    573 		pos += ret;
    574 	}
    575 #endif /* CONFIG_WPS */
    576 
    577 	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
    578 		ret = os_snprintf(pos, end - pos, "key_mgmt=");
    579 		if (ret < 0 || ret >= end - pos)
    580 			return pos - buf;
    581 		pos += ret;
    582 
    583 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
    584 			ret = os_snprintf(pos, end - pos, "WPA-PSK ");
    585 			if (ret < 0 || ret >= end - pos)
    586 				return pos - buf;
    587 			pos += ret;
    588 		}
    589 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    590 			ret = os_snprintf(pos, end - pos, "WPA-EAP ");
    591 			if (ret < 0 || ret >= end - pos)
    592 				return pos - buf;
    593 			pos += ret;
    594 		}
    595 #ifdef CONFIG_IEEE80211R
    596 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    597 			ret = os_snprintf(pos, end - pos, "FT-PSK ");
    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_FT_IEEE8021X) {
    603 			ret = os_snprintf(pos, end - pos, "FT-EAP ");
    604 			if (ret < 0 || ret >= end - pos)
    605 				return pos - buf;
    606 			pos += ret;
    607 		}
    608 #endif /* CONFIG_IEEE80211R */
    609 #ifdef CONFIG_IEEE80211W
    610 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    611 			ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
    612 			if (ret < 0 || ret >= end - pos)
    613 				return pos - buf;
    614 			pos += ret;
    615 		}
    616 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    617 			ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
    618 			if (ret < 0 || ret >= end - pos)
    619 				return pos - buf;
    620 			pos += ret;
    621 		}
    622 #endif /* CONFIG_IEEE80211W */
    623 
    624 		ret = os_snprintf(pos, end - pos, "\n");
    625 		if (ret < 0 || ret >= end - pos)
    626 			return pos - buf;
    627 		pos += ret;
    628 	}
    629 
    630 	if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) {
    631 		ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n");
    632 		if (ret < 0 || ret >= end - pos)
    633 			return pos - buf;
    634 		pos += ret;
    635 	} else if (hapd->conf->wpa &&
    636 		   hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
    637 		ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
    638 		if (ret < 0 || ret >= end - pos)
    639 			return pos - buf;
    640 		pos += ret;
    641 	}
    642 
    643 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
    644 		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
    645 		if (ret < 0 || ret >= end - pos)
    646 			return pos - buf;
    647 		pos += ret;
    648 
    649 		if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) {
    650 			ret = os_snprintf(pos, end - pos, "CCMP ");
    651 			if (ret < 0 || ret >= end - pos)
    652 				return pos - buf;
    653 			pos += ret;
    654 		}
    655 		if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
    656 			ret = os_snprintf(pos, end - pos, "TKIP ");
    657 			if (ret < 0 || ret >= end - pos)
    658 				return pos - buf;
    659 			pos += ret;
    660 		}
    661 
    662 		ret = os_snprintf(pos, end - pos, "\n");
    663 		if (ret < 0 || ret >= end - pos)
    664 			return pos - buf;
    665 		pos += ret;
    666 	}
    667 
    668 	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
    669 		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
    670 		if (ret < 0 || ret >= end - pos)
    671 			return pos - buf;
    672 		pos += ret;
    673 
    674 		if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {
    675 			ret = os_snprintf(pos, end - pos, "CCMP ");
    676 			if (ret < 0 || ret >= end - pos)
    677 				return pos - buf;
    678 			pos += ret;
    679 		}
    680 		if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
    681 			ret = os_snprintf(pos, end - pos, "TKIP ");
    682 			if (ret < 0 || ret >= end - pos)
    683 				return pos - buf;
    684 			pos += ret;
    685 		}
    686 
    687 		ret = os_snprintf(pos, end - pos, "\n");
    688 		if (ret < 0 || ret >= end - pos)
    689 			return pos - buf;
    690 		pos += ret;
    691 	}
    692 
    693 	return pos - buf;
    694 }
    695 
    696 
    697 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
    698 {
    699 	char *value;
    700 	int ret = 0;
    701 
    702 	value = os_strchr(cmd, ' ');
    703 	if (value == NULL)
    704 		return -1;
    705 	*value++ = '\0';
    706 
    707 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    708 	if (0) {
    709 #ifdef CONFIG_WPS_TESTING
    710 	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
    711 		long int val;
    712 		val = strtol(value, NULL, 0);
    713 		if (val < 0 || val > 0xff) {
    714 			ret = -1;
    715 			wpa_printf(MSG_DEBUG, "WPS: Invalid "
    716 				   "wps_version_number %ld", val);
    717 		} else {
    718 			wps_version_number = val;
    719 			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
    720 				   "version %u.%u",
    721 				   (wps_version_number & 0xf0) >> 4,
    722 				   wps_version_number & 0x0f);
    723 			hostapd_wps_update_ie(hapd);
    724 		}
    725 	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
    726 		wps_testing_dummy_cred = atoi(value);
    727 		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
    728 			   wps_testing_dummy_cred);
    729 #endif /* CONFIG_WPS_TESTING */
    730 	} else {
    731 		ret = -1;
    732 	}
    733 
    734 	return ret;
    735 }
    736 
    737 
    738 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
    739 				  char *buf, size_t buflen)
    740 {
    741 	int res;
    742 
    743 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
    744 
    745 	if (os_strcmp(cmd, "version") == 0) {
    746 		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
    747 		if (res < 0 || (unsigned int) res >= buflen)
    748 			return -1;
    749 		return res;
    750 	}
    751 
    752 	return -1;
    753 }
    754 
    755 
    756 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
    757 				       void *sock_ctx)
    758 {
    759 	struct hostapd_data *hapd = eloop_ctx;
    760 	char buf[256];
    761 	int res;
    762 	struct sockaddr_un from;
    763 	socklen_t fromlen = sizeof(from);
    764 	char *reply;
    765 	const int reply_size = 4096;
    766 	int reply_len;
    767 	int level = MSG_DEBUG;
    768 
    769 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    770 		       (struct sockaddr *) &from, &fromlen);
    771 	if (res < 0) {
    772 		perror("recvfrom(ctrl_iface)");
    773 		return;
    774 	}
    775 	buf[res] = '\0';
    776 	if (os_strcmp(buf, "PING") == 0)
    777 		level = MSG_EXCESSIVE;
    778 	wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
    779 
    780 	reply = os_malloc(reply_size);
    781 	if (reply == NULL) {
    782 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    783 		       fromlen);
    784 		return;
    785 	}
    786 
    787 	os_memcpy(reply, "OK\n", 3);
    788 	reply_len = 3;
    789 
    790 	if (os_strcmp(buf, "PING") == 0) {
    791 		os_memcpy(reply, "PONG\n", 5);
    792 		reply_len = 5;
    793 	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
    794 		if (wpa_debug_reopen_file() < 0)
    795 			reply_len = -1;
    796 	} else if (os_strcmp(buf, "MIB") == 0) {
    797 		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
    798 		if (reply_len >= 0) {
    799 			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
    800 					  reply_size - reply_len);
    801 			if (res < 0)
    802 				reply_len = -1;
    803 			else
    804 				reply_len += res;
    805 		}
    806 		if (reply_len >= 0) {
    807 			res = ieee802_1x_get_mib(hapd, reply + reply_len,
    808 						 reply_size - reply_len);
    809 			if (res < 0)
    810 				reply_len = -1;
    811 			else
    812 				reply_len += res;
    813 		}
    814 #ifndef CONFIG_NO_RADIUS
    815 		if (reply_len >= 0) {
    816 			res = radius_client_get_mib(hapd->radius,
    817 						    reply + reply_len,
    818 						    reply_size - reply_len);
    819 			if (res < 0)
    820 				reply_len = -1;
    821 			else
    822 				reply_len += res;
    823 		}
    824 #endif /* CONFIG_NO_RADIUS */
    825 	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
    826 		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
    827 							 reply_size);
    828 	} else if (os_strncmp(buf, "STA ", 4) == 0) {
    829 		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
    830 						   reply_size);
    831 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    832 		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
    833 							reply_size);
    834 	} else if (os_strcmp(buf, "ATTACH") == 0) {
    835 		if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
    836 			reply_len = -1;
    837 	} else if (os_strcmp(buf, "DETACH") == 0) {
    838 		if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
    839 			reply_len = -1;
    840 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
    841 		if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
    842 						    buf + 6))
    843 			reply_len = -1;
    844 	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
    845 		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
    846 			reply_len = -1;
    847 	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    848 		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
    849 			reply_len = -1;
    850 	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    851 		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
    852 			reply_len = -1;
    853 #ifdef CONFIG_IEEE80211W
    854 #ifdef NEED_AP_MLME
    855 	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
    856 		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
    857 			reply_len = -1;
    858 #endif /* NEED_AP_MLME */
    859 #endif /* CONFIG_IEEE80211W */
    860 #ifdef CONFIG_WPS
    861 	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    862 		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
    863 			reply_len = -1;
    864 	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    865 		reply_len = hostapd_ctrl_iface_wps_check_pin(
    866 			hapd, buf + 14, reply, reply_size);
    867 	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
    868 		if (hostapd_wps_button_pushed(hapd, NULL))
    869 			reply_len = -1;
    870 #ifdef CONFIG_WPS_OOB
    871 	} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
    872 		if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
    873 			reply_len = -1;
    874 #endif /* CONFIG_WPS_OOB */
    875 	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    876 		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
    877 							  reply, reply_size);
    878 	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
    879 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
    880 			reply_len = -1;
    881 #endif /* CONFIG_WPS */
    882 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
    883 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
    884 							  reply_size);
    885 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
    886 		if (hostapd_ctrl_iface_set(hapd, buf + 4))
    887 			reply_len = -1;
    888 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
    889 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
    890 						   reply_size);
    891 	} else {
    892 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    893 		reply_len = 16;
    894 	}
    895 
    896 	if (reply_len < 0) {
    897 		os_memcpy(reply, "FAIL\n", 5);
    898 		reply_len = 5;
    899 	}
    900 	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
    901 	os_free(reply);
    902 }
    903 
    904 
    905 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
    906 {
    907 	char *buf;
    908 	size_t len;
    909 
    910 	if (hapd->conf->ctrl_interface == NULL)
    911 		return NULL;
    912 
    913 	len = os_strlen(hapd->conf->ctrl_interface) +
    914 		os_strlen(hapd->conf->iface) + 2;
    915 	buf = os_malloc(len);
    916 	if (buf == NULL)
    917 		return NULL;
    918 
    919 	os_snprintf(buf, len, "%s/%s",
    920 		    hapd->conf->ctrl_interface, hapd->conf->iface);
    921 	buf[len - 1] = '\0';
    922 	return buf;
    923 }
    924 
    925 
    926 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
    927 				      const char *txt, size_t len)
    928 {
    929 	struct hostapd_data *hapd = ctx;
    930 	if (hapd == NULL)
    931 		return;
    932 	hostapd_ctrl_iface_send(hapd, level, txt, len);
    933 }
    934 
    935 
    936 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
    937 {
    938 	struct sockaddr_un addr;
    939 	int s = -1;
    940 	char *fname = NULL;
    941 
    942 	hapd->ctrl_sock = -1;
    943 
    944 	if (hapd->conf->ctrl_interface == NULL)
    945 		return 0;
    946 
    947 	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
    948 		if (errno == EEXIST) {
    949 			wpa_printf(MSG_DEBUG, "Using existing control "
    950 				   "interface directory.");
    951 		} else {
    952 			perror("mkdir[ctrl_interface]");
    953 			goto fail;
    954 		}
    955 	}
    956 
    957 	if (hapd->conf->ctrl_interface_gid_set &&
    958 	    chown(hapd->conf->ctrl_interface, 0,
    959 		  hapd->conf->ctrl_interface_gid) < 0) {
    960 		perror("chown[ctrl_interface]");
    961 		return -1;
    962 	}
    963 
    964 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
    965 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
    966 		goto fail;
    967 
    968 	s = socket(PF_UNIX, SOCK_DGRAM, 0);
    969 	if (s < 0) {
    970 		perror("socket(PF_UNIX)");
    971 		goto fail;
    972 	}
    973 
    974 	os_memset(&addr, 0, sizeof(addr));
    975 #ifdef __FreeBSD__
    976 	addr.sun_len = sizeof(addr);
    977 #endif /* __FreeBSD__ */
    978 	addr.sun_family = AF_UNIX;
    979 	fname = hostapd_ctrl_iface_path(hapd);
    980 	if (fname == NULL)
    981 		goto fail;
    982 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
    983 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    984 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
    985 			   strerror(errno));
    986 		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    987 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
    988 				   " allow connections - assuming it was left"
    989 				   "over from forced program termination");
    990 			if (unlink(fname) < 0) {
    991 				perror("unlink[ctrl_iface]");
    992 				wpa_printf(MSG_ERROR, "Could not unlink "
    993 					   "existing ctrl_iface socket '%s'",
    994 					   fname);
    995 				goto fail;
    996 			}
    997 			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
    998 			    0) {
    999 				perror("bind(PF_UNIX)");
   1000 				goto fail;
   1001 			}
   1002 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
   1003 				   "ctrl_iface socket '%s'", fname);
   1004 		} else {
   1005 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
   1006 				   "be in use - cannot override it");
   1007 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
   1008 				   "not used anymore", fname);
   1009 			os_free(fname);
   1010 			fname = NULL;
   1011 			goto fail;
   1012 		}
   1013 	}
   1014 
   1015 	if (hapd->conf->ctrl_interface_gid_set &&
   1016 	    chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) {
   1017 		perror("chown[ctrl_interface/ifname]");
   1018 		goto fail;
   1019 	}
   1020 
   1021 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
   1022 		perror("chmod[ctrl_interface/ifname]");
   1023 		goto fail;
   1024 	}
   1025 	os_free(fname);
   1026 
   1027 	hapd->ctrl_sock = s;
   1028 	eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
   1029 				 NULL);
   1030 	hapd->msg_ctx = hapd;
   1031 	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
   1032 
   1033 	return 0;
   1034 
   1035 fail:
   1036 	if (s >= 0)
   1037 		close(s);
   1038 	if (fname) {
   1039 		unlink(fname);
   1040 		os_free(fname);
   1041 	}
   1042 	return -1;
   1043 }
   1044 
   1045 
   1046 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
   1047 {
   1048 	struct wpa_ctrl_dst *dst, *prev;
   1049 
   1050 	if (hapd->ctrl_sock > -1) {
   1051 		char *fname;
   1052 		eloop_unregister_read_sock(hapd->ctrl_sock);
   1053 		close(hapd->ctrl_sock);
   1054 		hapd->ctrl_sock = -1;
   1055 		fname = hostapd_ctrl_iface_path(hapd);
   1056 		if (fname)
   1057 			unlink(fname);
   1058 		os_free(fname);
   1059 
   1060 		if (hapd->conf->ctrl_interface &&
   1061 		    rmdir(hapd->conf->ctrl_interface) < 0) {
   1062 			if (errno == ENOTEMPTY) {
   1063 				wpa_printf(MSG_DEBUG, "Control interface "
   1064 					   "directory not empty - leaving it "
   1065 					   "behind");
   1066 			} else {
   1067 				perror("rmdir[ctrl_interface]");
   1068 			}
   1069 		}
   1070 	}
   1071 
   1072 	dst = hapd->ctrl_dst;
   1073 	while (dst) {
   1074 		prev = dst;
   1075 		dst = dst->next;
   1076 		os_free(prev);
   1077 	}
   1078 }
   1079 
   1080 
   1081 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
   1082 				    const char *buf, size_t len)
   1083 {
   1084 	struct wpa_ctrl_dst *dst, *next;
   1085 	struct msghdr msg;
   1086 	int idx;
   1087 	struct iovec io[2];
   1088 	char levelstr[10];
   1089 
   1090 	dst = hapd->ctrl_dst;
   1091 	if (hapd->ctrl_sock < 0 || dst == NULL)
   1092 		return;
   1093 
   1094 	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
   1095 	io[0].iov_base = levelstr;
   1096 	io[0].iov_len = os_strlen(levelstr);
   1097 	io[1].iov_base = (char *) buf;
   1098 	io[1].iov_len = len;
   1099 	os_memset(&msg, 0, sizeof(msg));
   1100 	msg.msg_iov = io;
   1101 	msg.msg_iovlen = 2;
   1102 
   1103 	idx = 0;
   1104 	while (dst) {
   1105 		next = dst->next;
   1106 		if (level >= dst->debug_level) {
   1107 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
   1108 				    (u8 *) dst->addr.sun_path, dst->addrlen -
   1109 				    offsetof(struct sockaddr_un, sun_path));
   1110 			msg.msg_name = &dst->addr;
   1111 			msg.msg_namelen = dst->addrlen;
   1112 			if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
   1113 				int _errno = errno;
   1114 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
   1115 					   "%d - %s",
   1116 					   idx, errno, strerror(errno));
   1117 				dst->errors++;
   1118 				if (dst->errors > 10 || _errno == ENOENT) {
   1119 					hostapd_ctrl_iface_detach(
   1120 						hapd, &dst->addr,
   1121 						dst->addrlen);
   1122 				}
   1123 			} else
   1124 				dst->errors = 0;
   1125 		}
   1126 		idx++;
   1127 		dst = next;
   1128 	}
   1129 }
   1130 
   1131 #endif /* CONFIG_NATIVE_WINDOWS */
   1132