mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2026-03-10 10:19:21 +03:00
Compare commits
19 Commits
copilot/fi
...
df3ea19f0e
| Author | SHA1 | Date | |
|---|---|---|---|
| df3ea19f0e | |||
| 9da4aabda5 | |||
| 3cb3dd20fc | |||
| b551b77e25 | |||
| 609b8f4a5e | |||
| 0a87ff8fbd | |||
| 6016f84315 | |||
| 9d27b935b7 | |||
| 1e1104d3ba | |||
| 074efb5479 | |||
| fe460de5a6 | |||
| 6ef941db21 | |||
| d7d3ec8cac | |||
| 68e9f0b593 | |||
| f1012da5fb | |||
| 1411d4ceb4 | |||
| a3176175f9 | |||
| 88af7986b4 | |||
| 38f102e2e7 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -210,5 +210,3 @@ developer_tools/stbchecker/**/*.binlog
|
|||||||
developer_tools/stbchecker/**/*.nvuser
|
developer_tools/stbchecker/**/*.nvuser
|
||||||
developer_tools/stbchecker/**/.mfractor/
|
developer_tools/stbchecker/**/.mfractor/
|
||||||
/vcpkg_installed
|
/vcpkg_installed
|
||||||
_codeql_build_dir/
|
|
||||||
_codeql_detected_source_root
|
|
||||||
|
|||||||
@ -87,6 +87,10 @@ into it. So that is what will be described below.
|
|||||||
- x86-on-x64
|
- x86-on-x64
|
||||||
|
|
||||||
Cross compile x86 executables with 64-bit compiler
|
Cross compile x86 executables with 64-bit compiler
|
||||||
|
|
||||||
|
- arm64-on-x64
|
||||||
|
|
||||||
|
Cross compile arm64 executables with x64t compiler
|
||||||
|
|
||||||
On 64-bit Windows, all four configurations can be used. 32-bit platforms can only use 32-bit compiler.
|
On 64-bit Windows, all four configurations can be used. 32-bit platforms can only use 32-bit compiler.
|
||||||
|
|
||||||
|
|||||||
52
src/BUILD_WinArm64.md
Normal file
52
src/BUILD_WinArm64.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# How to build and install SoftEther VPN on Windows ARM64
|
||||||
|
|
||||||
|
This document describes how to build SoftEther VPN for Windows ARM64 and how to install the VPN Client and Neo6 virtual network adapter on Windows on ARM devices.
|
||||||
|
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
|
||||||
|
- Build host: Windows x64
|
||||||
|
|
||||||
|
- Target device: Windows 10 / Windows 11 ARM64
|
||||||
|
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
**Notes before building**: ARM64 builds are cross-compiled from an x64 Windows host. An existing x64-native build is required to generate hamcore.se2.
|
||||||
|
1. Follow [BUILD_WINDOWS.md](BUILD_WINDOWS.md##Building)
|
||||||
|
|
||||||
|
1. Build x64 (Native): From the build menu, select x64-on-x64. Complete the build successfully. This build is required to generate shared resources
|
||||||
|
|
||||||
|
1. Build ARM64 (Cross-Compiled): From the same build menu, select arm64-on-x64.
|
||||||
|
Build the ARM64 version of SoftEther VPN.
|
||||||
|
|
||||||
|
1. Building the Neo6 Virtual Network Adapter (ARM64)
|
||||||
|
|
||||||
|
Open the following project in Visual Studio:
|
||||||
|
```
|
||||||
|
.\src\Neo6\Neo6.vcxproj
|
||||||
|
```
|
||||||
|
|
||||||
|
SoftEther VPN Client uses the Neo6 virtual network adapter.
|
||||||
|
|
||||||
|
|
||||||
|
Driver Output Files
|
||||||
|
The ARM64 driver package includes:
|
||||||
|
```
|
||||||
|
Neo6_arm64_VPN.sys
|
||||||
|
Neo6_arm64_VPN.inf
|
||||||
|
```
|
||||||
|
Driver Signing and Installation (Windows ARM64)
|
||||||
|
```
|
||||||
|
Enable test-signing mode: bcdedit /set testsigning on
|
||||||
|
Reboot the system.
|
||||||
|
Testing signing:
|
||||||
|
Install the Neo6 ARM64 driver.
|
||||||
|
```
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
SoftEther VPN can be cross-compiled for Windows ARM64 on an x64 host
|
||||||
|
VPN Client works natively on Windows on ARM
|
||||||
|
Neo6 ARM64 driver requires Microsoft signing for production use
|
||||||
|
Test-signing is suitable for local development only
|
||||||
@ -1190,67 +1190,6 @@ void NnIpSendForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UCHAR ttl, UINT src_i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host IP address cache TTL in milliseconds (60 seconds)
|
|
||||||
#define HOST_IP_CACHE_TTL_MS 60000
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
LIST *new_list = NULL;
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
// Get new list while holding the lock to prevent multiple threads from refreshing
|
|
||||||
new_list = GetHostIPAddressList();
|
|
||||||
|
|
||||||
// Free old cache
|
|
||||||
if (v->HostIPAddressCache != NULL)
|
|
||||||
{
|
|
||||||
FreeHostIPAddressList(v->HostIPAddressCache);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set new cache with TTL
|
|
||||||
v->HostIPAddressCache = new_list;
|
|
||||||
v->HostIPCacheExpires = now + HOST_IP_CACHE_TTL_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if dest_ip matches any cached host IP
|
|
||||||
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
|
// 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)
|
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)
|
||||||
{
|
{
|
||||||
@ -1270,15 +1209,6 @@ void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UIN
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
|
||||||
if (IsDestinationHostOwnIP(v, dest_ip))
|
|
||||||
{
|
|
||||||
// Destination is the host's own IP - drop the packet
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = v->NativeNat;
|
t = v->NativeNat;
|
||||||
|
|
||||||
old_icmp_header = (ICMP_HEADER *)icmp_data;
|
old_icmp_header = (ICMP_HEADER *)icmp_data;
|
||||||
@ -1421,15 +1351,6 @@ void NnUdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
|
||||||
if (IsDestinationHostOwnIP(v, dest_ip))
|
|
||||||
{
|
|
||||||
// Destination is the host's own IP - drop the packet
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = v->NativeNat;
|
t = v->NativeNat;
|
||||||
|
|
||||||
// Search whether there is an existing session
|
// Search whether there is an existing session
|
||||||
@ -1528,15 +1449,6 @@ void NnTcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
|
||||||
if (IsDestinationHostOwnIP(v, dest_ip))
|
|
||||||
{
|
|
||||||
// Destination is the host's own IP - drop the packet
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = v->NativeNat;
|
t = v->NativeNat;
|
||||||
|
|
||||||
// Search whether there is an existing session
|
// Search whether there is an existing session
|
||||||
@ -10281,13 +10193,6 @@ void Virtual_Free(VH *v)
|
|||||||
|
|
||||||
LockVirtual(v);
|
LockVirtual(v);
|
||||||
{
|
{
|
||||||
// Free host IP cache
|
|
||||||
if (v->HostIPAddressCache != NULL)
|
|
||||||
{
|
|
||||||
FreeHostIPAddressList(v->HostIPAddressCache);
|
|
||||||
v->HostIPAddressCache = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the IP combining list
|
// Release the IP combining list
|
||||||
FreeIpCombineList(v);
|
FreeIpCombineList(v);
|
||||||
|
|
||||||
@ -10322,9 +10227,6 @@ void Virtual_Free(VH *v)
|
|||||||
}
|
}
|
||||||
UnlockVirtual(v);
|
UnlockVirtual(v);
|
||||||
|
|
||||||
// Release the host IP cache lock
|
|
||||||
DeleteLock(v->HostIPCacheLock);
|
|
||||||
|
|
||||||
// Release the logger
|
// Release the logger
|
||||||
FreeLog(v->Logger);
|
FreeLog(v->Logger);
|
||||||
}
|
}
|
||||||
@ -10455,11 +10357,6 @@ VH *NewVirtualHostEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_
|
|||||||
|
|
||||||
v->nat = nat;
|
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
|
// Examine whether ICMP Raw Socket can be created
|
||||||
s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
|
s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
|
|||||||
@ -313,11 +313,6 @@ struct VH
|
|||||||
HUB_OPTION *HubOption; // Pointer to the Virtual HUB options
|
HUB_OPTION *HubOption; // Pointer to the Virtual HUB options
|
||||||
|
|
||||||
NATIVE_NAT *NativeNat; // Native NAT
|
NATIVE_NAT *NativeNat; // Native NAT
|
||||||
|
|
||||||
// Host IP cache for Native NAT packet filtering
|
|
||||||
LIST *HostIPAddressCache; // Cached list of host IP addresses
|
|
||||||
UINT64 HostIPCacheExpires; // When the cache expires (tick64)
|
|
||||||
LOCK *HostIPCacheLock; // Lock for cache access
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Virtual host option
|
// Virtual host option
|
||||||
|
|||||||
@ -4761,7 +4761,7 @@ static void MY_SHA0_Transform(MY_SHA0_CTX* ctx) {
|
|||||||
UCHAR* p = ctx->buf;
|
UCHAR* p = ctx->buf;
|
||||||
int t;
|
int t;
|
||||||
for(t = 0; t < 16; ++t) {
|
for(t = 0; t < 16; ++t) {
|
||||||
UINT tmp = *p++ << 24;
|
UINT tmp = (UINT)*p++ << 24;
|
||||||
tmp |= *p++ << 16;
|
tmp |= *p++ << 16;
|
||||||
tmp |= *p++ << 8;
|
tmp |= *p++ << 8;
|
||||||
tmp |= *p++;
|
tmp |= *p++;
|
||||||
|
|||||||
@ -63,7 +63,7 @@ static int ydays[] =
|
|||||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
|
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
|
||||||
};
|
};
|
||||||
|
|
||||||
static UINT current_num_thread = 0;
|
static COUNTER *current_num_thread = NULL;
|
||||||
static UINT cached_number_of_cpus = 0;
|
static UINT cached_number_of_cpus = 0;
|
||||||
|
|
||||||
|
|
||||||
@ -776,6 +776,7 @@ void InitThreading()
|
|||||||
{
|
{
|
||||||
thread_pool = NewSk();
|
thread_pool = NewSk();
|
||||||
thread_count = NewCounter();
|
thread_count = NewCounter();
|
||||||
|
current_num_thread = NewCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release of thread pool
|
// Release of thread pool
|
||||||
@ -821,6 +822,9 @@ void FreeThreading()
|
|||||||
|
|
||||||
DeleteCounter(thread_count);
|
DeleteCounter(thread_count);
|
||||||
thread_count = NULL;
|
thread_count = NULL;
|
||||||
|
|
||||||
|
DeleteCounter(current_num_thread);
|
||||||
|
current_num_thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thread pool procedure
|
// Thread pool procedure
|
||||||
@ -1028,9 +1032,9 @@ THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
|
|||||||
|
|
||||||
Wait(pd->InitFinishEvent, INFINITE);
|
Wait(pd->InitFinishEvent, INFINITE);
|
||||||
|
|
||||||
current_num_thread++;
|
Inc(current_num_thread);
|
||||||
|
|
||||||
// Debug("current_num_thread = %u\n", current_num_thread);
|
// Debug("current_num_thread = %u\n", Count(current_num_thread));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1055,8 +1059,8 @@ void CleanupThread(THREAD *t)
|
|||||||
|
|
||||||
Free(t);
|
Free(t);
|
||||||
|
|
||||||
current_num_thread--;
|
Dec(current_num_thread);
|
||||||
//Debug("current_num_thread = %u\n", current_num_thread);
|
//Debug("current_num_thread = %u\n", Count(current_num_thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release thread (pool)
|
// Release thread (pool)
|
||||||
|
|||||||
@ -72,11 +72,26 @@ int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
|
|||||||
|
|
||||||
// Compiler dependent
|
// Compiler dependent
|
||||||
#ifndef OS_WIN32
|
#ifndef OS_WIN32
|
||||||
// Gcc compiler
|
// GCC or Clang compiler
|
||||||
#define GCC_PACKED __attribute__ ((__packed__))
|
#define GCC_PACKED __attribute__ ((__packed__))
|
||||||
|
// Clang compiler
|
||||||
|
#if defined(__has_feature)
|
||||||
|
#if __has_feature(thread_sanitizer)
|
||||||
|
#define ATTRIBUTE_NO_TSAN __attribute__((no_sanitize("thread")))
|
||||||
|
#endif // __has_feature(thread_sanitizer)
|
||||||
|
#endif // __has_feature
|
||||||
|
// GCC compiler
|
||||||
|
#if defined(__SANITIZE_THREAD__) && !defined(ATTRIBUTE_NO_TSAN)
|
||||||
|
#define ATTRIBUTE_NO_TSAN __attribute__((no_sanitize("thread")))
|
||||||
|
#endif // __SANITIZE_THREAD__
|
||||||
|
// Other or older Clang/GCC compiler
|
||||||
|
#ifndef ATTRIBUTE_NO_TSAN
|
||||||
|
#define ATTRIBUTE_NO_TSAN
|
||||||
|
#endif // ATTRIBUTE_NO_TSAN
|
||||||
#else // OS_WIN32
|
#else // OS_WIN32
|
||||||
// VC++ compiler
|
// VC++ compiler
|
||||||
#define GCC_PACKED
|
#define GCC_PACKED
|
||||||
|
#define ATTRIBUTE_NO_TSAN
|
||||||
#endif // OS_WIN32
|
#endif // OS_WIN32
|
||||||
|
|
||||||
// Macro that displays the current file name and line number
|
// Macro that displays the current file name and line number
|
||||||
|
|||||||
@ -470,6 +470,7 @@ LIST *LoadLangList()
|
|||||||
b = ReadDump(filename);
|
b = ReadDump(filename);
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
{
|
{
|
||||||
|
FreeLangList(o);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2140,9 +2140,13 @@ void UnixMemoryFree(void *addr)
|
|||||||
// SIGCHLD handler
|
// SIGCHLD handler
|
||||||
void UnixSigChldHandler(int sig)
|
void UnixSigChldHandler(int sig)
|
||||||
{
|
{
|
||||||
|
int old_errno = errno;
|
||||||
|
|
||||||
// Recall the zombie processes
|
// Recall the zombie processes
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||||
signal(SIGCHLD, UnixSigChldHandler);
|
signal(SIGCHLD, UnixSigChldHandler);
|
||||||
|
|
||||||
|
errno = old_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable core dump
|
// Disable core dump
|
||||||
|
|||||||
669
src/bin/hamcore/wwwroot/admin/default/package-lock.json
generated
669
src/bin/hamcore/wwwroot/admin/default/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user