aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libstrongswan/utils/windows.c266
-rw-r--r--src/libstrongswan/utils/windows.h77
2 files changed, 278 insertions, 65 deletions
diff --git a/src/libstrongswan/utils/windows.c b/src/libstrongswan/utils/windows.c
index 741d199ec..397f3b156 100644
--- a/src/libstrongswan/utils/windows.c
+++ b/src/libstrongswan/utils/windows.c
@@ -310,80 +310,132 @@ char* getpass(const char *prompt)
}
/**
+ * 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)
{
- switch (WSAGetLastError())
+ 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++)
{
- case WSANOTINITIALISED:
- errno = EBADF;
- break;
- case WSAENETDOWN:
- errno = ENETDOWN;
- break;
- case WSAENETRESET:
- errno = ENETRESET;
- break;
- case WSAESHUTDOWN:
- errno = ECONNABORTED;
- break;
- case WSAEACCES:
- errno = EACCES;
- break;
- case WSAEINTR:
- errno = EINTR;
- break;
- case WSAEINPROGRESS:
- errno = EINPROGRESS;
- break;
- case WSAEFAULT:
- errno = EFAULT;
- break;
- case WSAENOBUFS:
- errno = ENOBUFS;
- break;
- case WSAENOTSOCK:
- errno = ENOTSOCK;
- break;
- case WSAEOPNOTSUPP:
- errno = EOPNOTSUPP;
- break;
- case WSAEWOULDBLOCK:
- errno = EWOULDBLOCK;
- break;
- case WSAEMSGSIZE:
- errno = EMSGSIZE;
- break;
- case WSAEINVAL:
- errno = EINVAL;
- break;
- case WSAENOTCONN:
- errno = ENOTCONN;
- break;
- case WSAEHOSTUNREACH:
- errno = EHOSTUNREACH;
- break;
- case WSAECONNABORTED:
- errno = ECONNABORTED;
- break;
- case WSAECONNRESET:
- errno = ECONNRESET;
- break;
- case WSAETIMEDOUT:
- errno = ETIMEDOUT;
- break;
- default:
- errno = ENOENT;
- break;
+ if (map[i].wsa == wsa)
+ {
+ errno = map[i].err;
+ return retval;
+ }
}
+ errno = ENOENT;
+ return retval;
}
- else
- {
- errno = 0;
- }
+ errno = 0;
return retval;
}
@@ -403,6 +455,90 @@ static bool check_dontwait(int *flags)
/**
* 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)
{
diff --git a/src/libstrongswan/utils/windows.h b/src/libstrongswan/utils/windows.h
index fd4338455..a06a89ebf 100644
--- a/src/libstrongswan/utils/windows.h
+++ b/src/libstrongswan/utils/windows.h
@@ -273,6 +273,63 @@ char* getpass(const char *prompt);
#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
@@ -305,6 +362,26 @@ ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
/**
+ * Declaration missing on older WinGW
+ */
+_CRTIMP errno_t strerror_s(char *buf, size_t size, int errnum);
+
+/**
+ * strerror_s, but supporting POSIX compatiblity 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.
*/