|
@@ -58,6 +58,7 @@ struct wpa_ctrl_dst {
|
|
|
|
|
|
|
|
|
|
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
|
|
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
|
|
|
|
+ enum wpa_msg_type type,
|
|
const char *buf, size_t len);
|
|
const char *buf, size_t len);
|
|
|
|
|
|
|
|
|
|
@@ -2229,7 +2230,7 @@ static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
|
|
struct hostapd_data *hapd = ctx;
|
|
struct hostapd_data *hapd = ctx;
|
|
if (hapd == NULL)
|
|
if (hapd == NULL)
|
|
return;
|
|
return;
|
|
- hostapd_ctrl_iface_send(hapd, level, txt, len);
|
|
|
|
|
|
+ hostapd_ctrl_iface_send(hapd, level, type, txt, len);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2452,6 +2453,58 @@ static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
|
|
|
|
+ struct sockaddr_un *from,
|
|
|
|
+ socklen_t fromlen)
|
|
|
|
+{
|
|
|
|
+ struct wpa_ctrl_dst *dst;
|
|
|
|
+
|
|
|
|
+ dst = os_zalloc(sizeof(*dst));
|
|
|
|
+ if (dst == NULL)
|
|
|
|
+ return -1;
|
|
|
|
+ os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
|
|
|
|
+ dst->addrlen = fromlen;
|
|
|
|
+ dst->debug_level = MSG_INFO;
|
|
|
|
+ dst->next = interfaces->global_ctrl_dst;
|
|
|
|
+ interfaces->global_ctrl_dst = dst;
|
|
|
|
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached (global)",
|
|
|
|
+ from->sun_path,
|
|
|
|
+ fromlen - offsetof(struct sockaddr_un, sun_path));
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
|
|
|
|
+ struct sockaddr_un *from,
|
|
|
|
+ socklen_t fromlen)
|
|
|
|
+{
|
|
|
|
+ struct wpa_ctrl_dst *dst, *prev = NULL;
|
|
|
|
+
|
|
|
|
+ dst = interfaces->global_ctrl_dst;
|
|
|
|
+ while (dst) {
|
|
|
|
+ if (fromlen == dst->addrlen &&
|
|
|
|
+ os_memcmp(from->sun_path, dst->addr.sun_path,
|
|
|
|
+ fromlen - offsetof(struct sockaddr_un, sun_path))
|
|
|
|
+ == 0) {
|
|
|
|
+ wpa_hexdump(MSG_DEBUG,
|
|
|
|
+ "CTRL_IFACE monitor detached (global)",
|
|
|
|
+ from->sun_path,
|
|
|
|
+ fromlen -
|
|
|
|
+ offsetof(struct sockaddr_un, sun_path));
|
|
|
|
+ if (prev == NULL)
|
|
|
|
+ interfaces->global_ctrl_dst = dst->next;
|
|
|
|
+ else
|
|
|
|
+ prev->next = dst->next;
|
|
|
|
+ os_free(dst);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ prev = dst;
|
|
|
|
+ dst = dst->next;
|
|
|
|
+ }
|
|
|
|
+ return -1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
|
|
static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
|
|
{
|
|
{
|
|
#ifdef CONFIG_WPS_TESTING
|
|
#ifdef CONFIG_WPS_TESTING
|
|
@@ -2470,8 +2523,9 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|
int res;
|
|
int res;
|
|
struct sockaddr_un from;
|
|
struct sockaddr_un from;
|
|
socklen_t fromlen = sizeof(from);
|
|
socklen_t fromlen = sizeof(from);
|
|
- char reply[24];
|
|
|
|
|
|
+ char *reply;
|
|
int reply_len;
|
|
int reply_len;
|
|
|
|
+ const int reply_size = 4096;
|
|
|
|
|
|
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
|
|
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
|
|
(struct sockaddr *) &from, &fromlen);
|
|
(struct sockaddr *) &from, &fromlen);
|
|
@@ -2483,6 +2537,16 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|
buf[res] = '\0';
|
|
buf[res] = '\0';
|
|
wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
|
|
wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
|
|
|
|
|
|
|
|
+ reply = os_malloc(reply_size);
|
|
|
|
+ if (reply == NULL) {
|
|
|
|
+ if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
|
|
|
|
+ fromlen) < 0) {
|
|
|
|
+ wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
|
|
|
|
+ strerror(errno));
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
os_memcpy(reply, "OK\n", 3);
|
|
os_memcpy(reply, "OK\n", 3);
|
|
reply_len = 3;
|
|
reply_len = 3;
|
|
|
|
|
|
@@ -2500,6 +2564,14 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|
} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
|
|
} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
|
|
if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
|
|
if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
|
|
reply_len = -1;
|
|
reply_len = -1;
|
|
|
|
+ } else if (os_strcmp(buf, "ATTACH") == 0) {
|
|
|
|
+ if (hostapd_global_ctrl_iface_attach(interfaces, &from,
|
|
|
|
+ fromlen))
|
|
|
|
+ reply_len = -1;
|
|
|
|
+ } else if (os_strcmp(buf, "DETACH") == 0) {
|
|
|
|
+ if (hostapd_global_ctrl_iface_detach(interfaces, &from,
|
|
|
|
+ fromlen))
|
|
|
|
+ reply_len = -1;
|
|
#ifdef CONFIG_MODULE_TESTS
|
|
#ifdef CONFIG_MODULE_TESTS
|
|
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
|
|
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
|
|
int hapd_module_tests(void);
|
|
int hapd_module_tests(void);
|
|
@@ -2522,6 +2594,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|
wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
|
|
wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
|
|
strerror(errno));
|
|
strerror(errno));
|
|
}
|
|
}
|
|
|
|
+ os_free(reply);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2659,6 +2732,7 @@ fail:
|
|
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
|
|
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
|
|
{
|
|
{
|
|
char *fname = NULL;
|
|
char *fname = NULL;
|
|
|
|
+ struct wpa_ctrl_dst *dst, *prev;
|
|
|
|
|
|
if (interfaces->global_ctrl_sock > -1) {
|
|
if (interfaces->global_ctrl_sock > -1) {
|
|
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
|
|
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
|
|
@@ -2683,13 +2757,23 @@ void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
|
|
strerror(errno));
|
|
strerror(errno));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- os_free(interfaces->global_iface_path);
|
|
|
|
- interfaces->global_iface_path = NULL;
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ os_free(interfaces->global_iface_path);
|
|
|
|
+ interfaces->global_iface_path = NULL;
|
|
|
|
+
|
|
|
|
+ dst = interfaces->global_ctrl_dst;
|
|
|
|
+ interfaces->global_ctrl_dst = NULL;
|
|
|
|
+ while (dst) {
|
|
|
|
+ prev = dst;
|
|
|
|
+ dst = dst->next;
|
|
|
|
+ os_free(prev);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
|
|
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
|
|
|
|
+ enum wpa_msg_type type,
|
|
const char *buf, size_t len)
|
|
const char *buf, size_t len)
|
|
{
|
|
{
|
|
struct wpa_ctrl_dst *dst, *next;
|
|
struct wpa_ctrl_dst *dst, *next;
|
|
@@ -2697,9 +2781,17 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
|
|
int idx;
|
|
int idx;
|
|
struct iovec io[2];
|
|
struct iovec io[2];
|
|
char levelstr[10];
|
|
char levelstr[10];
|
|
|
|
+ int s;
|
|
|
|
|
|
- dst = hapd->ctrl_dst;
|
|
|
|
- if (hapd->ctrl_sock < 0 || dst == NULL)
|
|
|
|
|
|
+ if (type != WPA_MSG_ONLY_GLOBAL) {
|
|
|
|
+ s = hapd->ctrl_sock;
|
|
|
|
+ dst = hapd->ctrl_dst;
|
|
|
|
+ } else {
|
|
|
|
+ s = hapd->iface->interfaces->global_ctrl_sock;
|
|
|
|
+ dst = hapd->iface->interfaces->global_ctrl_dst;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (s < 0 || dst == NULL)
|
|
return;
|
|
return;
|
|
|
|
|
|
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
|
|
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
|
|
@@ -2720,16 +2812,22 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
|
|
offsetof(struct sockaddr_un, sun_path));
|
|
offsetof(struct sockaddr_un, sun_path));
|
|
msg.msg_name = &dst->addr;
|
|
msg.msg_name = &dst->addr;
|
|
msg.msg_namelen = dst->addrlen;
|
|
msg.msg_namelen = dst->addrlen;
|
|
- if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
|
|
|
|
|
|
+ if (sendmsg(s, &msg, 0) < 0) {
|
|
int _errno = errno;
|
|
int _errno = errno;
|
|
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
|
|
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
|
|
"%d - %s",
|
|
"%d - %s",
|
|
idx, errno, strerror(errno));
|
|
idx, errno, strerror(errno));
|
|
dst->errors++;
|
|
dst->errors++;
|
|
if (dst->errors > 10 || _errno == ENOENT) {
|
|
if (dst->errors > 10 || _errno == ENOENT) {
|
|
- hostapd_ctrl_iface_detach(
|
|
|
|
- hapd, &dst->addr,
|
|
|
|
- dst->addrlen);
|
|
|
|
|
|
+ if (type != WPA_MSG_ONLY_GLOBAL)
|
|
|
|
+ hostapd_ctrl_iface_detach(
|
|
|
|
+ hapd, &dst->addr,
|
|
|
|
+ dst->addrlen);
|
|
|
|
+ else
|
|
|
|
+ hostapd_global_ctrl_iface_detach(
|
|
|
|
+ hapd->iface->interfaces,
|
|
|
|
+ &dst->addr,
|
|
|
|
+ dst->addrlen);
|
|
}
|
|
}
|
|
} else
|
|
} else
|
|
dst->errors = 0;
|
|
dst->errors = 0;
|