mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2025-07-07 16:25:01 +03:00
Merge pull request #1867 from hiura2023/master
Bind outgoing connection to a specific IP address
This commit is contained in:
@ -13116,7 +13116,6 @@ SOCK *ListenEx63(UINT port, bool local_only, bool enable_ca, IP *listen_ip)
|
||||
#ifdef OS_WIN32
|
||||
if (enable_ca)
|
||||
{
|
||||
setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char *)&true_flag, sizeof(true_flag));
|
||||
backlog = 1;
|
||||
}
|
||||
#endif
|
||||
@ -13642,6 +13641,62 @@ 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 WSAEFAULT:
|
||||
Message = "Bad address.";
|
||||
break;
|
||||
|
||||
case WSAEWOULDBLOCK:
|
||||
Message = "Resource temporarily unavailable.";
|
||||
break;
|
||||
|
||||
case WSAEINPROGRESS:
|
||||
Message = "Operation now in progress.";
|
||||
break;
|
||||
|
||||
case WSAEALREADY:
|
||||
Message = "Operation already in progress.";
|
||||
break;
|
||||
|
||||
case WSAEAFNOSUPPORT:
|
||||
Message = "Address family not supported by protocol family.";
|
||||
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)
|
||||
{
|
||||
@ -13773,8 +13828,71 @@ 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];
|
||||
//memset(tmp, 0, sizeof(tmp));
|
||||
//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;
|
||||
|
||||
Zero(&sockaddr_in, sizeof(sockaddr_in));
|
||||
|
||||
// Set up the sockaddr structure
|
||||
sockaddr_in.sin_family = AF_INET;
|
||||
IPToInAddr(&sockaddr_in.sin_addr, ip);
|
||||
sockaddr_in.sin_port = htons((USHORT)port);
|
||||
//inet_pton(AF_INET, tmp, &addr_in.sin_addr.s_addr);
|
||||
|
||||
UINT true_flag = 1;
|
||||
// This only have enabled for UNIX system since there is a bug
|
||||
// in the implementation of REUSEADDR in Windows OS
|
||||
(void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&true_flag, sizeof(true_flag));
|
||||
|
||||
// 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;
|
||||
|
||||
Zero(&sockaddr_in, sizeof(sockaddr_in));
|
||||
|
||||
// Set up the sockaddr structure
|
||||
sockaddr_in.sin6_family = AF_INET6;
|
||||
IPToInAddr6(&sockaddr_in.sin6_addr, ip);
|
||||
sockaddr_in.sin6_scope_id = ip->ipv6_scope_id;
|
||||
sockaddr_in.sin6_port = htons((USHORT)port);
|
||||
//inet_pton(AF_INET6, tmp, &sockaddr_in.sin6_addr.s6_bytes);
|
||||
|
||||
UINT true_flag = 1;
|
||||
#ifdef OS_UNIX
|
||||
// It is necessary to set the IPv6 Only flag on a UNIX system
|
||||
(void)setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof(true_flag));
|
||||
#endif // OS_UNIX
|
||||
// This only have enabled for UNIX system since there is a bug
|
||||
// in the implementation of REUSEADDR in Windows OS
|
||||
(void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&true_flag, sizeof(true_flag));
|
||||
|
||||
// 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;
|
||||
@ -13791,6 +13909,34 @@ 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;
|
||||
IP tmpIP;
|
||||
|
||||
if (localIP == BIND_LOCALIP_NULL) {
|
||||
StrToIP(&tmpIP, "0.0.0.0"); // A NULL address for the argument "localIP" is treated as if "0::0" in IPV4 was specified.
|
||||
localIP = &tmpIP;
|
||||
}
|
||||
|
||||
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
|
||||
@ -14053,7 +14199,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;
|
||||
}
|
||||
p->LocalIP = BIND_LOCALIP_NULL;
|
||||
p->LocalPort = BIND_LOCALPORT_NULL;
|
||||
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;
|
||||
@ -14106,7 +14266,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)
|
||||
{
|
||||
@ -14408,7 +14569,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;
|
||||
}
|
||||
p->LocalIP = BIND_LOCALIP_NULL;
|
||||
p->LocalPort = BIND_LOCALPORT_NULL;
|
||||
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;
|
||||
@ -14463,6 +14638,34 @@ 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;
|
||||
IP tmpIP;
|
||||
|
||||
if (p->LocalIP == BIND_LOCALIP_NULL) {
|
||||
StrToIP(&tmpIP, "0::0"); // A NULL address for the argument "p->LocalIP" is treated as if "0::0" in IPV6 was specified.
|
||||
p->LocalIP = &tmpIP;
|
||||
}
|
||||
|
||||
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
|
||||
@ -14588,6 +14791,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;
|
||||
@ -14683,6 +14898,16 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
||||
if (LIST_NUM(iplist_v6) > 0)
|
||||
{
|
||||
p6.IpList = iplist_v6;
|
||||
|
||||
if (localIP == BIND_LOCALIP_NULL) {
|
||||
p6.LocalIP = BIND_LOCALIP_NULL; // Make the NULL address passing through
|
||||
}
|
||||
else {
|
||||
CopyIP(&p6.LocalIP_Cache, localIP);
|
||||
p6.LocalIP = &p6.LocalIP_Cache;
|
||||
}
|
||||
p6.LocalPort = localport;
|
||||
|
||||
p6.Port = port;
|
||||
p6.Timeout = timeout;
|
||||
StrCpy(p6.Hostname, sizeof(p6.Hostname), hostname);
|
||||
@ -14696,13 +14921,24 @@ 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;
|
||||
|
||||
if (localIP == BIND_LOCALIP_NULL) {
|
||||
p4.LocalIP = BIND_LOCALIP_NULL; // Make the NULL address passing through
|
||||
}
|
||||
else {
|
||||
CopyIP(&p4.LocalIP_Cache, localIP);
|
||||
p4.LocalIP = &p4.LocalIP_Cache;
|
||||
}
|
||||
p4.LocalPort = localport;
|
||||
|
||||
p4.Port = port;
|
||||
p4.Timeout = timeout;
|
||||
StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname);
|
||||
@ -14721,7 +14957,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)
|
||||
|
@ -812,6 +812,9 @@ struct RUDP_STACK
|
||||
struct CONNECT_SERIAL_PARAM
|
||||
{
|
||||
LIST *IpList;
|
||||
UINT LocalPort; // Local port number to bind
|
||||
IP *LocalIP; // Local IP address to bind. NULL address allowed to use.
|
||||
IP LocalIP_Cache; // Local IP address to bind
|
||||
UINT Port;
|
||||
UINT Timeout;
|
||||
char Hostname[MAX_SIZE];
|
||||
@ -950,6 +953,10 @@ void ConnectThreadForRUDP(THREAD *thread, void *param);
|
||||
void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param);
|
||||
void ConnectThreadForIPv4(THREAD *thread, void *param);
|
||||
void ConnectThreadForIPv6(THREAD *thread, void *param);
|
||||
|
||||
void BindConnectThreadForIPv4(THREAD *thread, void *param);
|
||||
void BindConnectThreadForIPv6(THREAD *thread, void *param);
|
||||
|
||||
SOCK *CreateTCPSock(SOCKET s, bool is_ipv6, IP *current_ip, bool no_get_hostname, char *hostname_original);
|
||||
SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname);
|
||||
RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id, IP *listen_ip);
|
||||
@ -1113,6 +1120,14 @@ SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
||||
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 *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);
|
||||
SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag);
|
||||
|
||||
// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one.
|
||||
#define BIND_LOCALIP_NULL NULL // NULL IP address specifies no binding
|
||||
#define BIND_LOCALPORT_NULL 0 // NULL port number specifies no binding
|
||||
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);
|
||||
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);
|
||||
SOCKET BindConnectTimeoutIPv4(IP *localIP, UINT localport, IP *ip, UINT port, UINT timeout, bool *cancel_flag);
|
||||
|
||||
bool SetSocketBufferSize(SOCKET s, bool send, UINT size);
|
||||
UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size);
|
||||
void InitUdpSocketBufferSize(SOCKET s);
|
||||
|
@ -16,11 +16,25 @@ SOCK *Internal_ProxyTcpConnect(PROXY_PARAM_IN *param, volatile bool *cancel_flag
|
||||
}
|
||||
#endif
|
||||
|
||||
return ConnectEx4(param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip);
|
||||
//return ConnectEx4(param->Hostname, param->Port, param->Timeout, (bool*)cancel_flag, NULL, NULL, false, true, resolved_ip);
|
||||
return BindConnectEx4(param->BindLocalIP, param->BindLocalPort, param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip);
|
||||
}
|
||||
|
||||
// Connect to an HTTP proxy
|
||||
UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
|
||||
{
|
||||
// Validate arguments
|
||||
if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname))
|
||||
{
|
||||
return PROXY_ERROR_PARAMETER;
|
||||
}
|
||||
in->BindLocalIP = BIND_LOCALIP_NULL;
|
||||
in->BindLocalPort = BIND_LOCALPORT_NULL;
|
||||
return BindProxyHttpConnect(out, in, cancel_flag);
|
||||
}
|
||||
|
||||
// Connect to an HTTP proxy
|
||||
UINT BindProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
|
||||
{
|
||||
bool dummy_cancel_flag = false, use_auth = false;
|
||||
char target_hostname[MAX_HOST_NAME_LEN + 1];
|
||||
@ -208,6 +222,19 @@ FAILURE:
|
||||
|
||||
// Connect to a SOCKS5 proxy (RFC1928, RFC1929 defines username/password authentication)
|
||||
UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
|
||||
{
|
||||
// Validate arguments
|
||||
if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname))
|
||||
{
|
||||
return PROXY_ERROR_PARAMETER;
|
||||
}
|
||||
in->BindLocalIP = BIND_LOCALIP_NULL;
|
||||
in->BindLocalPort = BIND_LOCALPORT_NULL;
|
||||
return BindProxySocks5Connect(out, in, cancel_flag);
|
||||
}
|
||||
|
||||
// Connect to a SOCKS5 proxy (RFC1928, RFC1929 defines username/password authentication)
|
||||
UINT BindProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
|
||||
{
|
||||
bool dummy_cancel_flag = false;
|
||||
UCHAR tmp, recv_buf[2], *recv_buf_final;
|
||||
@ -521,6 +548,19 @@ FAILURE:
|
||||
|
||||
// Connect to a SOCKS4 proxy
|
||||
UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
|
||||
{
|
||||
// Validate arguments
|
||||
if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname))
|
||||
{
|
||||
return PROXY_ERROR_PARAMETER;
|
||||
}
|
||||
in->BindLocalIP = BIND_LOCALIP_NULL;
|
||||
in->BindLocalPort = BIND_LOCALPORT_NULL;
|
||||
return BindProxySocks4Connect(out, in, cancel_flag);
|
||||
}
|
||||
|
||||
// Connect to a SOCKS4 proxy
|
||||
UINT BindProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
|
||||
{
|
||||
bool dummy_cancel_flag = false;
|
||||
UCHAR tmp, recv_buf[8];
|
||||
|
@ -30,6 +30,8 @@ struct PROXY_PARAM_IN
|
||||
UINT Timeout;
|
||||
char HttpCustomHeader[HTTP_CUSTOM_HEADER_MAX_SIZE];
|
||||
char HttpUserAgent[HTTP_HEADER_USER_AGENT_MAX_SIZE + 1];
|
||||
IP *BindLocalIP; // Source IP address for outgoing connection
|
||||
UINT BindLocalPort; // UINT used not USHORT // Source port number for outgoing connection
|
||||
#ifdef OS_WIN32
|
||||
void *Hwnd;
|
||||
#endif
|
||||
@ -45,4 +47,9 @@ UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *c
|
||||
UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
|
||||
UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
|
||||
|
||||
// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one.
|
||||
UINT BindProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
|
||||
UINT BindProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
|
||||
UINT BindProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user