[RFC 5/6] hostap: add UDP support for ctrl iface
Peter Oh
poh at codeaurora.org
Thu Jan 14 09:49:00 PST 2016
On 01/14/2016 05:19 AM, Janusz Dziedzic wrote:
> Add UDP support for ctrl interface.
can you add more details such as why we need it?
> 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 at tieto.com>
> ---
> 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;
> }
More information about the Hostap
mailing list