diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libstrongswan/utils/windows.c | 266 | ||||
-rw-r--r-- | src/libstrongswan/utils/windows.h | 77 |
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. */ |