Added IPv6 name servers support
This commit is contained in:
21
ares/CHANGES
21
ares/CHANGES
@@ -1,5 +1,26 @@
|
|||||||
Changelog for the c-ares project
|
Changelog for the c-ares project
|
||||||
|
|
||||||
|
* March 5, 2010 (Yang Tse)
|
||||||
|
- Added IPv6 name servers support. Implementation has been based on code,
|
||||||
|
comments and feedback provided November and December of 2008 by Daniel
|
||||||
|
Stenberg, Gregor Jasny, Phil Blundell and myself, December 2009 by Cedric
|
||||||
|
Bail, and February 2010 by Jakub Hrozek on the c-ares mailing list. On
|
||||||
|
March I reviewed all that, selected the best of each, and adjusted or
|
||||||
|
extended parts of it to make the best fit.
|
||||||
|
|
||||||
|
The external and visible result of all this is that two new functions are
|
||||||
|
added to the external API, ares_get_servers() and ares_set_servers(), which
|
||||||
|
becomes now the preferred way of getting and setting name servers for any
|
||||||
|
ares channel as these support both IPv4 and IPv6 name servers.
|
||||||
|
|
||||||
|
In order to not break ABI compatibility, ares_init_options() with option
|
||||||
|
mask ARES_OPT_SERVERS and ares_save_options() may still be used in code
|
||||||
|
which is intended to run on IPv4-only stacks. But remember that these
|
||||||
|
functions do not support IPv6 name servers. This implies that if the user
|
||||||
|
is capable of defining or providing an IPv6 name server, and the app is
|
||||||
|
using ares_init_options() or ares_save_options() at some point to handle
|
||||||
|
the name servers, the app will likely loose IPv6 name servers.
|
||||||
|
|
||||||
* January 28, 2010 (Daniel Stenberg)
|
* January 28, 2010 (Daniel Stenberg)
|
||||||
- Tommie Gannert pointed out a silly bug in ares_process_fd() since it didn't
|
- Tommie Gannert pointed out a silly bug in ares_process_fd() since it didn't
|
||||||
check for broken connections like ares_process() did. Based on that, I
|
check for broken connections like ares_process() did. Based on that, I
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ CSOURCES = ares__close_sockets.c \
|
|||||||
ares_llist.c \
|
ares_llist.c \
|
||||||
ares_mkquery.c \
|
ares_mkquery.c \
|
||||||
ares_nowarn.c \
|
ares_nowarn.c \
|
||||||
|
ares_options.c \
|
||||||
ares_parse_a_reply.c \
|
ares_parse_a_reply.c \
|
||||||
ares_parse_aaaa_reply.c \
|
ares_parse_aaaa_reply.c \
|
||||||
ares_parse_ns_reply.c \
|
ares_parse_ns_reply.c \
|
||||||
@@ -48,8 +49,8 @@ HHEADERS = ares.h \
|
|||||||
ares_ipv6.h \
|
ares_ipv6.h \
|
||||||
ares_library_init.h \
|
ares_library_init.h \
|
||||||
ares_llist.h \
|
ares_llist.h \
|
||||||
ares_private.h \
|
|
||||||
ares_nowarn.h \
|
ares_nowarn.h \
|
||||||
|
ares_private.h \
|
||||||
ares_rules.h \
|
ares_rules.h \
|
||||||
ares_strcasecmp.h \
|
ares_strcasecmp.h \
|
||||||
ares_strdup.h \
|
ares_strdup.h \
|
||||||
@@ -72,6 +73,7 @@ MANPAGES = ares_cancel.3 \
|
|||||||
ares_free_data.3 \
|
ares_free_data.3 \
|
||||||
ares_free_hostent.3 \
|
ares_free_hostent.3 \
|
||||||
ares_free_string.3 \
|
ares_free_string.3 \
|
||||||
|
ares_get_servers.3 \
|
||||||
ares_gethostbyaddr.3 \
|
ares_gethostbyaddr.3 \
|
||||||
ares_gethostbyname.3 \
|
ares_gethostbyname.3 \
|
||||||
ares_gethostbyname_file.3 \
|
ares_gethostbyname_file.3 \
|
||||||
@@ -93,6 +95,7 @@ MANPAGES = ares_cancel.3 \
|
|||||||
ares_save_options.3 \
|
ares_save_options.3 \
|
||||||
ares_search.3 \
|
ares_search.3 \
|
||||||
ares_send.3 \
|
ares_send.3 \
|
||||||
|
ares_set_servers.3 \
|
||||||
ares_set_socket_callback.3 \
|
ares_set_socket_callback.3 \
|
||||||
ares_strerror.3 \
|
ares_strerror.3 \
|
||||||
ares_timeout.3 \
|
ares_timeout.3 \
|
||||||
@@ -108,6 +111,7 @@ HTMLPAGES = ares_cancel.html \
|
|||||||
ares_free_data.html \
|
ares_free_data.html \
|
||||||
ares_free_hostent.html \
|
ares_free_hostent.html \
|
||||||
ares_free_string.html \
|
ares_free_string.html \
|
||||||
|
ares_get_servers.html \
|
||||||
ares_gethostbyaddr.html \
|
ares_gethostbyaddr.html \
|
||||||
ares_gethostbyname.html \
|
ares_gethostbyname.html \
|
||||||
ares_gethostbyname_file.html \
|
ares_gethostbyname_file.html \
|
||||||
@@ -129,6 +133,7 @@ HTMLPAGES = ares_cancel.html \
|
|||||||
ares_save_options.html \
|
ares_save_options.html \
|
||||||
ares_search.html \
|
ares_search.html \
|
||||||
ares_send.html \
|
ares_send.html \
|
||||||
|
ares_set_servers.html \
|
||||||
ares_set_socket_callback.html \
|
ares_set_socket_callback.html \
|
||||||
ares_strerror.html \
|
ares_strerror.html \
|
||||||
ares_timeout.html \
|
ares_timeout.html \
|
||||||
@@ -144,6 +149,7 @@ PDFPAGES = ares_cancel.pdf \
|
|||||||
ares_free_data.pdf \
|
ares_free_data.pdf \
|
||||||
ares_free_hostent.pdf \
|
ares_free_hostent.pdf \
|
||||||
ares_free_string.pdf \
|
ares_free_string.pdf \
|
||||||
|
ares_get_servers.pdf \
|
||||||
ares_gethostbyaddr.pdf \
|
ares_gethostbyaddr.pdf \
|
||||||
ares_gethostbyname.pdf \
|
ares_gethostbyname.pdf \
|
||||||
ares_gethostbyname_file.pdf \
|
ares_gethostbyname_file.pdf \
|
||||||
@@ -165,6 +171,7 @@ PDFPAGES = ares_cancel.pdf \
|
|||||||
ares_save_options.pdf \
|
ares_save_options.pdf \
|
||||||
ares_search.pdf \
|
ares_search.pdf \
|
||||||
ares_send.pdf \
|
ares_send.pdf \
|
||||||
|
ares_set_servers.pdf \
|
||||||
ares_set_socket_callback.pdf \
|
ares_set_socket_callback.pdf \
|
||||||
ares_strerror.pdf \
|
ares_strerror.pdf \
|
||||||
ares_timeout.pdf \
|
ares_timeout.pdf \
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ This is what's new and changed in the c-ares 1.7.1 release:
|
|||||||
|
|
||||||
Changed:
|
Changed:
|
||||||
|
|
||||||
o
|
o added IPv6 name servers support
|
||||||
|
|
||||||
Fixed:
|
Fixed:
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ Fixed:
|
|||||||
|
|
||||||
Thanks go to these friendly people for their efforts and contributions:
|
Thanks go to these friendly people for their efforts and contributions:
|
||||||
|
|
||||||
Ingmar Runge, Laszlo Tamas Szabo, Yang Tse, Tommie Gannert
|
Ingmar Runge, Laszlo Tamas Szabo, Yang Tse, Tommie Gannert, Gregor Jasny,
|
||||||
|
Phil Blundell, Cedric Bail, Jakub Hrozek
|
||||||
|
|
||||||
Have fun!
|
Have fun!
|
||||||
|
|||||||
107
ares/adig.c
107
ares/adig.c
@@ -164,8 +164,6 @@ static const char *rcodes[] = {
|
|||||||
"(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
|
"(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct in_addr inaddr;
|
|
||||||
|
|
||||||
static void callback(void *arg, int status, int timeouts,
|
static void callback(void *arg, int status, int timeouts,
|
||||||
unsigned char *abuf, int alen);
|
unsigned char *abuf, int alen);
|
||||||
static const unsigned char *display_question(const unsigned char *aptr,
|
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 *type_name(int type);
|
||||||
static const char *class_name(int dnsclass);
|
static const char *class_name(int dnsclass);
|
||||||
static void usage(void);
|
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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -186,6 +187,7 @@ int main(int argc, char **argv)
|
|||||||
struct hostent *hostent;
|
struct hostent *hostent;
|
||||||
fd_set read_fds, write_fds;
|
fd_set read_fds, write_fds;
|
||||||
struct timeval *tvp, tv;
|
struct timeval *tvp, tv;
|
||||||
|
struct ares_addr_node *srvr, *servers = NULL;
|
||||||
|
|
||||||
#ifdef USE_WINSOCK
|
#ifdef USE_WINSOCK
|
||||||
WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
|
WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
|
||||||
@@ -227,27 +229,56 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
/* Add a server, and specify servers in the option mask. */
|
/* User specified name servers override default ones. */
|
||||||
if (ares_inet_pton(AF_INET, optarg, &inaddr) <= 0)
|
srvr = malloc(sizeof(struct ares_addr_node));
|
||||||
{
|
if (!srvr)
|
||||||
hostent = gethostbyname(optarg);
|
|
||||||
if (!hostent || hostent->h_addrtype != AF_INET)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "adig: server %s not found.\n", optarg);
|
|
||||||
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");
|
fprintf(stderr, "Out of memory!\n");
|
||||||
|
destroy_addr_list(servers);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memcpy(&options.servers[options.nservers], &inaddr,
|
append_addr_list(&servers, srvr);
|
||||||
sizeof(struct in_addr));
|
if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
|
||||||
options.nservers++;
|
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)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "adig: server %s not found.\n", optarg);
|
||||||
|
destroy_addr_list(servers);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 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;
|
optmask |= ARES_OPT_SERVERS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -308,6 +339,18 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
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
|
/* Initiate the queries, one per command-line argument. If there is
|
||||||
* only one query to do, supply NULL as the callback argument;
|
* only one query to do, supply NULL as the callback argument;
|
||||||
* otherwise, supply the query name as an argument so we can
|
* 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");
|
"[-t type] [-p port] name ...\n");
|
||||||
exit(1);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ int main(int argc, char **argv)
|
|||||||
fd_set read_fds, write_fds;
|
fd_set read_fds, write_fds;
|
||||||
struct timeval *tvp, tv;
|
struct timeval *tvp, tv;
|
||||||
struct in_addr addr4;
|
struct in_addr addr4;
|
||||||
struct in6_addr addr6;
|
struct ares_in6_addr addr6;
|
||||||
|
|
||||||
#ifdef USE_WINSOCK
|
#ifdef USE_WINSOCK
|
||||||
WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
|
WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
|
||||||
|
|||||||
17
ares/ares.h
17
ares/ares.h
@@ -1,7 +1,7 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
/* Copyright 1998, 2009 by the Massachusetts Institute of Technology.
|
/* 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
|
* Permission to use, copy, modify, and distribute this
|
||||||
* software and its documentation for any purpose and without
|
* 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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
/* 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
|
* Permission to use, copy, modify, and distribute this
|
||||||
* software and its documentation for any purpose and without
|
* 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. */
|
/* Actual network address family and length. */
|
||||||
addr.family = AF_INET;
|
addr.family = AF_INET;
|
||||||
addrlen = sizeof(struct in_addr);
|
addrlen = sizeof(addr.addrV4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
|
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. */
|
/* Actual network address family and length. */
|
||||||
addr.family = AF_INET6;
|
addr.family = AF_INET6;
|
||||||
addrlen = sizeof(struct in6_addr);
|
addrlen = sizeof(addr.addrV6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!addrlen)
|
if (!addrlen)
|
||||||
@@ -189,9 +189,9 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
|
|||||||
if (!hostent->h_addr_list[0])
|
if (!hostent->h_addr_list[0])
|
||||||
break;
|
break;
|
||||||
if (addr.family == AF_INET)
|
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
|
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. */
|
/* Copy aliases. */
|
||||||
hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
|
hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
/* Copyright (C) 2009 by Daniel Stenberg
|
/* Copyright (C) 2009-2010 by Daniel Stenberg
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this
|
* Permission to use, copy, modify, and distribute this
|
||||||
* software and its documentation for any purpose and without
|
* software and its documentation for any purpose and without
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
** of c-ares functions returning pointers that must be free'ed using this
|
** of c-ares functions returning pointers that must be free'ed using this
|
||||||
** function is:
|
** function is:
|
||||||
**
|
**
|
||||||
|
** ares_get_servers()
|
||||||
** ares_parse_srv_reply()
|
** ares_parse_srv_reply()
|
||||||
** ares_parse_txt_reply()
|
** ares_parse_txt_reply()
|
||||||
*/
|
*/
|
||||||
@@ -78,6 +79,12 @@ void ares_free_data(void *dataptr)
|
|||||||
free(ptr->data.txt_reply.txt);
|
free(ptr->data.txt_reply.txt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARES_DATATYPE_ADDR_NODE:
|
||||||
|
|
||||||
|
if (ptr->data.addr_node.next)
|
||||||
|
ares_free_data(ptr->data.addr_node.next);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -121,6 +128,12 @@ void *ares_malloc_data(ares_datatype type)
|
|||||||
ptr->data.txt_reply.length = 0;
|
ptr->data.txt_reply.length = 0;
|
||||||
break;
|
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:
|
default:
|
||||||
free(ptr);
|
free(ptr);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
/* Copyright (C) 2009 by Daniel Stenberg
|
/* Copyright (C) 2009-2010 by Daniel Stenberg
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this
|
* Permission to use, copy, modify, and distribute this
|
||||||
* software and its documentation for any purpose and without
|
* 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_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_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_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
|
#if 0
|
||||||
ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */
|
ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */
|
||||||
ARES_DATATYPE_ADDRTTL, /* struct ares_addr6ttl */
|
ARES_DATATYPE_ADDRTTL, /* struct ares_addr6ttl */
|
||||||
@@ -54,6 +55,7 @@ struct ares_data {
|
|||||||
union {
|
union {
|
||||||
struct ares_txt_reply txt_reply;
|
struct ares_txt_reply txt_reply;
|
||||||
struct ares_srv_reply srv_reply;
|
struct ares_srv_reply srv_reply;
|
||||||
|
struct ares_addr_node addr_node;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
|
* Copyright (C) 2004-2010 by Daniel Stenberg
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this
|
* Permission to use, copy, modify, and distribute this
|
||||||
* software and its documentation for any purpose and without
|
* software and its documentation for any purpose and without
|
||||||
@@ -25,7 +26,8 @@ void ares_destroy_options(struct ares_options *options)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
free(options->servers);
|
if(options->servers)
|
||||||
|
free(options->servers);
|
||||||
for (i = 0; i < options->ndomains; i++)
|
for (i = 0; i < options->ndomains; i++)
|
||||||
free(options->domains[i]);
|
free(options->domains[i]);
|
||||||
free(options->domains);
|
free(options->domains);
|
||||||
@@ -67,15 +69,7 @@ void ares_destroy(ares_channel channel)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (channel->servers) {
|
ares__destroy_servers_state(channel);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel->domains) {
|
if (channel->domains) {
|
||||||
for (i = 0; i < channel->ndomains; i++)
|
for (i = 0; i < channel->ndomains; i++)
|
||||||
@@ -91,3 +85,22 @@ void ares_destroy(ares_channel channel)
|
|||||||
|
|
||||||
free(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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright 1998 by the Massachusetts Institute of Technology.
|
.\" 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
|
.\" Permission to use, copy, modify, and distribute this
|
||||||
.\" software and its documentation for any purpose and without
|
.\" software and its documentation for any purpose and without
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
.\" this software for any purpose. It is provided "as is"
|
.\" this software for any purpose. It is provided "as is"
|
||||||
.\" without express or implied warranty.
|
.\" without express or implied warranty.
|
||||||
.\"
|
.\"
|
||||||
.TH ARES_FREE_DATA 3 "23 Nov 2009"
|
.TH ARES_FREE_DATA 3 "5 March 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ares_free_data \- Free data allocated by several c-ares functions
|
ares_free_data \- Free data allocated by several c-ares functions
|
||||||
.SH SYNOPSIS
|
.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
|
by several c-ares functions. Specifically the data returned by the
|
||||||
following list of functions must be deallocated using this function.
|
following list of functions must be deallocated using this function.
|
||||||
.TP 5
|
.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)
|
.B ares_parse_srv_reply(3)
|
||||||
When used to free the data returned by ares_parse_srv_reply(3) this
|
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
|
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
|
.SH AVAILABILITY
|
||||||
This function was first introduced in c-ares version 1.7.0.
|
This function was first introduced in c-ares version 1.7.0.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
|
.BR ares_get_servers(3),
|
||||||
.BR ares_parse_srv_reply(3),
|
.BR ares_parse_srv_reply(3),
|
||||||
.BR ares_parse_txt_reply(3)
|
.BR ares_parse_txt_reply(3)
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
@@ -57,4 +63,4 @@ Yang Tse
|
|||||||
.PP
|
.PP
|
||||||
Copyright 1998 by the Massachusetts Institute of Technology.
|
Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
.br
|
.br
|
||||||
Copyright (C) 2004-2009 by Daniel Stenberg.
|
Copyright (C) 2004-2010 by Daniel Stenberg.
|
||||||
|
|||||||
78
ares/ares_get_servers.3
Normal file
78
ares/ares_get_servers.3
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
.\" $Id$
|
||||||
|
.\"
|
||||||
|
.\" Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
|
.\" Copyright (C) 2008-2010 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.\" Permission to use, copy, modify, and distribute this
|
||||||
|
.\" software and its documentation for any purpose and without
|
||||||
|
.\" fee is hereby granted, provided that the above copyright
|
||||||
|
.\" notice appear in all copies and that both that copyright
|
||||||
|
.\" notice and this permission notice appear in supporting
|
||||||
|
.\" documentation, and that the name of M.I.T. not be used in
|
||||||
|
.\" advertising or publicity pertaining to distribution of the
|
||||||
|
.\" software without specific, written prior permission.
|
||||||
|
.\" M.I.T. makes no representations about the suitability of
|
||||||
|
.\" this software for any purpose. It is provided "as is"
|
||||||
|
.\" without express or implied warranty.
|
||||||
|
.\"
|
||||||
|
.TH ARES_GET_SERVERS 3 "5 March 2010"
|
||||||
|
.SH NAME
|
||||||
|
ares_get_servers \- Retrieve name servers from an initialized ares_channel
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <ares.h>
|
||||||
|
.PP
|
||||||
|
.B int ares_get_servers(ares_channel \fIchannel\fP, struct ares_addr_node **\fIservers\fP)
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The \fBares_get_servers(3)\fP function retrieves name servers configuration
|
||||||
|
from the
|
||||||
|
channel data identified by
|
||||||
|
.IR channel ,
|
||||||
|
as a linked list of ares_addr_node structs storing a pointer to the first
|
||||||
|
node at the address specified by
|
||||||
|
.IR servers .
|
||||||
|
|
||||||
|
Function caller may traverse the returned name server linked list, or may use
|
||||||
|
it directly as suitable input for the \fBares_set_servers(3)\fP function, but
|
||||||
|
shall not shrink or extend the list on its own.
|
||||||
|
|
||||||
|
Each node of the name server linked list is stored in memory dynamically
|
||||||
|
allocated and managed by c-ares. It is the caller's responsibility to free
|
||||||
|
the resulting linked list, using \fBares_free_data(3)\fP , once the caller
|
||||||
|
does not need it any longer.
|
||||||
|
|
||||||
|
This function is capable of handling IPv4 and IPv6 name server
|
||||||
|
addresses simultaneously, rendering \fBares_save_options(3)\fP with
|
||||||
|
optmask \fBARES_OPT_SERVERS\fP functionally obsolete except for
|
||||||
|
IPv4-only name server usage.
|
||||||
|
|
||||||
|
.SH RETURN VALUES
|
||||||
|
.B ares_get_servers(3)
|
||||||
|
may return any of the following values:
|
||||||
|
.TP 15
|
||||||
|
.B ARES_SUCCESS
|
||||||
|
The name servers configuration was successfuly retrieved
|
||||||
|
.TP 15
|
||||||
|
.B ARES_ENOMEM
|
||||||
|
The memory was exhausted
|
||||||
|
.TP 15
|
||||||
|
.B ARES_ENODATA
|
||||||
|
The channel data identified by
|
||||||
|
.IR channel
|
||||||
|
was invalid.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ares_set_servers (3),
|
||||||
|
.BR ares_init_options (3),
|
||||||
|
.BR ares_save_options(3)
|
||||||
|
.SH AVAILABILITY
|
||||||
|
ares_get_servers(3) was added in c-ares 1.7.1
|
||||||
|
.SH AUTHOR
|
||||||
|
Implementation of this function and associated library internals are based
|
||||||
|
on code, comments and feedback provided November and December of 2008 by
|
||||||
|
Daniel Stenberg, Gregor Jasny, Phil Blundell and Yang Tse, December 2009
|
||||||
|
by Cedric Bail, February 2010 by Jakub Hrozek. On March 2010 Yang Tse
|
||||||
|
shuffled all the bits and this function popped out.
|
||||||
|
.br
|
||||||
|
Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
|
Copyright (C) 2008-2010 by Daniel Stenberg
|
||||||
@@ -79,8 +79,8 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((family == AF_INET && addrlen != sizeof(struct in_addr)) ||
|
if ((family == AF_INET && addrlen != sizeof(aquery->addr.addrV4)) ||
|
||||||
(family == AF_INET6 && addrlen != sizeof(struct in6_addr)))
|
(family == AF_INET6 && addrlen != sizeof(aquery->addr.addrV6)))
|
||||||
{
|
{
|
||||||
callback(arg, ARES_ENOTIMP, 0, NULL);
|
callback(arg, ARES_ENOTIMP, 0, NULL);
|
||||||
return;
|
return;
|
||||||
@@ -94,9 +94,9 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
|
|||||||
}
|
}
|
||||||
aquery->channel = channel;
|
aquery->channel = channel;
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
memcpy(&aquery->addr.addrV4, addr, sizeof(struct in_addr));
|
memcpy(&aquery->addr.addrV4, addr, sizeof(aquery->addr.addrV4));
|
||||||
else
|
else
|
||||||
memcpy(&aquery->addr.addrV6, addr, sizeof(struct in6_addr));
|
memcpy(&aquery->addr.addrV6, addr, sizeof(aquery->addr.addrV6));
|
||||||
aquery->addr.family = family;
|
aquery->addr.family = family;
|
||||||
aquery->callback = callback;
|
aquery->callback = callback;
|
||||||
aquery->arg = arg;
|
aquery->arg = arg;
|
||||||
@@ -152,13 +152,13 @@ static void addr_callback(void *arg, int status, int timeouts,
|
|||||||
{
|
{
|
||||||
if (aquery->addr.family == AF_INET)
|
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,
|
status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV4,
|
||||||
(int)addrlen, AF_INET, &host);
|
(int)addrlen, AF_INET, &host);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addrlen = sizeof(struct in6_addr);
|
addrlen = sizeof(aquery->addr.addrV6);
|
||||||
status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV6,
|
status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV6,
|
||||||
(int)addrlen, AF_INET6, &host);
|
(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 (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;
|
break;
|
||||||
}
|
}
|
||||||
else if (addr->family == AF_INET6)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
ares_free_hostent(*host);
|
ares_free_hostent(*host);
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ static void sort6_addresses(struct hostent *host,
|
|||||||
const struct apattern *sortlist, int nsort);
|
const struct apattern *sortlist, int nsort);
|
||||||
static int get_address_index(const struct in_addr *addr,
|
static int get_address_index(const struct in_addr *addr,
|
||||||
const struct apattern *sortlist, int nsort);
|
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);
|
const struct apattern *sortlist, int nsort);
|
||||||
|
|
||||||
void ares_gethostbyname(ares_channel channel, const char *name, int family,
|
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];
|
char *addrs[2];
|
||||||
int result = 0;
|
int result = 0;
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
struct in6_addr in6;
|
struct ares_in6_addr in6;
|
||||||
|
|
||||||
if (family == AF_INET || family == AF_INET6)
|
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)
|
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;
|
addrs[0] = (char *)&in6;
|
||||||
}
|
}
|
||||||
/* Duplicate the name, to avoid a constness violation. */
|
/* 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,
|
static void sort6_addresses(struct hostent *host, const struct apattern *sortlist,
|
||||||
int nsort)
|
int nsort)
|
||||||
{
|
{
|
||||||
struct in6_addr a1, a2;
|
struct ares_in6_addr a1, a2;
|
||||||
int i1, i2, ind1, ind2;
|
int i1, i2, ind1, ind2;
|
||||||
|
|
||||||
/* This is a simple insertion sort, not optimized at all. i1 walks
|
/* 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++)
|
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);
|
ind1 = get6_address_index(&a1, sortlist, nsort);
|
||||||
for (i2 = i1 - 1; i2 >= 0; i2--)
|
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);
|
ind2 = get6_address_index(&a2, sortlist, nsort);
|
||||||
if (ind2 <= ind1)
|
if (ind2 <= ind1)
|
||||||
break;
|
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
|
/* Find the first entry in sortlist which matches addr. Return nsort
|
||||||
* if none of them match.
|
* 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,
|
const struct apattern *sortlist,
|
||||||
int nsort)
|
int nsort)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,9 +74,11 @@ struct nameinfo_query {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
#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
|
#else
|
||||||
#define IPBUFSIZ 40
|
#define IPBUFSIZ \
|
||||||
|
(sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host);
|
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;
|
niquery->family = AF_INET;
|
||||||
memcpy(&niquery->addr.addr4, addr, sizeof(addr));
|
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);
|
nameinfo_callback, niquery);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
niquery->family = AF_INET6;
|
niquery->family = AF_INET6;
|
||||||
memcpy(&niquery->addr.addr6, addr6, sizeof(addr6));
|
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);
|
nameinfo_callback, niquery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright 1998 by the Massachusetts Institute of Technology.
|
.\" 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
|
.\" Permission to use, copy, modify, and distribute this
|
||||||
.\" software and its documentation for any purpose and without
|
.\" software and its documentation for any purpose and without
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
.\" this software for any purpose. It is provided "as is"
|
.\" this software for any purpose. It is provided "as is"
|
||||||
.\" without express or implied warranty.
|
.\" without express or implied warranty.
|
||||||
.\"
|
.\"
|
||||||
.TH ARES_INIT 3 "26 May 2009"
|
.TH ARES_INIT 3 "5 March 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ares_init, ares_init_options \- Initialize a resolver channel
|
ares_init, ares_init_options \- Initialize a resolver channel
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -93,8 +93,11 @@ service port.
|
|||||||
.br
|
.br
|
||||||
.B int \fInservers\fP;
|
.B int \fInservers\fP;
|
||||||
.br
|
.br
|
||||||
The list of servers to contact, instead of the servers specified in
|
The list of IPv4 servers to contact, instead of the servers specified in
|
||||||
resolv.conf or the local named.
|
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
|
.TP 18
|
||||||
.B ARES_OPT_DOMAINS
|
.B ARES_OPT_DOMAINS
|
||||||
.B char **\fIdomains\fP;
|
.B char **\fIdomains\fP;
|
||||||
@@ -190,10 +193,11 @@ c-ares library initialization not yet performed.
|
|||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR ares_destroy(3),
|
.BR ares_destroy(3),
|
||||||
.BR ares_dup(3),
|
.BR ares_dup(3),
|
||||||
.BR ares_library_init(3)
|
.BR ares_library_init(3),
|
||||||
|
.BR ares_set_servers(3)
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Greg Hudson, MIT Information Systems
|
Greg Hudson, MIT Information Systems
|
||||||
.br
|
.br
|
||||||
Copyright 1998 by the Massachusetts Institute of Technology.
|
Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
.br
|
.br
|
||||||
Copyright (C) 2004-2009 by Daniel Stenberg.
|
Copyright (C) 2004-2010 by Daniel Stenberg.
|
||||||
|
|||||||
203
ares/ares_init.c
203
ares/ares_init.c
@@ -1,7 +1,7 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
/* 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
|
* Permission to use, copy, modify, and distribute this
|
||||||
* software and its documentation for any purpose and without
|
* software and its documentation for any purpose and without
|
||||||
@@ -118,7 +118,6 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
|||||||
ares_channel channel;
|
ares_channel channel;
|
||||||
int i;
|
int i;
|
||||||
int status = ARES_SUCCESS;
|
int status = ARES_SUCCESS;
|
||||||
struct server_state *server;
|
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
#ifdef CURLDEBUG
|
#ifdef CURLDEBUG
|
||||||
@@ -247,21 +246,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
|||||||
if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
|
if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
|
||||||
channel->nservers = 1;
|
channel->nservers = 1;
|
||||||
|
|
||||||
/* Initialize server states. */
|
ares__init_servers_state(channel);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*channelptr = channel;
|
*channelptr = channel;
|
||||||
return ARES_SUCCESS;
|
return ARES_SUCCESS;
|
||||||
@@ -272,7 +257,9 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
|||||||
int ares_dup(ares_channel *dest, ares_channel src)
|
int ares_dup(ares_channel *dest, ares_channel src)
|
||||||
{
|
{
|
||||||
struct ares_options opts;
|
struct ares_options opts;
|
||||||
int rc;
|
struct ares_addr_node *servers;
|
||||||
|
int ipv6_nservers = 0;
|
||||||
|
int i, rc;
|
||||||
int optmask;
|
int optmask;
|
||||||
|
|
||||||
*dest = NULL; /* in case of failure return NULL explicitly */
|
*dest = NULL; /* in case of failure return NULL explicitly */
|
||||||
@@ -296,16 +283,33 @@ int ares_dup(ares_channel *dest, ares_channel src)
|
|||||||
(*dest)->sock_create_cb = src->sock_create_cb;
|
(*dest)->sock_create_cb = src->sock_create_cb;
|
||||||
(*dest)->sock_create_cb_data = src->sock_create_cb_data;
|
(*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 */
|
return ARES_SUCCESS; /* everything went fine */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save options from initialized channel */
|
/* Save options from initialized channel */
|
||||||
int ares_save_options(ares_channel channel, struct ares_options *options,
|
int ares_save_options(ares_channel channel, struct ares_options *options,
|
||||||
int *optmask)
|
int *optmask)
|
||||||
{
|
{
|
||||||
int i;
|
int i, j;
|
||||||
|
int ipv4_nservers = 0;
|
||||||
|
|
||||||
/* Zero everything out */
|
/* Zero everything out */
|
||||||
memset(options, 0, sizeof(struct ares_options));
|
memset(options, 0, sizeof(struct ares_options));
|
||||||
@@ -335,16 +339,27 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
|
|||||||
options->sock_state_cb = channel->sock_state_cb;
|
options->sock_state_cb = channel->sock_state_cb;
|
||||||
options->sock_state_cb_data = channel->sock_state_cb_data;
|
options->sock_state_cb_data = channel->sock_state_cb_data;
|
||||||
|
|
||||||
/* Copy servers */
|
/* Copy IPv4 servers */
|
||||||
if (channel->nservers) {
|
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++)
|
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 */
|
/* copy domains */
|
||||||
if (channel->ndomains) {
|
if (channel->ndomains) {
|
||||||
@@ -420,7 +435,7 @@ static int init_by_options(ares_channel channel,
|
|||||||
&& channel->socket_receive_buffer_size == -1)
|
&& channel->socket_receive_buffer_size == -1)
|
||||||
channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
|
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)
|
if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
|
||||||
{
|
{
|
||||||
/* Avoid zero size allocations at any cost */
|
/* Avoid zero size allocations at any cost */
|
||||||
@@ -431,7 +446,12 @@ static int init_by_options(ares_channel channel,
|
|||||||
if (!channel->servers)
|
if (!channel->servers)
|
||||||
return ARES_ENOMEM;
|
return ARES_ENOMEM;
|
||||||
for (i = 0; i < options->nservers; i++)
|
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;
|
channel->nservers = options->nservers;
|
||||||
}
|
}
|
||||||
@@ -1001,7 +1021,8 @@ static int init_by_defaults(ares_channel channel)
|
|||||||
rc = ARES_ENOMEM;
|
rc = ARES_ENOMEM;
|
||||||
goto error;
|
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;
|
channel->nservers = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1149,61 +1170,62 @@ static int config_lookup(ares_channel channel, const char *str,
|
|||||||
static int config_nameserver(struct server_state **servers, int *nservers,
|
static int config_nameserver(struct server_state **servers, int *nservers,
|
||||||
char *str)
|
char *str)
|
||||||
{
|
{
|
||||||
struct in_addr addr;
|
struct ares_addr host;
|
||||||
struct server_state *newserv;
|
struct server_state *newserv;
|
||||||
|
char *p, *txtaddr;
|
||||||
/* On Windows, there may be more than one nameserver specified in the same
|
/* 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
|
for (p = str; p;)
|
||||||
char *p = str;
|
|
||||||
char *begin = str;
|
|
||||||
int more = 1;
|
|
||||||
while (more)
|
|
||||||
{
|
|
||||||
more = 0;
|
|
||||||
while (*p && !ISSPACE(*p) && *p != ',')
|
|
||||||
p++;
|
|
||||||
|
|
||||||
if (*p)
|
|
||||||
{
|
{
|
||||||
*p = '\0';
|
/* Skip whitespace and commas. */
|
||||||
more = 1;
|
while (*p && (ISSPACE(*p) || (*p == ',')))
|
||||||
|
p++;
|
||||||
|
if (!*p)
|
||||||
|
/* No more input, done. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Pointer to start of IPv4 or IPv6 address part. */
|
||||||
|
txtaddr = p;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip multiple spaces or trailing spaces */
|
|
||||||
if (!*begin)
|
|
||||||
{
|
|
||||||
begin = ++p;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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)++;
|
|
||||||
|
|
||||||
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;
|
return ARES_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1580,3 +1602,26 @@ void ares_set_socket_callback(ares_channel channel,
|
|||||||
channel->sock_create_cb = cb;
|
channel->sock_create_cb = cb;
|
||||||
channel->sock_create_cb_data = data;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,22 +23,17 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HAVE_STRUCT_IN6_ADDR) && !defined(s6_addr)
|
#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
|
#define s6_addr _S6_un._S6_u8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_SOCKADDR_IN6
|
#ifndef HAVE_STRUCT_SOCKADDR_IN6
|
||||||
struct sockaddr_in6
|
struct sockaddr_in6
|
||||||
{
|
{
|
||||||
unsigned short sin6_family;
|
unsigned short sin6_family;
|
||||||
unsigned short sin6_port;
|
unsigned short sin6_port;
|
||||||
unsigned long sin6_flowinfo;
|
unsigned long sin6_flowinfo;
|
||||||
struct in6_addr sin6_addr;
|
struct ares_in6_addr sin6_addr;
|
||||||
unsigned int sin6_scope_id;
|
unsigned int sin6_scope_id;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
128
ares/ares_options.c
Normal file
128
ares/ares_options.c
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
|
* Copyright (C) 2008-2010 by Daniel Stenberg
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose and without
|
||||||
|
* fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting
|
||||||
|
* documentation, and that the name of M.I.T. not be used in
|
||||||
|
* advertising or publicity pertaining to distribution of the
|
||||||
|
* software without specific, written prior permission.
|
||||||
|
* M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is"
|
||||||
|
* without express or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ares_setup.h"
|
||||||
|
|
||||||
|
#include "ares.h"
|
||||||
|
#include "ares_data.h"
|
||||||
|
#include "ares_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -65,7 +65,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
|
|||||||
long len;
|
long len;
|
||||||
const unsigned char *aptr;
|
const unsigned char *aptr;
|
||||||
char *hostname, *rr_name, *rr_data, **aliases;
|
char *hostname, *rr_name, *rr_data, **aliases;
|
||||||
struct in6_addr *addrs;
|
struct ares_in6_addr *addrs;
|
||||||
struct hostent *hostent;
|
struct hostent *hostent;
|
||||||
const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0;
|
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. */
|
/* Allocate addresses and aliases; ancount gives an upper bound for both. */
|
||||||
if (host)
|
if (host)
|
||||||
{
|
{
|
||||||
addrs = malloc(ancount * sizeof(struct in6_addr));
|
addrs = malloc(ancount * sizeof(struct ares_in6_addr));
|
||||||
if (!addrs)
|
if (!addrs)
|
||||||
{
|
{
|
||||||
free(hostname);
|
free(hostname);
|
||||||
@@ -143,27 +143,27 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
|
|||||||
aptr += RRFIXEDSZ;
|
aptr += RRFIXEDSZ;
|
||||||
|
|
||||||
if (rr_class == C_IN && rr_type == T_AAAA
|
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)
|
&& strcasecmp(rr_name, hostname) == 0)
|
||||||
{
|
{
|
||||||
if (addrs)
|
if (addrs)
|
||||||
{
|
{
|
||||||
if (aptr + sizeof(struct in6_addr) > abuf + alen)
|
if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
|
||||||
{
|
{
|
||||||
status = ARES_EBADRESP;
|
status = ARES_EBADRESP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy(&addrs[naddrs], aptr, sizeof(struct in6_addr));
|
memcpy(&addrs[naddrs], aptr, sizeof(struct ares_in6_addr));
|
||||||
}
|
}
|
||||||
if (naddrs < max_addr_ttls)
|
if (naddrs < max_addr_ttls)
|
||||||
{
|
{
|
||||||
struct ares_addr6ttl * const at = &addrttls[naddrs];
|
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;
|
status = ARES_EBADRESP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy(&at->ip6addr, aptr, sizeof(struct in6_addr));
|
memcpy(&at->ip6addr, aptr, sizeof(struct ares_in6_addr));
|
||||||
at->ttl = rr_ttl;
|
at->ttl = rr_ttl;
|
||||||
}
|
}
|
||||||
naddrs++;
|
naddrs++;
|
||||||
@@ -233,7 +233,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
|
|||||||
hostent->h_name = hostname;
|
hostent->h_name = hostname;
|
||||||
hostent->h_aliases = aliases;
|
hostent->h_aliases = aliases;
|
||||||
hostent->h_addrtype = AF_INET6;
|
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++)
|
for (i = 0; i < naddrs; i++)
|
||||||
hostent->h_addr_list[i] = (char *) &addrs[i];
|
hostent->h_addr_list[i] = (char *) &addrs[i];
|
||||||
hostent->h_addr_list[naddrs] = NULL;
|
hostent->h_addr_list[naddrs] = NULL;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
/* 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
|
* Permission to use, copy, modify, and distribute this
|
||||||
* software and its documentation for any purpose and without
|
* software and its documentation for any purpose and without
|
||||||
@@ -113,8 +113,8 @@
|
|||||||
struct ares_addr {
|
struct ares_addr {
|
||||||
int family;
|
int family;
|
||||||
union {
|
union {
|
||||||
struct in_addr addr4;
|
struct in_addr addr4;
|
||||||
struct in6_addr addr6;
|
struct ares_in6_addr addr6;
|
||||||
} addr;
|
} addr;
|
||||||
};
|
};
|
||||||
#define addrV4 addr.addr4
|
#define addrV4 addr.addr4
|
||||||
@@ -137,7 +137,7 @@ struct send_request {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct server_state {
|
struct server_state {
|
||||||
struct in_addr addr;
|
struct ares_addr addr;
|
||||||
ares_socket_t udp_socket;
|
ares_socket_t udp_socket;
|
||||||
ares_socket_t tcp_socket;
|
ares_socket_t tcp_socket;
|
||||||
|
|
||||||
@@ -221,14 +221,14 @@ struct query_server_info {
|
|||||||
struct apattern {
|
struct apattern {
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct in_addr addr4;
|
struct in_addr addr4;
|
||||||
struct in6_addr addr6;
|
struct ares_in6_addr addr6;
|
||||||
} addr;
|
} addr;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct in_addr addr4;
|
struct in_addr addr4;
|
||||||
struct in6_addr addr6;
|
struct ares_in6_addr addr6;
|
||||||
unsigned short bits;
|
unsigned short bits;
|
||||||
} mask;
|
} mask;
|
||||||
int family;
|
int family;
|
||||||
unsigned short type;
|
unsigned short type;
|
||||||
@@ -319,6 +319,8 @@ struct timeval ares__tvnow(void);
|
|||||||
int ares__expand_name_for_response(const unsigned char *encoded,
|
int ares__expand_name_for_response(const unsigned char *encoded,
|
||||||
const unsigned char *abuf, int alen,
|
const unsigned char *abuf, int alen,
|
||||||
char **s, long *enclen);
|
char **s, long *enclen);
|
||||||
|
void ares__init_servers_state(ares_channel channel);
|
||||||
|
void ares__destroy_servers_state(ares_channel channel);
|
||||||
#if 0 /* Not used */
|
#if 0 /* Not used */
|
||||||
long ares__tvdiff(struct timeval t1, struct timeval t2);
|
long ares__tvdiff(struct timeval t1, struct timeval t2);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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 open_udp_socket(ares_channel channel, struct server_state *server);
|
||||||
static int same_questions(const unsigned char *qbuf, int qlen,
|
static int same_questions(const unsigned char *qbuf, int qlen,
|
||||||
const unsigned char *abuf, int alen);
|
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,
|
static void end_query(ares_channel channel, struct query *query, int status,
|
||||||
unsigned char *abuf, int alen);
|
unsigned char *abuf, int alen);
|
||||||
|
|
||||||
@@ -434,8 +435,11 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
|
|||||||
ssize_t count;
|
ssize_t count;
|
||||||
unsigned char buf[PACKETSZ + 1];
|
unsigned char buf[PACKETSZ + 1];
|
||||||
#ifdef HAVE_RECVFROM
|
#ifdef HAVE_RECVFROM
|
||||||
struct sockaddr_in from;
|
|
||||||
ares_socklen_t fromlen;
|
ares_socklen_t fromlen;
|
||||||
|
union {
|
||||||
|
struct sockaddr_in sa4;
|
||||||
|
struct sockaddr_in6 sa6;
|
||||||
|
} from;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!read_fds && (read_fd == ARES_SOCKET_BAD))
|
if(!read_fds && (read_fd == ARES_SOCKET_BAD))
|
||||||
@@ -471,7 +475,10 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
|
|||||||
* packets as we can. */
|
* packets as we can. */
|
||||||
do {
|
do {
|
||||||
#ifdef HAVE_RECVFROM
|
#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),
|
count = (ssize_t)recvfrom(server->udp_socket, (void *)buf, sizeof(buf),
|
||||||
0, (struct sockaddr *)&from, &fromlen);
|
0, (struct sockaddr *)&from, &fromlen);
|
||||||
#else
|
#else
|
||||||
@@ -482,10 +489,10 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
|
|||||||
else if (count <= 0)
|
else if (count <= 0)
|
||||||
handle_error(channel, i, now);
|
handle_error(channel, i, now);
|
||||||
#ifdef HAVE_RECVFROM
|
#ifdef HAVE_RECVFROM
|
||||||
else if (from.sin_addr.s_addr != server->addr.s_addr)
|
else if (!same_address((struct sockaddr *)&from, &server->addr))
|
||||||
/* Address response came from did not match the address
|
/* The address the response comes from does not match
|
||||||
* we sent the request to. Someone may be attempting
|
* the address we sent the request to. Someone may be
|
||||||
* to perform a cache poisoning attack */
|
* attempting to perform a cache poisoning attack. */
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
@@ -893,10 +900,39 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
|||||||
{
|
{
|
||||||
ares_socket_t s;
|
ares_socket_t s;
|
||||||
int opt;
|
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. */
|
/* Acquire a socket. */
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(server->addr.family, SOCK_STREAM, 0);
|
||||||
if (s == ARES_SOCKET_BAD)
|
if (s == ARES_SOCKET_BAD)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -924,11 +960,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Connect to the server. */
|
/* Connect to the server. */
|
||||||
memset(&sockin, 0, sizeof(sockin));
|
if (connect(s, sa, salen) == -1)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int err = SOCKERRNO;
|
int err = SOCKERRNO;
|
||||||
|
|
||||||
@@ -960,10 +992,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)
|
static int open_udp_socket(ares_channel channel, struct server_state *server)
|
||||||
{
|
{
|
||||||
ares_socket_t s;
|
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. */
|
/* Acquire a socket. */
|
||||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
s = socket(server->addr.family, SOCK_DGRAM, 0);
|
||||||
if (s == ARES_SOCKET_BAD)
|
if (s == ARES_SOCKET_BAD)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -975,11 +1036,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Connect to the server. */
|
/* Connect to the server. */
|
||||||
memset(&sockin, 0, sizeof(sockin));
|
if (connect(s, sa, salen) == -1)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int err = SOCKERRNO;
|
int err = SOCKERRNO;
|
||||||
|
|
||||||
@@ -1086,6 +1143,34 @@ static int same_questions(const unsigned char *qbuf, int qlen,
|
|||||||
return 1;
|
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,
|
static void end_query (ares_channel channel, struct query *query, int status,
|
||||||
unsigned char *abuf, int alen)
|
unsigned char *abuf, int alen)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
.\" this software for any purpose. It is provided "as is"
|
.\" this software for any purpose. It is provided "as is"
|
||||||
.\" without express or implied warranty.
|
.\" without express or implied warranty.
|
||||||
.\"
|
.\"
|
||||||
.TH ARES_SAVE_OPTIONS 3 "1 June 2007"
|
.TH ARES_SAVE_OPTIONS 3 "5 March 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ares_save_options \- Save configuration values obtained from initialized ares_channel
|
ares_save_options \- Save configuration values obtained from initialized ares_channel
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -52,13 +52,20 @@ The channel data identified by
|
|||||||
were invalid.
|
were invalid.
|
||||||
.SH NOTE
|
.SH NOTE
|
||||||
Since c-ares 1.6.0 the ares_options struct has been "locked" meaning that it
|
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
|
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
|
this config struct, which may no longer be the complete set of config
|
||||||
options. \fBares_dup(3)\fP will not have that restriction.
|
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
|
.SH SEE ALSO
|
||||||
.BR ares_destroy_options (3),
|
.BR ares_destroy_options (3),
|
||||||
.BR ares_init_options (3),
|
.BR ares_init_options (3),
|
||||||
|
.BR ares_get_servers (3),
|
||||||
.BR ares_dup (3)
|
.BR ares_dup (3)
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
ares_save_options(3) was added in c-ares 1.4.0
|
ares_save_options(3) was added in c-ares 1.4.0
|
||||||
|
|||||||
84
ares/ares_set_servers.3
Normal file
84
ares/ares_set_servers.3
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
.\" $Id$
|
||||||
|
.\"
|
||||||
|
.\" Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
|
.\" Copyright (C) 2008-2010 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.\" Permission to use, copy, modify, and distribute this
|
||||||
|
.\" software and its documentation for any purpose and without
|
||||||
|
.\" fee is hereby granted, provided that the above copyright
|
||||||
|
.\" notice appear in all copies and that both that copyright
|
||||||
|
.\" notice and this permission notice appear in supporting
|
||||||
|
.\" documentation, and that the name of M.I.T. not be used in
|
||||||
|
.\" advertising or publicity pertaining to distribution of the
|
||||||
|
.\" software without specific, written prior permission.
|
||||||
|
.\" M.I.T. makes no representations about the suitability of
|
||||||
|
.\" this software for any purpose. It is provided "as is"
|
||||||
|
.\" without express or implied warranty.
|
||||||
|
.\"
|
||||||
|
.TH ARES_SET_SERVERS 3 "5 March 2010"
|
||||||
|
.SH NAME
|
||||||
|
ares_set_servers \- Initialize an ares_channel name servers configuration
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <ares.h>
|
||||||
|
.PP
|
||||||
|
.B int ares_set_servers(ares_channel \fIchannel\fP, struct ares_addr_node *\fIservers\fP)
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The \fBares_set_servers(3)\fP function initializes name servers configuration
|
||||||
|
for the channel data identified by
|
||||||
|
.IR channel ,
|
||||||
|
from a
|
||||||
|
.IR servers
|
||||||
|
pointer to a linked list of ares_addr_node structs holding name servers
|
||||||
|
address data.
|
||||||
|
|
||||||
|
The name server linked list pointer argument may be the result of a previous
|
||||||
|
call to \fBares_get_servers(3)\fP or a linked list of ares_addr_node structs
|
||||||
|
setup by other means.
|
||||||
|
|
||||||
|
This function replaces any potentially previously configured name servers
|
||||||
|
with the ones given in the linked list. So, in order to configure a channel
|
||||||
|
with more than one name server all the desired ones must be specified in a
|
||||||
|
single list.
|
||||||
|
|
||||||
|
\fBares_set_servers(3)\fP does not take ownership of the linked list argument.
|
||||||
|
The caller is responsible to free the linked list when no longer needed.
|
||||||
|
|
||||||
|
This function is capable of handling IPv4 and IPv6 name server
|
||||||
|
addresses simultaneously, rendering \fBares_init_options(3)\fP with
|
||||||
|
optmask \fBARES_OPT_SERVERS\fP functionally obsolete except for
|
||||||
|
IPv4-only name server usage.
|
||||||
|
|
||||||
|
.SH RETURN VALUES
|
||||||
|
.B ares_set_servers(3)
|
||||||
|
may return any of the following values:
|
||||||
|
.TP 15
|
||||||
|
.B ARES_SUCCESS
|
||||||
|
The name servers configuration was successfuly initialized.
|
||||||
|
.TP 15
|
||||||
|
.B ARES_ENOMEM
|
||||||
|
The process's available memory was exhausted.
|
||||||
|
.TP 15
|
||||||
|
.B ARES_ENODATA
|
||||||
|
The channel data identified by
|
||||||
|
.IR channel
|
||||||
|
was invalid.
|
||||||
|
.TP 15
|
||||||
|
.B ARES_ENOTINITIALIZED
|
||||||
|
c-ares library initialization not yet performed.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ares_get_servers (3),
|
||||||
|
.BR ares_init_options (3),
|
||||||
|
.BR ares_dup(3)
|
||||||
|
.SH AVAILABILITY
|
||||||
|
ares_set_servers(3) was added in c-ares 1.7.1
|
||||||
|
.SH AUTHOR
|
||||||
|
Implementation of this function and associated library internals are based
|
||||||
|
on code, comments and feedback provided November and December of 2008 by
|
||||||
|
Daniel Stenberg, Gregor Jasny, Phil Blundell and Yang Tse, December 2009
|
||||||
|
by Cedric Bail, February 2010 by Jakub Hrozek. On March 2010 Yang Tse
|
||||||
|
shuffled all the bits and this function popped out.
|
||||||
|
.br
|
||||||
|
Copyright 1998 by the Massachusetts Institute of Technology.
|
||||||
|
Copyright (C) 2008-2010 by Daniel Stenberg
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "ares.h"
|
||||||
#include "ares_ipv6.h"
|
#include "ares_ipv6.h"
|
||||||
#include "inet_net_pton.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)
|
if (af == AF_INET)
|
||||||
size = sizeof(struct in_addr);
|
size = sizeof(struct in_addr);
|
||||||
else if (af == AF_INET6)
|
else if (af == AF_INET6)
|
||||||
size = sizeof(struct in6_addr);
|
size = sizeof(struct ares_in6_addr);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SET_ERRNO(EAFNOSUPPORT);
|
SET_ERRNO(EAFNOSUPPORT);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "ares.h"
|
||||||
#include "ares_ipv6.h"
|
#include "ares_ipv6.h"
|
||||||
#include "inet_ntop.h"
|
#include "inet_ntop.h"
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,10 @@ SOURCE=..\..\ares_nowarn.c
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\ares_options.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\ares_parse_a_reply.c
|
SOURCE=..\..\ares_parse_a_reply.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
Reference in New Issue
Block a user