New config option could be set:
CONFIG_CTRL_IFACE=udp
CONFIG_CTRL_IFACE=udp-remote
CONFIG_CTRL_IFACE=udp6
CONFIG_CTRL_IFACE=udp6-remote
And cli usage:
hostapd_cli -i localhost:8877
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@xxxxxxxxx>
---
hostapd/Makefile | 23 +++-
hostapd/ctrl_iface.c | 294
++++++++++++++++++++++++++++++++++++++++++++++++--
hostapd/hostapd_cli.c | 5 +
src/ap/hostapd.c | 1 +
4 files changed, 311 insertions(+), 12 deletions(-)
diff --git a/hostapd/Makefile b/hostapd/Makefile
index ab0d8f6..9cb1eca 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -201,12 +201,33 @@ endif
ifdef CONFIG_NO_CTRL_IFACE
CFLAGS += -DCONFIG_NO_CTRL_IFACE
else
+ifeq ($(CONFIG_CTRL_IFACE), udp)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp6)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp-remote)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp6-remote)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6
+else
+CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
+endif
+endif
+endif
+endif
OBJS += ../src/common/ctrl_iface_common.o
OBJS += ctrl_iface.o
OBJS += ../src/ap/ctrl_iface_ap.o
endif
-CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
+CFLAGS += -DCONFIG_CTRL_IFACE
ifdef CONFIG_IAPP
CFLAGS += -DCONFIG_IAPP
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 3f2867c..d5fc54d 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -19,6 +19,10 @@
#include <sys/stat.h>
#include <stddef.h>
+#ifdef CONFIG_CTRL_IFACE_UDP
+#include <netdb.h>
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/version.h"
@@ -52,6 +56,15 @@
#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
+#ifdef CONFIG_CTRL_IFACE_UDP
+#define COOKIE_LEN 8
+static unsigned char cookie[COOKIE_LEN];
+static unsigned char gcookie[COOKIE_LEN];
+#define HOSTAPD_CTRL_IFACE_PORT 8877
+#define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50
+#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878
+#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT 50
+#endif /* CONFIG_CTRL_IFACE_UDP */
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
enum wpa_msg_type type,
@@ -2237,10 +2250,13 @@ static void hostapd_ctrl_iface_receive(int sock,
void *eloop_ctx,
int res;
struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
- char *reply;
+ char *reply, *pos = buf;
const int reply_size = 4096;
int reply_len;
int level = MSG_DEBUG;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ unsigned char lcookie[COOKIE_LEN];
+#endif
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
@@ -2250,8 +2266,6 @@ static void hostapd_ctrl_iface_receive(int sock,
void *eloop_ctx,
return;
}
buf[res] = '\0';
- if (os_strcmp(buf, "PING") == 0)
- level = MSG_EXCESSIVE;
wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
reply = os_malloc(reply_size);
@@ -2264,10 +2278,50 @@ static void hostapd_ctrl_iface_receive(int sock,
void *eloop_ctx,
return;
}
- reply_len = hostapd_ctrl_iface_receive_process(hapd, buf,
+#ifdef CONFIG_CTRL_IFACE_UDP
+ if (os_strcmp(buf, "GET_COOKIE") == 0) {
+ os_memcpy(reply, "COOKIE=", 7);
+ wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
+ cookie, COOKIE_LEN);
+ reply_len = 7 + 2 * COOKIE_LEN;
+ goto done;
+ }
+
+ if (os_strncmp(buf, "COOKIE=", 7) != 0) {
+ wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
+ "drop request");
+ os_free(reply);
+ return;
+ }
+
+ if (hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+ wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the
"
+ "request - drop request");
+ os_free(reply);
+ return;
+ }
+
+ if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request
- "
+ "drop request");
+ os_free(reply);
+ return;
+ }
+
+ pos = buf + 7 + 2 * COOKIE_LEN;
+ while (*pos == ' ')
+ pos++;
+#endif
+ if (os_strcmp(pos, "PING") == 0)
+ level = MSG_EXCESSIVE;
+
+ reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
reply, reply_size,
&from, fromlen);
+#ifdef CONFIG_CTRL_IFACE_UDP
+done:
+#endif
if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen) < 0) {
wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
@@ -2276,7 +2330,7 @@ static void hostapd_ctrl_iface_receive(int sock,
void *eloop_ctx,
os_free(reply);
}
-
+#ifndef CONFIG_CTRL_IFACE_UDP
static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
{
char *buf;
@@ -2296,7 +2350,7 @@ static char * hostapd_ctrl_iface_path(struct
hostapd_data *hapd)
buf[len - 1] = '\0';
return buf;
}
-
+#endif /* CONFIG_CTRL_IFACE_UDP */
static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
enum wpa_msg_type type,
@@ -2308,7 +2362,99 @@ static void hostapd_ctrl_iface_msg_cb(void *ctx,
int level,
hostapd_ctrl_iface_send(hapd, level, type, txt, len);
}
+#ifdef CONFIG_CTRL_IFACE_UDP
+int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
+{
+ int port = HOSTAPD_CTRL_IFACE_PORT;
+ char p[32]={0};
+ struct addrinfo hints = { 0 }, *res, *saveres;
+ int n;
+
+ if (hapd->ctrl_sock > -1) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
+ return 0;
+ }
+
+ if (hapd->conf->ctrl_interface == NULL)
+ return 0;
+
+ dl_list_init(&hapd->ctrl_dst);
+ hapd->ctrl_sock = -1;
+ os_get_random(cookie, COOKIE_LEN);
+
+#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
+ hints.ai_flags = AI_PASSIVE;
+#endif
+
+#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
+ hints.ai_family = AF_INET6;
+#else
+ hints.ai_family = AF_INET;
+#endif
+ hints.ai_socktype = SOCK_DGRAM;
+
+try_again:
+ os_snprintf(p, sizeof(p), "%d", port);
+ n = getaddrinfo(NULL, p, &hints, &res);
+ if (n) {
+ wpa_printf(MSG_ERROR, "getaddrinfo(): %s",
gai_strerror(n));
+ goto fail;
+ }
+
+ saveres = res;
+ hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
+ if (hapd->ctrl_sock < 0) {
+ wpa_printf(MSG_ERROR, "socket(PF_INET): %s",
strerror(errno));
+ goto fail;
+ }
+
+ if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
+ port--;
+ if ((HOSTAPD_CTRL_IFACE_PORT - port) <
HOSTAPD_CTRL_IFACE_PORT_LIMIT)
+ goto try_again;
+ wpa_printf(MSG_ERROR, "bind(AF_INET): %s",
strerror(errno));
+ goto fail;
+ }
+
+ freeaddrinfo(saveres);
+
+ wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
+
+ if (eloop_register_read_sock(hapd->ctrl_sock,
hostapd_ctrl_iface_receive, hapd, NULL) < 0) {
+ hostapd_ctrl_iface_deinit(hapd);
+ return -1;
+ }
+
+ hapd->msg_ctx = hapd;
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
+ return 0;
+
+fail:
+ if (hapd->ctrl_sock >= 0)
+ close(hapd->ctrl_sock);
+ return -1;
+}
+
+void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
+{
+ struct wpa_ctrl_dst *dst, *prev;
+
+ if (hapd->ctrl_sock >= 0) {
+ eloop_unregister_read_sock(hapd->ctrl_sock);
+ close(hapd->ctrl_sock);
+ hapd->ctrl_sock = -1;
+ }
+
+ dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct
wpa_ctrl_dst, list)
+ os_free(dst);
+#ifdef CONFIG_TESTING_OPTIONS
+ l2_packet_deinit(hapd->l2_test);
+ hapd->l2_test = NULL;
+#endif /* CONFIG_TESTING_OPTIONS */
+}
+#else
int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
{
struct sockaddr_un addr;
@@ -2500,7 +2646,7 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data
*hapd)
hapd->l2_test = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
}
-
+#endif /* CONFIG_CTRL_UDP */
static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
char *buf)
@@ -2762,15 +2908,18 @@ static void hostapd_global_ctrl_iface_receive(int
sock, void *eloop_ctx,
void *sock_ctx)
{
void *interfaces = eloop_ctx;
- char buf[256];
+ char buffer[256], *buf = buffer;
int res;
struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
char *reply;
int reply_len;
const int reply_size = 4096;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ unsigned char lcookie[COOKIE_LEN];
+#endif
- res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
@@ -2793,6 +2942,41 @@ static void hostapd_global_ctrl_iface_receive(int
sock, void *eloop_ctx,
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ if (os_strcmp(buf, "GET_COOKIE") == 0) {
+ os_memcpy(reply, "COOKIE=", 7);
+ wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
+ gcookie, COOKIE_LEN);
+ reply_len = 7 + 2 * COOKIE_LEN;
+ goto send_reply;
+ }
+
+ if (os_strncmp(buf, "COOKIE=", 7) != 0) {
+ wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
+ "drop request");
+ os_free(reply);
+ return;
+ }
+
+ if (hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+ wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the
"
+ "request - drop request");
+ os_free(reply);
+ return;
+ }
+
+ if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request
- "
+ "drop request");
+ os_free(reply);
+ return;
+ }
+
+ buf = buf + 7 + 2 * COOKIE_LEN;
+ while (*buf == ' ')
+ buf++;
+#endif
+
if (os_strncmp(buf, "IFNAME=", 7) == 0) {
char *pos = os_strchr(buf + 7, ' ');
@@ -2873,7 +3057,7 @@ send_reply:
os_free(reply);
}
-
+#ifndef CONFIG_CTRL_IFACE_UDP
static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces
*interface)
{
char *buf;
@@ -2893,8 +3077,96 @@ static char * hostapd_global_ctrl_iface_path(struct
hapd_interfaces *interface)
buf[len - 1] = '\0';
return buf;
}
+#endif
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
+{
+ int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
+ char p[32]={0};
+ struct addrinfo hints = { 0 }, *res, *saveres;
+ int n;
+
+ if (interface->global_ctrl_sock > -1) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
+ return 0;
+ }
+
+ if (interface->global_iface_path == NULL)
+ return 0;
+
+ dl_list_init(&interface->global_ctrl_dst);
+ interface->global_ctrl_sock = -1;
+ os_get_random(gcookie, COOKIE_LEN);
+
+#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
+ hints.ai_flags = AI_PASSIVE;
+#endif
+
+#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
+ hints.ai_family = AF_INET6;
+#else
+ hints.ai_family = AF_INET;
+#endif
+ hints.ai_socktype = SOCK_DGRAM;
+
+try_again:
+ os_snprintf(p, sizeof(p), "%d", port);
+ n = getaddrinfo(NULL, p, &hints, &res);
+ if (n) {
+ wpa_printf(MSG_ERROR, "getaddrinfo(): %s",
gai_strerror(n));
+ goto fail;
+ }
+
+ saveres = res;
+ interface->global_ctrl_sock = socket(res->ai_family,
res->ai_socktype, res->ai_protocol);
+ if (interface->global_ctrl_sock < 0) {
+ wpa_printf(MSG_ERROR, "socket(PF_INET): %s",
strerror(errno));
+ goto fail;
+ }
+
+ if (bind(interface->global_ctrl_sock, res->ai_addr,
res->ai_addrlen) < 0) {
+ port++;
+ if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT)
+ goto try_again;
+ wpa_printf(MSG_ERROR, "bind(AF_INET): %s",
strerror(errno));
+ goto fail;
+ }
+
+ freeaddrinfo(saveres);
+
+ wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d",
port);
+
+ if (eloop_register_read_sock(interface->global_ctrl_sock,
hostapd_global_ctrl_iface_receive, interface, NULL) < 0) {
+ hostapd_global_ctrl_iface_deinit(interface);
+ return -1;
+ }
+
+ return 0;
+
+fail:
+ if (interface->global_ctrl_sock >= 0)
+ close(interface->global_ctrl_sock);
+ return -1;
+}
+void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface)
+{
+ struct wpa_ctrl_dst *dst, *prev;
+
+ if (interface->global_ctrl_sock > 0) {
+ eloop_unregister_read_sock(interface->global_ctrl_sock);
+ close(interface->global_ctrl_sock);
+ interface->global_ctrl_sock = -1;
+ }
+ os_free(interface->global_iface_path);
+ interface->global_iface_path = NULL;
+
+ dl_list_for_each_safe(dst, prev, &interface->global_ctrl_dst,
struct wpa_ctrl_dst, list)
+ os_free(dst);
+}
+#else
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
{
struct sockaddr_un addr;
@@ -3041,7 +3313,7 @@ void hostapd_global_ctrl_iface_deinit(struct
hapd_interfaces *interfaces)
dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
struct wpa_ctrl_dst, list)
os_free(dst);
}
-
+#endif
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
enum wpa_msg_type type,
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 52dfc9f..d227f29 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -142,6 +142,11 @@ static struct wpa_ctrl *
hostapd_cli_open_connection(const char *ifname)
if (ifname == NULL)
return NULL;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ ctrl_conn = wpa_ctrl_open(ifname);
+ return ctrl_conn;
+#endif
+
flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
cfile = malloc(flen);
if (cfile == NULL)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index b10b454..1b16c06 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1855,6 +1855,7 @@ hostapd_alloc_bss_data(struct hostapd_iface
*hapd_iface,
hapd->iface = hapd_iface;
hapd->driver = hapd->iconf->driver;
hapd->ctrl_sock = -1;
+ dl_list_init(&hapd->ctrl_dst);
return hapd;
}