1
0
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:
Daniel Stenberg 2008-07-09 18:39:49 +00:00
parent d4b253ba3e
commit 0cd8840dba
6 changed files with 214 additions and 95 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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 */

View File

@ -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 */

View File

@ -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! */

View File

@ -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;
}