mirror of
https://github.com/moparisthebest/curl
synced 2024-11-02 08:35:03 -04:00
Added IPv6 name servers support
This commit is contained in:
parent
f933747088
commit
21f331ead2
21
ares/CHANGES
21
ares/CHANGES
@ -1,5 +1,26 @@
|
||||
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)
|
||||
- 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
|
||||
|
@ -20,6 +20,7 @@ CSOURCES = ares__close_sockets.c \
|
||||
ares_llist.c \
|
||||
ares_mkquery.c \
|
||||
ares_nowarn.c \
|
||||
ares_options.c \
|
||||
ares_parse_a_reply.c \
|
||||
ares_parse_aaaa_reply.c \
|
||||
ares_parse_ns_reply.c \
|
||||
@ -48,8 +49,8 @@ HHEADERS = ares.h \
|
||||
ares_ipv6.h \
|
||||
ares_library_init.h \
|
||||
ares_llist.h \
|
||||
ares_private.h \
|
||||
ares_nowarn.h \
|
||||
ares_private.h \
|
||||
ares_rules.h \
|
||||
ares_strcasecmp.h \
|
||||
ares_strdup.h \
|
||||
@ -72,6 +73,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 \
|
||||
@ -93,6 +95,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 \
|
||||
@ -108,6 +111,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 \
|
||||
@ -129,6 +133,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 \
|
||||
@ -144,6 +149,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 \
|
||||
@ -165,6 +171,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 \
|
||||
|
@ -2,7 +2,7 @@ This is what's new and changed in the c-ares 1.7.1 release:
|
||||
|
||||
Changed:
|
||||
|
||||
o
|
||||
o added IPv6 name servers support
|
||||
|
||||
Fixed:
|
||||
|
||||
@ -12,6 +12,7 @@ Fixed:
|
||||
|
||||
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!
|
||||
|
107
ares/adig.c
107
ares/adig.c
@ -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)
|
||||
{
|
||||
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)
|
||||
/* 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;
|
||||
}
|
||||
memcpy(&options.servers[options.nservers], &inaddr,
|
||||
sizeof(struct in_addr));
|
||||
options.nservers++;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
17
ares/ares.h
17
ares/ares.h
@ -1,7 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* $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
|
||||
* 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 *));
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* 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
|
||||
@ -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()
|
||||
*/
|
||||
@ -78,6 +79,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;
|
||||
}
|
||||
@ -121,6 +128,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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
.\" $Id$
|
||||
.\"
|
||||
.\" 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.
|
||||
|
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
.\" $Id$
|
||||
.\"
|
||||
.\" 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.
|
||||
|
203
ares/ares_init.c
203
ares/ares_init.c
@ -1,7 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* 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
|
||||
@ -118,7 +118,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 +246,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 +257,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 +283,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 +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_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 +435,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 +446,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 +1021,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 +1170,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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -1580,3 +1602,26 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@ -23,22 +23,17 @@
|
||||
#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
|
||||
|
||||
|
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;
|
||||
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;
|
||||
|
@ -4,7 +4,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* 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
|
||||
|
@ -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);
|
||||
|
||||
@ -434,8 +435,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))
|
||||
@ -471,7 +475,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
|
||||
@ -482,10 +489,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
|
||||
@ -893,10 +900,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;
|
||||
|
||||
@ -924,11 +960,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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
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;
|
||||
|
||||
@ -975,11 +1036,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;
|
||||
|
||||
@ -1086,6 +1143,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)
|
||||
{
|
||||
|
@ -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
|
||||
|
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 <stdlib.h>
|
||||
|
||||
#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);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ares.h"
|
||||
#include "ares_ipv6.h"
|
||||
#include "inet_ntop.h"
|
||||
|
||||
|
@ -230,6 +230,10 @@ SOURCE=..\..\ares_nowarn.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
|
||||
|
Loading…
Reference in New Issue
Block a user