mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
[O] Filter GetIpAddrTable to selected network adapter (#724)
## Description of change Filter GetIpAddrTable to selected network adapter. Fixes the IP address error (5-1506-0000) on gitadora gw delta when multiple network adapters are present. ## Testing Tested on Gitadora GW Delta with both WiFi and Tailscale adapters present.
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "avs/core.h"
|
#include "avs/core.h"
|
||||||
#include "avs/ea3.h"
|
#include "avs/ea3.h"
|
||||||
@@ -18,12 +19,14 @@
|
|||||||
|
|
||||||
// hooking related stuff
|
// hooking related stuff
|
||||||
static decltype(GetAdaptersInfo) *GetAdaptersInfo_orig = nullptr;
|
static decltype(GetAdaptersInfo) *GetAdaptersInfo_orig = nullptr;
|
||||||
|
static decltype(GetIpAddrTable) *GetIpAddrTable_orig = nullptr;
|
||||||
static decltype(bind) *bind_orig = nullptr;
|
static decltype(bind) *bind_orig = nullptr;
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
std::string NETWORK_ADDRESS = "10.9.0.0";
|
std::string NETWORK_ADDRESS = "10.9.0.0";
|
||||||
std::string NETWORK_SUBNET = "255.255.0.0";
|
std::string NETWORK_SUBNET = "255.255.0.0";
|
||||||
static bool GetAdaptersInfo_log = true;
|
static bool GetAdaptersInfo_log = true;
|
||||||
|
static bool GetIpAddrTable_log = true;
|
||||||
|
|
||||||
// network structs
|
// network structs
|
||||||
static struct in_addr network;
|
static struct in_addr network;
|
||||||
@@ -43,6 +46,80 @@ static void defer_network_adapter_error() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_valid_ipaddr_row(const MIB_IPADDRROW &row) {
|
||||||
|
static const auto loopback = inet_addr("127.0.0.1");
|
||||||
|
|
||||||
|
return row.dwAddr != 0 && row.dwAddr != loopback;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MIB_IPADDRROW *find_preferred_ipaddr_row(PMIB_IPADDRTABLE table) {
|
||||||
|
|
||||||
|
if (table == nullptr || table->dwNumEntries == 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prefer the row matching -adapternetwork/-adaptersubnet
|
||||||
|
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
||||||
|
auto &row = table->table[i];
|
||||||
|
if (!is_valid_ipaddr_row(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row_prefix = row.dwAddr & row.dwMask;
|
||||||
|
if (row_prefix == prefix.s_addr && row.dwMask == subnet.s_addr) {
|
||||||
|
return &row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall back to the interface Windows would route through by default
|
||||||
|
PMIB_IPFORWARDTABLE pIpForwardTable = (MIB_IPFORWARDTABLE *) malloc(sizeof(MIB_IPFORWARDTABLE));
|
||||||
|
DWORD dwSize = 0;
|
||||||
|
if (GetIpForwardTable(pIpForwardTable, &dwSize, TRUE) == ERROR_INSUFFICIENT_BUFFER) {
|
||||||
|
free(pIpForwardTable);
|
||||||
|
pIpForwardTable = (MIB_IPFORWARDTABLE *) malloc(dwSize);
|
||||||
|
}
|
||||||
|
if (GetIpForwardTable(pIpForwardTable, &dwSize, TRUE) != NO_ERROR || pIpForwardTable->dwNumEntries == 0) {
|
||||||
|
free(pIpForwardTable);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD best = pIpForwardTable->table[0].dwForwardIfIndex;
|
||||||
|
free(pIpForwardTable);
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
||||||
|
auto &row = table->table[i];
|
||||||
|
if (row.dwIndex == best && is_valid_ipaddr_row(row)) {
|
||||||
|
return &row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// last resort: keep a deterministic valid row instead of exposing all adapters
|
||||||
|
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
||||||
|
auto &row = table->table[i];
|
||||||
|
if (is_valid_ipaddr_row(row)) {
|
||||||
|
return &row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keep_only_ipaddr_row(PMIB_IPADDRTABLE table, MIB_IPADDRROW *row) {
|
||||||
|
if (table == nullptr || row == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetIpAddrTable_log) {
|
||||||
|
in_addr addr {};
|
||||||
|
addr.s_addr = row->dwAddr;
|
||||||
|
log_info("network", "Using preferred IP address row: {}", inet_ntoa(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
table->table[0] = *row;
|
||||||
|
table->dwNumEntries = 1;
|
||||||
|
GetIpAddrTable_log = false;
|
||||||
|
}
|
||||||
|
|
||||||
static ULONG WINAPI GetAdaptersInfo_hook(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) {
|
static ULONG WINAPI GetAdaptersInfo_hook(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) {
|
||||||
|
|
||||||
// call orig
|
// call orig
|
||||||
@@ -183,6 +260,50 @@ static ULONG WINAPI GetAdaptersInfo_hook(PIP_ADAPTER_INFO pAdapterInfo, PULONG p
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI GetIpAddrTable_hook(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder) {
|
||||||
|
|
||||||
|
auto input_size = pdwSize != nullptr ? *pdwSize : 0;
|
||||||
|
auto ret = GetIpAddrTable_orig(pIpAddrTable, pdwSize, bOrder);
|
||||||
|
|
||||||
|
if (ret == NO_ERROR) {
|
||||||
|
auto row = find_preferred_ipaddr_row(pIpAddrTable);
|
||||||
|
if (row != nullptr) {
|
||||||
|
keep_only_ipaddr_row(pIpAddrTable, row);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != ERROR_INSUFFICIENT_BUFFER || pIpAddrTable == nullptr || pdwSize == nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the caller's buffer is large enough for the filtered single-row table,
|
||||||
|
// satisfy the call even when Windows needed more room for all adapters.
|
||||||
|
const auto one_row_size = offsetof(MIB_IPADDRTABLE, table) + sizeof(MIB_IPADDRROW);
|
||||||
|
if (input_size < one_row_size) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto full_size = *pdwSize;
|
||||||
|
auto table = (PMIB_IPADDRTABLE) malloc(full_size);
|
||||||
|
if (table == nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto full_ret = GetIpAddrTable_orig(table, &full_size, bOrder);
|
||||||
|
if (full_ret == NO_ERROR) {
|
||||||
|
auto row = find_preferred_ipaddr_row(table);
|
||||||
|
if (row != nullptr) {
|
||||||
|
keep_only_ipaddr_row(pIpAddrTable, row);
|
||||||
|
*pdwSize = one_row_size;
|
||||||
|
ret = NO_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(table);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int WINAPI bind_hook(SOCKET s, const struct sockaddr *name, int namelen) {
|
static int WINAPI bind_hook(SOCKET s, const struct sockaddr *name, int namelen) {
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@@ -243,6 +364,15 @@ void networkhook_init() {
|
|||||||
GetAdaptersInfo_orig = orig_addr;
|
GetAdaptersInfo_orig = orig_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetIpAddrTable hook
|
||||||
|
auto ip_addr_table_orig_addr = detour::iat_try(
|
||||||
|
"GetIpAddrTable", GetIpAddrTable_hook, nullptr);
|
||||||
|
if (!ip_addr_table_orig_addr) {
|
||||||
|
log_warning("network", "Could not hook GetIpAddrTable");
|
||||||
|
} else if (GetIpAddrTable_orig == nullptr) {
|
||||||
|
GetIpAddrTable_orig = ip_addr_table_orig_addr;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bind Hook
|
* Bind Hook
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user