summaryrefslogtreecommitdiff
path: root/src/core/wee-network.c
diff options
context:
space:
mode:
authorAndrew Potter <agpotter@gmail.com>2014-01-09 12:48:54 +0100
committerSebastien Helleu <flashcode@flashtux.org>2014-01-09 12:48:54 +0100
commit144dc60d0ab062aa5b3943d57f8f6515310f2dd5 (patch)
tree06c0e13ad72be462a3b018cf9905c5af5921ff07 /src/core/wee-network.c
parent9040dfbf521b12b675b6f7d5d93bb10767a40f90 (diff)
downloadweechat-144dc60d0ab062aa5b3943d57f8f6515310f2dd5.zip
xfer: add support of IPv6 for DCC chat/file (patch #7992)
Diffstat (limited to 'src/core/wee-network.c')
-rw-r--r--src/core/wee-network.c88
1 files changed, 58 insertions, 30 deletions
diff --git a/src/core/wee-network.c b/src/core/wee-network.c
index 49b258d49..1066d2ba9 100644
--- a/src/core/wee-network.c
+++ b/src/core/wee-network.c
@@ -645,56 +645,84 @@ network_connect (int sock, const struct sockaddr *addr, socklen_t addrlen)
* process.
*
* Returns:
- * 1: OK
- * 0: error
+ * >= 0: connected socket fd
+ * -1: error
*/
int
-network_connect_to (const char *proxy, int sock,
- unsigned long address, int port)
+network_connect_to (const char *proxy, struct sockaddr *address,
+ socklen_t address_length)
{
struct t_proxy *ptr_proxy;
- struct sockaddr_in addr;
- struct hostent *hostent;
- char *ip4;
+ struct addrinfo *proxy_addrinfo, hints;
+ char str_port[16], ip[NI_MAXHOST];
+ int port, sock;
+
+ sock = -1;
+ proxy_addrinfo = NULL;
ptr_proxy = NULL;
if (proxy && proxy[0])
{
ptr_proxy = proxy_search (proxy);
if (!ptr_proxy)
- return 0;
+ return -1;
}
if (ptr_proxy)
{
- memset (&addr, 0, sizeof (addr));
- addr.sin_addr.s_addr = htonl (address);
- ip4 = inet_ntoa(addr.sin_addr);
-
- memset (&addr, 0, sizeof (addr));
- addr.sin_port = htons (CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_PORT]));
- addr.sin_family = AF_INET;
- hostent = gethostbyname (CONFIG_STRING(ptr_proxy->options[PROXY_OPTION_ADDRESS]));
- if (!hostent)
- return 0;
- memcpy(&(addr.sin_addr), *(hostent->h_addr_list), sizeof(struct in_addr));
- if (!network_connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
- return 0;
- if (!network_pass_proxy (proxy, sock, ip4, port))
- return 0;
+ /* get IP address/port */
+ if (getnameinfo (address, address_length, ip, sizeof (ip),
+ str_port, sizeof (str_port),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ {
+ goto error;
+ }
+ port = atoi (str_port);
+
+ /* get sockaddr for proxy */
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICSERV;
+ snprintf (str_port, sizeof (str_port), "%d",
+ CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_PORT]));
+ if (getaddrinfo (CONFIG_STRING(ptr_proxy->options[PROXY_OPTION_ADDRESS]),
+ str_port, &hints, &proxy_addrinfo) != 0)
+ {
+ goto error;
+ }
+
+ /* connect and pass address to proxy */
+ sock = socket (proxy_addrinfo->ai_family, SOCK_STREAM, 0);
+ if (sock == -1)
+ goto error;
+ if (!network_connect (sock, proxy_addrinfo->ai_addr,
+ proxy_addrinfo->ai_addrlen))
+ goto error;
+ if (!network_pass_proxy (proxy, sock, ip, port))
+ goto error;
}
else
{
- memset (&addr, 0, sizeof (addr));
- addr.sin_port = htons (port);
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl (address);
- if (!network_connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
- return 0;
+ sock = socket (address->sa_family, SOCK_STREAM, 0);
+ if (sock == -1)
+ goto error;
+ if (!network_connect (sock, address, address_length))
+ goto error;
}
- return 1;
+ if (proxy_addrinfo)
+ freeaddrinfo (proxy_addrinfo);
+
+ return sock;
+
+error:
+ if (sock >= 0)
+ close (sock);
+ if (proxy_addrinfo)
+ freeaddrinfo (proxy_addrinfo);
+ return -1;
}
/*