aboutsummaryrefslogtreecommitdiffstats
path: root/hostapd/ctrl_iface.c
diff options
context:
space:
mode:
authorAnton Nayshtut <qca_antonn@qca.qualcomm.com>2014-11-16 14:52:49 (GMT)
committerJouni Malinen <j@w1.fi>2015-07-16 09:33:29 (GMT)
commitee1e3f57b58498882adbfa75633b0931000f5264 (patch)
tree7d46e8284628f2390257fc52df095f7b65ec8707 /hostapd/ctrl_iface.c
parentcb05808c46539922cf02e9e8527a062e90637ff9 (diff)
downloadhostap-ee1e3f57b58498882adbfa75633b0931000f5264.zip
hostap-ee1e3f57b58498882adbfa75633b0931000f5264.tar.gz
hostap-ee1e3f57b58498882adbfa75633b0931000f5264.tar.bz2
hostapd: Global control interface notifications
This commit implements hostapd global control interface notifications infrastructure. hostapd global control interface clients issue ATTACH/DETACH commands to register and deregister with hostapd correspondingly - the same way as for any other hostapd/wpa_supplicant control interface. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'hostapd/ctrl_iface.c')
-rw-r--r--hostapd/ctrl_iface.c118
1 files changed, 108 insertions, 10 deletions
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 16add37..aa4c912 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -58,6 +58,7 @@ struct wpa_ctrl_dst {
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ enum wpa_msg_type type,
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;
if (hapd == NULL)
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)
{
#ifdef CONFIG_WPS_TESTING
@@ -2470,8 +2523,9 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
- char reply[24];
+ char *reply;
int reply_len;
+ const int reply_size = 4096;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
@@ -2483,6 +2537,16 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
buf[res] = '\0';
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);
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) {
if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
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
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
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",
strerror(errno));
}
+ os_free(reply);
}
@@ -2659,6 +2732,7 @@ fail:
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
{
char *fname = NULL;
+ struct wpa_ctrl_dst *dst, *prev;
if (interfaces->global_ctrl_sock > -1) {
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
@@ -2683,13 +2757,23 @@ void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
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,
+ enum wpa_msg_type type,
const char *buf, size_t len)
{
struct wpa_ctrl_dst *dst, *next;
@@ -2697,9 +2781,17 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
int idx;
struct iovec io[2];
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;
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));
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
- if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
+ if (sendmsg(s, &msg, 0) < 0) {
int _errno = errno;
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
"%d - %s",
idx, errno, strerror(errno));
dst->errors++;
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
dst->errors = 0;