diff --git a/Makefile.inc b/Makefile.inc index c6fc54e..c4efa3c 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -82,6 +82,7 @@ MANPAGES = ares_cancel.3 \ ares_free_hostent.3 \ ares_free_string.3 \ ares_get_servers.3 \ + ares_get_servers_ports.3 \ ares_gethostbyaddr.3 \ ares_gethostbyname.3 \ ares_gethostbyname_file.3 \ @@ -112,6 +113,8 @@ MANPAGES = ares_cancel.3 \ ares_set_local_ip6.3 \ ares_set_servers.3 \ ares_set_servers_csv.3 \ + ares_set_servers_ports.3 \ + ares_set_servers_ports_csv.3 \ ares_set_socket_callback.3 \ ares_set_sortlist.3 \ ares_strerror.3 \ @@ -131,6 +134,7 @@ HTMLPAGES = ares_cancel.html \ ares_free_hostent.html \ ares_free_string.html \ ares_get_servers.html \ + ares_get_servers_ports.html \ ares_gethostbyaddr.html \ ares_gethostbyname.html \ ares_gethostbyname_file.html \ @@ -160,6 +164,8 @@ HTMLPAGES = ares_cancel.html \ ares_set_local_ip6.html \ ares_set_servers.html \ ares_set_servers_csv.html \ + ares_set_servers_ports.html \ + ares_set_servers_ports_csv.html \ ares_set_socket_callback.html \ ares_set_sortlist.html \ ares_strerror.html \ @@ -179,6 +185,7 @@ PDFPAGES = ares_cancel.pdf \ ares_free_hostent.pdf \ ares_free_string.pdf \ ares_get_servers.pdf \ + ares_get_servers_ports.pdf \ ares_gethostbyaddr.pdf \ ares_gethostbyname.pdf \ ares_gethostbyname_file.pdf \ @@ -208,6 +215,8 @@ PDFPAGES = ares_cancel.pdf \ ares_set_local_ip6.pdf \ ares_set_servers.pdf \ ares_set_servers_csv.pdf \ + ares_set_servers_ports.pdf \ + ares_set_servers_ports_csv.pdf \ ares_set_socket_callback.pdf \ ares_set_sortlist.pdf \ ares_strerror.pdf \ diff --git a/ares.h b/ares.h index b7ecf7c..8d4ab8c 100644 --- a/ares.h +++ b/ares.h @@ -563,7 +563,6 @@ CARES_EXTERN void ares_free_data(void *dataptr); CARES_EXTERN const char *ares_strerror(int code); -/* TODO: Hold port here as well. */ struct ares_addr_node { struct ares_addr_node *next; int family; @@ -573,15 +572,32 @@ struct ares_addr_node { } addr; }; +struct ares_addr_port_node { + struct ares_addr_port_node *next; + int family; + union { + struct in_addr addr4; + struct ares_in6_addr addr6; + } addr; + int udp_port; + int tcp_port; +}; + CARES_EXTERN int ares_set_servers(ares_channel channel, struct ares_addr_node *servers); +CARES_EXTERN int ares_set_servers_ports(ares_channel channel, + struct ares_addr_port_node *servers); /* Incomming string format: host[:port][,host[:port]]... */ CARES_EXTERN int ares_set_servers_csv(ares_channel channel, const char* servers); +CARES_EXTERN int ares_set_servers_ports_csv(ares_channel channel, + const char* servers); CARES_EXTERN int ares_get_servers(ares_channel channel, struct ares_addr_node **servers); +CARES_EXTERN int ares_get_servers_ports(ares_channel channel, + struct ares_addr_port_node **servers); CARES_EXTERN const char *ares_inet_ntop(int af, const void *src, char *dst, ares_socklen_t size); diff --git a/ares_data.c b/ares_data.c index 290bdaa..2d2afeb 100644 --- a/ares_data.c +++ b/ares_data.c @@ -92,6 +92,12 @@ void ares_free_data(void *dataptr) ares_free_data(ptr->data.addr_node.next); break; + case ARES_DATATYPE_ADDR_PORT_NODE: + + if (ptr->data.addr_port_node.next) + ares_free_data(ptr->data.addr_port_node.next); + break; + case ARES_DATATYPE_NAPTR_REPLY: if (ptr->data.naptr_reply.next) @@ -169,6 +175,15 @@ void *ares_malloc_data(ares_datatype type) sizeof(ptr->data.addr_node.addrV6)); break; + case ARES_DATATYPE_ADDR_PORT_NODE: + ptr->data.addr_port_node.next = NULL; + ptr->data.addr_port_node.family = 0; + ptr->data.addr_port_node.udp_port = 0; + ptr->data.addr_port_node.tcp_port = 0; + memset(&ptr->data.addr_port_node.addrV6, 0, + sizeof(ptr->data.addr_port_node.addrV6)); + break; + case ARES_DATATYPE_NAPTR_REPLY: ptr->data.naptr_reply.next = NULL; ptr->data.naptr_reply.flags = NULL; diff --git a/ares_data.h b/ares_data.h index 12e3b67..bd4a951 100644 --- a/ares_data.h +++ b/ares_data.h @@ -28,6 +28,7 @@ typedef enum { ARES_DATATYPE_HOSTENT, /* struct hostent */ ARES_DATATYPE_OPTIONS, /* struct ares_options */ #endif + ARES_DATATYPE_ADDR_PORT_NODE, /* struct ares_addr_port_node - introduced in 1.11.0 */ ARES_DATATYPE_LAST /* not used - introduced in 1.7.0 */ } ares_datatype; @@ -58,6 +59,7 @@ struct ares_data { struct ares_txt_reply txt_reply; struct ares_srv_reply srv_reply; struct ares_addr_node addr_node; + struct ares_addr_port_node addr_port_node; struct ares_mx_reply mx_reply; struct ares_naptr_reply naptr_reply; struct ares_soa_reply soa_reply; diff --git a/ares_get_servers.3 b/ares_get_servers.3 index feea3a0..7752845 100644 --- a/ares_get_servers.3 +++ b/ares_get_servers.3 @@ -16,12 +16,13 @@ .\" .TH ARES_GET_SERVERS 3 "5 March 2010" .SH NAME -ares_get_servers \- Retrieve name servers from an initialized ares_channel +ares_get_servers, ares_get_servers_ports \- Retrieve name servers from an initialized ares_channel .SH SYNOPSIS .nf .B #include .PP .B int ares_get_servers(ares_channel \fIchannel\fP, struct ares_addr_node **\fIservers\fP) +.B int ares_get_servers_ports(ares_channel \fIchannel\fP, struct ares_addr_port_node **\fIservers\fP) .fi .SH DESCRIPTION The \fBares_get_servers(3)\fP function retrieves name servers configuration @@ -32,8 +33,13 @@ as a linked list of ares_addr_node structs storing a pointer to the first node at the address specified by .IR servers . +The \fBares_get_servers_ports(3)\fP function also retrieves any per-server +port information that may have been previously configured, returning a linked +list of ares_addr_port structures. + 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 +it directly as suitable input for the \fBares_set_servers(3)\fP / +\fBares_set_servers_ports(3)\fP functions, but shall not shrink or extend the list on its own. Each node of the name server linked list is stored in memory dynamically @@ -47,8 +53,7 @@ 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: +This function may return any of the following values: .TP 15 .B ARES_SUCCESS The name servers configuration was successfuly retrieved @@ -57,7 +62,7 @@ The name servers configuration was successfuly retrieved The memory was exhausted .TP 15 .B ARES_ENODATA -The channel data identified by +The channel data identified by .IR channel was invalid. .SH SEE ALSO @@ -65,7 +70,8 @@ was invalid. .BR ares_init_options (3), .BR ares_save_options(3) .SH AVAILABILITY -ares_get_servers(3) was added in c-ares 1.7.1 +\fBares_get_servers(3)\fP was added in c-ares 1.7.1; +\fBares_get_servers_ports(3)\fP was added in c-ares 1.11.0. .SH AUTHOR Implementation of this function and associated library internals are based on code, comments and feedback provided in November and December of 2008 by diff --git a/ares_get_servers_ports.3 b/ares_get_servers_ports.3 new file mode 100644 index 0000000..1f5d1f7 --- /dev/null +++ b/ares_get_servers_ports.3 @@ -0,0 +1 @@ +.so man3/ares_get_servers.3 diff --git a/ares_init.c b/ares_init.c index 7e0da9a..4607944 100644 --- a/ares_init.c +++ b/ares_init.c @@ -263,8 +263,8 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, int ares_dup(ares_channel *dest, ares_channel src) { struct ares_options opts; - struct ares_addr_node *servers; - int ipv6_nservers = 0; + struct ares_addr_port_node *servers; + int non_v4_default_port = 0; int i, rc; int optmask; @@ -297,22 +297,24 @@ int ares_dup(ares_channel *dest, ares_channel src) (*dest)->local_ip4 = src->local_ip4; memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6)); - /* Full name server cloning required when not all are IPv4 */ + /* Full name server cloning required if there is a non-IPv4, or non-default port, nameserver */ for (i = 0; i < src->nservers; i++) { - if (src->servers[i].addr.family != AF_INET) { - ipv6_nservers++; + if ((src->servers[i].addr.family != AF_INET) || + (src->servers[i].addr.udp_port != 0) || + (src->servers[i].addr.tcp_port != 0)) { + non_v4_default_port++; break; } } - if (ipv6_nservers) { - rc = ares_get_servers(src, &servers); + if (non_v4_default_port) { + rc = ares_get_servers_ports(src, &servers); if (rc != ARES_SUCCESS) { ares_destroy(*dest); *dest = NULL; return rc; } - rc = ares_set_servers(*dest, servers); + rc = ares_set_servers_ports(*dest, servers); ares_free_data(servers); if (rc != ARES_SUCCESS) { ares_destroy(*dest); @@ -359,11 +361,13 @@ 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 IPv4 servers */ + /* Copy IPv4 servers that use the default port */ if (channel->nservers) { for (i = 0; i < channel->nservers; i++) { - if (channel->servers[i].addr.family == AF_INET) + if ((channel->servers[i].addr.family == AF_INET) && + (channel->servers[i].addr.udp_port == 0) && + (channel->servers[i].addr.tcp_port == 0)) ipv4_nservers++; } if (ipv4_nservers) { @@ -372,7 +376,9 @@ int ares_save_options(ares_channel channel, struct ares_options *options, return ARES_ENOMEM; for (i = j = 0; i < channel->nservers; i++) { - if (channel->servers[i].addr.family == AF_INET) + if ((channel->servers[i].addr.family == AF_INET) && + (channel->servers[i].addr.udp_port == 0) && + (channel->servers[i].addr.tcp_port == 0)) memcpy(&options->servers[j++], &channel->servers[i].addr.addrV4, sizeof(channel->servers[i].addr.addrV4)); @@ -468,6 +474,8 @@ static int init_by_options(ares_channel channel, for (i = 0; i < options->nservers; i++) { channel->servers[i].addr.family = AF_INET; + channel->servers[i].addr.udp_port = 0; + channel->servers[i].addr.tcp_port = 0; memcpy(&channel->servers[i].addr.addrV4, &options->servers[i], sizeof(channel->servers[i].addr.addrV4)); @@ -1156,6 +1164,8 @@ static int init_by_resolv_conf(ares_channel channel) { servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]); servers[i].addr.family = AF_INET; + servers[i].addr.udp_port = 0; + servers[i].addr.tcp_port = 0; } status = ARES_EOF; @@ -1444,6 +1454,8 @@ static int init_by_defaults(ares_channel channel) } channel->servers[0].addr.family = AF_INET; channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK); + channel->servers[0].addr.udp_port = 0; + channel->servers[0].addr.tcp_port = 0; channel->nservers = 1; } @@ -1650,6 +1662,8 @@ static int config_nameserver(struct server_state **servers, int *nservers, /* Store address data. */ newserv[*nservers].addr.family = host.family; + newserv[*nservers].addr.udp_port = 0; + newserv[*nservers].addr.tcp_port = 0; if (host.family == AF_INET) memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4, sizeof(host.addrV4)); diff --git a/ares_options.c b/ares_options.c index 7b70e97..c3cbd1d 100644 --- a/ares_options.c +++ b/ares_options.c @@ -83,6 +83,62 @@ int ares_get_servers(ares_channel channel, return status; } +int ares_get_servers_ports(ares_channel channel, + struct ares_addr_port_node **servers) +{ + struct ares_addr_port_node *srvr_head = NULL; + struct ares_addr_port_node *srvr_last = NULL; + struct ares_addr_port_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_PORT_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; + srvr_curr->udp_port = ntohs((unsigned short)channel->servers[i].addr.udp_port); + srvr_curr->tcp_port = ntohs((unsigned short)channel->servers[i].addr.tcp_port); + 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) @@ -117,6 +173,57 @@ int ares_set_servers(ares_channel channel, for (i = 0, srvr = servers; srvr; i++, srvr = srvr->next) { channel->servers[i].addr.family = srvr->family; + channel->servers[i].addr.udp_port = 0; + channel->servers[i].addr.tcp_port = 0; + 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; +} + +int ares_set_servers_ports(ares_channel channel, + struct ares_addr_port_node *servers) +{ + struct ares_addr_port_node *srvr; + int num_srvrs = 0; + int i; + + if (ares_library_initialized() != ARES_SUCCESS) + return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ + + 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 = ares_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; + channel->servers[i].addr.udp_port = htons((unsigned short)srvr->udp_port); + channel->servers[i].addr.tcp_port = htons((unsigned short)srvr->tcp_port); if (srvr->family == AF_INET) memcpy(&channel->servers[i].addr.addrV4, &srvr->addrV4, sizeof(srvr->addrV4)); @@ -133,8 +240,8 @@ int ares_set_servers(ares_channel channel, /* Incomming string format: host[:port][,host[:port]]... */ /* IPv6 addresses with ports require square brackets [fe80::1%lo0]:53 */ -int ares_set_servers_csv(ares_channel channel, - const char* _csv) +static int set_servers_csv(ares_channel channel, + const char* _csv, int use_port) { size_t i; char* csv = NULL; @@ -142,8 +249,8 @@ int ares_set_servers_csv(ares_channel channel, char* start_host; int cc = 0; int rv = ARES_SUCCESS; - struct ares_addr_node *servers = NULL; - struct ares_addr_node *last = NULL; + struct ares_addr_port_node *servers = NULL; + struct ares_addr_port_node *last = NULL; if (ares_library_initialized() != ARES_SUCCESS) return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ @@ -182,9 +289,10 @@ int ares_set_servers_csv(ares_channel channel, else if (*ptr == ',') { char* pp = ptr - 1; char* p = ptr; + int port = 0; struct in_addr in4; struct ares_in6_addr in6; - struct ares_addr_node *s = NULL; + struct ares_addr_port_node *s = NULL; *ptr = 0; /* null terminate host:port string */ /* Got an entry..see if the port was specified. */ @@ -213,7 +321,7 @@ int ares_set_servers_csv(ares_channel channel, if (*pp == ']') p++; /* move p before ':' */ /* p will point to the start of the port */ - (void)strtol(p, NULL, 10); + port = (int)strtol(p, NULL, 10); *pp = 0; /* null terminate host */ } } @@ -246,8 +354,8 @@ int ares_set_servers_csv(ares_channel channel, memcpy(&s->addr, &in4, sizeof(struct in_addr)); } if (s) { - /* TODO: Add port to ares_addr_node and assign it here. */ - + s->udp_port = use_port ? port: 0; + s->tcp_port = s->udp_port; s->next = NULL; if (last) { last->next = s; @@ -266,16 +374,29 @@ int ares_set_servers_csv(ares_channel channel, } } - rv = ares_set_servers(channel, servers); + rv = ares_set_servers_ports(channel, servers); out: if (csv) ares_free(csv); while (servers) { - struct ares_addr_node *s = servers; + struct ares_addr_port_node *s = servers; servers = servers->next; ares_free(s); } return rv; } + +int ares_set_servers_csv(ares_channel channel, + const char* _csv) +{ + return set_servers_csv(channel, _csv, FALSE); +} + +int ares_set_servers_ports_csv(ares_channel channel, + const char* _csv) +{ + return set_servers_csv(channel, _csv, TRUE); +} + diff --git a/ares_private.h b/ares_private.h index 824222d..45f34ab 100644 --- a/ares_private.h +++ b/ares_private.h @@ -123,6 +123,8 @@ struct ares_addr { struct in_addr addr4; struct ares_in6_addr addr6; } addr; + int udp_port; /* stored in network order */ + int tcp_port; /* stored in network order */ }; #define addrV4 addr.addr4 #define addrV6 addr.addr6 @@ -255,8 +257,8 @@ struct ares_channeldata { int tries; int ndots; int rotate; /* if true, all servers specified are used */ - int udp_port; - int tcp_port; + int udp_port; /* stored in network order */ + int tcp_port; /* stored in network order */ int socket_send_buffer_size; int socket_receive_buffer_size; char **domains; diff --git a/ares_process.c b/ares_process.c index f73d0a2..c3ac77b 100644 --- a/ares_process.c +++ b/ares_process.c @@ -978,7 +978,11 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa4); memset(sa, 0, salen); saddr.sa4.sin_family = AF_INET; - saddr.sa4.sin_port = aresx_sitous(channel->tcp_port); + if (server->addr.tcp_port) { + saddr.sa4.sin_port = aresx_sitous(server->addr.tcp_port); + } else { + saddr.sa4.sin_port = aresx_sitous(channel->tcp_port); + } memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, sizeof(server->addr.addrV4)); break; @@ -987,7 +991,11 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa6); memset(sa, 0, salen); saddr.sa6.sin6_family = AF_INET6; - saddr.sa6.sin6_port = aresx_sitous(channel->tcp_port); + if (server->addr.tcp_port) { + saddr.sa6.sin6_port = aresx_sitous(server->addr.tcp_port); + } else { + saddr.sa6.sin6_port = aresx_sitous(channel->tcp_port); + } memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, sizeof(server->addr.addrV6)); break; @@ -1070,7 +1078,11 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa4); memset(sa, 0, salen); saddr.sa4.sin_family = AF_INET; - saddr.sa4.sin_port = aresx_sitous(channel->udp_port); + if (server->addr.udp_port) { + saddr.sa4.sin_port = aresx_sitous(server->addr.udp_port); + } else { + saddr.sa4.sin_port = aresx_sitous(channel->udp_port); + } memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, sizeof(server->addr.addrV4)); break; @@ -1079,7 +1091,11 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa6); memset(sa, 0, salen); saddr.sa6.sin6_family = AF_INET6; - saddr.sa6.sin6_port = aresx_sitous(channel->udp_port); + if (server->addr.udp_port) { + saddr.sa6.sin6_port = aresx_sitous(server->addr.udp_port); + } else { + saddr.sa6.sin6_port = aresx_sitous(channel->udp_port); + } memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, sizeof(server->addr.addrV6)); break; diff --git a/ares_set_servers.3 b/ares_set_servers.3 index 6f25c29..4948f4e 100644 --- a/ares_set_servers.3 +++ b/ares_set_servers.3 @@ -15,12 +15,13 @@ .\" .TH ARES_SET_SERVERS 3 "5 March 2010" .SH NAME -ares_set_servers \- Initialize an ares_channel name servers configuration +ares_set_servers, ares_set_servers_ports \- Initialize an ares_channel name servers configuration .SH SYNOPSIS .nf .B #include .PP .B int ares_set_servers(ares_channel \fIchannel\fP, struct ares_addr_node *\fIservers\fP) +.B int ares_set_servers_ports(ares_channel \fIchannel\fP, struct ares_addr_port_node *\fIservers\fP) .fi .SH DESCRIPTION The \fBares_set_servers(3)\fP function initializes name servers configuration @@ -30,19 +31,25 @@ from a .IR servers pointer to a linked list of ares_addr_node structs holding name servers address data. - +.PP 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. - +call to \fBares_get_servers(3)\fP or a linked list of \fBares_addr_node\fP structs +set up by other means. +.PP +The \fBares_set_servers(3)\fP function also allows the specification of UDP and +TCP ports to be used for communication on a per-server basis. The provided +linked list argument may be the result of a previous call to +\fBares_get_servers_ports(3)\fP or a linked list of \fBares_addr_port_node\fP structs +set up by other means. +.PP 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 +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. +.PP +The function does not take ownership of the linked list argument. The caller is responsible for freeing the linked list when no longer needed. - +.PP 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 @@ -71,7 +78,8 @@ c-ares library initialization not yet performed. .BR ares_init_options (3), .BR ares_dup(3) .SH AVAILABILITY -ares_set_servers(3) was added in c-ares 1.7.1 +\fBares_set_servers(3)\fP was added in c-ares 1.7.1; +\fBares_set_servers_ports(3)\fP was added in c-ares 1.11.0. .SH AUTHOR Implementation of this function and associated library internals are based on code, comments and feedback provided in November and December of 2008 by diff --git a/ares_set_servers_csv.3 b/ares_set_servers_csv.3 index c8c34fd..5c16efb 100644 --- a/ares_set_servers_csv.3 +++ b/ares_set_servers_csv.3 @@ -15,26 +15,32 @@ .\" .TH ARES_SET_SERVERS_CSV 3 "30 June 2010" .SH NAME -ares_set_servers_csv \- Set list of DNS servers to be used. +ares_set_servers_csv, ares_set_servers_ports_csv \- Set list of DNS servers to be used. .SH SYNOPSIS .nf .B #include .PP .B int ares_set_servers_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP) +.B int ares_set_servers_ports_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP) .fi .SH DESCRIPTION -The \fBares_set_servers_csv\fP function sets the list of DNS servers -that ARES will query. The format of the servers option is: +The \fBares_set_servers_csv\fP and \fBares_set_servers_ports_csv\fPfunctions set +the list of DNS servers that ARES will query. The format of the servers option is: host[:port][,host[:port]]... For example: 192.168.1.100,192.168.1.101,3.4.5.6 +.PP +The \fBares_set_servers_csv\fP function will ignore any port values specified in +the input string, whereare the \fBares_set_servers_ports_csv\fP function will +apply any specified port values as the UDP and TCP port to be used for that +particular nameserver. .SH RETURN VALUES .B ares_set_servers_csv(3) -may return any of the following values: +This function may return any of the following values: .TP 15 .B ARES_SUCCESS The name servers configuration was successfuly initialized. @@ -51,10 +57,8 @@ was invalid. c-ares library initialization not yet performed. .SH SEE ALSO .BR ares_set_servers (3) -.SH NOTES -The port option is currently ignored by c-ares internals -and the standard port is always used. - -This function was added in c-ares 1.7.2 +.SH AVAILABILITY +\fBares_set_servers_csv\fP was added in c-ares 1.7.2; +\fBares_set_servers_ports_csv\fP was added in c-ares 1.11.0. .SH AUTHOR Ben Greear diff --git a/ares_set_servers_ports.3 b/ares_set_servers_ports.3 new file mode 100644 index 0000000..a3be189 --- /dev/null +++ b/ares_set_servers_ports.3 @@ -0,0 +1 @@ +.so man3/ares_set_servers.3 diff --git a/ares_set_servers_ports_csv.3 b/ares_set_servers_ports_csv.3 new file mode 100644 index 0000000..30535c6 --- /dev/null +++ b/ares_set_servers_ports_csv.3 @@ -0,0 +1 @@ +.so man3/ares_set_servers_csv.3