X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=hostapd%2Fctrl_iface.c;h=7f628f1456b5feaf463ed22aaeb8e1676d190fef;hb=3981cb3cb81641813b1f51292032f2225ccdd70b;hp=9e6505a77c5358274f269891726b548d064c7bba;hpb=46bdb83acdb9c2f1a031971e665b75fce6bcbe47;p=libeap.git diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 9e6505a..7f628f1 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1,6 +1,6 @@ /* * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004-2008, Jouni Malinen + * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,25 +12,31 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" #ifndef CONFIG_NATIVE_WINDOWS #include #include +#include -#include "hostapd.h" -#include "eloop.h" -#include "config.h" -#include "ieee802_1x.h" -#include "wpa.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "drivers/driver.h" #include "radius/radius_client.h" -#include "ieee802_11.h" +#include "ap/hostapd.h" +#include "ap/ap_config.h" +#include "ap/ieee802_1x.h" +#include "ap/wpa_auth.h" +#include "ap/ieee802_11.h" +#include "ap/sta_info.h" +#include "ap/accounting.h" +#include "ap/wps_hostapd.h" +#include "ap/ctrl_iface_ap.h" +#include "wps/wps_defs.h" +#include "wps/wps.h" #include "ctrl_iface.h" -#include "sta_info.h" -#include "accounting.h" -#include "wps_hostapd.h" -#include "driver.h" struct wpa_ctrl_dst { @@ -61,7 +67,8 @@ static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, dst->next = hapd->ctrl_dst; hapd->ctrl_dst = dst; wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", - (u8 *) from->sun_path, fromlen); + (u8 *) from->sun_path, + fromlen - offsetof(struct sockaddr_un, sun_path)); return 0; } @@ -75,15 +82,18 @@ static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, dst = hapd->ctrl_dst; while (dst) { if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, fromlen) == - 0) { + os_memcmp(from->sun_path, dst->addr.sun_path, + fromlen - offsetof(struct sockaddr_un, sun_path)) + == 0) { if (prev == NULL) hapd->ctrl_dst = dst->next; else prev->next = dst->next; os_free(dst); wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", - (u8 *) from->sun_path, fromlen); + (u8 *) from->sun_path, + fromlen - + offsetof(struct sockaddr_un, sun_path)); return 0; } prev = dst; @@ -105,10 +115,12 @@ static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, dst = hapd->ctrl_dst; while (dst) { if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, fromlen) == - 0) { + os_memcmp(from->sun_path, dst->addr.sun_path, + fromlen - offsetof(struct sockaddr_un, sun_path)) + == 0) { wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level", (u8 *) from->sun_path, fromlen); + "level", (u8 *) from->sun_path, fromlen - + offsetof(struct sockaddr_un, sun_path)); dst->debug_level = atoi(level); return 0; } @@ -119,111 +131,195 @@ static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, } -static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, - struct sta_info *sta, - char *buf, size_t buflen) +static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, + const char *txtaddr) { - int len, res, ret; + u8 addr[ETH_ALEN]; + struct sta_info *sta; - if (sta == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } + wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); - len = 0; - ret = os_snprintf(buf + len, buflen - len, MACSTR "\n", - MAC2STR(sta->addr)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len); - if (res >= 0) - len += res; - res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - - return len; -} + if (hwaddr_aton(txtaddr, addr)) + return -1; + sta = ap_get_sta(hapd, addr); + if (sta) + return 0; -static int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd, - char *buf, size_t buflen) -{ - return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen); + wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " + "notification", MAC2STR(addr)); + sta = ap_sta_add(hapd, addr); + if (sta == NULL) + return -1; + + hostapd_new_assoc_sta(hapd, sta, 0); + return 0; } -static int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, - const char *txtaddr, - char *buf, size_t buflen) +#ifdef CONFIG_P2P_MANAGER +static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, + u8 minor_reason_code, const u8 *addr) { - u8 addr[ETH_ALEN]; + struct ieee80211_mgmt *mgmt; int ret; + u8 *pos; - if (hwaddr_aton(txtaddr, addr)) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; + if (hapd->driver->send_frame == NULL) + return -1; + + mgmt = os_zalloc(sizeof(*mgmt) + 100); + if (mgmt == NULL) + return -1; + + wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor " + "reason code %u (stype=%u)", + MAC2STR(addr), minor_reason_code, stype); + + mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); + os_memcpy(mgmt->da, addr, ETH_ALEN); + os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); + if (stype == WLAN_FC_STYPE_DEAUTH) { + mgmt->u.deauth.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + pos = (u8 *) (&mgmt->u.deauth.reason_code + 1); + } else { + mgmt->u.disassoc.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1); } - return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr), - buf, buflen); + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4 + 3 + 1; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = P2P_OUI_TYPE; + + *pos++ = P2P_ATTR_MINOR_REASON_CODE; + WPA_PUT_LE16(pos, 1); + pos += 2; + *pos++ = minor_reason_code; + + ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt, + pos - (u8 *) mgmt, 1); + os_free(mgmt); + + return ret < 0 ? -1 : 0; } +#endif /* CONFIG_P2P_MANAGER */ -static int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, - const char *txtaddr, - char *buf, size_t buflen) +static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, + const char *txtaddr) { u8 addr[ETH_ALEN]; struct sta_info *sta; - int ret; + const char *pos; - if (hwaddr_aton(txtaddr, addr) || - (sta = ap_get_sta(hapd, addr)) == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); + wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + return -1; + + pos = os_strstr(txtaddr, " test="); + if (pos) { + struct ieee80211_mgmt mgmt; + int encrypt; + if (hapd->driver->send_frame == NULL) + return -1; + pos += 6; + encrypt = atoi(pos); + os_memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_DEAUTH); + os_memcpy(mgmt.da, addr, ETH_ALEN); + os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); + mgmt.u.deauth.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, + IEEE80211_HDRLEN + + sizeof(mgmt.u.deauth), + encrypt) < 0) + return -1; + return 0; + } + +#ifdef CONFIG_P2P_MANAGER + pos = os_strstr(txtaddr, " p2p="); + if (pos) { + return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH, + atoi(pos + 5), addr); + } +#endif /* CONFIG_P2P_MANAGER */ + + hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + sta = ap_get_sta(hapd, addr); + if (sta) + ap_sta_deauthenticate(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + + return 0; } -static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, - const char *txtaddr) +static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, + const char *txtaddr) { u8 addr[ETH_ALEN]; struct sta_info *sta; + const char *pos; - wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); + wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr); if (hwaddr_aton(txtaddr, addr)) return -1; - sta = ap_get_sta(hapd, addr); - if (sta) + pos = os_strstr(txtaddr, " test="); + if (pos) { + struct ieee80211_mgmt mgmt; + int encrypt; + if (hapd->driver->send_frame == NULL) + return -1; + pos += 6; + encrypt = atoi(pos); + os_memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_DISASSOC); + os_memcpy(mgmt.da, addr, ETH_ALEN); + os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); + mgmt.u.disassoc.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, + IEEE80211_HDRLEN + + sizeof(mgmt.u.deauth), + encrypt) < 0) + return -1; return 0; + } - wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " - "notification", MAC2STR(addr)); - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; +#ifdef CONFIG_P2P_MANAGER + pos = os_strstr(txtaddr, " p2p="); + if (pos) { + return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC, + atoi(pos + 5), addr); + } +#endif /* CONFIG_P2P_MANAGER */ + + hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + sta = ap_get_sta(hapd, addr); + if (sta) + ap_sta_disassociate(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); - hostapd_new_assoc_sta(hapd, sta, 0); return 0; } #ifdef CONFIG_IEEE80211W +#ifdef NEED_AP_MLME static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, const char *txtaddr) { @@ -232,14 +328,15 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); - if (hwaddr_aton(txtaddr, addr)) + if (hwaddr_aton(txtaddr, addr) || + os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) return -1; - os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); ieee802_11_send_sa_query_req(hapd, addr, trans_id); return 0; } +#endif /* NEED_AP_MLME */ #endif /* CONFIG_IEEE80211W */ @@ -247,16 +344,81 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) { char *pin = os_strchr(txt, ' '); + char *timeout_txt; + int timeout; + u8 addr_buf[ETH_ALEN], *addr = NULL; + char *pos; + if (pin == NULL) return -1; *pin++ = '\0'; - return hostapd_wps_add_pin(hapd, txt, pin); + + timeout_txt = os_strchr(pin, ' '); + if (timeout_txt) { + *timeout_txt++ = '\0'; + timeout = atoi(timeout_txt); + pos = os_strchr(timeout_txt, ' '); + if (pos) { + *pos++ = '\0'; + if (hwaddr_aton(pos, addr_buf) == 0) + addr = addr_buf; + } + } else + timeout = 0; + + return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); } +static int hostapd_ctrl_iface_wps_check_pin( + struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) +{ + char pin[9]; + size_t len; + char *pos; + int ret; + + wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", + (u8 *) cmd, os_strlen(cmd)); + for (pos = cmd, len = 0; *pos != '\0'; pos++) { + if (*pos < '0' || *pos > '9') + continue; + pin[len++] = *pos; + if (len == 9) { + wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); + return -1; + } + } + if (len != 4 && len != 8) { + wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); + return -1; + } + pin[len] = '\0'; + + if (len == 8) { + unsigned int pin_val; + pin_val = atoi(pin); + if (!wps_pin_valid(pin_val)) { + wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); + ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); + if (ret < 0 || (size_t) ret >= buflen) + return -1; + return ret; + } + } + + ret = os_snprintf(buf, buflen, "%s", pin); + if (ret < 0 || (size_t) ret >= buflen) + return -1; + + return ret; +} + + +#ifdef CONFIG_WPS_OOB static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt) { - char *path, *method; + char *path, *method, *name; path = os_strchr(txt, ' '); if (path == NULL) @@ -268,11 +430,109 @@ static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt) return -1; *method++ = '\0'; - return hostapd_wps_start_oob(hapd, txt, path, method); + name = os_strchr(method, ' '); + if (name != NULL) + *name++ = '\0'; + + return hostapd_wps_start_oob(hapd, txt, path, method, name); +} +#endif /* CONFIG_WPS_OOB */ + + +static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, + char *buf, size_t buflen) +{ + int timeout = 300; + char *pos; + const char *pin_txt; + + pos = os_strchr(txt, ' '); + if (pos) + *pos++ = '\0'; + + if (os_strcmp(txt, "disable") == 0) { + hostapd_wps_ap_pin_disable(hapd); + return os_snprintf(buf, buflen, "OK\n"); + } + + if (os_strcmp(txt, "random") == 0) { + if (pos) + timeout = atoi(pos); + pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); + if (pin_txt == NULL) + return -1; + return os_snprintf(buf, buflen, "%s", pin_txt); + } + + if (os_strcmp(txt, "get") == 0) { + pin_txt = hostapd_wps_ap_pin_get(hapd); + if (pin_txt == NULL) + return -1; + return os_snprintf(buf, buflen, "%s", pin_txt); + } + + if (os_strcmp(txt, "set") == 0) { + char *pin; + if (pos == NULL) + return -1; + pin = pos; + pos = os_strchr(pos, ' '); + if (pos) { + *pos++ = '\0'; + timeout = atoi(pos); + } + if (os_strlen(pin) > buflen) + return -1; + if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) + return -1; + return os_snprintf(buf, buflen, "%s", pin); + } + + return -1; } #endif /* CONFIG_WPS */ +static int hostapd_ctrl_iface_set(struct hostapd_data *wpa_s, char *cmd) +{ + char *value; + int ret = 0; + + value = os_strchr(cmd, ' '); + if (value == NULL) + return -1; + *value++ = '\0'; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); + if (0) { +#ifdef CONFIG_WPS_TESTING + } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { + long int val; + val = strtol(value, NULL, 0); + if (val < 0 || val > 0xff) { + ret = -1; + wpa_printf(MSG_DEBUG, "WPS: Invalid " + "wps_version_number %ld", val); + } else { + wps_version_number = val; + wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " + "version %u.%u", + (wps_version_number & 0xf0) >> 4, + wps_version_number & 0x0f); + } + } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { + wps_testing_dummy_cred = atoi(value); + wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", + wps_testing_dummy_cred); +#endif /* CONFIG_WPS_TESTING */ + } else { + ret = -1; + } + + return ret; +} + + static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx) { @@ -325,6 +585,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, else reply_len += res; } +#ifndef CONFIG_NO_RADIUS if (reply_len >= 0) { res = radius_client_get_mib(hapd->radius, reply + reply_len, @@ -334,6 +595,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, else reply_len += res; } +#endif /* CONFIG_NO_RADIUS */ } else if (os_strcmp(buf, "STA-FIRST") == 0) { reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, reply_size); @@ -356,22 +618,41 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) reply_len = -1; + } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { + if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) + reply_len = -1; + } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { + if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) + reply_len = -1; #ifdef CONFIG_IEEE80211W +#ifdef NEED_AP_MLME } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) reply_len = -1; +#endif /* NEED_AP_MLME */ #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) reply_len = -1; + } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { + reply_len = hostapd_ctrl_iface_wps_check_pin( + hapd, buf + 14, reply, reply_size); } else if (os_strcmp(buf, "WPS_PBC") == 0) { if (hostapd_wps_button_pushed(hapd)) reply_len = -1; +#ifdef CONFIG_WPS_OOB } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8)) reply_len = -1; +#endif /* CONFIG_WPS_OOB */ + } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { + reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, + reply, reply_size); #endif /* CONFIG_WPS */ + } else if (os_strncmp(buf, "SET ", 4) == 0) { + if (hostapd_ctrl_iface_set(hapd, buf + 4)) + reply_len = -1; } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; @@ -456,14 +737,44 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd) } os_memset(&addr, 0, sizeof(addr)); +#ifdef __FreeBSD__ + addr.sun_len = sizeof(addr); +#endif /* __FreeBSD__ */ addr.sun_family = AF_UNIX; fname = hostapd_ctrl_iface_path(hapd); if (fname == NULL) goto fail; os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - goto fail; + wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", + strerror(errno)); + if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" + " allow connections - assuming it was left" + "over from forced program termination"); + if (unlink(fname) < 0) { + perror("unlink[ctrl_iface]"); + wpa_printf(MSG_ERROR, "Could not unlink " + "existing ctrl_iface socket '%s'", + fname); + goto fail; + } + if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < + 0) { + perror("bind(PF_UNIX)"); + goto fail; + } + wpa_printf(MSG_DEBUG, "Successfully replaced leftover " + "ctrl_iface socket '%s'", fname); + } else { + wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " + "be in use - cannot override it"); + wpa_printf(MSG_INFO, "Delete '%s' manually if it is " + "not used anymore", fname); + os_free(fname); + fname = NULL; + goto fail; + } } if (hapd->conf->ctrl_interface_gid_set && @@ -481,6 +792,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd) hapd->ctrl_sock = s; eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, NULL); + hapd->msg_ctx = hapd; wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); return 0; @@ -558,15 +870,17 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, next = dst->next; if (level >= dst->debug_level) { wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", - (u8 *) dst->addr.sun_path, dst->addrlen); + (u8 *) dst->addr.sun_path, dst->addrlen - + offsetof(struct sockaddr_un, sun_path)); msg.msg_name = &dst->addr; msg.msg_namelen = dst->addrlen; if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { - fprintf(stderr, "CTRL_IFACE monitor[%d]: ", - idx); - perror("sendmsg"); + int _errno = errno; + wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " + "%d - %s", + idx, errno, strerror(errno)); dst->errors++; - if (dst->errors > 10) { + if (dst->errors > 10 || _errno == ENOENT) { hostapd_ctrl_iface_detach( hapd, &dst->addr, dst->addrlen);