summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils/compat
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2015-04-11 22:03:59 +0200
committerYves-Alexis Perez <corsac@debian.org>2015-04-11 22:03:59 +0200
commit83b8aebb19fe6e49e13a05d4e8f5ab9a06177642 (patch)
tree51255545ba43b84aa5d673bd0eb557cbd0155c9e /src/libstrongswan/utils/compat
parent2b8de74ff4c334c25e89988c4a401b24b5bcf03d (diff)
downloadvyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.tar.gz
vyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.zip
Imported Upstream version 5.3.0
Diffstat (limited to 'src/libstrongswan/utils/compat')
-rw-r--r--src/libstrongswan/utils/compat/apple.h119
-rw-r--r--src/libstrongswan/utils/compat/windows.c684
-rw-r--r--src/libstrongswan/utils/compat/windows.h627
3 files changed, 1430 insertions, 0 deletions
diff --git a/src/libstrongswan/utils/compat/apple.h b/src/libstrongswan/utils/compat/apple.h
new file mode 100644
index 000000000..61afb9d9e
--- /dev/null
+++ b/src/libstrongswan/utils/compat/apple.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup apple apple
+ * @{ @ingroup compat
+ */
+
+#ifndef APPLE_H_
+#define APPLE_H_
+
+#include <poll.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+
+/* thread_create is a syscall used to create Mach kernel threads and although
+ * there are no errors or warnings during compilation or linkage the dynamic
+ * linker does not use our implementation, therefore we rename it here
+ */
+#define thread_create(main, arg) strongswan_thread_create(main, arg)
+
+/* Mach uses a semaphore_create() call, use a different name for ours */
+#define semaphore_create(x) strongswan_semaphore_create(x)
+
+/* Since OS X 10.10 XPC includes some additional conflicting Mach types */
+#define host_t strongswan_host_t
+#define processor_t strongswan_processor_t
+#define task_t strongswan_task_t
+#define thread_t strongswan_thread_t
+
+/* forward declaration, see below */
+static inline int precancellable_poll(struct pollfd fds[], nfds_t nfds,
+ int timeout);
+
+/* on Mac OS X 10.5 several system calls we use are no cancellation points.
+ * fortunately, select isn't one of them, so we wrap some of the others with
+ * calls to select(2).
+ */
+
+#define WRAP_WITH_POLL(func, socket, ...) \
+ struct pollfd pfd = { \
+ .fd = socket, \
+ .events = POLLIN, \
+ }; \
+ if (precancellable_poll(&pfd, 1, -1) <= 0) \
+ {\
+ return -1; \
+ }\
+ return func(socket, __VA_ARGS__)
+
+static inline int cancellable_accept(int socket, struct sockaddr *address,
+ socklen_t *address_len)
+{
+ WRAP_WITH_POLL(accept, socket, address, address_len);
+}
+#define accept cancellable_accept
+static inline int cancellable_recvfrom(int socket, void *buffer, size_t length,
+ int flags, struct sockaddr *address, socklen_t *address_len)
+{
+ WRAP_WITH_POLL(recvfrom, socket, buffer, length, flags, address, address_len);
+}
+#define recvfrom cancellable_recvfrom
+
+#include <threading/thread.h>
+
+/*
+ * While select() is a cancellation point, it seems that OS X does not honor
+ * pending cancellation points when entering the function. We manually test for
+ * and honor pending cancellation requests, but this obviously can't prevent
+ * some race conditions where the the cancellation happens after the check,
+ * but before the select.
+ */
+static inline int precancellable_select(int nfds, fd_set *restrict readfds,
+ fd_set *restrict writefds, fd_set *restrict errorfds,
+ struct timeval *restrict timeout)
+{
+ if (thread_cancelability(TRUE))
+ {
+ thread_cancellation_point();
+ }
+ else
+ {
+ thread_cancelability(FALSE);
+ }
+ return select(nfds, readfds, writefds, errorfds, timeout);
+}
+#define select precancellable_select
+
+/*
+ * The same as to select(2) applies to poll(2)
+ */
+static inline int precancellable_poll(struct pollfd fds[], nfds_t nfds,
+ int timeout)
+{
+ if (thread_cancelability(TRUE))
+ {
+ thread_cancellation_point();
+ }
+ else
+ {
+ thread_cancelability(FALSE);
+ }
+ return poll(fds, nfds, timeout);
+}
+#define poll precancellable_poll
+
+#endif /** APPLE_H_ @}*/
diff --git a/src/libstrongswan/utils/compat/windows.c b/src/libstrongswan/utils/compat/windows.c
new file mode 100644
index 000000000..1f22ffa02
--- /dev/null
+++ b/src/libstrongswan/utils/compat/windows.c
@@ -0,0 +1,684 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* WSAPoll() */
+#define _WIN32_WINNT 0x0600
+
+#include <utils/utils.h>
+
+#include <errno.h>
+
+/**
+ * See header
+ */
+void windows_init()
+{
+ WSADATA wsad;
+
+ /* initialize winsock2 */
+ WSAStartup(MAKEWORD(2, 2), &wsad);
+}
+
+/**
+ * See header
+ */
+void windows_deinit()
+{
+ WSACleanup();
+}
+
+/**
+ * See header
+ */
+int usleep(useconds_t usec)
+{
+ if (usec > 0 && usec < 1000)
+ { /* do not Sleep(0) for small values */
+ usec = 1000;
+ }
+ SleepEx(usec / 1000, TRUE);
+ return 0;
+}
+
+/**
+ * See header.
+ */
+char* strndup(const char *s, size_t n)
+{
+ char *dst;
+
+ n = min(strnlen(s, n), n);
+ dst = malloc(n + 1);
+ memcpy(dst, s, n);
+ dst[n] = '\0';
+
+ return dst;
+}
+
+/*
+ * See header.
+ */
+void *dlopen(const char *filename, int flag)
+{
+ return LoadLibrary(filename);
+}
+
+/**
+ * Load a symbol from known default libs (monolithic build)
+ */
+static void* dlsym_default(const char *name)
+{
+ const char *dlls[] = {
+ "libstrongswan-0.dll",
+ "libhydra-0.dll",
+ "libcharon-0.dll",
+ "libtnccs-0.dll",
+ NULL /* .exe */
+ };
+ HANDLE handle;
+ void *sym = NULL;
+ int i;
+
+ for (i = 0; i < countof(dlls); i++)
+ {
+ handle = GetModuleHandle(dlls[i]);
+ if (handle)
+ {
+ sym = GetProcAddress(handle, name);
+ if (sym)
+ {
+ break;
+ }
+ }
+ }
+ return sym;
+}
+
+/**
+ * Emulate RTLD_NEXT for some known symbols
+ */
+static void* dlsym_next(const char *name)
+{
+ struct {
+ const char *dll;
+ const char *syms[4];
+ } dlls[] = {
+ /* for leak detective */
+ { "msvcrt",
+ { "malloc", "calloc", "realloc", "free" }
+ },
+ };
+ HANDLE handle = NULL;
+ int i, j;
+
+ for (i = 0; i < countof(dlls); i++)
+ {
+ for (j = 0; j < countof(dlls[0].syms); j++)
+ {
+ if (dlls[i].syms[j] && streq(dlls[i].syms[j], name))
+ {
+ handle = GetModuleHandle(dlls[i].dll);
+ break;
+ }
+ }
+ }
+ if (handle)
+ {
+ return GetProcAddress(handle, name);
+ }
+ return handle;
+}
+
+/**
+ * See header.
+ */
+void* dlsym(void *handle, const char *symbol)
+{
+ if (handle == RTLD_DEFAULT)
+ {
+ return dlsym_default(symbol);
+ }
+ if (handle == RTLD_NEXT)
+ {
+ return dlsym_next(symbol);
+ }
+ return GetProcAddress((HMODULE)handle, symbol);
+}
+
+/**
+ * See header.
+ */
+char* dlerror(void)
+{
+ static char buf[128];
+ char *pos;
+ DWORD err;
+
+ err = GetLastError();
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, 0, buf, sizeof(buf), NULL) > 0)
+ {
+ pos = strchr(buf, '\n');
+ if (pos)
+ {
+ *pos = '\0';
+ }
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), "(%u)", err);
+ }
+ return buf;
+}
+
+/**
+ * See header.
+ */
+int dlclose(void *handle)
+{
+ return FreeLibrary((HMODULE)handle);
+}
+
+/**
+ * See header
+ */
+int socketpair(int domain, int type, int protocol, int sv[2])
+{
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+ };
+ socklen_t len = sizeof(addr);
+ int s, c, sc;
+ BOOL on;
+
+ /* We don't check domain for AF_INET, as we use it as replacement for
+ * AF_UNIX. */
+ if (type != SOCK_STREAM)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (protocol != 0 && protocol != IPPROTO_TCP)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (s == -1)
+ {
+ return -1;
+ }
+ c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (c == -1)
+ {
+ closesocket(s);
+ return -1;
+ }
+ if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == 0 &&
+ getsockname(s,(struct sockaddr*)&addr, &len) == 0 &&
+ listen(s, 0) == 0 &&
+ connect(c, (struct sockaddr*)&addr, sizeof(addr)) == 0)
+ {
+ sc = accept(s, NULL, NULL);
+ if (sc >= 0)
+ {
+ closesocket(s);
+ s = sc;
+ if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
+ (void*)&on, sizeof(on)) == 0 &&
+ setsockopt(c, IPPROTO_TCP, TCP_NODELAY,
+ (void*)&on, sizeof(on)) == 0)
+ {
+ sv[0] = s;
+ sv[1] = c;
+ return 0;
+ }
+ }
+ }
+ closesocket(s);
+ closesocket(c);
+ return -1;
+}
+
+/**
+ * See header
+ */
+char* getpass(const char *prompt)
+{
+ static char buf[64] = "";
+ char *pos;
+ HANDLE in, out;
+ DWORD mode, written = 0, total, done;
+
+ out = GetStdHandle(STD_OUTPUT_HANDLE);
+ in = GetStdHandle(STD_INPUT_HANDLE);
+
+ if (out == INVALID_HANDLE_VALUE || in == INVALID_HANDLE_VALUE ||
+ !GetConsoleMode(out, &mode) || !GetConsoleMode(in, &mode))
+ {
+ return NULL;
+ }
+
+ total = strlen(prompt);
+ while (written < total)
+ {
+ if (!WriteConsole(out, prompt + written, total - written, &done, NULL))
+ {
+ return NULL;
+ }
+ written += done;
+ }
+
+ if (!SetConsoleMode(in, mode & ~ENABLE_ECHO_INPUT))
+ {
+ return NULL;
+ }
+
+ while (TRUE)
+ {
+ if (!ReadConsole(in, buf, sizeof(buf), &done, NULL))
+ {
+ SetConsoleMode(in, mode);
+ return NULL;
+ }
+ buf[sizeof(buf)-1] = '\0';
+
+ if (done)
+ {
+ pos = strchr(buf, '\r');
+ if (pos)
+ {
+ *pos = '\0';
+ }
+ break;
+ }
+ }
+ SetConsoleMode(in, mode);
+
+ /* append a newline, as we have no echo during input */
+ WriteConsole(out, "\r\n", 2, &done, NULL);
+
+ return buf;
+}
+
+/**
+ * See header.
+ */
+#undef strerror_s
+int strerror_s_extended(char *buf, size_t buflen, int errnum)
+{
+ const char *errstr [] = {
+ /* EADDRINUSE */ "Address in use",
+ /* EADDRNOTAVAIL */ "Address not available",
+ /* EAFNOSUPPORT */ "Address family not supported",
+ /* EALREADY */ "Connection already in progress",
+ /* EBADMSG */ "Bad message",
+ /* ECANCELED */ "Operation canceled",
+ /* ECONNABORTED */ "Connection aborted",
+ /* ECONNREFUSED */ "Connection refused",
+ /* ECONNRESET */ "Connection reset",
+ /* EDESTADDRREQ */ "Destination address required",
+ /* EHOSTUNREACH */ "Host is unreachable",
+ /* EIDRM */ "Identifier removed",
+ /* EINPROGRESS */ "Operation in progress",
+ /* EISCONN */ "Socket is connected",
+ /* ELOOP */ "Too many levels of symbolic links",
+ /* EMSGSIZE */ "Message too large",
+ /* ENETDOWN */ "Network is down",
+ /* ENETRESET */ "Connection aborted by network",
+ /* ENETUNREACH */ "Network unreachable",
+ /* ENOBUFS */ "No buffer space available",
+ /* ENODATA */ "No message is available",
+ /* ENOLINK */ "No link",
+ /* ENOMSG */ "No message of the desired type",
+ /* ENOPROTOOPT */ "Protocol not available",
+ /* ENOSR */ "No stream resources",
+ /* ENOSTR */ "Not a stream",
+ /* ENOTCONN */ "The socket is not connected",
+ /* ENOTRECOVERABLE */ "State not recoverable",
+ /* ENOTSOCK */ "Not a socket",
+ /* ENOTSUP */ "Not supported",
+ /* EOPNOTSUPP */ "Operation not supported on socket",
+ /* EOTHER */ "Other error",
+ /* EOVERFLOW */ "Value too large to be stored in data type",
+ /* EOWNERDEAD */ "Previous owner died",
+ /* EPROTO */ "Protocol error",
+ /* EPROTONOSUPPORT */ "Protocol not supported",
+ /* EPROTOTYPE */ "Protocol wrong type for socket",
+ /* ETIME */ "Timeout",
+ /* ETIMEDOUT */ "Connection timed out",
+ /* ETXTBSY */ "Text file busy",
+ /* EWOULDBLOCK */ "Operation would block",
+ };
+ int offset = EADDRINUSE;
+
+ if (errnum < offset || errnum >= offset + countof(errstr))
+ {
+ return strerror_s(buf, buflen, errnum);
+ }
+ strncpy(buf, errstr[errnum - offset], buflen);
+ buf[buflen - 1] = '\0';
+ return 0;
+}
+
+/**
+ * Set errno for a function setting WSA error on failure
+ */
+static int wserr(int retval)
+{
+ if (retval < 0)
+ {
+ static const struct {
+ DWORD wsa;
+ int err;
+ } map[] = {
+ { WSANOTINITIALISED, EBADF },
+ { WSAENETDOWN, ENETDOWN },
+ { WSAENETRESET, ENETRESET },
+ { WSAECONNABORTED, ECONNABORTED },
+ { WSAESHUTDOWN, ECONNABORTED },
+ { WSAEACCES, EACCES },
+ { WSAEINTR, EINTR },
+ { WSAEINPROGRESS, EINPROGRESS },
+ { WSAEFAULT, EFAULT },
+ { WSAENOBUFS, ENOBUFS },
+ { WSAENOTSOCK, ENOTSOCK },
+ { WSAEOPNOTSUPP, EOPNOTSUPP },
+ { WSAEWOULDBLOCK, EWOULDBLOCK },
+ { WSAEMSGSIZE, EMSGSIZE },
+ { WSAEINVAL, EINVAL },
+ { WSAENOTCONN, ENOTCONN },
+ { WSAEHOSTUNREACH, EHOSTUNREACH },
+ { WSAENETUNREACH, ENETUNREACH },
+ { WSAECONNABORTED, ECONNABORTED },
+ { WSAECONNRESET, ECONNRESET },
+ { WSAETIMEDOUT, ETIMEDOUT },
+ { WSAEMFILE, EMFILE },
+ { WSAEALREADY, EALREADY },
+ { WSAEDESTADDRREQ, EDESTADDRREQ },
+ { WSAEISCONN, EISCONN },
+ { WSAEOPNOTSUPP, EOPNOTSUPP },
+ { WSAEPROTOTYPE, EPROTOTYPE },
+ { WSAENOPROTOOPT, ENOPROTOOPT },
+ { WSAEPROTONOSUPPORT, EPROTONOSUPPORT },
+ { WSAEPFNOSUPPORT, EPROTONOSUPPORT },
+ { WSAEAFNOSUPPORT, EAFNOSUPPORT },
+ { WSAEADDRNOTAVAIL, EADDRNOTAVAIL },
+ { WSAEADDRINUSE, EADDRINUSE },
+ { WSAETIMEDOUT, ETIMEDOUT },
+ { WSAECONNREFUSED, ECONNREFUSED },
+ { WSAELOOP, ELOOP },
+ { WSAENAMETOOLONG, ENAMETOOLONG },
+ { WSAENOTEMPTY, ENOTEMPTY },
+ { WSAEPROTOTYPE, EPROTOTYPE },
+ { WSAVERNOTSUPPORTED, ENOTSUP },
+ };
+ DWORD wsa, i;
+
+ wsa = WSAGetLastError();
+ for (i = 0; i < countof(map); i++)
+ {
+ if (map[i].wsa == wsa)
+ {
+ errno = map[i].err;
+ return retval;
+ }
+ }
+ errno = ENOENT;
+ return retval;
+ }
+ errno = 0;
+ return retval;
+}
+
+/**
+ * Check and clear the dontwait flag
+ */
+static bool check_dontwait(int *flags)
+{
+ if (*flags & MSG_DONTWAIT)
+ {
+ *flags &= ~MSG_DONTWAIT;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * See header
+ */
+#undef shutdown
+int windows_shutdown(int sockfd, int how)
+{
+ return wserr(shutdown(sockfd, how));
+}
+
+/**
+ * See header
+ */
+#undef accept
+int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ return wserr(accept(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef bind
+int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ return wserr(bind(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef connect
+int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ return wserr(connect(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef getsockname
+int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ return wserr(getsockname(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef getsockopt
+int windows_getsockopt(int sockfd, int level, int optname,
+ void *optval, socklen_t *optlen)
+{
+ return wserr(getsockopt(sockfd, level, optname, optval, optlen));
+}
+
+/**
+ * See header
+ */
+#undef setsockopt
+int windows_setsockopt(int sockfd, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ return wserr(setsockopt(sockfd, level, optname, optval, optlen));
+}
+
+/**
+ * See header
+ */
+#undef socket
+int windows_socket(int domain, int type, int protocol)
+{
+ return wserr(socket(domain, type, protocol));
+}
+
+/**
+ * See header
+ */
+#undef select
+int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout)
+{
+ return wserr(select(nfds, readfds, writefds, exceptfds, timeout));
+}
+
+/**
+ * See header
+ */
+#undef close
+int windows_close(int fd)
+{
+ int ret;
+
+ ret = close(fd);
+ if (ret == -1 && errno == EBADF)
+ { /* Winsock socket? */
+ ret = wserr(closesocket(fd));
+ }
+ return ret;
+}
+
+/**
+ * See header
+ */
+#undef recv
+ssize_t windows_recv(int sockfd, void *buf, size_t len, int flags)
+{
+ u_long on = 1, off = 0;
+ ssize_t outlen = -1;
+
+ if (!check_dontwait(&flags))
+ {
+ return wserr(recv(sockfd, buf, len, flags));
+ }
+ if (wserr(ioctlsocket(sockfd, FIONBIO, &on) == 0))
+ {
+ outlen = wserr(recv(sockfd, buf, len, flags));
+ ioctlsocket(sockfd, FIONBIO, &off);
+ }
+ return outlen;
+}
+
+/**
+ * See header
+ */
+#undef recvfrom
+ssize_t windows_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen)
+{
+ u_long on = 1, off = 0;
+ ssize_t outlen = -1;
+
+ if (!check_dontwait(&flags))
+ {
+ return wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
+ }
+ if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
+ {
+ outlen = wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
+ ioctlsocket(sockfd, FIONBIO, &off);
+ }
+ return outlen;
+}
+
+/**
+ * See header
+ */
+#undef send
+ssize_t windows_send(int sockfd, const void *buf, size_t len, int flags)
+{
+ u_long on = 1, off = 0;
+ ssize_t outlen = -1;
+
+ if (!check_dontwait(&flags))
+ {
+ return wserr(send(sockfd, buf, len, flags));
+ }
+ if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
+ {
+ outlen = wserr(send(sockfd, buf, len, flags));
+ ioctlsocket(sockfd, FIONBIO, &off);
+ }
+ return outlen;
+}
+
+/**
+ * See header
+ */
+#undef sendto
+ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+ u_long on = 1, off = 0;
+ ssize_t outlen = -1;
+
+ if (!check_dontwait(&flags))
+ {
+ return wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
+ }
+ if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
+ {
+ outlen = wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
+ ioctlsocket(sockfd, FIONBIO, &off);
+ }
+ return outlen;
+}
+
+/**
+ * See header
+ */
+#undef read
+ssize_t windows_read(int fd, void *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = wserr(recv(fd, buf, count, 0));
+ if (ret == -1 && errno == ENOTSOCK)
+ {
+ ret = read(fd, buf, count);
+ }
+ return ret;
+}
+
+/**
+ * See header
+ */
+#undef write
+ssize_t windows_write(int fd, void *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = wserr(send(fd, buf, count, 0));
+ if (ret == -1 && errno == ENOTSOCK)
+ {
+ ret = write(fd, buf, count);
+ }
+ return ret;
+}
+
+/**
+ * See header
+ */
+int poll(struct pollfd *fds, int nfds, int timeout)
+{
+ return wserr(WSAPoll(fds, nfds, timeout));
+}
diff --git a/src/libstrongswan/utils/compat/windows.h b/src/libstrongswan/utils/compat/windows.h
new file mode 100644
index 000000000..fd4f1f196
--- /dev/null
+++ b/src/libstrongswan/utils/compat/windows.h
@@ -0,0 +1,627 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup windows windows
+ * @{ @ingroup compat
+ */
+
+#ifndef WINDOWS_H_
+#define WINDOWS_H_
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <direct.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/* undef Windows variants evaluating values more than once */
+#undef min
+#undef max
+
+/* interface is defined as an alias to "struct" in basetypes.h, but
+ * we use it here and there as ordinary identifier. */
+#undef interface
+
+/* used by Windows API, but we have our own */
+#undef CALLBACK
+
+/* UID/GID types for capabilities, even if not supported */
+typedef u_int uid_t;
+typedef u_int gid_t;
+
+/**
+ * Initialize Windows libraries
+ */
+void windows_init();
+
+/**
+ * Deinitialize windows libraries
+ */
+void windows_deinit();
+
+/**
+ * Replacement for random(3)
+ */
+static inline long random(void)
+{
+ return rand();
+}
+
+/**
+ * Replacement for srandom(3)
+ */
+static inline void srandom(unsigned int seed)
+{
+ srand(seed);
+}
+
+/**
+ * Replacement of sched_yield(2) from <sched.h>
+ */
+static inline int sched_yield(void)
+{
+ Sleep(0);
+ return 0;
+}
+
+/**
+ * Replacement of sleep(3), cancellable by thread_cancel()
+ */
+#define sleep sleep_cancellable
+static inline int sleep_cancellable(unsigned int seconds)
+{
+ SleepEx(seconds * 1000, TRUE);
+ return 0;
+}
+
+/**
+ * Replacement of usleep(3), cancellable, ms resolution only
+ */
+int usleep(useconds_t usec);
+
+/**
+ * strdup(3), the Windows variant can't free(strdup("")) and others
+ */
+#define strdup strdup_windows
+static inline char* strdup_windows(const char *src)
+{
+ size_t len;
+ char *dst;
+
+ len = strlen(src) + 1;
+ dst = malloc(len);
+ memcpy(dst, src, len);
+ return dst;
+}
+
+/**
+ * strndup(3)
+ */
+char* strndup(const char *s, size_t n);
+
+/**
+ * Provided via ws2_32
+ */
+#ifndef InetNtop
+const char WINAPI *inet_ntop(int af, const void *src, char *dst, socklen_t size);
+#endif
+
+/**
+ * Provided via ws2_32
+ */
+#ifndef InetPton
+int WINAPI inet_pton(int af, const char *src, void *dst);
+#endif
+
+/**
+ * Provided by printf hook backend
+ */
+int asprintf(char **strp, const char *fmt, ...);
+
+/**
+ * Provided by printf hook backend
+ */
+int vasprintf(char **strp, const char *fmt, va_list ap);
+
+/**
+ * timeradd(3) from <sys/time.h>
+ */
+static inline void timeradd(struct timeval *a, struct timeval *b,
+ struct timeval *res)
+{
+ res->tv_sec = a->tv_sec + b->tv_sec;
+ res->tv_usec = a->tv_usec + b->tv_usec;
+ if (res->tv_usec >= 1000000)
+ {
+ res->tv_usec -= 1000000;
+ res->tv_sec++;
+ }
+}
+
+/**
+ * timersub(3) from <sys/time.h>
+ */
+static inline void timersub(struct timeval *a, struct timeval *b,
+ struct timeval *res)
+{
+ res->tv_sec = a->tv_sec - b->tv_sec;
+ res->tv_usec = a->tv_usec - b->tv_usec;
+ if (res->tv_usec < 0)
+ {
+ res->tv_usec += 1000000;
+ res->tv_sec--;
+ }
+}
+
+/**
+ * gmtime_r(3) from <time.h>
+ */
+static inline struct tm *gmtime_r(const time_t *timep, struct tm *result)
+{
+ struct tm *ret;
+
+ /* gmtime_s() and friends seem not to be implemented/functioning.
+ * Relying on gmtime() on Windows works as well, as it uses thread
+ * specific buffers. */
+ ret = gmtime(timep);
+ if (ret)
+ {
+ memcpy(result, ret, sizeof(*result));
+ }
+ return ret;
+}
+
+/**
+ * localtime_r(3) from <time.h>
+ */
+static inline struct tm *localtime_r(const time_t *timep, struct tm *result)
+{
+ struct tm *ret;
+
+ /* localtime_s() and friends seem not to be implemented/functioning.
+ * Relying on localtime() on Windows works as well, as it uses thread
+ * specific buffers. */
+ ret = localtime(timep);
+ if (ret)
+ {
+ memcpy(result, ret, sizeof(*result));
+ }
+ return ret;
+}
+
+/**
+ * setenv(3) from <stdlib.h>, overwrite flag is ignored
+ */
+static inline int setenv(const char *name, const char *value, int overwrite)
+{
+ if (SetEnvironmentVariableA(name, value) == 0)
+ { /* failed */
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Lazy binding, ignored on Windows
+ */
+#define RTLD_LAZY 1
+
+/**
+ * Default handle targeting .exe
+ */
+#define RTLD_DEFAULT (NULL)
+
+/**
+ * Find symbol in next library
+ */
+#define RTLD_NEXT ((void*)~(uintptr_t)0)
+
+/**
+ * dlopen(3) from <dlfcn.h>
+ */
+void* dlopen(const char *filename, int flag);
+
+/**
+ * dlsym() from <dlfcn.h>
+ */
+void* dlsym(void *handle, const char *symbol);
+
+/**
+ * dlerror(3) from <dlfcn.h>, currently not thread save
+ */
+char* dlerror(void);
+
+/**
+ * dlclose() from <dlfcn.h>
+ */
+int dlclose(void *handle);
+
+/**
+ * socketpair(2) for SOCK_STREAM, uses TCP on loopback
+ */
+int socketpair(int domain, int type, int protocol, int sv[2]);
+
+/**
+ * getpass(3) on Windows consoles
+ */
+char* getpass(const char *prompt);
+#define HAVE_GETPASS
+
+/**
+ * Map MSG_DONTWAIT to the reserved, but deprecated MSG_INTERRUPT
+ */
+#define MSG_DONTWAIT MSG_INTERRUPT
+
+/**
+ * shutdown(2) "how"-aliases, to use Unix variant on Windows
+ */
+#define SHUT_RD SD_RECEIVE
+#define SHUT_WR SD_SEND
+#define SHUT_RDWR SD_BOTH
+
+/**
+ * shutdown(2) setting errno
+ */
+#define shutdown windows_shutdown
+int windows_shutdown(int sockfd, int how);
+
+/**
+ * accept(2) setting errno
+ */
+#define accept windows_accept
+int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+/**
+ * bind(2) setting errno
+ */
+#define bind windows_bind
+int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+/**
+ * connect(2) setting errno
+ */
+#define connect windows_connect
+int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+/**
+ * getsockname(2) setting errno
+ */
+#define getsockname windows_getsockname
+int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+/**
+ * getsockopt(2) setting errno
+ */
+#define getsockopt windows_getsockopt
+int windows_getsockopt(int sockfd, int level, int optname,
+ void *optval, socklen_t *optlen);
+
+/**
+ * setsockopt(2) setting errno
+ */
+#define setsockopt windows_setsockopt
+int windows_setsockopt(int sockfd, int level, int optname,
+ const void *optval, socklen_t optlen);
+
+/**
+ * socket(2) setting errno
+ */
+#define socket windows_socket
+int windows_socket(int domain, int type, int protocol);
+
+/**
+ * select(2) setting errno
+ */
+#define select windows_select
+int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout);
+
+/**
+ * close(2) working for file handles and Winsock sockets
+ */
+#define close windows_close
+int windows_close(int fd);
+
+/**
+ * recv(2) with support for MSG_DONTWAIT
+ */
+#define recv windows_recv
+ssize_t windows_recv(int sockfd, void *buf, size_t len, int flags);
+
+/**
+ * recvfrom(2) with support for MSG_DONTWAIT
+ */
+#define recvfrom windows_recvfrom
+ssize_t windows_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen);
+
+/**
+ * recvfrom(2) with support for MSG_DONTWAIT
+ */
+#define send windows_send
+ssize_t windows_send(int sockfd, const void *buf, size_t len, int flags);
+
+/**
+ * recvfrom(2) with support for MSG_DONTWAIT
+ */
+#define sendto windows_send
+ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen);
+
+/**
+ * read(2) working on files and sockets, cancellable on sockets only
+ *
+ * On Windows, there does not seem to be a way how a cancellable read can
+ * be implemented on Low level I/O functions for files, _pipe()s or stdio.
+ */
+#define read windows_read
+ssize_t windows_read(int fd, void *buf, size_t count);
+
+/**
+ * write(2) working on files and sockets
+ */
+#define write windows_write
+ssize_t windows_write(int fd, void *buf, size_t count);
+
+#if _WIN32_WINNT < 0x0600
+/**
+ * Define pollfd and flags on our own if not specified
+ */
+struct pollfd {
+ SOCKET fd;
+ short events;
+ short revents;
+};
+enum {
+ POLLERR = 0x0001,
+ POLLHUP = 0x0002,
+ POLLNVAL = 0x0004,
+ POLLWRNORM = 0x0010,
+ POLLWRBAND = 0x0020,
+ POLLPRI = 0x0400,
+ POLLRDNORM = 0x0100,
+ POLLRDBAND = 0x0200,
+ POLLIN = POLLRDNORM | POLLRDBAND,
+ POLLOUT = POLLWRNORM,
+};
+#endif /* _WIN32_WINNT < 0x0600 */
+
+/**
+ * poll(2), implemented using Winsock2 WSAPoll()
+ */
+int poll(struct pollfd *fds, int nfds, int timeout);
+
+/**
+ * Declaration missing on older WinGW
+ */
+_CRTIMP errno_t strerror_s(char *buf, size_t size, int errnum);
+
+/**
+ * strerror_s, but supporting POSIX compatibility errno >= 100
+ */
+#define strerror_s strerror_s_extended
+int strerror_s_extended(char *buf, size_t buflen, int errnum);
+
+/**
+ * strerror_r(2) replacement, XSI variant
+ */
+static inline int strerror_r(int errnum, char *buf, size_t buflen)
+{
+ return strerror_s(buf, buflen, errnum);
+}
+#define HAVE_STRERROR_R /* but not STRERROR_R_CHAR_P */
+
+/**
+ * MinGW does provide extended errno values. Windows itself knowns them
+ * for POSIX compatibility; we define them as well.
+ */
+#ifndef EADDRINUSE
+#define EADDRINUSE 100
+#endif
+#ifndef EADDRNOTAVAIL
+#define EADDRNOTAVAIL 101
+#endif
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT 102
+#endif
+#ifndef EALREADY
+#define EALREADY 103
+#endif
+#ifndef EBADMSG
+#define EBADMSG 104
+#endif
+#ifndef ECANCELED
+#define ECANCELED 105
+#endif
+#ifndef ECONNABORTED
+#define ECONNABORTED 106
+#endif
+#ifndef ECONNREFUSED
+#define ECONNREFUSED 107
+#endif
+#ifndef ECONNRESET
+#define ECONNRESET 108
+#endif
+#ifndef EDESTADDRREQ
+#define EDESTADDRREQ 109
+#endif
+#ifndef EHOSTUNREACH
+#define EHOSTUNREACH 110
+#endif
+#ifndef EIDRM
+#define EIDRM 111
+#endif
+#ifndef EINPROGRESS
+#define EINPROGRESS 112
+#endif
+#ifndef EISCONN
+#define EISCONN 113
+#endif
+#ifndef ELOOP
+#define ELOOP 114
+#endif
+#ifndef EMSGSIZE
+#define EMSGSIZE 115
+#endif
+#ifndef ENETDOWN
+#define ENETDOWN 116
+#endif
+#ifndef ENETRESET
+#define ENETRESET 117
+#endif
+#ifndef ENETUNREACH
+#define ENETUNREACH 118
+#endif
+#ifndef ENOBUFS
+#define ENOBUFS 119
+#endif
+#ifndef ENODATA
+#define ENODATA 120
+#endif
+#ifndef ENOLINK
+#define ENOLINK 121
+#endif
+#ifndef ENOMSG
+#define ENOMSG 122
+#endif
+#ifndef ENOPROTOOPT
+#define ENOPROTOOPT 123
+#endif
+#ifndef ENOSR
+#define ENOSR 124
+#endif
+#ifndef ENOSTR
+#define ENOSTR 125
+#endif
+#ifndef ENOTCONN
+#define ENOTCONN 126
+#endif
+#ifndef ENOTRECOVERABLE
+#define ENOTRECOVERABLE 127
+#endif
+#ifndef ENOTSOCK
+#define ENOTSOCK 128
+#endif
+#ifndef ENOTSUP
+#define ENOTSUP 129
+#endif
+#ifndef EOPNOTSUPP
+#define EOPNOTSUPP 130
+#endif
+#ifndef EOTHER
+#define EOTHER 131
+#endif
+#ifndef EOVERFLOW
+#define EOVERFLOW 132
+#endif
+#ifndef EOWNERDEAD
+#define EOWNERDEAD 133
+#endif
+#ifndef EPROTO
+#define EPROTO 134
+#endif
+#ifndef EPROTONOSUPPORT
+#define EPROTONOSUPPORT 135
+#endif
+#ifndef EPROTOTYPE
+#define EPROTOTYPE 136
+#endif
+#ifndef ETIME
+#define ETIME 137
+#endif
+#ifndef ETIMEDOUT
+#define ETIMEDOUT 138
+#endif
+#ifndef ETXTBSY
+#define ETXTBSY 139
+#endif
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK 140
+#endif
+
+
+/* Windows does not support "ll" format printf length modifiers. Mingw
+ * therefore maps these to the Windows specific I64 length modifier. That
+ * won't work for us, as we use our own printf backend on Windows, which works
+ * just fine with "ll". */
+#undef PRId64
+#define PRId64 "lld"
+#undef PRId64
+#define PRId64 "lld"
+#undef PRIdLEAST64
+#define PRIdLEAST64 "lld"
+#undef PRIdFAST64
+#define PRIdFAST64 "lld"
+#undef PRIdMAX
+#define PRIdMAX "lld"
+#undef PRIi64
+#define PRIi64 "lli"
+#undef PRIiLEAST64
+#define PRIiLEAST64 "lli"
+#undef PRIiFAST64
+#define PRIiFAST64 "lli"
+#undef PRIiMAX
+#define PRIiMAX "lli"
+#undef PRIo64
+#define PRIo64 "llo"
+#undef PRIoLEAST64
+#define PRIoLEAST64 "llo"
+#undef PRIoFAST64
+#define PRIoFAST64 "llo"
+#undef PRIoMAX
+#define PRIoMAX "llo"
+#undef PRIu64
+#define PRIu64 "llu"
+#undef PRIuLEAST64
+#define PRIuLEAST64 "llu"
+#undef PRIuFAST64
+#define PRIuFAST64 "llu"
+#undef PRIuMAX
+#define PRIuMAX "llu"
+#undef PRIx64
+#define PRIx64 "llx"
+#undef PRIxLEAST64
+#define PRIxLEAST64 "llx"
+#undef PRIxFAST64
+#define PRIxFAST64 "llx"
+#undef PRIxMAX
+#define PRIxMAX "llx"
+#undef PRIX64
+#define PRIX64 "llX"
+#undef PRIXLEAST64
+#define PRIXLEAST64 "llX"
+#undef PRIXFAST64
+#define PRIXFAST64 "llX"
+#undef PRIXMAX
+#define PRIXMAX "llX"
+
+#ifdef _WIN64
+# undef PRIdPTR
+# define PRIdPTR "lld"
+# undef PRIiPTR
+# define PRIiPTR "lli"
+# undef PRIoPTR
+# define PRIoPTR "llo"
+# undef PRIuPTR
+# define PRIuPTR "llu"
+# undef PRIxPTR
+# define PRIxPTR "llx"
+# undef PRIXPTR
+# define PRIXPTR "llX"
+#endif /* _WIN64 */
+
+#endif /** WINDOWS_H_ @}*/