mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
- Andreas Schuldei improved Phil Blundell's patch for IPv6 using c-ares, and I
edited it slightly. Now you should be able to use IPv6 addresses fine even with libcurl built to use c-ares.
This commit is contained in:
parent
d4b253ba3e
commit
0cd8840dba
5
CHANGES
5
CHANGES
@ -6,6 +6,11 @@
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Daniel Stenberg (9 Jul 2008)
|
||||||
|
- Andreas Schuldei improved Phil Blundell's patch for IPv6 using c-ares, and I
|
||||||
|
edited it slightly. Now you should be able to use IPv6 addresses fine even
|
||||||
|
with libcurl built to use c-ares.
|
||||||
|
|
||||||
Daniel Fandrich (9 Jul 2008)
|
Daniel Fandrich (9 Jul 2008)
|
||||||
- Fixed an OOM handling problem that cause test 11 to fail the torture test.
|
- Fixed an OOM handling problem that cause test 11 to fail the torture test.
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ This release includes the following bugfixes:
|
|||||||
o range numbers could be made to wrongly get output as signed
|
o range numbers could be made to wrongly get output as signed
|
||||||
o unexpected 1xx responses hung transfers
|
o unexpected 1xx responses hung transfers
|
||||||
o FTP transfers segfault when using different CURLOPT_FTP_FILEMETHOD
|
o FTP transfers segfault when using different CURLOPT_FTP_FILEMETHOD
|
||||||
|
o c-ares powered libcurls can resolve/use IPv6 addresses
|
||||||
|
|
||||||
This release includes the following known bugs:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ advice from friends like these:
|
|||||||
Lenny Rachitsky, Axel Tillequin, Arnaud Ebalard, Yang Tse, Dan Fandrich,
|
Lenny Rachitsky, Axel Tillequin, Arnaud Ebalard, Yang Tse, Dan Fandrich,
|
||||||
Rob Crittenden, Dengminwen, Christopher Palow, Hans-Jurgen May,
|
Rob Crittenden, Dengminwen, Christopher Palow, Hans-Jurgen May,
|
||||||
Phil Pellouchoud, Eduard Bloch, John Lightsey, Stephen Collyer, Tor Arntsen,
|
Phil Pellouchoud, Eduard Bloch, John Lightsey, Stephen Collyer, Tor Arntsen,
|
||||||
Rolland Dudemaine, Phil Blundell, Scott Barrett
|
Rolland Dudemaine, Phil Blundell, Scott Barrett, Andreas Schuldei
|
||||||
|
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
@ -297,6 +297,70 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
||||||
|
/*
|
||||||
|
* Curl_ip2addr6() takes an ipv6 internet address as input parameter
|
||||||
|
* together with a pointer to the string version of the address, and it
|
||||||
|
* returns a Curl_addrinfo chain filled in correctly with information for this
|
||||||
|
* address/host.
|
||||||
|
*
|
||||||
|
* The input parameters ARE NOT checked for validity but they are expected
|
||||||
|
* to have been checked already when this is called.
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_ip2addr6(struct in6_addr *in,
|
||||||
|
const char *hostname, int port)
|
||||||
|
{
|
||||||
|
Curl_addrinfo *ai;
|
||||||
|
|
||||||
|
#if defined(VMS) && defined(__INITIAL_POINTER_SIZE) && \
|
||||||
|
(__INITIAL_POINTER_SIZE == 64)
|
||||||
|
#pragma pointer_size save
|
||||||
|
#pragma pointer_size short
|
||||||
|
#pragma message disable PTRMISMATCH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct hostent *h;
|
||||||
|
struct in6_addr *addrentry;
|
||||||
|
struct namebuf6 {
|
||||||
|
struct hostent hostentry;
|
||||||
|
char *h_addr_list[2];
|
||||||
|
struct in6_addr addrentry;
|
||||||
|
char hostname[1];
|
||||||
|
};
|
||||||
|
struct namebuf6 *buf = malloc(sizeof (struct namebuf6) + strlen(hostname));
|
||||||
|
|
||||||
|
if(!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
h = &buf->hostentry;
|
||||||
|
h->h_addr_list = &buf->h_addr_list[0];
|
||||||
|
addrentry = &buf->addrentry;
|
||||||
|
memcpy(addrentry, in, sizeof (*in));
|
||||||
|
h->h_addr_list[0] = (char*)addrentry;
|
||||||
|
h->h_addr_list[1] = NULL; /* terminate list of entries */
|
||||||
|
h->h_name = &buf->hostname[0];
|
||||||
|
h->h_aliases = NULL;
|
||||||
|
h->h_addrtype = AF_INET6;
|
||||||
|
|
||||||
|
/* Now store the dotted version of the address */
|
||||||
|
strcpy (h->h_name, hostname);
|
||||||
|
|
||||||
|
#if defined(VMS) && defined(__INITIAL_POINTER_SIZE) && \
|
||||||
|
(__INITIAL_POINTER_SIZE == 64)
|
||||||
|
#pragma pointer_size restore
|
||||||
|
#pragma message enable PTRMISMATCH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ai = Curl_he2ai(h, port);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
#endif /* CURLRES_IPV6 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_getaddrinfo() - when using ares
|
* Curl_getaddrinfo() - when using ares
|
||||||
*
|
*
|
||||||
@ -313,7 +377,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
char *bufp;
|
char *bufp;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
in_addr_t in = inet_addr(hostname);
|
in_addr_t in = inet_addr(hostname);
|
||||||
|
int family = PF_INET;
|
||||||
|
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
||||||
|
struct in6_addr in6;
|
||||||
|
#endif /* CURLRES_IPV6 */
|
||||||
*waitp = FALSE;
|
*waitp = FALSE;
|
||||||
|
|
||||||
if(in != CURL_INADDR_NONE) {
|
if(in != CURL_INADDR_NONE) {
|
||||||
@ -321,6 +388,23 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
return Curl_ip2addr(in, hostname, port);
|
return Curl_ip2addr(in, hostname, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
||||||
|
if (inet_pton (AF_INET6, hostname, &in6) > 0) {
|
||||||
|
/* This must be an IPv6 address literal. */
|
||||||
|
return Curl_ip2addr6(&in6, hostname, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(data->set.ip_version) {
|
||||||
|
case CURL_IPRESOLVE_V4:
|
||||||
|
family = PF_INET;
|
||||||
|
break;
|
||||||
|
default: /* by default we try ipv6, as PF_UNSPEC isn't supported by (c-)ares */
|
||||||
|
case CURL_IPRESOLVE_V6:
|
||||||
|
family = PF_INET6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* CURLRES_IPV6 */
|
||||||
|
|
||||||
bufp = strdup(hostname);
|
bufp = strdup(hostname);
|
||||||
|
|
||||||
if(bufp) {
|
if(bufp) {
|
||||||
@ -332,7 +416,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
conn->async.dns = NULL; /* clear */
|
conn->async.dns = NULL; /* clear */
|
||||||
|
|
||||||
/* areschannel is already setup in the Curl_open() function */
|
/* areschannel is already setup in the Curl_open() function */
|
||||||
ares_gethostbyname(data->state.areschannel, hostname, PF_INET,
|
ares_gethostbyname(data->state.areschannel, hostname, family,
|
||||||
(ares_host_callback)Curl_addrinfo4_callback, conn);
|
(ares_host_callback)Curl_addrinfo4_callback, conn);
|
||||||
|
|
||||||
*waitp = TRUE; /* please wait for the response */
|
*waitp = TRUE; /* please wait for the response */
|
||||||
|
119
lib/hostip.c
119
lib/hostip.c
@ -545,7 +545,8 @@ Curl_addrinfo *Curl_addrinfo_copy(const void *org, int port)
|
|||||||
#endif /* CURLRES_ADDRINFO_COPY */
|
#endif /* CURLRES_ADDRINFO_COPY */
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Only for plain-ipv4 and c-ares builds
|
* Only for plain-ipv4 and c-ares builds (NOTE: c-ares builds can be IPv6
|
||||||
|
* enabled)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
|
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
|
||||||
@ -630,6 +631,118 @@ Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port)
|
|||||||
|
|
||||||
return ai;
|
return ai;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_he2ai() translates from a hostent struct to a Curl_addrinfo struct.
|
||||||
|
* The Curl_addrinfo is meant to work like the addrinfo struct does for IPv6
|
||||||
|
* stacks, but for all hosts and environments.
|
||||||
|
*
|
||||||
|
* Curl_addrinfo defined in "lib/hostip.h"
|
||||||
|
*
|
||||||
|
* struct Curl_addrinfo {
|
||||||
|
* int ai_flags;
|
||||||
|
* int ai_family;
|
||||||
|
* int ai_socktype;
|
||||||
|
* int ai_protocol;
|
||||||
|
* socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
|
||||||
|
* char *ai_canonname;
|
||||||
|
* struct sockaddr *ai_addr;
|
||||||
|
* struct Curl_addrinfo *ai_next;
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* hostent defined in <netdb.h>
|
||||||
|
*
|
||||||
|
* struct hostent {
|
||||||
|
* char *h_name;
|
||||||
|
* char **h_aliases;
|
||||||
|
* int h_addrtype;
|
||||||
|
* int h_length;
|
||||||
|
* char **h_addr_list;
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* for backward compatibility:
|
||||||
|
*
|
||||||
|
* #define h_addr h_addr_list[0]
|
||||||
|
*/
|
||||||
|
|
||||||
|
Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port)
|
||||||
|
{
|
||||||
|
Curl_addrinfo *ai;
|
||||||
|
Curl_addrinfo *prevai = NULL;
|
||||||
|
Curl_addrinfo *firstai = NULL;
|
||||||
|
struct sockaddr_in *addr;
|
||||||
|
#ifdef CURLRES_IPV6
|
||||||
|
struct sockaddr_in6 *addr6;
|
||||||
|
#endif /* CURLRES_IPV6 */
|
||||||
|
int i;
|
||||||
|
struct in_addr *curr;
|
||||||
|
|
||||||
|
if(!he)
|
||||||
|
/* no input == no output! */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for(i=0; (curr = (struct in_addr *)he->h_addr_list[i]) != NULL; i++) {
|
||||||
|
|
||||||
|
int ss_size;
|
||||||
|
#ifdef CURLRES_IPV6
|
||||||
|
if (he->h_addrtype == AF_INET6)
|
||||||
|
ss_size = sizeof (struct sockaddr_in6);
|
||||||
|
else
|
||||||
|
#endif /* CURLRES_IPV6 */
|
||||||
|
ss_size = sizeof (struct sockaddr_in);
|
||||||
|
|
||||||
|
ai = calloc(1, sizeof(Curl_addrinfo) + ss_size);
|
||||||
|
|
||||||
|
if(!ai)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(!firstai)
|
||||||
|
/* store the pointer we want to return from this function */
|
||||||
|
firstai = ai;
|
||||||
|
|
||||||
|
if(prevai)
|
||||||
|
/* make the previous entry point to this */
|
||||||
|
prevai->ai_next = ai;
|
||||||
|
|
||||||
|
ai->ai_family = he->h_addrtype;
|
||||||
|
|
||||||
|
/* we return all names as STREAM, so when using this address for TFTP
|
||||||
|
the type must be ignored and conn->socktype be used instead! */
|
||||||
|
ai->ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
ai->ai_addrlen = ss_size;
|
||||||
|
/* make the ai_addr point to the address immediately following this struct
|
||||||
|
and use that area to store the address */
|
||||||
|
ai->ai_addr = (struct sockaddr *) ((char*)ai + sizeof(Curl_addrinfo));
|
||||||
|
|
||||||
|
/* need to free this eventually */
|
||||||
|
ai->ai_canonname = strdup(he->h_name);
|
||||||
|
|
||||||
|
/* leave the rest of the struct filled with zero */
|
||||||
|
|
||||||
|
switch (ai->ai_family) {
|
||||||
|
case AF_INET:
|
||||||
|
addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */
|
||||||
|
|
||||||
|
memcpy((char *)&(addr->sin_addr), curr, sizeof(struct in_addr));
|
||||||
|
addr->sin_family = (unsigned short)(he->h_addrtype);
|
||||||
|
addr->sin_port = htons((unsigned short)port);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef CURLRES_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
addr6 = (struct sockaddr_in6 *)ai->ai_addr; /* storage area for this info */
|
||||||
|
|
||||||
|
memcpy((char *)&(addr6->sin6_addr), curr, sizeof(struct in6_addr));
|
||||||
|
addr6->sin6_family = (unsigned short)(he->h_addrtype);
|
||||||
|
addr6->sin6_port = htons((unsigned short)port);
|
||||||
|
break;
|
||||||
|
#endif /* CURLRES_IPV6 */
|
||||||
|
}
|
||||||
|
|
||||||
|
prevai = ai;
|
||||||
|
}
|
||||||
|
return firstai;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CURLRES_IPV4 || CURLRES_ARES */
|
#endif /* CURLRES_IPV4 || CURLRES_ARES */
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,6 +104,10 @@
|
|||||||
*/
|
*/
|
||||||
#ifdef CURLRES_IPV6
|
#ifdef CURLRES_IPV6
|
||||||
typedef struct addrinfo Curl_addrinfo;
|
typedef struct addrinfo Curl_addrinfo;
|
||||||
|
#ifdef CURLRES_ARES
|
||||||
|
Curl_addrinfo *Curl_ip2addr6(struct in6_addr *in,
|
||||||
|
const char *hostname, int port);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
/* OK, so some ipv4-only include tree probably have the addrinfo struct, but
|
/* OK, so some ipv4-only include tree probably have the addrinfo struct, but
|
||||||
to work even on those that don't, we provide our own look-alike! */
|
to work even on those that don't, we provide our own look-alike! */
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -307,91 +307,3 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
#endif /* CURLRES_SYNCH */
|
#endif /* CURLRES_SYNCH */
|
||||||
#endif /* CURLRES_IPV4 */
|
#endif /* CURLRES_IPV4 */
|
||||||
|
|
||||||
/*
|
|
||||||
* Curl_he2ai() translates from a hostent struct to a Curl_addrinfo struct.
|
|
||||||
* The Curl_addrinfo is meant to work like the addrinfo struct does for IPv6
|
|
||||||
* stacks, but for all hosts and environments.
|
|
||||||
*
|
|
||||||
* Curl_addrinfo defined in "lib/hostip.h"
|
|
||||||
*
|
|
||||||
* struct Curl_addrinfo {
|
|
||||||
* int ai_flags;
|
|
||||||
* int ai_family;
|
|
||||||
* int ai_socktype;
|
|
||||||
* int ai_protocol;
|
|
||||||
* socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
|
|
||||||
* char *ai_canonname;
|
|
||||||
* struct sockaddr *ai_addr;
|
|
||||||
* struct Curl_addrinfo *ai_next;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* hostent defined in <netdb.h>
|
|
||||||
*
|
|
||||||
* struct hostent {
|
|
||||||
* char *h_name;
|
|
||||||
* char **h_aliases;
|
|
||||||
* int h_addrtype;
|
|
||||||
* int h_length;
|
|
||||||
* char **h_addr_list;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* for backward compatibility:
|
|
||||||
*
|
|
||||||
* #define h_addr h_addr_list[0]
|
|
||||||
*/
|
|
||||||
|
|
||||||
Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port)
|
|
||||||
{
|
|
||||||
Curl_addrinfo *ai;
|
|
||||||
Curl_addrinfo *prevai = NULL;
|
|
||||||
Curl_addrinfo *firstai = NULL;
|
|
||||||
struct sockaddr_in *addr;
|
|
||||||
int i;
|
|
||||||
struct in_addr *curr;
|
|
||||||
|
|
||||||
if(!he)
|
|
||||||
/* no input == no output! */
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for(i=0; (curr = (struct in_addr *)he->h_addr_list[i]) != NULL; i++) {
|
|
||||||
|
|
||||||
ai = calloc(1, sizeof(Curl_addrinfo) + sizeof(struct sockaddr_in));
|
|
||||||
|
|
||||||
if(!ai)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(!firstai)
|
|
||||||
/* store the pointer we want to return from this function */
|
|
||||||
firstai = ai;
|
|
||||||
|
|
||||||
if(prevai)
|
|
||||||
/* make the previous entry point to this */
|
|
||||||
prevai->ai_next = ai;
|
|
||||||
|
|
||||||
ai->ai_family = AF_INET; /* we only support this */
|
|
||||||
|
|
||||||
/* we return all names as STREAM, so when using this address for TFTP
|
|
||||||
the type must be ignored and conn->socktype be used instead! */
|
|
||||||
ai->ai_socktype = SOCK_STREAM;
|
|
||||||
|
|
||||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
|
||||||
/* make the ai_addr point to the address immediately following this struct
|
|
||||||
and use that area to store the address */
|
|
||||||
ai->ai_addr = (struct sockaddr *) ((char*)ai + sizeof(Curl_addrinfo));
|
|
||||||
|
|
||||||
/* FIXME: need to free this eventually */
|
|
||||||
ai->ai_canonname = strdup(he->h_name);
|
|
||||||
|
|
||||||
/* leave the rest of the struct filled with zero */
|
|
||||||
|
|
||||||
addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */
|
|
||||||
|
|
||||||
memcpy((char *)&(addr->sin_addr), curr, sizeof(struct in_addr));
|
|
||||||
addr->sin_family = (unsigned short)(he->h_addrtype);
|
|
||||||
addr->sin_port = htons((unsigned short)port);
|
|
||||||
|
|
||||||
prevai = ai;
|
|
||||||
}
|
|
||||||
return firstai;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user