summaryrefslogtreecommitdiffstats
path: root/contrib/wpa_supplicant/wpa_ctrl.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2007-07-11 15:58:52 +0000
committersam <sam@FreeBSD.org>2007-07-11 15:58:52 +0000
commitf2e5f38ec4b02cb33d67218cb24312f6e522cf58 (patch)
tree2ac7b230023aef064f602608ca239d971e0e4ac3 /contrib/wpa_supplicant/wpa_ctrl.c
parent752f54d1e6282a9ab07c3c1b8873e85478e1b5d2 (diff)
downloadFreeBSD-src-f2e5f38ec4b02cb33d67218cb24312f6e522cf58.zip
FreeBSD-src-f2e5f38ec4b02cb33d67218cb24312f6e522cf58.tar.gz
resolve merge conflicts
Reviewed by: thompsa, sephe Approved by: re (hrs)
Diffstat (limited to 'contrib/wpa_supplicant/wpa_ctrl.c')
-rw-r--r--contrib/wpa_supplicant/wpa_ctrl.c295
1 files changed, 241 insertions, 54 deletions
diff --git a/contrib/wpa_supplicant/wpa_ctrl.c b/contrib/wpa_supplicant/wpa_ctrl.c
index e7a9a4f..8e621b0 100644
--- a/contrib/wpa_supplicant/wpa_ctrl.c
+++ b/contrib/wpa_supplicant/wpa_ctrl.c
@@ -1,6 +1,6 @@
/*
* wpa_supplicant/hostapd control interface library
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,22 +14,21 @@
* $FreeBSD$
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <sys/socket.h>
-#include <netinet/in.h>
+#include "includes.h"
+
+#ifdef CONFIG_CTRL_IFACE
+
+#ifdef CONFIG_CTRL_IFACE_UNIX
#include <sys/un.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#endif /* CONFIG_CTRL_IFACE_UNIX */
#include "wpa_ctrl.h"
-#ifdef CONFIG_NATIVE_WINDOWS
#include "common.h"
-#endif /* CONFIG_NATIVE_WINDOWS */
+
+
+#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
+#define CTRL_IFACE_SOCKET
+#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
/**
@@ -42,83 +41,121 @@
* the arguments for most of the control interface library functions.
*/
struct wpa_ctrl {
- int s;
#ifdef CONFIG_CTRL_IFACE_UDP
+ int s;
struct sockaddr_in local;
struct sockaddr_in dest;
-#else /* CONFIG_CTRL_IFACE_UDP */
+ char *cookie;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+#ifdef CONFIG_CTRL_IFACE_UNIX
+ int s;
struct sockaddr_un local;
struct sockaddr_un dest;
-#endif /* CONFIG_CTRL_IFACE_UDP */
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+ HANDLE pipe;
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
};
+#ifdef CONFIG_CTRL_IFACE_UNIX
+
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
struct wpa_ctrl *ctrl;
-#ifndef CONFIG_CTRL_IFACE_UDP
static int counter = 0;
-#endif /* CONFIG_CTRL_IFACE_UDP */
- ctrl = malloc(sizeof(*ctrl));
+ ctrl = os_malloc(sizeof(*ctrl));
if (ctrl == NULL)
return NULL;
- memset(ctrl, 0, sizeof(*ctrl));
+ os_memset(ctrl, 0, sizeof(*ctrl));
-#ifdef CONFIG_CTRL_IFACE_UDP
- ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
+ ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (ctrl->s < 0) {
- perror("socket");
- free(ctrl);
+ os_free(ctrl);
return NULL;
}
- ctrl->local.sin_family = AF_INET;
- ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
+ ctrl->local.sun_family = AF_UNIX;
+ os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
+ "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
- sizeof(ctrl->local)) < 0) {
+ sizeof(ctrl->local)) < 0) {
close(ctrl->s);
- free(ctrl);
+ os_free(ctrl);
return NULL;
}
- ctrl->dest.sin_family = AF_INET;
- ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
- ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
+ ctrl->dest.sun_family = AF_UNIX;
+ os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s",
+ ctrl_path);
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
- perror("connect");
close(ctrl->s);
- free(ctrl);
+ unlink(ctrl->local.sun_path);
+ os_free(ctrl);
return NULL;
}
-#else /* CONFIG_CTRL_IFACE_UDP */
- ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
+
+ return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+ unlink(ctrl->local.sun_path);
+ close(ctrl->s);
+ os_free(ctrl);
+}
+
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+ struct wpa_ctrl *ctrl;
+ char buf[128];
+ size_t len;
+
+ ctrl = os_malloc(sizeof(*ctrl));
+ if (ctrl == NULL)
+ return NULL;
+ os_memset(ctrl, 0, sizeof(*ctrl));
+
+ ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
if (ctrl->s < 0) {
- free(ctrl);
+ perror("socket");
+ os_free(ctrl);
return NULL;
}
- ctrl->local.sun_family = AF_UNIX;
- snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path) - 1,
- "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
+ ctrl->local.sin_family = AF_INET;
+ ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
- sizeof(ctrl->local)) < 0) {
+ sizeof(ctrl->local)) < 0) {
close(ctrl->s);
- free(ctrl);
+ os_free(ctrl);
return NULL;
}
- ctrl->dest.sun_family = AF_UNIX;
- strncpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path) - 1);
+ ctrl->dest.sin_family = AF_INET;
+ ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
+ ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
+ perror("connect");
close(ctrl->s);
- unlink(ctrl->local.sun_path);
- free(ctrl);
+ os_free(ctrl);
return NULL;
}
-#endif /* CONFIG_CTRL_IFACE_UDP */
+
+ len = sizeof(buf) - 1;
+ if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
+ buf[len] = '\0';
+ ctrl->cookie = strdup(buf);
+ }
return ctrl;
}
@@ -126,14 +163,15 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
-#ifndef CONFIG_CTRL_IFACE_UDP
- unlink(ctrl->local.sun_path);
-#endif /* CONFIG_CTRL_IFACE_UDP */
close(ctrl->s);
- free(ctrl);
+ os_free(ctrl->cookie);
+ os_free(ctrl);
}
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+#ifdef CTRL_IFACE_SOCKET
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len))
@@ -141,9 +179,35 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
struct timeval tv;
int res;
fd_set rfds;
+ const char *_cmd;
+ char *cmd_buf = NULL;
+ size_t _cmd_len;
- if (send(ctrl->s, cmd, cmd_len, 0) < 0)
+#ifdef CONFIG_CTRL_IFACE_UDP
+ if (ctrl->cookie) {
+ char *pos;
+ _cmd_len = strlen(ctrl->cookie) + 1 + cmd_len;
+ cmd_buf = os_malloc(_cmd_len );
+ if (cmd_buf == NULL)
+ return -1;
+ _cmd = cmd_buf;
+ pos = cmd_buf;
+ strcpy(pos, ctrl->cookie);
+ pos += strlen(ctrl->cookie);
+ *pos++ = ' ';
+ memcpy(pos, cmd, cmd_len);
+ } else
+#endif /* CONFIG_CTRL_IFACE_UDP */
+ {
+ _cmd = cmd;
+ _cmd_len = cmd_len;
+ }
+
+ if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
+ os_free(cmd_buf);
return -1;
+ }
+ os_free(cmd_buf);
for (;;) {
tv.tv_sec = 2;
@@ -178,6 +242,7 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
}
return 0;
}
+#endif /* CTRL_IFACE_SOCKET */
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
@@ -190,7 +255,7 @@ static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
buf, &len, NULL);
if (ret < 0)
return ret;
- if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
+ if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
return 0;
return -1;
}
@@ -208,6 +273,8 @@ int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
}
+#ifdef CTRL_IFACE_SOCKET
+
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
{
int res;
@@ -223,13 +290,12 @@ int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
{
struct timeval tv;
- int res;
fd_set rfds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
- res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+ select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
return FD_ISSET(ctrl->s, &rfds);
}
@@ -238,3 +304,124 @@ int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
{
return ctrl->s;
}
+
+#endif /* CTRL_IFACE_SOCKET */
+
+
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+
+#ifndef WPA_SUPPLICANT_NAMED_PIPE
+#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
+#endif
+#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+ struct wpa_ctrl *ctrl;
+ DWORD mode;
+ TCHAR name[256];
+ int i;
+
+ ctrl = os_malloc(sizeof(*ctrl));
+ if (ctrl == NULL)
+ return NULL;
+ os_memset(ctrl, 0, sizeof(*ctrl));
+
+#ifdef UNICODE
+ if (ctrl_path == NULL)
+ _snwprintf(name, 256, NAMED_PIPE_PREFIX);
+ else
+ _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
+ ctrl_path);
+#else /* UNICODE */
+ if (ctrl_path == NULL)
+ os_snprintf(name, 256, NAMED_PIPE_PREFIX);
+ else
+ os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
+ ctrl_path);
+#endif /* UNICODE */
+
+ for (i = 0; i < 10; i++) {
+ ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
+ NULL, OPEN_EXISTING, 0, NULL);
+ /*
+ * Current named pipe server side in wpa_supplicant is
+ * re-opening the pipe for new clients only after the previous
+ * one is taken into use. This leaves a small window for race
+ * conditions when two connections are being opened at almost
+ * the same time. Retry if that was the case.
+ */
+ if (ctrl->pipe != INVALID_HANDLE_VALUE ||
+ GetLastError() != ERROR_PIPE_BUSY)
+ break;
+ WaitNamedPipe(name, 1000);
+ }
+ if (ctrl->pipe == INVALID_HANDLE_VALUE) {
+ os_free(ctrl);
+ return NULL;
+ }
+
+ mode = PIPE_READMODE_MESSAGE;
+ if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
+ CloseHandle(ctrl->pipe);
+ os_free(ctrl);
+ return NULL;
+ }
+
+ return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+ CloseHandle(ctrl->pipe);
+ os_free(ctrl);
+}
+
+
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len,
+ void (*msg_cb)(char *msg, size_t len))
+{
+ DWORD written;
+ DWORD readlen = *reply_len;
+
+ if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
+ return -1;
+
+ if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
+ return -1;
+ *reply_len = readlen;
+
+ return 0;
+}
+
+
+int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
+{
+ DWORD len = *reply_len;
+ if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
+ return -1;
+ *reply_len = len;
+ return 0;
+}
+
+
+int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
+{
+ DWORD left;
+
+ if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
+ return -1;
+ return left ? 1 : 0;
+}
+
+
+int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
+{
+ return -1;
+}
+
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+
+#endif /* CONFIG_CTRL_IFACE */
OpenPOWER on IntegriCloud