|
|
|
|
@ -3,16 +3,27 @@
|
|
|
|
|
#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> |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@ -35,3 +46,93 @@ int random_bytes(uint8_t *buffer, size_t len) {
|
|
|
|
|
return (ret == (ssize_t)len) ? 0 : -1; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
static uint32_t get_default_route_ip_linux(void) { |
|
|
|
|
FILE *f = fopen("/proc/net/route", "r"); |
|
|
|
|
if (!f) return 0; |
|
|
|
|
|
|
|
|
|
char line[256]; |
|
|
|
|
char *ifname = NULL; |
|
|
|
|
unsigned int dest, gw; |
|
|
|
|
|
|
|
|
|
if (!fgets(line, sizeof(line), f)) { |
|
|
|
|
fclose(f); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (fgets(line, sizeof(line), f)) { |
|
|
|
|
int items = sscanf(line, "%ms %x %x", &ifname, &dest, &gw); |
|
|
|
|
if (items != 3) { |
|
|
|
|
free(ifname); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (dest == 0) { |
|
|
|
|
free(ifname); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
free(ifname); |
|
|
|
|
ifname = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fclose(f); |
|
|
|
|
|
|
|
|
|
if (!ifname) return 0; |
|
|
|
|
|
|
|
|
|
struct ifaddrs *ifaddr, *ifa; |
|
|
|
|
if (getifaddrs(&ifaddr) == -1) { |
|
|
|
|
free(ifname); |
|
|
|
|
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; |
|
|
|
|
if (strcmp(ifa->ifa_name, ifname) != 0) 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); |
|
|
|
|
free(ifname); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
static uint32_t get_default_route_ip_windows(void) { |
|
|
|
|
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); |
|
|
|
|
if (s == INVALID_SOCKET) return 0; |
|
|
|
|
|
|
|
|
|
struct sockaddr_in remote; |
|
|
|
|
remote.sin_family = AF_INET; |
|
|
|
|
remote.sin_port = htons(53); |
|
|
|
|
remote.sin_addr.s_addr = inet_addr("8.8.8.8"); |
|
|
|
|
|
|
|
|
|
if (connect(s, (struct sockaddr *)&remote, sizeof(remote)) == SOCKET_ERROR) { |
|
|
|
|
closesocket(s); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct sockaddr_in local; |
|
|
|
|
int len = sizeof(local); |
|
|
|
|
if (getsockname(s, (struct sockaddr *)&local, &len) == SOCKET_ERROR) { |
|
|
|
|
closesocket(s); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
closesocket(s); |
|
|
|
|
return local.sin_addr.s_addr; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
uint32_t get_default_route_ip(void) { |
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
return get_default_route_ip_windows(); |
|
|
|
|
#else |
|
|
|
|
return get_default_route_ip_linux(); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|