You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

119 lines
3.4 KiB

/* platform_compat.c - Platform compatibility layer implementation */
#include "platform_compat.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#include <bcrypt.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
#else
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
#ifndef IFA_F_TEMPORARY
#define IFA_F_TEMPORARY 0x01
#endif
#endif
/*
* Generate cryptographically secure random bytes
* Returns 0 on success, -1 on error
*/
int random_bytes(uint8_t *buffer, size_t len) {
if (!buffer || len == 0) return -1;
#ifdef _WIN32
NTSTATUS status = BCryptGenRandom(NULL, buffer, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
return (status == STATUS_SUCCESS) ? 0 : -1;
#else
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) return -1;
ssize_t ret = read(fd, buffer, len);
close(fd);
return (ret == (ssize_t)len) ? 0 : -1;
#endif
}
#ifndef _WIN32
uint32_t get_interface_ip_by_index(uint32_t netif_index) {
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1) return 0;
uint32_t result = 0;
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) continue;
if (ifa->ifa_name == NULL) continue;
unsigned int idx = if_nametoindex(ifa->ifa_name);
if (idx != netif_index) continue;
if (ifa->ifa_addr->sa_family != AF_INET) continue;
struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
result = addr->sin_addr.s_addr;
break;
}
freeifaddrs(ifaddr);
return result;
}
int get_interface_ipv6_by_index(uint32_t netif_index, int temporary, uint8_t* addr_out) {
if (!addr_out) return -1;
memset(addr_out, 0, 16);
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1) return -1;
int found = 0;
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) continue;
if (ifa->ifa_name == NULL) continue;
unsigned int idx = if_nametoindex(ifa->ifa_name);
if (idx != netif_index) continue;
if (ifa->ifa_addr->sa_family != AF_INET6) continue;
// Skip link-local addresses (fe80::/10)
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ifa->ifa_addr;
if ((sin6->sin6_addr.s6_addr[0] & 0xfe) == 0xfe && sin6->sin6_addr.s6_addr[1] == 0x80) continue;
int is_temporary = (ifa->ifa_flags & IFA_F_TEMPORARY) ? 1 : 0;
if (temporary && is_temporary) {
memcpy(addr_out, &sin6->sin6_addr, 16);
found = 1;
break;
}
if (!temporary && !is_temporary) {
memcpy(addr_out, &sin6->sin6_addr, 16);
found = 1;
break;
}
}
freeifaddrs(ifaddr);
return found ? 0 : -1;
}
#else
uint32_t get_interface_ip_by_index(uint32_t netif_index) {
(void)netif_index;
return 0;
}
int get_interface_ipv6_by_index(uint32_t netif_index, int temporary, uint8_t* addr_out) {
(void)netif_index; (void)temporary;
if (addr_out) memset(addr_out, 0, 16);
return -1;
}
#endif