[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