585 lines
12 KiB
C
585 lines
12 KiB
C
/*
|
|
* 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 utils
|
|
*/
|
|
|
|
#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);
|
|
|
|
/**
|
|
* 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_ @}*/
|