153 lines
4.1 KiB
C
153 lines
4.1 KiB
C
#include <iphlpapi.h>
|
|
#include <wincrypt.h> /* Required by mingw for some reason */
|
|
#include <windows.h>
|
|
#include <winsock2.h>
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
#include "iface-core/log.h"
|
|
|
|
#include "hook/table.h"
|
|
|
|
#include "hooklib/adapter.h"
|
|
|
|
#include "util/codepage.h"
|
|
#include "util/defs.h"
|
|
|
|
static DWORD WINAPI
|
|
my_GetAdaptersInfo(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len);
|
|
|
|
static DWORD(WINAPI *real_GetAdaptersInfo)(
|
|
PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len);
|
|
|
|
static IP_ADDRESS_STRING override_address;
|
|
static bool use_address_override;
|
|
|
|
static const struct hook_symbol adapter_hook_syms[] = {
|
|
{.name = "GetAdaptersInfo",
|
|
.patch = my_GetAdaptersInfo,
|
|
.link = (void *) &real_GetAdaptersInfo},
|
|
};
|
|
|
|
static DWORD WINAPI
|
|
my_GetAdaptersInfo(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len)
|
|
{
|
|
DWORD ret;
|
|
PMIB_IPFORWARDTABLE ip_fwd_table;
|
|
DWORD table_size;
|
|
DWORD best_adapter;
|
|
PIP_ADAPTER_INFO info;
|
|
|
|
ret = real_GetAdaptersInfo(adapter_info, out_buf_len);
|
|
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
info = adapter_info;
|
|
|
|
if (use_address_override) {
|
|
while (info) {
|
|
// this is well defined to be at most sizeof(IP_ADDRESS_STRING)
|
|
// and NULL filled if shorter (hence the memset in
|
|
// adapter_hook_override)
|
|
if (!memcmp(
|
|
info->IpAddressList.IpAddress.String,
|
|
override_address.String,
|
|
sizeof(IP_ADDRESS_STRING))) {
|
|
log_info(
|
|
"%s: using [override] adapter: %s, %s, %s, %s",
|
|
__FUNCTION__,
|
|
info->AdapterName,
|
|
info->Description,
|
|
info->IpAddressList.IpAddress.String,
|
|
info->IpAddressList.IpMask.String);
|
|
|
|
// copy only this adapter over
|
|
memcpy(adapter_info, info, sizeof(*info));
|
|
adapter_info->Next = 0;
|
|
return ret;
|
|
}
|
|
info = info->Next;
|
|
}
|
|
}
|
|
|
|
ip_fwd_table = (MIB_IPFORWARDTABLE *) malloc(sizeof(MIB_IPFORWARDTABLE));
|
|
table_size = 0;
|
|
|
|
if (GetIpForwardTable(ip_fwd_table, &table_size, 1) ==
|
|
ERROR_INSUFFICIENT_BUFFER) {
|
|
free(ip_fwd_table);
|
|
ip_fwd_table = (MIB_IPFORWARDTABLE *) malloc(table_size);
|
|
}
|
|
|
|
if (GetIpForwardTable(ip_fwd_table, &table_size, 1) != NO_ERROR ||
|
|
ip_fwd_table->dwNumEntries == 0) {
|
|
return ret;
|
|
}
|
|
|
|
best_adapter = ip_fwd_table->table[0].dwForwardIfIndex;
|
|
free(ip_fwd_table);
|
|
|
|
info = adapter_info;
|
|
|
|
while (info) {
|
|
if (info->Index == best_adapter) {
|
|
log_info(
|
|
"%s: using [best] adapter: %s, %s, %s, %s",
|
|
__FUNCTION__,
|
|
info->AdapterName,
|
|
info->Description,
|
|
info->IpAddressList.IpAddress.String,
|
|
info->IpAddressList.IpMask.String);
|
|
|
|
// copy only this adapter over
|
|
memcpy(adapter_info, info, sizeof(*info));
|
|
adapter_info->Next = 0;
|
|
return ret;
|
|
}
|
|
info = info->Next;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void adapter_hook_init(void)
|
|
{
|
|
hook_table_apply(
|
|
NULL, "iphlpapi.dll", adapter_hook_syms, lengthof(adapter_hook_syms));
|
|
|
|
log_info("Inserted adapter hooks");
|
|
}
|
|
|
|
void adapter_hook_fini()
|
|
{
|
|
hook_table_revert(
|
|
NULL, "iphlpapi.dll", adapter_hook_syms, lengthof(adapter_hook_syms));
|
|
|
|
log_info("Removed adapter hooks");
|
|
}
|
|
|
|
void adapter_hook_override(const char *adapter_address)
|
|
{
|
|
// starts off false anyways due to static
|
|
// but in case it gets called multiple times, set it anyways
|
|
use_address_override = false;
|
|
|
|
if (adapter_address == NULL || *adapter_address == '\0') {
|
|
// empty, do nothing
|
|
return;
|
|
}
|
|
|
|
if (strlen(adapter_address) > sizeof(IP_ADDRESS_STRING)) {
|
|
log_warning(
|
|
"%s: %s is not an ipv4 address", __FUNCTION__, adapter_address);
|
|
return;
|
|
}
|
|
|
|
memset(override_address.String, 0, sizeof(IP_ADDRESS_STRING));
|
|
memcpy(override_address.String, adapter_address, sizeof(IP_ADDRESS_STRING));
|
|
|
|
use_address_override = true;
|
|
} |