BIO* bufferedBio = NULL;
rdpSettings* settings = rdg->settings;
const char* peerHostname = settings->GatewayHostname;
- int peerPort = settings->GatewayPort;
+ UINT16 peerPort = settings->GatewayPort;
BOOL isProxyConnection = FALSE;
+ int outChannelSocket = 0;
+ char* gatewayAddress = NULL;
assert(hostname != NULL);
if (settings->ProxyType)
peerPort = settings->ProxyPort;
isProxyConnection = TRUE;
}
+ else
+ {
+ /**
+ * if settings->GatewayHostname is a name, it may be mapped to more than one
+ * IP address (thus potentially multiple gateway servers) - to avoid openning
+ * the IN channel with one server and the OUT channel with another server
+ * we want to use the same IP when connecting to both IN and OUT channels
+ * below we get the peer ip address in use by the OUT channel and use it
+ * when opening the connection for the IN channel
+ */
+ BIO_get_socket(rdg->tlsOut->underlying, &outChannelSocket);
+ gatewayAddress = freerdp_tcp_get_peer_address(outChannelSocket);
+
+ if (gatewayAddress == NULL)
+ {
+ WLog_DBG(TAG,
+ "RDG out channel was created but gateway IP couldn't be resolved. Falling back to resolving gateway hostname again for IN channel.");
+ }
+ else
+ {
+ WLog_DBG(TAG, "Gateway hostname %s resolved to IP %s.", peerHostname, gatewayAddress);
+ peerHostname = gatewayAddress;
+ }
+ }
sockfd = freerdp_tcp_connect(rdg->context, settings, peerHostname,
peerPort, timeout);
if (sockfd < 1)
+ {
+ free(gatewayAddress);
return FALSE;
+ }
socketBio = BIO_new(BIO_s_simple_socket());
if (!socketBio)
{
+ free(gatewayAddress);
closesocket(sockfd);
return FALSE;
}
if (!bufferedBio)
{
+ free(gatewayAddress);
BIO_free(socketBio);
return FALSE;
}
if (!status)
{
+ free(gatewayAddress);
BIO_free_all(bufferedBio);
return FALSE;
}
if (status < 1)
{
+ free(gatewayAddress);
return FALSE;
}
return bio_methods;
}
-static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
+static char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
{
- socklen_t length;
char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 };
- struct sockaddr_storage saddr = { 0 };
- struct sockaddr_in6* sockaddr_ipv6 = (struct sockaddr_in6*)&saddr;
- struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*)&saddr;
- length = sizeof(struct sockaddr_storage);
+ struct sockaddr_in6* sockaddr_ipv6 = (struct sockaddr_in6*)addr;
+ struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*)addr;
- if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
+ if (addr == NULL)
+ {
return NULL;
+ }
switch (sockaddr_ipv4->sin_family)
{
return NULL;
}
- if (pIPv6)
+ if (pIPv6 != NULL)
+ {
*pIPv6 = (sockaddr_ipv4->sin_family == AF_INET6);
+ }
return _strdup(ipAddress);
}
+static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
+{
+ struct sockaddr_storage saddr = { 0 };
+ socklen_t length = sizeof(struct sockaddr_storage);
+
+ if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
+ {
+ return NULL;
+ }
+
+ return freerdp_tcp_address_to_string(&saddr, pIPv6);
+}
+
+char* freerdp_tcp_get_peer_address(int sockfd)
+{
+ struct sockaddr_storage saddr = { 0 };
+ socklen_t length = sizeof(struct sockaddr_storage);
+
+ if (getpeername(sockfd, (struct sockaddr*)&saddr, &length) != 0)
+ {
+ return NULL;
+ }
+
+ return freerdp_tcp_address_to_string(&saddr, NULL);
+}
+
static int freerdp_uds_connect(const char* path)
{
#ifndef _WIN32
if (sockfd <= 0)
{
char port_str[16];
+ char* peerAddress;
struct addrinfo hints;
struct addrinfo* addr;
struct addrinfo* result;
return -1;
}
+ if ((peerAddress = freerdp_tcp_address_to_string(addr->ai_addr, NULL)) != NULL)
+ {
+ WLog_DBG(TAG, "connecting to peer %s", peerAddress);
+ free(peerAddress);
+ }
+
if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr,
addr->ai_addrlen, timeout))
{