1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2026-02-06 02:30:11 +03:00

Refactor host IP checking with caching and helper function

Co-authored-by: chipitsine <2217296+chipitsine@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-05 08:26:13 +00:00
parent 55bfcb9a94
commit 1e36ff0f77
2 changed files with 100 additions and 72 deletions

View File

@ -1190,6 +1190,77 @@ void NnIpSendForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UCHAR ttl, UINT src_i
}
}
// Check if destination IP is one of the host's own IP addresses
// Uses caching to avoid frequent system calls
// Returns true if dest_ip matches any of the host's IPs
bool IsDestinationHostOwnIP(VH *v, UINT dest_ip)
{
bool is_host_ip = false;
UINT64 now;
bool need_refresh = false;
// Validate arguments
if (v == NULL)
{
return false;
}
now = Tick64();
Lock(v->HostIPCacheLock);
{
// Check if cache needs refresh (every 60 seconds or if not initialized)
if (v->HostIPAddressCache == NULL || now >= v->HostIPCacheExpires)
{
need_refresh = true;
}
}
Unlock(v->HostIPCacheLock);
if (need_refresh)
{
// Refresh the cache
LIST *new_list = GetHostIPAddressList();
Lock(v->HostIPCacheLock);
{
// Free old cache
if (v->HostIPAddressCache != NULL)
{
FreeHostIPAddressList(v->HostIPAddressCache);
}
// Set new cache with 60 second expiration
v->HostIPAddressCache = new_list;
v->HostIPCacheExpires = now + 60000; // 60 seconds
}
Unlock(v->HostIPCacheLock);
}
// Check if dest_ip matches any cached host IP
Lock(v->HostIPCacheLock);
{
if (v->HostIPAddressCache != NULL)
{
UINT i;
IP dest_ip_obj;
UINTToIP(&dest_ip_obj, dest_ip);
for (i = 0; i < LIST_NUM(v->HostIPAddressCache); i++)
{
IP *host_ip = LIST_DATA(v->HostIPAddressCache, i);
if (IsIP4(host_ip) && CmpIpAddr(&dest_ip_obj, host_ip) == 0)
{
is_host_ip = true;
break;
}
}
}
}
Unlock(v->HostIPCacheLock);
return is_host_ip;
}
// Communication of ICMP towards the Internet
void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
{
@ -1212,31 +1283,10 @@ void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UIN
// Check if destination is the host's own IP address
// When Native NAT tries to send packets to the host's own IP, the OS routing
// may fail or behave unexpectedly. Drop such packets to avoid issues.
LIST *local_ip_list = GetHostIPAddressList();
if (local_ip_list != NULL)
if (IsDestinationHostOwnIP(v, dest_ip))
{
UINT i;
bool is_host_ip = false;
IP dest_ip_obj;
UINTToIP(&dest_ip_obj, dest_ip);
for (i = 0; i < LIST_NUM(local_ip_list); i++)
{
IP *host_ip = LIST_DATA(local_ip_list, i);
if (IsIP4(host_ip) && CmpIpAddr(&dest_ip_obj, host_ip) == 0)
{
is_host_ip = true;
break;
}
}
FreeHostIPAddressList(local_ip_list);
if (is_host_ip)
{
// Destination is the host's own IP - drop the packet
return;
}
// Destination is the host's own IP - drop the packet
return;
}
t = v->NativeNat;
@ -1384,31 +1434,10 @@ void NnUdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT
// Check if destination is the host's own IP address
// When Native NAT tries to send packets to the host's own IP, the OS routing
// may fail or behave unexpectedly. Drop such packets to avoid issues.
LIST *local_ip_list = GetHostIPAddressList();
if (local_ip_list != NULL)
if (IsDestinationHostOwnIP(v, dest_ip))
{
UINT i;
bool is_host_ip = false;
IP dest_ip_obj;
UINTToIP(&dest_ip_obj, dest_ip);
for (i = 0; i < LIST_NUM(local_ip_list); i++)
{
IP *host_ip = LIST_DATA(local_ip_list, i);
if (IsIP4(host_ip) && CmpIpAddr(&dest_ip_obj, host_ip) == 0)
{
is_host_ip = true;
break;
}
}
FreeHostIPAddressList(local_ip_list);
if (is_host_ip)
{
// Destination is the host's own IP - drop the packet
return;
}
// Destination is the host's own IP - drop the packet
return;
}
t = v->NativeNat;
@ -1512,31 +1541,10 @@ void NnTcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT
// Check if destination is the host's own IP address
// When Native NAT tries to send packets to the host's own IP, the OS routing
// may fail or behave unexpectedly. Drop such packets to avoid issues.
LIST *local_ip_list = GetHostIPAddressList();
if (local_ip_list != NULL)
if (IsDestinationHostOwnIP(v, dest_ip))
{
UINT i;
bool is_host_ip = false;
IP dest_ip_obj;
UINTToIP(&dest_ip_obj, dest_ip);
for (i = 0; i < LIST_NUM(local_ip_list); i++)
{
IP *host_ip = LIST_DATA(local_ip_list, i);
if (IsIP4(host_ip) && CmpIpAddr(&dest_ip_obj, host_ip) == 0)
{
is_host_ip = true;
break;
}
}
FreeHostIPAddressList(local_ip_list);
if (is_host_ip)
{
// Destination is the host's own IP - drop the packet
return;
}
// Destination is the host's own IP - drop the packet
return;
}
t = v->NativeNat;
@ -10283,6 +10291,13 @@ void Virtual_Free(VH *v)
LockVirtual(v);
{
// Free host IP cache
if (v->HostIPAddressCache != NULL)
{
FreeHostIPAddressList(v->HostIPAddressCache);
v->HostIPAddressCache = NULL;
}
// Release the IP combining list
FreeIpCombineList(v);
@ -10317,6 +10332,9 @@ void Virtual_Free(VH *v)
}
UnlockVirtual(v);
// Release the host IP cache lock
DeleteLock(v->HostIPCacheLock);
// Release the logger
FreeLog(v->Logger);
}
@ -10447,6 +10465,11 @@ VH *NewVirtualHostEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_
v->nat = nat;
// Initialize host IP cache for Native NAT
v->HostIPAddressCache = NULL;
v->HostIPCacheExpires = 0;
v->HostIPCacheLock = NewLock();
// Examine whether ICMP Raw Socket can be created
s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
if (s != NULL)