diff --git a/0001-Allow-the-use-of-IPv6-nameservers.patch b/0001-Allow-the-use-of-IPv6-nameservers.patch deleted file mode 100644 index 1f57cea..0000000 --- a/0001-Allow-the-use-of-IPv6-nameservers.patch +++ /dev/null @@ -1,1659 +0,0 @@ -From a9794547f61ccca1cdf71949f3f7183387300a7a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Sun, 7 Mar 2010 18:37:47 +0100 -Subject: [PATCH] IPv6 nameserver patch - ---- - Makefile.inc | 6 + - adig.c | 103 +++++++++++++--- - ahost.c | 4 +- - ares.h | 19 +++- - ares__get_hostent.c | 12 +- - ares_data.c | 13 ++ - ares_data.h | 6 +- - ares_destroy.c | 35 ++++-- - ares_free_data.3 | 14 ++- - ares_gethostbyaddr.c | 20 ++-- - ares_gethostbyname.c | 24 ++-- - ares_getnameinfo.c | 14 ++- - ares_init.3 | 18 ++- - ares_init.c | 307 +++++++++++++++++++++++++++++++++++------------ - ares_ipv6.h | 21 +--- - ares_parse_aaaa_reply.c | 18 ++-- - ares_private.h | 22 ++-- - ares_process.c | 125 ++++++++++++++++--- - ares_save_options.3 | 13 ++- - inet_net_pton.c | 5 +- - inet_ntop.c | 3 +- - vc/cares/vc6cares.dsp | 4 + - 22 files changed, 590 insertions(+), 216 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 3227858..365de6c 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -70,6 +70,7 @@ MANPAGES = ares_cancel.3 \ - ares_free_data.3 \ - ares_free_hostent.3 \ - ares_free_string.3 \ -+ ares_get_servers.3 \ - ares_gethostbyaddr.3 \ - ares_gethostbyname.3 \ - ares_gethostbyname_file.3 \ -@@ -91,6 +92,7 @@ MANPAGES = ares_cancel.3 \ - ares_save_options.3 \ - ares_search.3 \ - ares_send.3 \ -+ ares_set_servers.3 \ - ares_set_socket_callback.3 \ - ares_strerror.3 \ - ares_timeout.3 \ -@@ -106,6 +108,7 @@ HTMLPAGES = ares_cancel.html \ - ares_free_data.html \ - ares_free_hostent.html \ - ares_free_string.html \ -+ ares_get_servers.html \ - ares_gethostbyaddr.html \ - ares_gethostbyname.html \ - ares_gethostbyname_file.html \ -@@ -127,6 +130,7 @@ HTMLPAGES = ares_cancel.html \ - ares_save_options.html \ - ares_search.html \ - ares_send.html \ -+ ares_set_servers.html \ - ares_set_socket_callback.html \ - ares_strerror.html \ - ares_timeout.html \ -@@ -142,6 +146,7 @@ PDFPAGES = ares_cancel.pdf \ - ares_free_data.pdf \ - ares_free_hostent.pdf \ - ares_free_string.pdf \ -+ ares_get_servers.pdf \ - ares_gethostbyaddr.pdf \ - ares_gethostbyname.pdf \ - ares_gethostbyname_file.pdf \ -@@ -163,6 +168,7 @@ PDFPAGES = ares_cancel.pdf \ - ares_save_options.pdf \ - ares_search.pdf \ - ares_send.pdf \ -+ ares_set_servers.pdf \ - ares_set_socket_callback.pdf \ - ares_strerror.pdf \ - ares_timeout.pdf \ -diff --git a/adig.c b/adig.c -index 8897448..d827e0e 100644 ---- a/adig.c -+++ b/adig.c -@@ -1,6 +1,6 @@ - /* Copyright 1998 by the Massachusetts Institute of Technology. - * -- * $Id: adig.c,v 1.43 2009-11-16 20:02:12 yangtse Exp $ -+ * $Id: adig.c,v 1.44 2010-03-05 20:01:47 yangtse Exp $ - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -164,8 +164,6 @@ static const char *rcodes[] = { - "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE" - }; - --static struct in_addr inaddr; -- - static void callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); - static const unsigned char *display_question(const unsigned char *aptr, -@@ -176,6 +174,9 @@ static const unsigned char *display_rr(const unsigned char *aptr, - static const char *type_name(int type); - static const char *class_name(int dnsclass); - static void usage(void); -+static void destroy_addr_list(struct ares_addr_node *head); -+static void append_addr_list(struct ares_addr_node **head, -+ struct ares_addr_node *node); - - int main(int argc, char **argv) - { -@@ -186,6 +187,7 @@ int main(int argc, char **argv) - struct hostent *hostent; - fd_set read_fds, write_fds; - struct timeval *tvp, tv; -+ struct ares_addr_node *srvr, *servers = NULL; - - #ifdef USE_WINSOCK - WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK); -@@ -227,27 +229,56 @@ int main(int argc, char **argv) - break; - - case 's': -- /* Add a server, and specify servers in the option mask. */ -- if (ares_inet_pton(AF_INET, optarg, &inaddr) <= 0) -+ /* User specified name servers override default ones. */ -+ srvr = malloc(sizeof(struct ares_addr_node)); -+ if (!srvr) -+ { -+ fprintf(stderr, "Out of memory!\n"); -+ destroy_addr_list(servers); -+ return 1; -+ } -+ append_addr_list(&servers, srvr); -+ if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0) -+ srvr->family = AF_INET; -+ else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0) -+ srvr->family = AF_INET6; -+ else - { - hostent = gethostbyname(optarg); -- if (!hostent || hostent->h_addrtype != AF_INET) -+ if (!hostent) - { - fprintf(stderr, "adig: server %s not found.\n", optarg); -+ destroy_addr_list(servers); - return 1; - } -- memcpy(&inaddr, hostent->h_addr, sizeof(struct in_addr)); -- } -- options.servers = realloc(options.servers, (options.nservers + 1) -- * sizeof(struct in_addr)); -- if (!options.servers) -- { -- fprintf(stderr, "Out of memory!\n"); -- return 1; -+ switch (hostent->h_addrtype) -+ { -+ case AF_INET: -+ srvr->family = AF_INET; -+ memcpy(&srvr->addr.addr4, hostent->h_addr, -+ sizeof(srvr->addr.addr4)); -+ break; -+ case AF_INET6: -+ srvr->family = AF_INET6; -+ memcpy(&srvr->addr.addr6, hostent->h_addr, -+ sizeof(srvr->addr.addr6)); -+ break; -+ default: -+ fprintf(stderr, -+ "adig: server %s unsupported address family.\n", optarg); -+ destroy_addr_list(servers); -+ return 1; -+ } - } -- memcpy(&options.servers[options.nservers], &inaddr, -- sizeof(struct in_addr)); -- options.nservers++; -+ /* Notice that calling ares_init_options() without servers in the -+ * options struct and with ARES_OPT_SERVERS set simultaneously in -+ * the options mask, results in an initialization with no servers. -+ * When alternative name servers have been specified these are set -+ * later calling ares_set_servers() overriding any existing server -+ * configuration. To prevent initial configuration with default -+ * servers that will be discarded later ARES_OPT_SERVERS is set. -+ * If this flag is not set here the result shall be the same but -+ * ares_init_options() will do needless work. */ - optmask |= ARES_OPT_SERVERS; - break; - -@@ -308,6 +339,18 @@ int main(int argc, char **argv) - return 1; - } - -+ if(servers) -+ { -+ status = ares_set_servers(channel, servers); -+ destroy_addr_list(servers); -+ if (status != ARES_SUCCESS) -+ { -+ fprintf(stderr, "ares_init_options: %s\n", -+ ares_strerror(status)); -+ return 1; -+ } -+ } -+ - /* Initiate the queries, one per command-line argument. If there is - * only one query to do, supply NULL as the callback argument; - * otherwise, supply the query name as an argument so we can -@@ -749,3 +792,29 @@ static void usage(void) - "[-t type] [-p port] name ...\n"); - exit(1); - } -+ -+static void destroy_addr_list(struct ares_addr_node *head) -+{ -+ while(head) -+ { -+ struct ares_addr_node *detached = head; -+ head = head->next; -+ free(detached); -+ } -+} -+ -+static void append_addr_list(struct ares_addr_node **head, -+ struct ares_addr_node *node) -+{ -+ struct ares_addr_node *last; -+ node->next = NULL; -+ if(*head) -+ { -+ last = *head; -+ while(last->next) -+ last = last->next; -+ last->next = node; -+ } -+ else -+ *head = node; -+} -diff --git a/ahost.c b/ahost.c -index ebfa97f..5256186 100644 ---- a/ahost.c -+++ b/ahost.c -@@ -1,6 +1,6 @@ - /* Copyright 1998 by the Massachusetts Institute of Technology. - * -- * $Id: ahost.c,v 1.28 2009-11-10 18:41:03 yangtse Exp $ -+ * $Id: ahost.c,v 1.29 2010-03-05 20:01:47 yangtse Exp $ - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -69,7 +69,7 @@ int main(int argc, char **argv) - fd_set read_fds, write_fds; - struct timeval *tvp, tv; - struct in_addr addr4; -- struct in6_addr addr6; -+ struct ares_in6_addr addr6; - - #ifdef USE_WINSOCK - WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK); -diff --git a/ares.h b/ares.h -index b1c2c22..fc333e5 100644 ---- a/ares.h -+++ b/ares.h -@@ -1,7 +1,7 @@ --/* $Id: ares.h,v 1.72 2009-11-23 12:03:32 yangtse Exp $ */ -+/* $Id: ares.h,v 1.73 2010-03-05 20:01:47 yangtse Exp $ */ - - /* Copyright 1998, 2009 by the Massachusetts Institute of Technology. -- * Copyright (C) 2007-2009 by Daniel Stenberg -+ * Copyright (C) 2007-2010 by Daniel Stenberg - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -487,6 +487,21 @@ CARES_EXTERN void ares_free_data(void *dataptr); - - CARES_EXTERN const char *ares_strerror(int code); - -+struct ares_addr_node { -+ struct ares_addr_node *next; -+ int family; -+ union { -+ struct in_addr addr4; -+ struct ares_in6_addr addr6; -+ } addr; -+}; -+ -+CARES_EXTERN int ares_set_servers(ares_channel channel, -+ struct ares_addr_node *servers); -+ -+CARES_EXTERN int ares_get_servers(ares_channel channel, -+ struct ares_addr_node **servers); -+ - #ifdef __cplusplus - } - #endif -diff --git a/ares__get_hostent.c b/ares__get_hostent.c -index 335f763..5d4956b 100644 ---- a/ares__get_hostent.c -+++ b/ares__get_hostent.c -@@ -1,6 +1,6 @@ --/* $Id: ares__get_hostent.c,v 1.24 2009-11-02 11:55:53 yangtse Exp $ */ -+/* $Id: ares__get_hostent.c,v 1.25 2010-03-05 20:01:47 yangtse Exp $ */ - --/* Copyright 1998, 2009 by the Massachusetts Institute of Technology. -+/* Copyright 1998, 2010 by the Massachusetts Institute of Technology. - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -146,7 +146,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host) - { - /* Actual network address family and length. */ - addr.family = AF_INET; -- addrlen = sizeof(struct in_addr); -+ addrlen = sizeof(addr.addrV4); - } - } - if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen))) -@@ -155,7 +155,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host) - { - /* Actual network address family and length. */ - addr.family = AF_INET6; -- addrlen = sizeof(struct in6_addr); -+ addrlen = sizeof(addr.addrV6); - } - } - if (!addrlen) -@@ -189,9 +189,9 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host) - if (!hostent->h_addr_list[0]) - break; - if (addr.family == AF_INET) -- memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(struct in_addr)); -+ memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4)); - else -- memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(struct in6_addr)); -+ memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6)); - - /* Copy aliases. */ - hostent->h_aliases = malloc((naliases + 1) * sizeof(char *)); -diff --git a/ares_data.c b/ares_data.c -index 1ad66a6..06d61c5 100644 ---- a/ares_data.c -+++ b/ares_data.c -@@ -34,6 +34,7 @@ - ** of c-ares functions returning pointers that must be free'ed using this - ** function is: - ** -+** ares_get_servers() - ** ares_parse_srv_reply() - ** ares_parse_txt_reply() - */ -@@ -68,6 +69,12 @@ void ares_free_data(void *dataptr) - free(ptr->data.txt_reply.txt); - break; - -+ case ARES_DATATYPE_ADDR_NODE: -+ -+ if (ptr->data.addr_node.next) -+ ares_free_data(ptr->data.addr_node.next); -+ break; -+ - default: - return; - } -@@ -111,6 +118,12 @@ void *ares_malloc_data(ares_datatype type) - ptr->data.txt_reply.length = 0; - break; - -+ case ARES_DATATYPE_ADDR_NODE: -+ ptr->data.addr_node.next = NULL; -+ ptr->data.addr_node.family = 0; -+ memset(&ptr->data.addr_node.addrV6, 0, -+ sizeof(ptr->data.addr_node.addrV6)); -+ - default: - free(ptr); - return NULL; -diff --git a/ares_data.h b/ares_data.h -index 18794e3..4ed626b 100644 ---- a/ares_data.h -+++ b/ares_data.h -@@ -1,6 +1,6 @@ --/* $Id: ares_data.h,v 1.2 2009-11-23 12:03:33 yangtse Exp $ */ -+/* $Id: ares_data.h,v 1.3 2010-03-05 20:01:47 yangtse Exp $ */ - --/* Copyright (C) 2009 by Daniel Stenberg -+/* Copyright (C) 2009-2010 by Daniel Stenberg - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -19,6 +19,7 @@ typedef enum { - ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */ - ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */ - ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */ -+ ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */ - #if 0 - ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */ - ARES_DATATYPE_ADDRTTL, /* struct ares_addr6ttl */ -@@ -54,6 +55,7 @@ struct ares_data { - union { - struct ares_txt_reply txt_reply; - struct ares_srv_reply srv_reply; -+ struct ares_addr_node addr_node; - } data; - }; - -diff --git a/ares_destroy.c b/ares_destroy.c -index 0044a71..1fa0196 100644 ---- a/ares_destroy.c -+++ b/ares_destroy.c -@@ -1,6 +1,7 @@ --/* $Id: ares_destroy.c,v 1.14 2009-11-02 11:55:53 yangtse Exp $ */ -+/* $Id: ares_destroy.c,v 1.15 2010-03-05 20:01:48 yangtse Exp $ */ - - /* Copyright 1998 by the Massachusetts Institute of Technology. -+ * Copyright (C) 2004-2010 by Daniel Stenberg - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -25,7 +26,8 @@ void ares_destroy_options(struct ares_options *options) - { - int i; - -- free(options->servers); -+ if(options->servers) -+ free(options->servers); - for (i = 0; i < options->ndomains; i++) - free(options->domains[i]); - free(options->domains); -@@ -67,15 +69,7 @@ void ares_destroy(ares_channel channel) - } - #endif - -- if (channel->servers) { -- for (i = 0; i < channel->nservers; i++) -- { -- struct server_state *server = &channel->servers[i]; -- ares__close_sockets(channel, server); -- assert(ares__is_list_empty(&(server->queries_to_server))); -- } -- free(channel->servers); -- } -+ ares__destroy_servers_state(channel); - - if (channel->domains) { - for (i = 0; i < channel->ndomains; i++) -@@ -91,3 +85,22 @@ void ares_destroy(ares_channel channel) - - free(channel); - } -+ -+void ares__destroy_servers_state(ares_channel channel) -+{ -+ struct server_state *server; -+ int i; -+ -+ if (channel->servers) -+ { -+ for (i = 0; i < channel->nservers; i++) -+ { -+ server = &channel->servers[i]; -+ ares__close_sockets(channel, server); -+ assert(ares__is_list_empty(&server->queries_to_server)); -+ } -+ free(channel->servers); -+ channel->servers = NULL; -+ } -+ channel->nservers = -1; -+} -diff --git a/ares_free_data.3 b/ares_free_data.3 -index f0655c6..633f0b1 100644 ---- a/ares_free_data.3 -+++ b/ares_free_data.3 -@@ -1,7 +1,7 @@ --.\" $Id: ares_free_data.3,v 1.3 2009-11-23 12:03:33 yangtse Exp $ -+.\" $Id: ares_free_data.3,v 1.4 2010-03-05 20:01:48 yangtse Exp $ - .\" - .\" Copyright 1998 by the Massachusetts Institute of Technology. --.\" Copyright (C) 2004-2009 by Daniel Stenberg -+.\" Copyright (C) 2004-2010 by Daniel Stenberg - .\" - .\" Permission to use, copy, modify, and distribute this - .\" software and its documentation for any purpose and without -@@ -15,7 +15,7 @@ - .\" this software for any purpose. It is provided "as is" - .\" without express or implied warranty. - .\" --.TH ARES_FREE_DATA 3 "23 Nov 2009" -+.TH ARES_FREE_DATA 3 "5 March 2010" - .SH NAME - ares_free_data \- Free data allocated by several c-ares functions - .SH SYNOPSIS -@@ -34,6 +34,11 @@ function frees one or more data structures allocated and returned - by several c-ares functions. Specifically the data returned by the - following list of functions must be deallocated using this function. - .TP 5 -+.B ares_get_servers(3) -+When used to free the data returned by ares_get_servers(3) this -+will free the whole linked list of ares_addr_node structures returned -+by ares_get_servers(3). -+.TP - .B ares_parse_srv_reply(3) - When used to free the data returned by ares_parse_srv_reply(3) this - will free the whole linked list of ares_srv_reply structures returned -@@ -50,6 +55,7 @@ The ares_free_data() function does not return a value. - .SH AVAILABILITY - This function was first introduced in c-ares version 1.7.0. - .SH SEE ALSO -+.BR ares_get_servers(3), - .BR ares_parse_srv_reply(3), - .BR ares_parse_txt_reply(3) - .SH AUTHOR -@@ -57,4 +63,4 @@ Yang Tse - .PP - Copyright 1998 by the Massachusetts Institute of Technology. - .br --Copyright (C) 2004-2009 by Daniel Stenberg. -+Copyright (C) 2004-2010 by Daniel Stenberg. -diff --git a/ares_gethostbyaddr.c b/ares_gethostbyaddr.c -index 732a031..25dc8cb 100644 ---- a/ares_gethostbyaddr.c -+++ b/ares_gethostbyaddr.c -@@ -1,4 +1,4 @@ --/* $Id: ares_gethostbyaddr.c,v 1.35 2009-11-02 11:55:53 yangtse Exp $ */ -+/* $Id: ares_gethostbyaddr.c,v 1.37 2010-03-06 01:23:09 yangtse Exp $ */ - - /* Copyright 1998 by the Massachusetts Institute of Technology. - * -@@ -79,8 +79,8 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, - return; - } - -- if ((family == AF_INET && addrlen != sizeof(struct in_addr)) || -- (family == AF_INET6 && addrlen != sizeof(struct in6_addr))) -+ if ((family == AF_INET && addrlen != sizeof(aquery->addr.addrV4)) || -+ (family == AF_INET6 && addrlen != sizeof(aquery->addr.addrV6))) - { - callback(arg, ARES_ENOTIMP, 0, NULL); - return; -@@ -94,9 +94,9 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, - } - aquery->channel = channel; - if (family == AF_INET) -- memcpy(&aquery->addr.addrV4, addr, sizeof(struct in_addr)); -+ memcpy(&aquery->addr.addrV4, addr, sizeof(aquery->addr.addrV4)); - else -- memcpy(&aquery->addr.addrV6, addr, sizeof(struct in6_addr)); -+ memcpy(&aquery->addr.addrV6, addr, sizeof(aquery->addr.addrV6)); - aquery->addr.family = family; - aquery->callback = callback; - aquery->arg = arg; -@@ -152,13 +152,13 @@ static void addr_callback(void *arg, int status, int timeouts, - { - if (aquery->addr.family == AF_INET) - { -- addrlen = sizeof(struct in_addr); -+ addrlen = sizeof(aquery->addr.addrV4); - status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV4, - (int)addrlen, AF_INET, &host); - } - else - { -- addrlen = sizeof(struct in6_addr); -+ addrlen = sizeof(aquery->addr.addrV6); - status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV6, - (int)addrlen, AF_INET6, &host); - } -@@ -241,12 +241,12 @@ static int file_lookup(struct ares_addr *addr, struct hostent **host) - } - if (addr->family == AF_INET) - { -- if (memcmp((*host)->h_addr, &addr->addrV4, sizeof(struct in_addr)) == 0) -+ if (memcmp((*host)->h_addr, &addr->addrV4, sizeof(addr->addrV4)) == 0) - break; - } - else if (addr->family == AF_INET6) - { -- if (memcmp((*host)->h_addr, &addr->addrV6, sizeof(struct in6_addr)) == 0) -+ if (memcmp((*host)->h_addr, &addr->addrV6, sizeof(addr->addrV6)) == 0) - break; - } - ares_free_hostent(*host); -@@ -272,7 +272,7 @@ static void ptr_rr_name(char *name, const struct ares_addr *addr) - } - else - { -- unsigned char *bytes = (unsigned char *)&addr->addrV6.s6_addr; -+ unsigned char *bytes = (unsigned char *)&addr->addrV6; - /* There are too many arguments to do this in one line using - * minimally C89-compliant compilers */ - sprintf(name, -diff --git a/ares_gethostbyname.c b/ares_gethostbyname.c -index fc66c6f..7d0f8c6 100644 ---- a/ares_gethostbyname.c -+++ b/ares_gethostbyname.c -@@ -1,4 +1,4 @@ --/* $Id: ares_gethostbyname.c,v 1.50 2009-11-02 11:55:53 yangtse Exp $ */ -+/* $Id: ares_gethostbyname.c,v 1.52 2010-03-06 01:23:09 yangtse Exp $ */ - - /* Copyright 1998 by the Massachusetts Institute of Technology. - * -@@ -81,7 +81,7 @@ static void sort6_addresses(struct hostent *host, - const struct apattern *sortlist, int nsort); - static int get_address_index(const struct in_addr *addr, - const struct apattern *sortlist, int nsort); --static int get6_address_index(const struct in6_addr *addr, -+static int get6_address_index(const struct ares_in6_addr *addr, - const struct apattern *sortlist, int nsort); - - void ares_gethostbyname(ares_channel channel, const char *name, int family, -@@ -243,7 +243,7 @@ static int fake_hostent(const char *name, int family, ares_host_callback callbac - char *addrs[2]; - int result = 0; - struct in_addr in; -- struct in6_addr in6; -+ struct ares_in6_addr in6; - - if (family == AF_INET || family == AF_INET6) - { -@@ -284,7 +284,7 @@ static int fake_hostent(const char *name, int family, ares_host_callback callbac - } - else if (family == AF_INET6) - { -- hostent.h_length = (int)sizeof(struct in6_addr); -+ hostent.h_length = (int)sizeof(struct ares_in6_addr); - addrs[0] = (char *)&in6; - } - /* Duplicate the name, to avoid a constness violation. */ -@@ -467,7 +467,7 @@ static int get_address_index(const struct in_addr *addr, - static void sort6_addresses(struct hostent *host, const struct apattern *sortlist, - int nsort) - { -- struct in6_addr a1, a2; -+ struct ares_in6_addr a1, a2; - int i1, i2, ind1, ind2; - - /* This is a simple insertion sort, not optimized at all. i1 walks -@@ -477,24 +477,24 @@ static void sort6_addresses(struct hostent *host, const struct apattern *sortlis - */ - for (i1 = 0; host->h_addr_list[i1]; i1++) - { -- memcpy(&a1, host->h_addr_list[i1], sizeof(struct in6_addr)); -+ memcpy(&a1, host->h_addr_list[i1], sizeof(struct ares_in6_addr)); - ind1 = get6_address_index(&a1, sortlist, nsort); - for (i2 = i1 - 1; i2 >= 0; i2--) - { -- memcpy(&a2, host->h_addr_list[i2], sizeof(struct in6_addr)); -+ memcpy(&a2, host->h_addr_list[i2], sizeof(struct ares_in6_addr)); - ind2 = get6_address_index(&a2, sortlist, nsort); - if (ind2 <= ind1) - break; -- memcpy(host->h_addr_list[i2 + 1], &a2, sizeof(struct in6_addr)); -+ memcpy(host->h_addr_list[i2 + 1], &a2, sizeof(struct ares_in6_addr)); - } -- memcpy(host->h_addr_list[i2 + 1], &a1, sizeof(struct in6_addr)); -+ memcpy(host->h_addr_list[i2 + 1], &a1, sizeof(struct ares_in6_addr)); - } - } - - /* Find the first entry in sortlist which matches addr. Return nsort - * if none of them match. - */ --static int get6_address_index(const struct in6_addr *addr, -+static int get6_address_index(const struct ares_in6_addr *addr, - const struct apattern *sortlist, - int nsort) - { -@@ -504,7 +504,9 @@ static int get6_address_index(const struct in6_addr *addr, - { - if (sortlist[i].family != AF_INET6) - continue; -- if (!ares_bitncmp(&addr->s6_addr, &sortlist[i].addrV6.s6_addr, sortlist[i].mask.bits)) -+ if (!ares_bitncmp(addr, -+ &sortlist[i].addrV6, -+ sortlist[i].mask.bits)) - break; - } - return i; -diff --git a/ares_getnameinfo.c b/ares_getnameinfo.c -index c1c0b16..94891ce 100644 ---- a/ares_getnameinfo.c -+++ b/ares_getnameinfo.c -@@ -1,4 +1,4 @@ --/* $Id: ares_getnameinfo.c,v 1.36 2009-11-09 12:56:11 yangtse Exp $ */ -+/* $Id: ares_getnameinfo.c,v 1.37 2010-03-05 20:01:48 yangtse Exp $ */ - - /* Copyright 2005 by Dominick Meglio - * -@@ -74,9 +74,11 @@ struct nameinfo_query { - }; - - #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID --#define IPBUFSIZ 40+IF_NAMESIZE -+#define IPBUFSIZ \ -+ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + IF_NAMESIZE) - #else --#define IPBUFSIZ 40 -+#define IPBUFSIZ \ -+ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")) - #endif - - static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host); -@@ -184,14 +186,16 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, - { - niquery->family = AF_INET; - memcpy(&niquery->addr.addr4, addr, sizeof(addr)); -- ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr), AF_INET, -+ ares_gethostbyaddr(channel, &addr->sin_addr, -+ sizeof(struct in_addr), AF_INET, - nameinfo_callback, niquery); - } - else - { - niquery->family = AF_INET6; - memcpy(&niquery->addr.addr6, addr6, sizeof(addr6)); -- ares_gethostbyaddr(channel, &addr6->sin6_addr, sizeof(struct in6_addr), AF_INET6, -+ ares_gethostbyaddr(channel, &addr6->sin6_addr, -+ sizeof(struct ares_in6_addr), AF_INET6, - nameinfo_callback, niquery); - } - } -diff --git a/ares_init.3 b/ares_init.3 -index 14be75f..d974090 100644 ---- a/ares_init.3 -+++ b/ares_init.3 -@@ -1,7 +1,7 @@ --.\" $Id: ares_init.3,v 1.8 2009-11-23 00:57:51 yangtse Exp $ -+.\" $Id: ares_init.3,v 1.9 2010-03-05 20:01:48 yangtse Exp $ - .\" - .\" Copyright 1998 by the Massachusetts Institute of Technology. --.\" Copyright (C) 2004-2009 by Daniel Stenberg -+.\" Copyright (C) 2004-2010 by Daniel Stenberg - .\" - .\" Permission to use, copy, modify, and distribute this - .\" software and its documentation for any purpose and without -@@ -15,7 +15,7 @@ - .\" this software for any purpose. It is provided "as is" - .\" without express or implied warranty. - .\" --.TH ARES_INIT 3 "26 May 2009" -+.TH ARES_INIT 3 "5 March 2010" - .SH NAME - ares_init, ares_init_options \- Initialize a resolver channel - .SH SYNOPSIS -@@ -93,8 +93,11 @@ service port. - .br - .B int \fInservers\fP; - .br --The list of servers to contact, instead of the servers specified in --resolv.conf or the local named. -+The list of IPv4 servers to contact, instead of the servers specified in -+resolv.conf or the local named. In order to allow specification of either -+IPv4 or IPv6 name servers, function -+.BR ares_set_servers(3) -+must be used instead. - .TP 18 - .B ARES_OPT_DOMAINS - .B char **\fIdomains\fP; -@@ -190,10 +193,11 @@ c-ares library initialization not yet performed. - .SH SEE ALSO - .BR ares_destroy(3), - .BR ares_dup(3), --.BR ares_library_init(3) -+.BR ares_library_init(3), -+.BR ares_set_servers(3) - .SH AUTHOR - Greg Hudson, MIT Information Systems - .br - Copyright 1998 by the Massachusetts Institute of Technology. - .br --Copyright (C) 2004-2009 by Daniel Stenberg. -+Copyright (C) 2004-2010 by Daniel Stenberg. -diff --git a/ares_init.c b/ares_init.c -index cb541af..cdcf38a 100644 ---- a/ares_init.c -+++ b/ares_init.c -@@ -1,7 +1,7 @@ --/* $Id: ares_init.c,v 1.103 2009-11-18 10:33:54 yangtse Exp $ */ -+/* $Id: ares_init.c,v 1.104 2010-03-05 20:01:48 yangtse Exp $ */ - - /* Copyright 1998 by the Massachusetts Institute of Technology. -- * Copyright (C) 2007-2009 by Daniel Stenberg -+ * Copyright (C) 2007-2010 by Daniel Stenberg - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -68,6 +68,7 @@ - #include "ares.h" - #include "inet_net_pton.h" - #include "ares_library_init.h" -+#include "ares_data.h" - #include "ares_private.h" - - #ifdef WATT32 -@@ -118,7 +119,6 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, - ares_channel channel; - int i; - int status = ARES_SUCCESS; -- struct server_state *server; - struct timeval now; - - #ifdef CURLDEBUG -@@ -247,21 +247,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, - if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1) - channel->nservers = 1; - -- /* Initialize server states. */ -- for (i = 0; i < channel->nservers; i++) -- { -- server = &channel->servers[i]; -- server->udp_socket = ARES_SOCKET_BAD; -- server->tcp_socket = ARES_SOCKET_BAD; -- server->tcp_connection_generation = ++channel->tcp_connection_generation; -- server->tcp_lenbuf_pos = 0; -- server->tcp_buffer = NULL; -- server->qhead = NULL; -- server->qtail = NULL; -- ares__init_list_head(&(server->queries_to_server)); -- server->channel = channel; -- server->is_broken = 0; -- } -+ ares__init_servers_state(channel); - - *channelptr = channel; - return ARES_SUCCESS; -@@ -272,7 +258,9 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, - int ares_dup(ares_channel *dest, ares_channel src) - { - struct ares_options opts; -- int rc; -+ struct ares_addr_node *servers; -+ int ipv6_nservers = 0; -+ int i, rc; - int optmask; - - *dest = NULL; /* in case of failure return NULL explicitly */ -@@ -296,16 +284,33 @@ int ares_dup(ares_channel *dest, ares_channel src) - (*dest)->sock_create_cb = src->sock_create_cb; - (*dest)->sock_create_cb_data = src->sock_create_cb_data; - -+ /* Full name server cloning required when not all are IPv4 */ -+ for (i = 0; i < src->nservers; i++) -+ { -+ if (src->servers[i].addr.family != AF_INET) { -+ ipv6_nservers++; -+ break; -+ } -+ } -+ if (ipv6_nservers) { -+ rc = ares_get_servers(src, &servers); -+ if (rc != ARES_SUCCESS) -+ return rc; -+ rc = ares_set_servers(*dest, servers); -+ ares_free_data(servers); -+ if (rc != ARES_SUCCESS) -+ return rc; -+ } - - return ARES_SUCCESS; /* everything went fine */ -- - } - - /* Save options from initialized channel */ - int ares_save_options(ares_channel channel, struct ares_options *options, - int *optmask) - { -- int i; -+ int i, j; -+ int ipv4_nservers = 0; - - /* Zero everything out */ - memset(options, 0, sizeof(struct ares_options)); -@@ -335,16 +340,27 @@ int ares_save_options(ares_channel channel, struct ares_options *options, - options->sock_state_cb = channel->sock_state_cb; - options->sock_state_cb_data = channel->sock_state_cb_data; - -- /* Copy servers */ -+ /* Copy IPv4 servers */ - if (channel->nservers) { -- options->servers = -- malloc(channel->nservers * sizeof(struct server_state)); -- if (!options->servers && channel->nservers != 0) -- return ARES_ENOMEM; - for (i = 0; i < channel->nservers; i++) -- options->servers[i] = channel->servers[i].addr; -+ { -+ if (channel->servers[i].addr.family == AF_INET) -+ ipv4_nservers++; -+ } -+ if (ipv4_nservers) { -+ options->servers = malloc(ipv4_nservers * sizeof(struct server_state)); -+ if (!options->servers) -+ return ARES_ENOMEM; -+ for (i = j = 0; i < channel->nservers; i++) -+ { -+ if (channel->servers[i].addr.family == AF_INET) -+ memcpy(&options->servers[j++], -+ &channel->servers[i].addr.addrV4, -+ sizeof(channel->servers[i].addr.addrV4)); -+ } -+ } - } -- options->nservers = channel->nservers; -+ options->nservers = ipv4_nservers; - - /* copy domains */ - if (channel->ndomains) { -@@ -420,7 +436,7 @@ static int init_by_options(ares_channel channel, - && channel->socket_receive_buffer_size == -1) - channel->socket_receive_buffer_size = options->socket_receive_buffer_size; - -- /* Copy the servers, if given. */ -+ /* Copy the IPv4 servers, if given. */ - if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1) - { - /* Avoid zero size allocations at any cost */ -@@ -431,7 +447,12 @@ static int init_by_options(ares_channel channel, - if (!channel->servers) - return ARES_ENOMEM; - for (i = 0; i < options->nservers; i++) -- channel->servers[i].addr = options->servers[i]; -+ { -+ channel->servers[i].addr.family = AF_INET; -+ memcpy(&channel->servers[i].addr.addrV4, -+ &options->servers[i], -+ sizeof(channel->servers[i].addr.addrV4)); -+ } - } - channel->nservers = options->nservers; - } -@@ -1001,7 +1022,8 @@ static int init_by_defaults(ares_channel channel) - rc = ARES_ENOMEM; - goto error; - } -- channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK); -+ channel->servers[0].addr.family = AF_INET; -+ channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK); - channel->nservers = 1; - } - -@@ -1149,61 +1171,62 @@ static int config_lookup(ares_channel channel, const char *str, - static int config_nameserver(struct server_state **servers, int *nservers, - char *str) - { -- struct in_addr addr; -+ struct ares_addr host; - struct server_state *newserv; -+ char *p, *txtaddr; - /* On Windows, there may be more than one nameserver specified in the same -- * registry key, so we parse it as a space or comma seperated list. -+ * registry key, so we parse input as a space or comma seperated list. - */ --#ifdef WIN32 -- char *p = str; -- char *begin = str; -- int more = 1; -- while (more) -- { -- more = 0; -- while (*p && !ISSPACE(*p) && *p != ',') -- p++; -- -- if (*p) -+ for (p = str; p;) - { -- *p = '\0'; -- more = 1; -- } -+ /* Skip whitespace and commas. */ -+ while (*p && (ISSPACE(*p) || (*p == ','))) -+ p++; -+ if (!*p) -+ /* No more input, done. */ -+ break; - -- /* Skip multiple spaces or trailing spaces */ -- if (!*begin) -- { -- begin = ++p; -- continue; -- } -+ /* Pointer to start of IPv4 or IPv6 address part. */ -+ txtaddr = p; - -- /* This is the part that actually sets the nameserver */ -- addr.s_addr = inet_addr(begin); -- if (addr.s_addr == INADDR_NONE) -- continue; -- newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state)); -- if (!newserv) -- return ARES_ENOMEM; -- newserv[*nservers].addr = addr; -- *servers = newserv; -- (*nservers)++; -+ /* Advance past this address. */ -+ while (*p && !ISSPACE(*p) && (*p != ',')) -+ p++; -+ if (*p) -+ /* Null terminate this address. */ -+ *p++ = '\0'; -+ else -+ /* Reached end of input, done when this address is processed. */ -+ p = NULL; -+ -+ /* Convert textual address to binary format. */ -+ if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1) -+ host.family = AF_INET; -+ else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1) -+ host.family = AF_INET6; -+ else -+ continue; -+ -+ /* Resize servers state array. */ -+ newserv = realloc(*servers, (*nservers + 1) * -+ sizeof(struct server_state)); -+ if (!newserv) -+ return ARES_ENOMEM; -+ -+ /* Store address data. */ -+ newserv[*nservers].addr.family = host.family; -+ if (host.family == AF_INET) -+ memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4, -+ sizeof(host.addrV4)); -+ else -+ memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6, -+ sizeof(host.addrV6)); -+ -+ /* Update arguments. */ -+ *servers = newserv; -+ *nservers += 1; -+ } - -- if (!more) -- break; -- begin = ++p; -- } --#else -- /* Add a nameserver entry, if this is a valid address. */ -- addr.s_addr = inet_addr(str); -- if (addr.s_addr == INADDR_NONE) -- return ARES_SUCCESS; -- newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state)); -- if (!newserv) -- return ARES_ENOMEM; -- newserv[*nservers].addr = addr; -- *servers = newserv; -- (*nservers)++; --#endif - return ARES_SUCCESS; - } - -@@ -1580,3 +1603,129 @@ void ares_set_socket_callback(ares_channel channel, - channel->sock_create_cb = cb; - channel->sock_create_cb_data = data; - } -+ -+void ares__init_servers_state(ares_channel channel) -+{ -+ struct server_state *server; -+ int i; -+ -+ for (i = 0; i < channel->nservers; i++) -+ { -+ server = &channel->servers[i]; -+ server->udp_socket = ARES_SOCKET_BAD; -+ server->tcp_socket = ARES_SOCKET_BAD; -+ server->tcp_connection_generation = ++channel->tcp_connection_generation; -+ server->tcp_lenbuf_pos = 0; -+ server->tcp_buffer_pos = 0; -+ server->tcp_buffer = NULL; -+ server->tcp_length = 0; -+ server->qhead = NULL; -+ server->qtail = NULL; -+ ares__init_list_head(&server->queries_to_server); -+ server->channel = channel; -+ server->is_broken = 0; -+ } -+} -+ -+int ares_get_servers(ares_channel channel, -+ struct ares_addr_node **servers) -+{ -+ struct ares_addr_node *srvr_head = NULL; -+ struct ares_addr_node *srvr_last = NULL; -+ struct ares_addr_node *srvr_curr; -+ int status = ARES_SUCCESS; -+ int i; -+ -+ if (!channel) -+ return ARES_ENODATA; -+ -+ for (i = 0; i < channel->nservers; i++) -+ { -+ /* Allocate storage for this server node appending it to the list */ -+ srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_NODE); -+ if (!srvr_curr) -+ { -+ status = ARES_ENOMEM; -+ break; -+ } -+ if (srvr_last) -+ { -+ srvr_last->next = srvr_curr; -+ } -+ else -+ { -+ srvr_head = srvr_curr; -+ } -+ srvr_last = srvr_curr; -+ -+ /* Fill this server node data */ -+ srvr_curr->family = channel->servers[i].addr.family; -+ if (srvr_curr->family == AF_INET) -+ memcpy(&srvr_curr->addrV4, &channel->servers[i].addr.addrV4, -+ sizeof(srvr_curr->addrV4)); -+ else -+ memcpy(&srvr_curr->addrV6, &channel->servers[i].addr.addrV6, -+ sizeof(srvr_curr->addrV6)); -+ } -+ -+ if (status != ARES_SUCCESS) -+ { -+ if (srvr_head) -+ { -+ ares_free_data(srvr_head); -+ srvr_head = NULL; -+ } -+ } -+ -+ *servers = srvr_head; -+ -+ return status; -+} -+ -+ -+int ares_set_servers(ares_channel channel, -+ struct ares_addr_node *servers) -+{ -+ struct ares_addr_node *srvr; -+ int num_srvrs = 0; -+ int i; -+ -+ if (ares_library_initialized() != ARES_SUCCESS) -+ return ARES_ENOTINITIALIZED; -+ -+ if (!channel) -+ return ARES_ENODATA; -+ -+ ares__destroy_servers_state(channel); -+ -+ for (srvr = servers; srvr; srvr = srvr->next) -+ { -+ num_srvrs++; -+ } -+ -+ if (num_srvrs > 0) -+ { -+ /* Allocate storage for servers state */ -+ channel->servers = malloc(num_srvrs * sizeof(struct server_state)); -+ if (!channel->servers) -+ { -+ return ARES_ENOMEM; -+ } -+ channel->nservers = num_srvrs; -+ /* Fill servers state address data */ -+ for (i = 0, srvr = servers; srvr; i++, srvr = srvr->next) -+ { -+ channel->servers[i].addr.family = srvr->family; -+ if (srvr->family == AF_INET) -+ memcpy(&channel->servers[i].addr.addrV4, &srvr->addrV4, -+ sizeof(srvr->addrV4)); -+ else -+ memcpy(&channel->servers[i].addr.addrV6, &srvr->addrV6, -+ sizeof(srvr->addrV6)); -+ } -+ /* Initialize servers state remaining data */ -+ ares__init_servers_state(channel); -+ } -+ -+ return ARES_SUCCESS; -+} -diff --git a/ares_ipv6.h b/ares_ipv6.h -index 18914d1..eb19f31 100644 ---- a/ares_ipv6.h -+++ b/ares_ipv6.h -@@ -1,4 +1,4 @@ --/* $Id: ares_ipv6.h,v 1.9 2009-05-02 02:36:48 yangtse Exp $ */ -+/* $Id: ares_ipv6.h,v 1.11 2010-03-06 01:23:09 yangtse Exp $ */ - - /* Copyright (C) 2005 by Dominick Meglio - * -@@ -22,23 +22,14 @@ - #define PF_INET6 AF_INET6 - #endif - --#if !defined(HAVE_STRUCT_IN6_ADDR) && !defined(s6_addr) --struct in6_addr { -- union { -- unsigned char _S6_u8[16]; -- } _S6_un; --}; --#define s6_addr _S6_un._S6_u8 --#endif -- - #ifndef HAVE_STRUCT_SOCKADDR_IN6 - struct sockaddr_in6 - { -- unsigned short sin6_family; -- unsigned short sin6_port; -- unsigned long sin6_flowinfo; -- struct in6_addr sin6_addr; -- unsigned int sin6_scope_id; -+ unsigned short sin6_family; -+ unsigned short sin6_port; -+ unsigned long sin6_flowinfo; -+ struct ares_in6_addr sin6_addr; -+ unsigned int sin6_scope_id; - }; - #endif - -diff --git a/ares_parse_aaaa_reply.c b/ares_parse_aaaa_reply.c -index c2329cc..364f430 100644 ---- a/ares_parse_aaaa_reply.c -+++ b/ares_parse_aaaa_reply.c -@@ -1,4 +1,4 @@ --/* $Id: ares_parse_aaaa_reply.c,v 1.16 2009-11-23 01:24:17 yangtse Exp $ */ -+/* $Id: ares_parse_aaaa_reply.c,v 1.17 2010-03-05 20:01:48 yangtse Exp $ */ - - /* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright 2005 Dominick Meglio -@@ -65,7 +65,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, - long len; - const unsigned char *aptr; - char *hostname, *rr_name, *rr_data, **aliases; -- struct in6_addr *addrs; -+ struct ares_in6_addr *addrs; - struct hostent *hostent; - const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0; - -@@ -101,7 +101,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, - /* Allocate addresses and aliases; ancount gives an upper bound for both. */ - if (host) - { -- addrs = malloc(ancount * sizeof(struct in6_addr)); -+ addrs = malloc(ancount * sizeof(struct ares_in6_addr)); - if (!addrs) - { - free(hostname); -@@ -143,27 +143,27 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, - aptr += RRFIXEDSZ; - - if (rr_class == C_IN && rr_type == T_AAAA -- && rr_len == sizeof(struct in6_addr) -+ && rr_len == sizeof(struct ares_in6_addr) - && strcasecmp(rr_name, hostname) == 0) - { - if (addrs) - { -- if (aptr + sizeof(struct in6_addr) > abuf + alen) -+ if (aptr + sizeof(struct ares_in6_addr) > abuf + alen) - { - status = ARES_EBADRESP; - break; - } -- memcpy(&addrs[naddrs], aptr, sizeof(struct in6_addr)); -+ memcpy(&addrs[naddrs], aptr, sizeof(struct ares_in6_addr)); - } - if (naddrs < max_addr_ttls) - { - struct ares_addr6ttl * const at = &addrttls[naddrs]; -- if (aptr + sizeof(struct in6_addr) > abuf + alen) -+ if (aptr + sizeof(struct ares_in6_addr) > abuf + alen) - { - status = ARES_EBADRESP; - break; - } -- memcpy(&at->ip6addr, aptr, sizeof(struct in6_addr)); -+ memcpy(&at->ip6addr, aptr, sizeof(struct ares_in6_addr)); - at->ttl = rr_ttl; - } - naddrs++; -@@ -233,7 +233,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, - hostent->h_name = hostname; - hostent->h_aliases = aliases; - hostent->h_addrtype = AF_INET6; -- hostent->h_length = sizeof(struct in6_addr); -+ hostent->h_length = sizeof(struct ares_in6_addr); - for (i = 0; i < naddrs; i++) - hostent->h_addr_list[i] = (char *) &addrs[i]; - hostent->h_addr_list[naddrs] = NULL; -diff --git a/ares_private.h b/ares_private.h -index 4726d7a..1de693a 100644 ---- a/ares_private.h -+++ b/ares_private.h -@@ -1,10 +1,10 @@ - #ifndef __ARES_PRIVATE_H - #define __ARES_PRIVATE_H - --/* $Id: ares_private.h,v 1.50 2009-11-09 12:56:50 yangtse Exp $ */ -+/* $Id: ares_private.h,v 1.51 2010-03-05 20:01:48 yangtse Exp $ */ - - /* Copyright 1998 by the Massachusetts Institute of Technology. -- * Copyright (C) 2004-2009 by Daniel Stenberg -+ * Copyright (C) 2004-2010 by Daniel Stenberg - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without -@@ -113,8 +113,8 @@ - struct ares_addr { - int family; - union { -- struct in_addr addr4; -- struct in6_addr addr6; -+ struct in_addr addr4; -+ struct ares_in6_addr addr6; - } addr; - }; - #define addrV4 addr.addr4 -@@ -137,7 +137,7 @@ struct send_request { - }; - - struct server_state { -- struct in_addr addr; -+ struct ares_addr addr; - ares_socket_t udp_socket; - ares_socket_t tcp_socket; - -@@ -221,14 +221,14 @@ struct query_server_info { - struct apattern { - union - { -- struct in_addr addr4; -- struct in6_addr addr6; -+ struct in_addr addr4; -+ struct ares_in6_addr addr6; - } addr; - union - { -- struct in_addr addr4; -- struct in6_addr addr6; -- unsigned short bits; -+ struct in_addr addr4; -+ struct ares_in6_addr addr6; -+ unsigned short bits; - } mask; - int family; - unsigned short type; -@@ -319,6 +319,8 @@ struct timeval ares__tvnow(void); - int ares__expand_name_for_response(const unsigned char *encoded, - const unsigned char *abuf, int alen, - char **s, long *enclen); -+void ares__init_servers_state(ares_channel channel); -+void ares__destroy_servers_state(ares_channel channel); - #if 0 /* Not used */ - long ares__tvdiff(struct timeval t1, struct timeval t2); - #endif -diff --git a/ares_process.c b/ares_process.c -index 6182ccc..ef4060a 100644 ---- a/ares_process.c -+++ b/ares_process.c -@@ -97,6 +97,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server); - static int open_udp_socket(ares_channel channel, struct server_state *server); - static int same_questions(const unsigned char *qbuf, int qlen, - const unsigned char *abuf, int alen); -+static int same_address(struct sockaddr *sa, struct ares_addr *aa); - static void end_query(ares_channel channel, struct query *query, int status, - unsigned char *abuf, int alen); - -@@ -428,8 +429,11 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds, - ssize_t count; - unsigned char buf[PACKETSZ + 1]; - #ifdef HAVE_RECVFROM -- struct sockaddr_in from; - ares_socklen_t fromlen; -+ union { -+ struct sockaddr_in sa4; -+ struct sockaddr_in6 sa6; -+ } from; - #endif - - if(!read_fds && (read_fd == ARES_SOCKET_BAD)) -@@ -465,7 +469,10 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds, - * packets as we can. */ - do { - #ifdef HAVE_RECVFROM -- fromlen = sizeof(from); -+ if (server->addr.family == AF_INET) -+ fromlen = sizeof(from.sa4); -+ else -+ fromlen = sizeof(from.sa6); - count = (ssize_t)recvfrom(server->udp_socket, (void *)buf, sizeof(buf), - 0, (struct sockaddr *)&from, &fromlen); - #else -@@ -476,10 +483,10 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds, - else if (count <= 0) - handle_error(channel, i, now); - #ifdef HAVE_RECVFROM -- else if (from.sin_addr.s_addr != server->addr.s_addr) -- /* Address response came from did not match the address -- * we sent the request to. Someone may be attempting -- * to perform a cache poisoning attack */ -+ else if (!same_address((struct sockaddr *)&from, &server->addr)) -+ /* The address the response comes from does not match -+ * the address we sent the request to. Someone may be -+ * attempting to perform a cache poisoning attack. */ - break; - #endif - else -@@ -886,10 +893,39 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) - { - ares_socket_t s; - int opt; -- struct sockaddr_in sockin; -+ ares_socklen_t salen; -+ union { -+ struct sockaddr_in sa4; -+ struct sockaddr_in6 sa6; -+ } saddr; -+ struct sockaddr *sa; -+ -+ switch (server->addr.family) -+ { -+ case AF_INET: -+ sa = (void *)&saddr.sa4; -+ salen = sizeof(saddr.sa4); -+ memset(sa, 0, salen); -+ saddr.sa4.sin_family = AF_INET; -+ saddr.sa4.sin_port = (unsigned short)(channel->tcp_port & 0xffff); -+ memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, -+ sizeof(server->addr.addrV4)); -+ break; -+ case AF_INET6: -+ sa = (void *)&saddr.sa6; -+ salen = sizeof(saddr.sa6); -+ memset(sa, 0, salen); -+ saddr.sa6.sin6_family = AF_INET6; -+ saddr.sa6.sin6_port = (unsigned short)(channel->tcp_port & 0xffff); -+ memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, -+ sizeof(server->addr.addrV6)); -+ break; -+ default: -+ return -1; -+ } - - /* Acquire a socket. */ -- s = socket(AF_INET, SOCK_STREAM, 0); -+ s = socket(server->addr.family, SOCK_STREAM, 0); - if (s == ARES_SOCKET_BAD) - return -1; - -@@ -917,11 +953,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) - #endif - - /* Connect to the server. */ -- memset(&sockin, 0, sizeof(sockin)); -- sockin.sin_family = AF_INET; -- sockin.sin_addr = server->addr; -- sockin.sin_port = (unsigned short)(channel->tcp_port & 0xffff); -- if (connect(s, (struct sockaddr *) &sockin, sizeof(sockin)) == -1) -+ if (connect(s, sa, salen) == -1) - { - int err = SOCKERRNO; - -@@ -953,10 +985,39 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) - static int open_udp_socket(ares_channel channel, struct server_state *server) - { - ares_socket_t s; -- struct sockaddr_in sockin; -+ ares_socklen_t salen; -+ union { -+ struct sockaddr_in sa4; -+ struct sockaddr_in6 sa6; -+ } saddr; -+ struct sockaddr *sa; -+ -+ switch (server->addr.family) -+ { -+ case AF_INET: -+ sa = (void *)&saddr.sa4; -+ salen = sizeof(saddr.sa4); -+ memset(sa, 0, salen); -+ saddr.sa4.sin_family = AF_INET; -+ saddr.sa4.sin_port = (unsigned short)(channel->udp_port & 0xffff); -+ memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, -+ sizeof(server->addr.addrV4)); -+ break; -+ case AF_INET6: -+ sa = (void *)&saddr.sa6; -+ salen = sizeof(saddr.sa6); -+ memset(sa, 0, salen); -+ saddr.sa6.sin6_family = AF_INET6; -+ saddr.sa6.sin6_port = (unsigned short)(channel->udp_port & 0xffff); -+ memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, -+ sizeof(server->addr.addrV6)); -+ break; -+ default: -+ return -1; -+ } - - /* Acquire a socket. */ -- s = socket(AF_INET, SOCK_DGRAM, 0); -+ s = socket(server->addr.family, SOCK_DGRAM, 0); - if (s == ARES_SOCKET_BAD) - return -1; - -@@ -968,11 +1029,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) - } - - /* Connect to the server. */ -- memset(&sockin, 0, sizeof(sockin)); -- sockin.sin_family = AF_INET; -- sockin.sin_addr = server->addr; -- sockin.sin_port = (unsigned short)(channel->udp_port & 0xffff); -- if (connect(s, (struct sockaddr *) &sockin, sizeof(sockin)) == -1) -+ if (connect(s, sa, salen) == -1) - { - int err = SOCKERRNO; - -@@ -1079,6 +1136,34 @@ static int same_questions(const unsigned char *qbuf, int qlen, - return 1; - } - -+static int same_address(struct sockaddr *sa, struct ares_addr *aa) -+{ -+ void *addr1; -+ void *addr2; -+ -+ if (sa->sa_family == aa->family) -+ { -+ switch (aa->family) -+ { -+ case AF_INET: -+ addr1 = &aa->addrV4; -+ addr2 = &((struct sockaddr_in *)sa)->sin_addr; -+ if (memcmp(addr1, addr2, sizeof(aa->addrV4)) == 0) -+ return 1; /* match */ -+ break; -+ case AF_INET6: -+ addr1 = &aa->addrV6; -+ addr2 = &((struct sockaddr_in6 *)sa)->sin6_addr; -+ if (memcmp(addr1, addr2, sizeof(aa->addrV6)) == 0) -+ return 1; /* match */ -+ break; -+ default: -+ break; -+ } -+ } -+ return 0; /* different */ -+} -+ - static void end_query (ares_channel channel, struct query *query, int status, - unsigned char *abuf, int alen) - { -diff --git a/ares_save_options.3 b/ares_save_options.3 -index 268327c..8ed8925 100644 ---- a/ares_save_options.3 -+++ b/ares_save_options.3 -@@ -1,4 +1,4 @@ --.\" $Id: ares_save_options.3,v 1.3 2009-11-23 00:57:51 yangtse Exp $ -+.\" $Id: ares_save_options.3,v 1.4 2010-03-05 20:01:48 yangtse Exp $ - .\" - .\" Copyright 1998 by the Massachusetts Institute of Technology. - .\" -@@ -14,7 +14,7 @@ - .\" this software for any purpose. It is provided "as is" - .\" without express or implied warranty. - .\" --.TH ARES_SAVE_OPTIONS 3 "1 June 2007" -+.TH ARES_SAVE_OPTIONS 3 "5 March 2010" - .SH NAME - ares_save_options \- Save configuration values obtained from initialized ares_channel - .SH SYNOPSIS -@@ -52,13 +52,20 @@ The channel data identified by - were invalid. - .SH NOTE - Since c-ares 1.6.0 the ares_options struct has been "locked" meaning that it --won't be extended to cover new funtions. This function will remain -+won't be extended to cover new functions. This function will remain - functioning, but it can only return config data that can be represented in - this config struct, which may no longer be the complete set of config - options. \fBares_dup(3)\fP will not have that restriction. -+ -+The ares_options struct can not handle potential IPv6 name servers the -+ares_channel might be configured to use. Function \fBares_save_options(3)\fP -+will only return IPv4 servers if any. In order to retrieve all name servers -+an ares_channel might be using, function \fBares_get_servers(3)\fP must be -+used instead. - .SH SEE ALSO - .BR ares_destroy_options (3), - .BR ares_init_options (3), -+.BR ares_get_servers (3), - .BR ares_dup (3) - .SH AVAILABILITY - ares_save_options(3) was added in c-ares 1.4.0 -diff --git a/inet_net_pton.c b/inet_net_pton.c -index de09ace..f4a0812 100644 ---- a/inet_net_pton.c -+++ b/inet_net_pton.c -@@ -1,4 +1,4 @@ --/* $Id: inet_net_pton.c,v 1.17 2009-11-02 11:55:54 yangtse Exp $ */ -+/* $Id: inet_net_pton.c,v 1.18 2010-03-05 20:01:48 yangtse Exp $ */ - - /* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") -@@ -43,6 +43,7 @@ - #include - #include - -+#include "ares.h" - #include "ares_ipv6.h" - #include "inet_net_pton.h" - -@@ -432,7 +433,7 @@ int ares_inet_pton(int af, const char *src, void *dst) - if (af == AF_INET) - size = sizeof(struct in_addr); - else if (af == AF_INET6) -- size = sizeof(struct in6_addr); -+ size = sizeof(struct ares_in6_addr); - else - { - SET_ERRNO(EAFNOSUPPORT); -diff --git a/inet_ntop.c b/inet_ntop.c -index 5b0d097..31b9ab1 100644 ---- a/inet_ntop.c -+++ b/inet_ntop.c -@@ -1,4 +1,4 @@ --/* $Id: inet_ntop.c,v 1.12 2009-11-02 11:55:54 yangtse Exp $ */ -+/* $Id: inet_ntop.c,v 1.13 2010-03-05 20:01:48 yangtse Exp $ */ - - /* Copyright (c) 1996 by Internet Software Consortium. - * -@@ -42,6 +42,7 @@ - #include - #include - -+#include "ares.h" - #include "ares_ipv6.h" - #include "inet_ntop.h" - -diff --git a/vc/cares/vc6cares.dsp b/vc/cares/vc6cares.dsp -index b7c50c6..583a55c 100644 ---- a/vc/cares/vc6cares.dsp -+++ b/vc/cares/vc6cares.dsp -@@ -226,6 +226,10 @@ SOURCE=..\..\ares_mkquery.c - # End Source File - # Begin Source File - -+SOURCE=..\..\ares_options.c -+# End Source File -+# Begin Source File -+ - SOURCE=..\..\ares_parse_a_reply.c - # End Source File - # Begin Source File --- -1.6.6.1 -