- get_default_route_netif_index(): UDP connect trick + getifaddrs to find default route iface - etcp_socket_add(): auto-detect netif_index when not specified in config - queue_new() API: explicit index_offset/index_size params instead of implicit from hash_size - radix: cleanup types (uint8_t*), replace bzero/bcmp with memset/memcmp, remove kernel ifdefs - route6_lib: new IPv6 routing library + get_node_v6_routes()
178 lines
5.2 KiB
C
178 lines
5.2 KiB
C
/**
|
|
* Platform compatibility layer for POSIX functions on Windows
|
|
*/
|
|
|
|
#ifndef PLATFORM_COMPAT_H
|
|
#define PLATFORM_COMPAT_H
|
|
|
|
#ifdef _WIN32
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#include <windows.h>
|
|
#include <io.h>
|
|
#include <time.h>
|
|
#include <fcntl.h>
|
|
#include <stdint.h>
|
|
|
|
// Byte order conversion functions
|
|
#ifdef _WIN32
|
|
#include <stdlib.h>
|
|
#define htobe16(x) _byteswap_ushort(x)
|
|
#define be16toh(x) _byteswap_ushort(x)
|
|
#define htobe32(x) _byteswap_ulong(x)
|
|
#define be32toh(x) _byteswap_ulong(x)
|
|
#define htobe64(x) _byteswap_uint64(x)
|
|
#define be64toh(x) _byteswap_uint64(x)
|
|
#else
|
|
#include <endian.h>
|
|
#endif
|
|
|
|
// POSIX functions missing on Windows
|
|
#define strcasecmp _stricmp
|
|
#define strncasecmp _strnicmp
|
|
|
|
// poll() and pollfd are already defined in winsock2.h on MSYS2 UCRT64
|
|
// Only define if not already present
|
|
#ifndef POLLIN
|
|
#define POLLIN 0x0001
|
|
#endif
|
|
#ifndef POLLOUT
|
|
#define POLLOUT 0x0004
|
|
#endif
|
|
#ifndef POLLERR
|
|
#define POLLERR 0x0008
|
|
#endif
|
|
#ifndef POLLHUP
|
|
#define POLLHUP 0x0010
|
|
#endif
|
|
#ifndef POLLNVAL
|
|
#define POLLNVAL 0x0020
|
|
#endif
|
|
#ifndef POLLPRI
|
|
#define POLLPRI 0x0002
|
|
#endif
|
|
|
|
// ssize_t for Windows (signed size type)
|
|
#ifndef _SSIZE_T_DEFINED
|
|
typedef long ssize_t;
|
|
#define _SSIZE_T_DEFINED
|
|
#endif
|
|
|
|
// gettimeofday for Windows - provide our own implementation if not already defined
|
|
#ifndef _GETTIMEOFDAY_DEFINED
|
|
#define _GETTIMEOFDAY_DEFINED
|
|
static inline int utun_gettimeofday(struct timeval *tv, void *tz) {
|
|
FILETIME ft;
|
|
unsigned __int64 tmpres = 0;
|
|
|
|
if (tv != NULL) {
|
|
GetSystemTimeAsFileTime(&ft);
|
|
tmpres |= ft.dwHighDateTime;
|
|
tmpres <<= 32;
|
|
tmpres |= ft.dwLowDateTime;
|
|
// Convert from 100-nanosecond intervals to microseconds
|
|
tmpres /= 10;
|
|
// Convert to Unix epoch (January 1, 1970)
|
|
tmpres -= 11644473600000000ULL;
|
|
tv->tv_sec = (long)(tmpres / 1000000UL);
|
|
tv->tv_usec = (long)(tmpres % 1000000UL);
|
|
}
|
|
|
|
// tz parameter is ignored (for compatibility with POSIX)
|
|
|
|
return 0;
|
|
}
|
|
#endif // _GETTIMEOFDAY_DEFINED
|
|
|
|
// Pipe creation for Windows
|
|
static inline int platform_pipe(int pipefd[2]) {
|
|
return _pipe(pipefd, 4096, _O_BINARY);
|
|
}
|
|
#define pipe platform_pipe
|
|
|
|
// nfds_t already defined in winsock2.h on MSYS2
|
|
|
|
// fcntl replacement for Windows (simplified - only supports F_GETFL/F_SETFL with O_NONBLOCK)
|
|
#ifndef F_GETFL
|
|
#define F_GETFL 3
|
|
#endif
|
|
#ifndef F_SETFL
|
|
#define F_SETFL 4
|
|
#endif
|
|
#ifndef O_NONBLOCK
|
|
#define O_NONBLOCK 0x4000
|
|
#endif
|
|
|
|
static inline int platform_fcntl(int fd, int cmd, ... /* arg */ ) {
|
|
va_list ap;
|
|
va_start(ap, cmd);
|
|
|
|
if (cmd == F_GETFL) {
|
|
va_end(ap);
|
|
// Return current flags (always 0 on Windows, can't query easily)
|
|
return 0;
|
|
} else if (cmd == F_SETFL) {
|
|
int flags = va_arg(ap, int);
|
|
va_end(ap);
|
|
if (flags & O_NONBLOCK) {
|
|
// Set non-blocking mode
|
|
u_long mode = 1;
|
|
return ioctlsocket(fd, FIONBIO, &mode);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
va_end(ap);
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
#define fcntl platform_fcntl
|
|
|
|
// nanosleep already defined in pthread_time.h on MSYS2
|
|
// poll() and pollfd already defined in winsock2.h on MSYS2
|
|
// Use WSAPoll on Windows (available in Vista and later)
|
|
#define poll WSAPoll
|
|
|
|
// sa_family_t might not be defined on some Windows setups
|
|
#ifndef sa_family_t
|
|
typedef unsigned short sa_family_t;
|
|
#endif
|
|
|
|
#else
|
|
// POSIX - include standard headers
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <strings.h>
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <poll.h>
|
|
#define utun_gettimeofday(A,B) gettimeofday(A,B)
|
|
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
|
|
// Generate cryptographically secure random bytes
|
|
// Returns 0 on success, -1 on error
|
|
int random_bytes(uint8_t *buffer, size_t len);
|
|
|
|
// Get IPv4 address of interface by its index (ifindex)
|
|
// Returns IPv4 address in network byte order, 0 on error
|
|
uint32_t get_interface_ip_by_index(uint32_t netif_index);
|
|
|
|
// Get IPv6 address of interface by its index (ifindex)
|
|
// temporary=1: get temporary (privacy) IPv6, temporary=0: get permanent IPv6
|
|
// Returns 0 on success (fills addr_out with 16 bytes), -1 on error or not found
|
|
int get_interface_ipv6_by_index(uint32_t netif_index, int temporary, uint8_t* addr_out);
|
|
|
|
// Determine the interface index for the default route (outgoing traffic)
|
|
// Creates a temp UDP socket, connects to a well-known address to force
|
|
// kernel routing, then matches the chosen source IP to getifaddrs()
|
|
// family: AF_INET or AF_INET6, returns ifindex (0 on failure)
|
|
uint32_t get_default_route_netif_index(int family);
|
|
|
|
#endif // PLATFORM_COMPAT_H
|