1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-07-08 00:34:57 +03:00

bind outgoing connection

This commit is contained in:
hiura
2023-06-28 23:18:09 +09:00
parent 1c0bdb0c30
commit e4330ca71a
16 changed files with 479 additions and 29 deletions

View File

@ -13634,6 +13634,54 @@ int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool
}
}
#else
#if 0
LPSTR PrintError(int ErrorCode)
{
static char Message[1024];
// If this program was multithreaded, we'd want to use
// FORMAT_MESSAGE_ALLOCATE_BUFFER instead of a static buffer here.
// (And of course, free the buffer when we were done with it)
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)Message, 1024, NULL);
return Message;
}
#else
char *PrintError(int ErrorCode)
{
char *Message;
switch (ErrorCode) {
case WSAEWOULDBLOCK:
Message = "Resource temporarily unavailable.";
break;
case WSAEINPROGRESS:
Message = "Operation now in progress.";
break;
case WSAEALREADY:
Message = "Operation already in progress.";
break;
case WSAEADDRINUSE:
Message = "Address already in use.";
break;
case WSAEADDRNOTAVAIL:
Message = "Cannot assign requested address.";
break;
default:
Message = "";
break;
}
return Message;
}
#endif
// Connection with timeout (Win32 version)
int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
{
@ -13765,8 +13813,63 @@ void SetSockHighPriority(SOCK *s, bool flag)
SetSockTos(s, (flag ? 16 : 0));
}
// Bind the socket to IPv4 or IPV6 address
int bind_sock(SOCKET sock, IP* ip, UINT port)
{
//char tmp[MAX_HOST_NAME_LEN + 1];
//IPToStr(tmp, sizeof(tmp), ip);
//Debug("_____ bind_sock(): Binding... IP address %s:%d\n", tmp, port);
if (IsIP4(ip))
{
// Declare variables
struct sockaddr_in sockaddr_in;
struct in_addr in_addr;
Zero(&sockaddr_in, sizeof(sockaddr_in));
Zero(&in_addr, sizeof(in_addr));
IPToInAddr(&in_addr, ip);
// Set up the sockaddr structure
sockaddr_in.sin_family = AF_INET;
//inet_pton(AF_INET, tmp, &addr_in.sin_addr.s_addr);
sockaddr_in.sin_addr.s_addr = in_addr.s_addr;
sockaddr_in.sin_port = htons((USHORT)port);
// Bind the socket using the information in the sockaddr structure
return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)));
}
else
{
// Declare variables
struct sockaddr_in6 sockaddr_in;
struct in6_addr in_addr;
Zero(&sockaddr_in, sizeof(sockaddr_in));
Zero(&in_addr, sizeof(in_addr));
IPToInAddr6(&in_addr, ip);
// Set up the sockaddr structure
sockaddr_in.sin6_family = AF_INET6;
//inet_pton(AF_INET6, tmp, &sockaddr_in.sin6_addr.s6_bytes);
Copy(&sockaddr_in.sin6_addr, &in_addr, sizeof(in_addr));
sockaddr_in.sin6_port = htons((USHORT)port);
// Bind the socket using the information in the sockaddr structure
return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)));
}
}
// Connect to the IPv4 host using a socket
SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag)
SOCKET ConnectTimeoutIPv4(IP* ip, UINT port, UINT timeout, bool* cancel_flag)
{
return BindConnectTimeoutIPv4(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, ip, port, timeout, cancel_flag);
}
// Connect to the IPv4 host using a socket
SOCKET BindConnectTimeoutIPv4(IP* localIP, UINT localport, IP* ip, UINT port, UINT timeout, bool* cancel_flag)
{
SOCKET s;
struct sockaddr_in sockaddr4;
@ -13783,6 +13886,28 @@ SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag)
// Socket creation
s = socket(AF_INET, SOCK_STREAM, 0);
// Top of Bind outgoing connection
if (s != INVALID_SOCKET) {
int ier;
if ((IsZeroIP(localIP) == false) || (localport != 0)) {
// Bind the socket
if (bind_sock(s, localIP, localport) != 0) {
#ifdef OS_WIN32
ier = WSAGetLastError();
Debug("IPv4 bind() failed with error: %d %s\n", ier, PrintError(ier));
#else
Debug("IPv4 bind() failed with error: %d %s\n", errno, strerror(errno));
#endif
closesocket(s);
s = INVALID_SOCKET;
}
}
}
// Bottom of Bind outgoing connection
if (s != INVALID_SOCKET)
{
// Connection
@ -14045,7 +14170,21 @@ void ConnectThreadForRUDP(THREAD *thread, void *param)
}
// IPv4 connection thread (multiple protocols, multiple addresses)
void ConnectThreadForIPv4(THREAD *thread, void *param)
void ConnectThreadForIPv4(THREAD* thread, void* param)
{
CONNECT_SERIAL_PARAM* p = (CONNECT_SERIAL_PARAM*)param;
if (thread == NULL || p == NULL)
{
return;
}
StrToIP(&p->LocalIP, "0.0.0.0");
p->LocalPort = 0;
return BindConnectThreadForIPv4(thread, param);
}
// IPv4 connection thread (multiple protocols, multiple addresses)
//void ConnectThreadForIPv4(THREAD* thread, void* param)
void BindConnectThreadForIPv4(THREAD *thread, void *param)
{
SOCKET s = INVALID_SOCKET;
IP current_ip;
@ -14098,7 +14237,8 @@ void ConnectThreadForIPv4(THREAD *thread, void *param)
if (use_natt == false)
{
// Normal connection without using NAT-T
s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag);
// s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag);
s = BindConnectTimeoutIPv4(&p->LocalIP, p->LocalPort, ip, p->Port, p->Timeout, p->CancelFlag);
if (s != INVALID_SOCKET)
{
@ -14400,7 +14540,21 @@ void ConnectThreadForIPv4(THREAD *thread, void *param)
}
// IPv6 connection thread (multiple addresses)
void ConnectThreadForIPv6(THREAD *thread, void *param)
void ConnectThreadForIPv6(THREAD* thread, void* param)
{
CONNECT_SERIAL_PARAM* p = (CONNECT_SERIAL_PARAM*)param;
if (thread == NULL || p == NULL)
{
return;
}
StrToIP(&p->LocalIP, "0::0");
p->LocalPort = 0;
return BindConnectThreadForIPv6(thread, param);
}
// IPv6 connection thread (multiple addresses)
//void ConnectThreadForIPv6(THREAD *thread, void *param)
void BindConnectThreadForIPv6(THREAD* thread, void* param)
{
SOCKET s = INVALID_SOCKET;
IP current_ip;
@ -14455,6 +14609,28 @@ void ConnectThreadForIPv6(THREAD *thread, void *param)
// Socket creation
s = socket(AF_INET6, SOCK_STREAM, 0);
// Top of Bind outgoing connection
if (s != INVALID_SOCKET){
int ier;
if ((IsZeroIP(&p->LocalIP) == false) || (p->LocalPort != 0)){
// Bind the socket
if (bind_sock(s, &p->LocalIP, p->LocalPort) != 0) {
#ifdef OS_WIN32
ier = WSAGetLastError();
Debug("IPv6 bind() failed with error: %d %s\n", ier, PrintError(ier));
#else
Debug("IPv6 bind() failed with error: %d %s\n", errno, strerror(errno));
#endif
closesocket(s);
s = INVALID_SOCKET;
}
}
}
// Bottom of Bind outgoing connection
if (s != INVALID_SOCKET)
{
// Connection
@ -14580,6 +14756,18 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
return ConnectEx5(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip);
}
SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{
return BindConnectEx5(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, ssl_option, ssl_err, hint_str, ret_ip);
}
//SOCK* ConnectEx4(char* hostname, UINT port, UINT timeout, bool* cancel_flag, char* nat_t_svc_name, UINT* nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP* ret_ip)
SOCK *BindConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip)
{
// return ConnectEx5(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip);
return BindConnectEx5(localIP, localport, hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip);
}
//SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
SOCK *BindConnectEx5(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{
bool dummy = false;
bool use_natt = false;
@ -14675,6 +14863,12 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
if (LIST_NUM(iplist_v6) > 0)
{
p6.IpList = iplist_v6;
//ZeroIP6(&p6.LocalIP);
Zero(&p6.LocalIP, sizeof(p6.LocalIP)); // Zero IP6 must be used when argument localIP is NULL
CopyIP(&p6.LocalIP, localIP);
p6.LocalPort = localport;
p6.Port = port;
p6.Timeout = timeout;
StrCpy(p6.Hostname, sizeof(p6.Hostname), hostname);
@ -14688,13 +14882,19 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
p6.Ret_Ip = &ret_ip6;
p6.RetryDelay = 250;
p6.Delay = 0;
t6 = NewThread(ConnectThreadForIPv6, &p6);
// t6 = NewThread(ConnectThreadForIPv6, &p6);
t6 = NewThread(BindConnectThreadForIPv6, &p6); // For binding a socket
}
// IPv4 connection thread
if (LIST_NUM(iplist_v4) > 0)
{
p4.IpList = iplist_v4;
ZeroIP4(&p4.LocalIP); // Zero IP4 must be used when argument localIP is NULL
CopyIP(&p4.LocalIP, localIP);
p4.LocalPort = localport;
p4.Port = port;
p4.Timeout = timeout;
StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname);
@ -14713,7 +14913,8 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
p4.Ret_Ip = &ret_ip4;
p4.RetryDelay = 250;
p4.Delay = 250; // Delay by 250ms to prioritize IPv6 (RFC 6555 recommends 150-250ms, Chrome uses 300ms)
t4 = NewThread(ConnectThreadForIPv4, &p4);
// t4 = NewThread(ConnectThreadForIPv4, &p4);
t4 = NewThread(BindConnectThreadForIPv4, &p4); // For binding a socket
}
if (t6 == NULL || t4 == NULL)