Loading CHANGES +5 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,11 @@ 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) - Fixed an OOM handling problem that cause test 11 to fail the torture test. Loading RELEASE-NOTES +2 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ This release includes the following bugfixes: o range numbers could be made to wrongly get output as signed o unexpected 1xx responses hung transfers 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: Loading @@ -50,7 +51,7 @@ advice from friends like these: Lenny Rachitsky, Axel Tillequin, Arnaud Ebalard, Yang Tse, Dan Fandrich, Rob Crittenden, Dengminwen, Christopher Palow, Hans-Jurgen May, 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) lib/hostares.c +86 −2 Original line number Diff line number Diff line Loading @@ -297,6 +297,70 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, 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 * Loading @@ -313,7 +377,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, char *bufp; struct SessionHandle *data = conn->data; 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; if(in != CURL_INADDR_NONE) { Loading @@ -321,6 +388,23 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, 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); if(bufp) { Loading @@ -332,7 +416,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, conn->async.dns = NULL; /* clear */ /* 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); *waitp = TRUE; /* please wait for the response */ Loading lib/hostip.c +115 −2 Original line number Diff line number Diff line Loading @@ -545,7 +545,8 @@ Curl_addrinfo *Curl_addrinfo_copy(const void *org, int port) #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) Loading Loading @@ -630,6 +631,118 @@ Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port) return ai; } #endif /* CURLRES_IPV4 || CURLRES_ARES */ /* * 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 */ lib/hostip.h +4 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,10 @@ */ #ifdef CURLRES_IPV6 typedef struct addrinfo Curl_addrinfo; #ifdef CURLRES_ARES Curl_addrinfo *Curl_ip2addr6(struct in6_addr *in, const char *hostname, int port); #endif #else /* 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! */ Loading Loading
CHANGES +5 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,11 @@ 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) - Fixed an OOM handling problem that cause test 11 to fail the torture test. Loading
RELEASE-NOTES +2 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ This release includes the following bugfixes: o range numbers could be made to wrongly get output as signed o unexpected 1xx responses hung transfers 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: Loading @@ -50,7 +51,7 @@ advice from friends like these: Lenny Rachitsky, Axel Tillequin, Arnaud Ebalard, Yang Tse, Dan Fandrich, Rob Crittenden, Dengminwen, Christopher Palow, Hans-Jurgen May, 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)
lib/hostares.c +86 −2 Original line number Diff line number Diff line Loading @@ -297,6 +297,70 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, 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 * Loading @@ -313,7 +377,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, char *bufp; struct SessionHandle *data = conn->data; 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; if(in != CURL_INADDR_NONE) { Loading @@ -321,6 +388,23 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, 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); if(bufp) { Loading @@ -332,7 +416,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, conn->async.dns = NULL; /* clear */ /* 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); *waitp = TRUE; /* please wait for the response */ Loading
lib/hostip.c +115 −2 Original line number Diff line number Diff line Loading @@ -545,7 +545,8 @@ Curl_addrinfo *Curl_addrinfo_copy(const void *org, int port) #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) Loading Loading @@ -630,6 +631,118 @@ Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port) return ai; } #endif /* CURLRES_IPV4 || CURLRES_ARES */ /* * 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 */
lib/hostip.h +4 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,10 @@ */ #ifdef CURLRES_IPV6 typedef struct addrinfo Curl_addrinfo; #ifdef CURLRES_ARES Curl_addrinfo *Curl_ip2addr6(struct in6_addr *in, const char *hostname, int port); #endif #else /* 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! */ Loading