2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3 * Copyright (C) 2007-2012 by Daniel Stenberg
5 * Permission to use, copy, modify, and distribute this
6 * software and its documentation for any purpose and without
7 * fee is hereby granted, provided that the above copyright
8 * notice appear in all copies and that both that copyright
9 * notice and this permission notice appear in supporting
10 * documentation, and that the name of M.I.T. not be used in
11 * advertising or publicity pertaining to distribution of the
12 * software without specific, written prior permission.
13 * M.I.T. makes no representations about the suitability of
14 * this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
18 #include "ares_setup.h"
20 #ifdef HAVE_SYS_PARAM_H
21 #include <sys/param.h>
24 #ifdef HAVE_SYS_TIME_H
28 #ifdef HAVE_SYS_SOCKET_H
29 #include <sys/socket.h>
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
44 #ifdef HAVE_ARPA_NAMESER_H
45 # include <arpa/nameser.h>
49 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
50 # include <arpa/nameser_compat.h>
63 #if defined(ANDROID) || defined(__ANDROID__)
64 #include <sys/system_properties.h>
65 /* From the Bionic sources */
66 #define DNS_PROP_NAME_PREFIX "net.dns"
67 #define MAX_DNS_PROPERTIES 8
71 #include "inet_ntop.h"
72 #include "inet_net_pton.h"
73 #include "ares_library_init.h"
74 #include "ares_nowarn.h"
75 #include "ares_platform.h"
76 #include "ares_private.h"
79 #undef WIN32 /* Redefined in MingW/MSVC headers */
82 static int init_by_options(ares_channel channel,
83 const struct ares_options *options,
85 static int init_by_environment(ares_channel channel);
86 static int init_by_resolv_conf(ares_channel channel);
87 static int init_by_defaults(ares_channel channel);
90 static int config_nameserver(struct server_state **servers, int *nservers,
93 static int set_search(ares_channel channel, const char *str);
94 static int set_options(ares_channel channel, const char *str);
95 static const char *try_option(const char *p, const char *q, const char *opt);
96 static int init_id_key(rc4_key* key,int key_data_len);
98 #if !defined(WIN32) && !defined(WATT32) && \
99 !defined(ANDROID) && !defined(__ANDROID__)
100 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
101 struct apattern *pat);
102 static int ip_addr(const char *s, ssize_t len, struct in_addr *addr);
103 static void natural_mask(struct apattern *pat);
104 static int config_domain(ares_channel channel, char *str);
105 static int config_lookup(ares_channel channel, const char *str,
106 const char *bindch, const char *filech);
107 static int config_sortlist(struct apattern **sortlist, int *nsort,
109 static char *try_config(char *s, const char *opt, char scc);
112 #define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
113 x->nservers > -1 && \
114 x->ndomains > -1 && \
115 x->ndots > -1 && x->timeout > -1 && \
118 int ares_init(ares_channel *channelptr)
120 return ares_init_options(channelptr, NULL, 0);
123 int ares_init_options(ares_channel *channelptr, struct ares_options *options,
126 ares_channel channel;
128 int status = ARES_SUCCESS;
132 const char *env = getenv("CARES_MEMDEBUG");
136 env = getenv("CARES_MEMLIMIT");
139 long num = strtol(env, &endptr, 10);
140 if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
145 if (ares_library_initialized() != ARES_SUCCESS)
146 return ARES_ENOTINITIALIZED;
148 channel = malloc(sizeof(struct ares_channeldata));
156 /* Set everything to distinguished values so we know they haven't
160 channel->timeout = -1;
163 channel->rotate = -1;
164 channel->udp_port = -1;
165 channel->tcp_port = -1;
166 channel->socket_send_buffer_size = -1;
167 channel->socket_receive_buffer_size = -1;
168 channel->nservers = -1;
169 channel->ndomains = -1;
171 channel->tcp_connection_generation = 0;
172 channel->lookups = NULL;
173 channel->domains = NULL;
174 channel->sortlist = NULL;
175 channel->servers = NULL;
176 channel->sock_state_cb = NULL;
177 channel->sock_state_cb_data = NULL;
178 channel->sock_create_cb = NULL;
179 channel->sock_create_cb_data = NULL;
181 channel->last_server = 0;
182 channel->last_timeout_processed = (time_t)now.tv_sec;
184 memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name));
185 channel->local_ip4 = 0;
186 memset(&channel->local_ip6, 0, sizeof(channel->local_ip6));
188 /* Initialize our lists of queries */
189 ares__init_list_head(&(channel->all_queries));
190 for (i = 0; i < ARES_QID_TABLE_SIZE; i++)
192 ares__init_list_head(&(channel->queries_by_qid[i]));
194 for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++)
196 ares__init_list_head(&(channel->queries_by_timeout[i]));
199 /* Initialize configuration by each of the four sources, from highest
200 * precedence to lowest.
203 if (status == ARES_SUCCESS) {
204 status = init_by_options(channel, options, optmask);
205 if (status != ARES_SUCCESS)
206 DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
207 ares_strerror(status)));
209 if (status == ARES_SUCCESS) {
210 status = init_by_environment(channel);
211 if (status != ARES_SUCCESS)
212 DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
213 ares_strerror(status)));
215 if (status == ARES_SUCCESS) {
216 status = init_by_resolv_conf(channel);
217 if (status != ARES_SUCCESS)
218 DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n",
219 ares_strerror(status)));
223 * No matter what failed or succeeded, seed defaults to provide
224 * useful behavior for things that we missed.
226 status = init_by_defaults(channel);
227 if (status != ARES_SUCCESS)
228 DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
229 ares_strerror(status)));
231 /* Generate random key */
233 if (status == ARES_SUCCESS) {
234 status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
235 if (status == ARES_SUCCESS)
236 channel->next_id = ares__generate_new_id(&channel->id_key);
238 DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
239 ares_strerror(status)));
242 if (status != ARES_SUCCESS)
244 /* Something failed; clean up memory we may have allocated. */
245 if (channel->servers)
246 free(channel->servers);
247 if (channel->domains)
249 for (i = 0; i < channel->ndomains; i++)
250 free(channel->domains[i]);
251 free(channel->domains);
253 if (channel->sortlist)
254 free(channel->sortlist);
256 free(channel->lookups);
261 /* Trim to one server if ARES_FLAG_PRIMARY is set. */
262 if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
263 channel->nservers = 1;
265 ares__init_servers_state(channel);
267 *channelptr = channel;
271 /* ares_dup() duplicates a channel handle with all its options and returns a
272 new channel handle */
273 int ares_dup(ares_channel *dest, ares_channel src)
275 struct ares_options opts;
276 struct ares_addr_node *servers;
277 int ipv6_nservers = 0;
281 *dest = NULL; /* in case of failure return NULL explicitly */
283 /* First get the options supported by the old ares_save_options() function,
284 which is most of them */
285 rc = ares_save_options(src, &opts, &optmask);
289 /* Then create the new channel with those options */
290 rc = ares_init_options(dest, &opts, optmask);
292 /* destroy the options copy to not leak any memory */
293 ares_destroy_options(&opts);
298 /* Now clone the options that ares_save_options() doesn't support. */
299 (*dest)->sock_create_cb = src->sock_create_cb;
300 (*dest)->sock_create_cb_data = src->sock_create_cb_data;
302 strncpy((*dest)->local_dev_name, src->local_dev_name,
303 sizeof(src->local_dev_name));
304 (*dest)->local_ip4 = src->local_ip4;
305 memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
307 /* Full name server cloning required when not all are IPv4 */
308 for (i = 0; i < src->nservers; i++)
310 if (src->servers[i].addr.family != AF_INET) {
316 rc = ares_get_servers(src, &servers);
317 if (rc != ARES_SUCCESS)
319 rc = ares_set_servers(*dest, servers);
320 ares_free_data(servers);
321 if (rc != ARES_SUCCESS)
325 return ARES_SUCCESS; /* everything went fine */
328 /* Save options from initialized channel */
329 int ares_save_options(ares_channel channel, struct ares_options *options,
333 int ipv4_nservers = 0;
335 /* Zero everything out */
336 memset(options, 0, sizeof(struct ares_options));
338 if (!ARES_CONFIG_CHECK(channel))
341 /* Traditionally the optmask wasn't saved in the channel struct so it was
342 recreated here. ROTATE is the first option that has no struct field of
343 its own in the public config struct */
344 (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS|
345 ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
346 ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
347 ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS) |
348 (channel->optmask & ARES_OPT_ROTATE);
350 /* Copy easy stuff */
351 options->flags = channel->flags;
353 /* We return full millisecond resolution but that's only because we don't
354 set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */
355 options->timeout = channel->timeout;
356 options->tries = channel->tries;
357 options->ndots = channel->ndots;
358 options->udp_port = ntohs(aresx_sitous(channel->udp_port));
359 options->tcp_port = ntohs(aresx_sitous(channel->tcp_port));
360 options->sock_state_cb = channel->sock_state_cb;
361 options->sock_state_cb_data = channel->sock_state_cb_data;
363 /* Copy IPv4 servers */
364 if (channel->nservers) {
365 for (i = 0; i < channel->nservers; i++)
367 if (channel->servers[i].addr.family == AF_INET)
371 options->servers = malloc(ipv4_nservers * sizeof(struct in_addr));
372 if (!options->servers)
374 for (i = j = 0; i < channel->nservers; i++)
376 if (channel->servers[i].addr.family == AF_INET)
377 memcpy(&options->servers[j++],
378 &channel->servers[i].addr.addrV4,
379 sizeof(channel->servers[i].addr.addrV4));
383 options->nservers = ipv4_nservers;
386 if (channel->ndomains) {
387 options->domains = malloc(channel->ndomains * sizeof(char *));
388 if (!options->domains)
391 for (i = 0; i < channel->ndomains; i++)
393 options->ndomains = i;
394 options->domains[i] = strdup(channel->domains[i]);
395 if (!options->domains[i])
399 options->ndomains = channel->ndomains;
402 if (channel->lookups) {
403 options->lookups = strdup(channel->lookups);
404 if (!options->lookups && channel->lookups)
409 if (channel->nsort) {
410 options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
411 if (!options->sortlist)
413 for (i = 0; i < channel->nsort; i++)
414 options->sortlist[i] = channel->sortlist[i];
416 options->nsort = channel->nsort;
421 static int init_by_options(ares_channel channel,
422 const struct ares_options *options,
428 if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
429 channel->flags = options->flags;
430 if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1)
431 channel->timeout = options->timeout;
432 else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
433 channel->timeout = options->timeout * 1000;
434 if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
435 channel->tries = options->tries;
436 if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
437 channel->ndots = options->ndots;
438 if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1)
440 if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
441 channel->udp_port = htons(options->udp_port);
442 if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
443 channel->tcp_port = htons(options->tcp_port);
444 if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL)
446 channel->sock_state_cb = options->sock_state_cb;
447 channel->sock_state_cb_data = options->sock_state_cb_data;
449 if ((optmask & ARES_OPT_SOCK_SNDBUF)
450 && channel->socket_send_buffer_size == -1)
451 channel->socket_send_buffer_size = options->socket_send_buffer_size;
452 if ((optmask & ARES_OPT_SOCK_RCVBUF)
453 && channel->socket_receive_buffer_size == -1)
454 channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
456 /* Copy the IPv4 servers, if given. */
457 if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
459 /* Avoid zero size allocations at any cost */
460 if (options->nservers > 0)
463 malloc(options->nservers * sizeof(struct server_state));
464 if (!channel->servers)
466 for (i = 0; i < options->nservers; i++)
468 channel->servers[i].addr.family = AF_INET;
469 memcpy(&channel->servers[i].addr.addrV4,
470 &options->servers[i],
471 sizeof(channel->servers[i].addr.addrV4));
474 channel->nservers = options->nservers;
477 /* Copy the domains, if given. Keep channel->ndomains consistent so
478 * we can clean up in case of error.
480 if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
482 /* Avoid zero size allocations at any cost */
483 if (options->ndomains > 0)
485 channel->domains = malloc(options->ndomains * sizeof(char *));
486 if (!channel->domains)
488 for (i = 0; i < options->ndomains; i++)
490 channel->ndomains = i;
491 channel->domains[i] = strdup(options->domains[i]);
492 if (!channel->domains[i])
496 channel->ndomains = options->ndomains;
499 /* Set lookups, if given. */
500 if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
502 channel->lookups = strdup(options->lookups);
503 if (!channel->lookups)
508 if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1) &&
509 (options->nsort>0)) {
510 channel->sortlist = malloc(options->nsort * sizeof(struct apattern));
511 if (!channel->sortlist)
513 for (i = 0; i < options->nsort; i++)
514 channel->sortlist[i] = options->sortlist[i];
515 channel->nsort = options->nsort;
518 channel->optmask = optmask;
523 static int init_by_environment(ares_channel channel)
525 const char *localdomain, *res_options;
528 localdomain = getenv("LOCALDOMAIN");
529 if (localdomain && channel->ndomains == -1)
531 status = set_search(channel, localdomain);
532 if (status != ARES_SUCCESS)
536 res_options = getenv("RES_OPTIONS");
539 status = set_options(channel, res_options);
540 if (status != ARES_SUCCESS)
551 * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer
552 * to the name of the registry leaf key to be queried, fetch it's string
553 * value and return a pointer in *outptr to a newly allocated memory area
554 * holding it as a null-terminated string.
556 * Returns 0 and nullifies *outptr upon inability to return a string value.
558 * Returns 1 and sets *outptr when returning a dynamically allocated string.
560 * Supported on Windows NT 3.5 and newer.
562 static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
569 /* Find out size of string stored in registry */
570 res = RegQueryValueEx(hKey, leafKeyName, 0, NULL, NULL, &size);
571 if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
574 /* Allocate buffer of indicated size plus one given that string
575 might have been stored without null termination */
576 *outptr = malloc(size+1);
580 /* Get the value for real */
581 res = RegQueryValueEx(hKey, leafKeyName, 0, NULL,
582 (unsigned char *)*outptr, &size);
583 if ((res != ERROR_SUCCESS) || (size == 1))
590 /* Null terminate buffer allways */
591 *(*outptr + size) = '\0';
599 * Functionally identical to get_REG_SZ()
601 * Supported on Windows 95, 98 and ME.
603 static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
611 /* Find out size of string stored in registry */
612 res = RegQueryValueEx(hKey, leafKeyName, 0, &dataType, NULL, &size);
613 if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
616 /* Allocate buffer of indicated size plus one given that string
617 might have been stored without null termination */
618 *outptr = malloc(size+1);
622 /* Get the value for real */
623 res = RegQueryValueEx(hKey, leafKeyName, 0, &dataType,
624 (unsigned char *)*outptr, &size);
625 if ((res != ERROR_SUCCESS) || (size == 1))
632 /* Null terminate buffer allways */
633 *(*outptr + size) = '\0';
641 * Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName'
642 * pointer to the name of the registry leaf key to be queried, parent key
643 * is enumerated searching in child keys for given leaf key name and its
644 * associated string value. When located, this returns a pointer in *outptr
645 * to a newly allocated memory area holding it as a null-terminated string.
647 * Returns 0 and nullifies *outptr upon inability to return a string value.
649 * Returns 1 and sets *outptr when returning a dynamically allocated string.
651 * Supported on Windows NT 3.5 and newer.
653 static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName,
656 char enumKeyName[256];
657 DWORD enumKeyNameBuffSize;
658 DWORD enumKeyIdx = 0;
667 enumKeyNameBuffSize = sizeof(enumKeyName);
668 res = RegEnumKeyEx(hKeyParent, enumKeyIdx++, enumKeyName,
669 &enumKeyNameBuffSize, 0, NULL, NULL, NULL);
670 if (res != ERROR_SUCCESS)
672 res = RegOpenKeyEx(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE,
674 if (res != ERROR_SUCCESS)
676 gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr);
677 RegCloseKey(hKeyEnum);
689 * get_DNS_Registry_9X()
691 * Functionally identical to get_DNS_Registry()
693 * Implementation supports Windows 95, 98 and ME.
695 static int get_DNS_Registry_9X(char **outptr)
703 res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ,
705 if (res != ERROR_SUCCESS)
708 gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr);
709 RegCloseKey(hKey_VxD_MStcp);
711 if (!gotString || !*outptr)
718 * get_DNS_Registry_NT()
720 * Functionally identical to get_DNS_Registry()
722 * Refs: Microsoft Knowledge Base articles KB120642 and KB314053.
724 * Implementation supports Windows NT 3.5 and newer.
726 static int get_DNS_Registry_NT(char **outptr)
728 HKEY hKey_Interfaces = NULL;
729 HKEY hKey_Tcpip_Parameters;
735 res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
736 &hKey_Tcpip_Parameters);
737 if (res != ERROR_SUCCESS)
741 ** Global DNS settings override adapter specific parameters when both
742 ** are set. Additionally static DNS settings override DHCP-configured
743 ** parameters when both are set.
746 /* Global DNS static parameters */
747 gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr);
751 /* Global DNS DHCP-configured parameters */
752 gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr);
756 /* Try adapter specific parameters */
757 res = RegOpenKeyEx(hKey_Tcpip_Parameters, "Interfaces", 0,
758 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
760 if (res != ERROR_SUCCESS)
762 hKey_Interfaces = NULL;
766 /* Adapter specific DNS static parameters */
767 gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr);
771 /* Adapter specific DNS DHCP-configured parameters */
772 gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr);
776 RegCloseKey(hKey_Interfaces);
778 RegCloseKey(hKey_Tcpip_Parameters);
780 if (!gotString || !*outptr)
789 * Locates DNS info in the registry. When located, this returns a pointer
790 * in *outptr to a newly allocated memory area holding a null-terminated
791 * string with a space or comma seperated list of DNS IP addresses.
793 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
795 * Returns 1 and sets *outptr when returning a dynamically allocated string.
797 static int get_DNS_Registry(char **outptr)
799 win_platform platform;
804 platform = ares__getplatform();
806 if (platform == WIN_NT)
807 gotString = get_DNS_Registry_NT(outptr);
808 else if (platform == WIN_9X)
809 gotString = get_DNS_Registry_9X(outptr);
822 static void commajoin(char **dst, const char *src)
828 tmp = malloc(strlen(*dst) + strlen(src) + 2);
831 sprintf(tmp, "%s,%s", *dst, src);
837 *dst = malloc(strlen(src) + 1);
845 * get_DNS_NetworkParams()
847 * Locates DNS info using GetNetworkParams() function from the Internet
848 * Protocol Helper (IP Helper) API. When located, this returns a pointer
849 * in *outptr to a newly allocated memory area holding a null-terminated
850 * string with a space or comma seperated list of DNS IP addresses.
852 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
854 * Returns 1 and sets *outptr when returning a dynamically allocated string.
856 * Implementation supports Windows 98 and newer.
858 * Note: Ancient PSDK required in order to build a W98 target.
860 static int get_DNS_NetworkParams(char **outptr)
862 FIXED_INFO *fi, *newfi;
863 struct ares_addr namesrvr;
865 IP_ADDR_STRING *ipAddr;
867 DWORD size = sizeof (*fi);
871 /* Verify run-time availability of GetNetworkParams() */
872 if (ares_fpGetNetworkParams == ZERO_NULL)
879 res = (*ares_fpGetNetworkParams) (fi, &size);
880 if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
883 newfi = realloc(fi, size);
888 res = (*ares_fpGetNetworkParams) (fi, &size);
889 if (res != ERROR_SUCCESS)
892 for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next)
894 txtaddr = &ipAddr->IpAddress.String[0];
896 /* Validate converting textual address to binary format. */
897 if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1)
899 if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) ||
900 (namesrvr.addrV4.S_un.S_addr == INADDR_NONE))
903 else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1)
905 if (memcmp(&namesrvr.addrV6, &ares_in6addr_any,
906 sizeof(namesrvr.addrV6)) == 0)
912 commajoin(outptr, txtaddr);
929 * get_DNS_AdaptersAddresses()
931 * Locates DNS info using GetAdaptersAddresses() function from the Internet
932 * Protocol Helper (IP Helper) API. When located, this returns a pointer
933 * in *outptr to a newly allocated memory area holding a null-terminated
934 * string with a space or comma seperated list of DNS IP addresses.
936 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
938 * Returns 1 and sets *outptr when returning a dynamically allocated string.
940 * Implementation supports Windows XP and newer.
942 #define IPAA_INITIAL_BUF_SZ 15 * 1024
943 #define IPAA_MAX_TRIES 3
944 static int get_DNS_AdaptersAddresses(char **outptr)
946 IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
947 IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry;
948 ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ;
949 ULONG Bufsz = IPAA_INITIAL_BUF_SZ;
951 int trying = IPAA_MAX_TRIES;
956 struct sockaddr_in *sa4;
957 struct sockaddr_in6 *sa6;
960 char txtaddr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
964 /* Verify run-time availability of GetAdaptersAddresses() */
965 if (ares_fpGetAdaptersAddresses == ZERO_NULL)
968 ipaa = malloc(Bufsz);
972 /* Usually this call suceeds with initial buffer size */
973 res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
975 if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
978 while ((res == ERROR_BUFFER_OVERFLOW) && (--trying))
980 if (Bufsz < ReqBufsz)
982 newipaa = realloc(ipaa, ReqBufsz);
988 res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
990 if (res == ERROR_SUCCESS)
993 if (res != ERROR_SUCCESS)
996 for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next)
998 for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress;
1000 ipaDNSAddr = ipaDNSAddr->Next)
1002 namesrvr.sa = ipaDNSAddr->Address.lpSockaddr;
1004 if (namesrvr.sa->sa_family == AF_INET)
1006 if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) ||
1007 (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE))
1009 if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
1010 txtaddr, sizeof(txtaddr)))
1013 else if (namesrvr.sa->sa_family == AF_INET6)
1015 if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any,
1016 sizeof(namesrvr.sa6->sin6_addr)) == 0)
1018 if (! ares_inet_ntop(AF_INET, &namesrvr.sa6->sin6_addr,
1019 txtaddr, sizeof(txtaddr)))
1025 commajoin(outptr, txtaddr);
1045 * Locates DNS info from Windows employing most suitable methods available at
1046 * run-time no matter which Windows version it is. When located, this returns
1047 * a pointer in *outptr to a newly allocated memory area holding a string with
1048 * a space or comma seperated list of DNS IP addresses, null-terminated.
1050 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
1052 * Returns 1 and sets *outptr when returning a dynamically allocated string.
1054 * Implementation supports Windows 95 and newer.
1056 static int get_DNS_Windows(char **outptr)
1058 /* Try using IP helper API GetAdaptersAddresses() */
1059 if (get_DNS_AdaptersAddresses(outptr))
1062 /* Try using IP helper API GetNetworkParams() */
1063 if (get_DNS_NetworkParams(outptr))
1066 /* Fall-back to registry information */
1067 return get_DNS_Registry(outptr);
1071 static int init_by_resolv_conf(ares_channel channel)
1073 #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32)
1076 int status = -1, nservers = 0, nsort = 0;
1077 struct server_state *servers = NULL;
1078 struct apattern *sortlist = NULL;
1082 if (channel->nservers > -1) /* don't override ARES_OPT_SERVER */
1083 return ARES_SUCCESS;
1085 if (get_DNS_Windows(&line))
1087 status = config_nameserver(&servers, &nservers, line);
1091 if (status == ARES_SUCCESS)
1094 /* Catch the case when all the above checks fail (which happens when there
1095 is no network card or the cable is unplugged) */
1096 status = ARES_EFILE;
1098 #elif defined(__riscos__)
1100 /* Under RISC OS, name servers are listed in the
1101 system variable Inet$Resolvers, space separated. */
1103 line = getenv("Inet$Resolvers");
1106 char *resolvers = strdup(line), *pos, *space;
1113 space = strchr(pos, ' ');
1116 status = config_nameserver(&servers, &nservers, pos);
1117 if (status != ARES_SUCCESS)
1122 if (status == ARES_SUCCESS)
1128 #elif defined(WATT32)
1132 for (i = 0; def_nameservers[i]; i++)
1135 return ARES_SUCCESS; /* use localhost DNS server */
1138 servers = calloc(i, sizeof(struct server_state));
1142 for (i = 0; def_nameservers[i]; i++)
1144 servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]);
1145 servers[i].addr.family = AF_INET;
1149 #elif defined(ANDROID) || defined(__ANDROID__)
1151 char propname[PROP_NAME_MAX];
1152 char propvalue[PROP_VALUE_MAX]="";
1154 for (i = 1; i <= MAX_DNS_PROPERTIES; i++) {
1155 snprintf(propname, sizeof(propname), "%s%u", DNS_PROP_NAME_PREFIX, i);
1156 if (__system_property_get(propname, propvalue) < 1) {
1160 status = config_nameserver(&servers, &nservers, propvalue);
1161 if (status != ARES_SUCCESS)
1172 /* Don't read resolv.conf and friends if we don't have to */
1173 if (ARES_CONFIG_CHECK(channel))
1174 return ARES_SUCCESS;
1176 fp = fopen(PATH_RESOLV_CONF, "r");
1178 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
1180 if ((p = try_config(line, "domain", ';')))
1181 status = config_domain(channel, p);
1182 else if ((p = try_config(line, "lookup", ';')) && !channel->lookups)
1183 status = config_lookup(channel, p, "bind", "file");
1184 else if ((p = try_config(line, "search", ';')))
1185 status = set_search(channel, p);
1186 else if ((p = try_config(line, "nameserver", ';')) &&
1187 channel->nservers == -1)
1188 status = config_nameserver(&servers, &nservers, p);
1189 else if ((p = try_config(line, "sortlist", ';')) &&
1190 channel->nsort == -1)
1191 status = config_sortlist(&sortlist, &nsort, p);
1192 else if ((p = try_config(line, "options", ';')))
1193 status = set_options(channel, p);
1195 status = ARES_SUCCESS;
1196 if (status != ARES_SUCCESS)
1209 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1210 error, strerror(error)));
1211 DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
1212 status = ARES_EFILE;
1216 if ((status == ARES_EOF) && (!channel->lookups)) {
1217 /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
1218 fp = fopen("/etc/nsswitch.conf", "r");
1220 while ((status = ares__read_line(fp, &line, &linesize)) ==
1223 if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups)
1225 (void)config_lookup(channel, p, "dns", "files");
1237 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1238 error, strerror(error)));
1239 DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1240 "/etc/nsswitch.conf"));
1241 status = ARES_EFILE;
1246 if ((status == ARES_EOF) && (!channel->lookups)) {
1247 /* Linux / GNU libc 2.x and possibly others have host.conf */
1248 fp = fopen("/etc/host.conf", "r");
1250 while ((status = ares__read_line(fp, &line, &linesize)) ==
1253 if ((p = try_config(line, "order", '\0')) && !channel->lookups)
1255 (void)config_lookup(channel, p, "bind", "hosts");
1267 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1268 error, strerror(error)));
1269 DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1271 status = ARES_EFILE;
1276 if ((status == ARES_EOF) && (!channel->lookups)) {
1277 /* Tru64 uses /etc/svc.conf */
1278 fp = fopen("/etc/svc.conf", "r");
1280 while ((status = ares__read_line(fp, &line, &linesize)) ==
1283 if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups)
1285 (void)config_lookup(channel, p, "bind", "local");
1297 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1298 error, strerror(error)));
1299 DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
1300 status = ARES_EFILE;
1311 /* Handle errors. */
1312 if (status != ARES_EOF)
1314 if (servers != NULL)
1316 if (sortlist != NULL)
1321 /* If we got any name server entries, fill them in. */
1324 channel->servers = servers;
1325 channel->nservers = nservers;
1328 /* If we got any sortlist entries, fill them in. */
1331 channel->sortlist = sortlist;
1332 channel->nsort = nsort;
1335 return ARES_SUCCESS;
1338 static int init_by_defaults(ares_channel channel)
1340 char *hostname = NULL;
1341 int rc = ARES_SUCCESS;
1342 #ifdef HAVE_GETHOSTNAME
1346 if (channel->flags == -1)
1348 if (channel->timeout == -1)
1349 channel->timeout = DEFAULT_TIMEOUT;
1350 if (channel->tries == -1)
1351 channel->tries = DEFAULT_TRIES;
1352 if (channel->ndots == -1)
1354 if (channel->rotate == -1)
1355 channel->rotate = 0;
1356 if (channel->udp_port == -1)
1357 channel->udp_port = htons(NAMESERVER_PORT);
1358 if (channel->tcp_port == -1)
1359 channel->tcp_port = htons(NAMESERVER_PORT);
1361 if (channel->nservers == -1) {
1362 /* If nobody specified servers, try a local named. */
1363 channel->servers = malloc(sizeof(struct server_state));
1364 if (!channel->servers) {
1368 channel->servers[0].addr.family = AF_INET;
1369 channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK);
1370 channel->nservers = 1;
1373 #if defined(USE_WINSOCK)
1374 #define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT)
1375 #elif defined(ENAMETOOLONG)
1376 #define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \
1377 (SOCKERRNO == EINVAL))
1379 #define toolong(x) (x == -1) && (SOCKERRNO == EINVAL)
1382 if (channel->ndomains == -1) {
1383 /* Derive a default domain search list from the kernel hostname,
1384 * or set it to empty if the hostname isn't helpful.
1386 #ifndef HAVE_GETHOSTNAME
1387 channel->ndomains = 0; /* default to none */
1389 GETHOSTNAME_TYPE_ARG2 lenv = 64;
1392 channel->ndomains = 0; /* default to none */
1394 hostname = malloc(len);
1401 res = gethostname(hostname, lenv);
1407 p = realloc(hostname, len);
1422 dot = strchr(hostname, '.');
1424 /* a dot was found */
1425 channel->domains = malloc(sizeof(char *));
1426 if (!channel->domains) {
1430 channel->domains[0] = strdup(dot + 1);
1431 if (!channel->domains[0]) {
1435 channel->ndomains = 1;
1440 if (channel->nsort == -1) {
1441 channel->sortlist = NULL;
1445 if (!channel->lookups) {
1446 channel->lookups = strdup("fb");
1447 if (!channel->lookups)
1453 if(channel->servers) {
1454 free(channel->servers);
1455 channel->servers = NULL;
1458 if(channel->domains && channel->domains[0])
1459 free(channel->domains[0]);
1460 if(channel->domains) {
1461 free(channel->domains);
1462 channel->domains = NULL;
1465 if(channel->lookups) {
1466 free(channel->lookups);
1467 channel->lookups = NULL;
1477 #if !defined(WIN32) && !defined(WATT32) && \
1478 !defined(ANDROID) && !defined(__ANDROID__)
1479 static int config_domain(ares_channel channel, char *str)
1483 /* Set a single search domain. */
1485 while (*q && !ISSPACE(*q))
1488 return set_search(channel, str);
1491 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
1492 defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
1493 /* workaround icc 9.1 optimizer issue */
1494 # define vqualifier volatile
1499 static int config_lookup(ares_channel channel, const char *str,
1500 const char *bindch, const char *filech)
1502 char lookups[3], *l;
1503 const char *vqualifier p;
1505 /* Set the lookup order. Only the first letter of each work
1506 * is relevant, and it has to be "b" for DNS or "f" for the
1507 * host file. Ignore everything else.
1513 if ((*p == *bindch || *p == *filech) && l < lookups + 2) {
1514 if (*p == *bindch) *l++ = 'b';
1517 while (*p && !ISSPACE(*p) && (*p != ','))
1519 while (*p && (ISSPACE(*p) || (*p == ',')))
1523 channel->lookups = strdup(lookups);
1524 return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
1526 #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */
1529 static int config_nameserver(struct server_state **servers, int *nservers,
1532 struct ares_addr host;
1533 struct server_state *newserv;
1535 /* On Windows, there may be more than one nameserver specified in the same
1536 * registry key, so we parse input as a space or comma seperated list.
1540 /* Skip whitespace and commas. */
1541 while (*p && (ISSPACE(*p) || (*p == ',')))
1544 /* No more input, done. */
1547 /* Pointer to start of IPv4 or IPv6 address part. */
1550 /* Advance past this address. */
1551 while (*p && !ISSPACE(*p) && (*p != ','))
1554 /* Null terminate this address. */
1557 /* Reached end of input, done when this address is processed. */
1560 /* Convert textual address to binary format. */
1561 if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
1562 host.family = AF_INET;
1563 else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1)
1564 host.family = AF_INET6;
1568 /* Resize servers state array. */
1569 newserv = realloc(*servers, (*nservers + 1) *
1570 sizeof(struct server_state));
1574 /* Store address data. */
1575 newserv[*nservers].addr.family = host.family;
1576 if (host.family == AF_INET)
1577 memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
1578 sizeof(host.addrV4));
1580 memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
1581 sizeof(host.addrV6));
1583 /* Update arguments. */
1588 return ARES_SUCCESS;
1591 #if !defined(WIN32) && !defined(ANDROID) && !defined(__ANDROID__)
1592 static int config_sortlist(struct apattern **sortlist, int *nsort,
1595 struct apattern pat;
1598 /* Add sortlist entries. */
1599 while (*str && *str != ';')
1602 char ipbuf[16], ipbufpfx[32];
1603 /* Find just the IP */
1605 while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
1607 memcpy(ipbuf, str, q-str);
1608 ipbuf[q-str] = '\0';
1609 /* Find the prefix */
1612 const char *str2 = q+1;
1613 while (*q && *q != ';' && !ISSPACE(*q))
1615 memcpy(ipbufpfx, str, q-str);
1616 ipbufpfx[q-str] = '\0';
1621 /* Lets see if it is CIDR */
1622 /* First we'll try IPv6 */
1623 if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf,
1625 sizeof(pat.addrV6))) > 0)
1627 pat.type = PATTERN_CIDR;
1628 pat.mask.bits = (unsigned short)bits;
1629 pat.family = AF_INET6;
1630 if (!sortlist_alloc(sortlist, nsort, &pat))
1633 else if (ipbufpfx[0] &&
1634 (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4,
1635 sizeof(pat.addrV4))) > 0)
1637 pat.type = PATTERN_CIDR;
1638 pat.mask.bits = (unsigned short)bits;
1639 pat.family = AF_INET;
1640 if (!sortlist_alloc(sortlist, nsort, &pat))
1643 /* See if it is just a regular IP */
1644 else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0)
1648 memcpy(ipbuf, str, q-str);
1649 ipbuf[q-str] = '\0';
1650 if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0)
1655 pat.family = AF_INET;
1656 pat.type = PATTERN_MASK;
1657 if (!sortlist_alloc(sortlist, nsort, &pat))
1662 while (*q && *q != ';' && !ISSPACE(*q))
1666 while (ISSPACE(*str))
1670 return ARES_SUCCESS;
1672 #endif /* !WIN32 & !ANDROID & !__ANDROID__ */
1673 #endif /* !WATT32 */
1675 static int set_search(ares_channel channel, const char *str)
1680 if(channel->ndomains != -1) {
1681 /* if we already have some domains present, free them first */
1682 for(n=0; n < channel->ndomains; n++)
1683 free(channel->domains[n]);
1684 free(channel->domains);
1685 channel->domains = NULL;
1686 channel->ndomains = -1;
1689 /* Count the domains given. */
1694 while (*p && !ISSPACE(*p))
1703 channel->ndomains = 0;
1704 return ARES_SUCCESS;
1707 channel->domains = malloc(n * sizeof(char *));
1708 if (!channel->domains)
1711 /* Now copy the domains. */
1716 channel->ndomains = n;
1718 while (*q && !ISSPACE(*q))
1720 channel->domains[n] = malloc(q - p + 1);
1721 if (!channel->domains[n])
1723 memcpy(channel->domains[n], p, q - p);
1724 channel->domains[n][q - p] = 0;
1730 channel->ndomains = n;
1732 return ARES_SUCCESS;
1735 static int set_options(ares_channel channel, const char *str)
1737 const char *p, *q, *val;
1743 while (*q && !ISSPACE(*q))
1745 val = try_option(p, q, "ndots:");
1746 if (val && channel->ndots == -1)
1747 channel->ndots = aresx_sltosi(strtol(val, NULL, 10));
1748 val = try_option(p, q, "retrans:");
1749 if (val && channel->timeout == -1)
1750 channel->timeout = aresx_sltosi(strtol(val, NULL, 10));
1751 val = try_option(p, q, "retry:");
1752 if (val && channel->tries == -1)
1753 channel->tries = aresx_sltosi(strtol(val, NULL, 10));
1754 val = try_option(p, q, "rotate");
1755 if (val && channel->rotate == -1)
1756 channel->rotate = 1;
1762 return ARES_SUCCESS;
1765 static const char *try_option(const char *p, const char *q, const char *opt)
1767 size_t len = strlen(opt);
1768 return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL;
1771 #if !defined(WIN32) && !defined(WATT32) && \
1772 !defined(ANDROID) && !defined(__ANDROID__)
1773 static char *try_config(char *s, const char *opt, char scc)
1780 /* no line or no option */
1783 /* Hash '#' character is always used as primary comment char, additionally
1784 a not-NUL secondary comment char will be considered when specified. */
1786 /* trim line comment */
1789 while (*p && (*p != '#') && (*p != scc))
1792 while (*p && (*p != '#'))
1796 /* trim trailing whitespace */
1798 while ((q >= s) && ISSPACE(*q))
1802 /* skip leading whitespace */
1804 while (*p && ISSPACE(*p))
1811 if ((len = strlen(opt)) == 0)
1815 if (strncmp(p, opt, len) != 0)
1816 /* line and option do not match */
1819 /* skip over given option name */
1823 /* no option value */
1826 if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p))
1827 /* whitespace between option name and value is mandatory
1828 for given option names which do not end with ':' or '=' */
1831 /* skip over whitespace */
1832 while (*p && ISSPACE(*p))
1836 /* no option value */
1839 /* return pointer to option value */
1843 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
1844 struct apattern *pat)
1846 struct apattern *newsort;
1847 newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
1850 newsort[*nsort] = *pat;
1851 *sortlist = newsort;
1856 static int ip_addr(const char *ipbuf, ssize_t len, struct in_addr *addr)
1859 /* Four octets and three periods yields at most 15 characters. */
1863 addr->s_addr = inet_addr(ipbuf);
1864 if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
1869 static void natural_mask(struct apattern *pat)
1871 struct in_addr addr;
1873 /* Store a host-byte-order copy of pat in a struct in_addr. Icky,
1876 addr.s_addr = ntohl(pat->addrV4.s_addr);
1878 /* This is out of date in the CIDR world, but some people might
1881 if (IN_CLASSA(addr.s_addr))
1882 pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET);
1883 else if (IN_CLASSB(addr.s_addr))
1884 pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET);
1886 pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET);
1888 #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */
1890 /* initialize an rc4 key. If possible a cryptographically secure random key
1891 is generated using a suitable function (for example win32's RtlGenRandom as
1893 http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
1894 otherwise the code defaults to cross-platform albeit less secure mechanism
1897 static void randomize_key(unsigned char* key,int key_data_len)
1903 if (ares_fpSystemFunction036)
1905 res = (*ares_fpSystemFunction036) (key, key_data_len);
1911 FILE *f = fopen(RANDOM_FILE, "rb");
1913 counter = aresx_uztosi(fread(key, 1, key_data_len, f));
1920 for (;counter<key_data_len;counter++)
1921 key[counter]=(unsigned char)(rand() % 256);
1925 static int init_id_key(rc4_key* key,int key_data_len)
1927 unsigned char index1;
1928 unsigned char index2;
1929 unsigned char* state;
1931 unsigned char *key_data_ptr = 0;
1933 key_data_ptr = calloc(1,key_data_len);
1937 state = &key->state[0];
1938 for(counter = 0; counter < 256; counter++)
1939 /* unnecessary AND but it keeps some compilers happier */
1940 state[counter] = (unsigned char)(counter & 0xff);
1941 randomize_key(key->state,key_data_len);
1946 for(counter = 0; counter < 256; counter++)
1948 index2 = (unsigned char)((key_data_ptr[index1] + state[counter] +
1950 ARES_SWAP_BYTE(&state[counter], &state[index2]);
1952 index1 = (unsigned char)((index1 + 1) % key_data_len);
1955 return ARES_SUCCESS;
1958 unsigned short ares__generate_new_id(rc4_key* key)
1961 ares__rc4(key, (unsigned char *)&r, sizeof(r));
1965 void ares_set_local_ip4(ares_channel channel, unsigned int local_ip)
1967 channel->local_ip4 = local_ip;
1970 /* local_ip6 should be 16 bytes in length */
1971 void ares_set_local_ip6(ares_channel channel,
1972 const unsigned char* local_ip6)
1974 memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
1977 /* local_dev_name should be null terminated. */
1978 void ares_set_local_dev(ares_channel channel,
1979 const char* local_dev_name)
1981 strncpy(channel->local_dev_name, local_dev_name,
1982 sizeof(channel->local_dev_name));
1983 channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
1987 void ares_set_socket_callback(ares_channel channel,
1988 ares_sock_create_callback cb,
1991 channel->sock_create_cb = cb;
1992 channel->sock_create_cb_data = data;
1995 void ares__init_servers_state(ares_channel channel)
1997 struct server_state *server;
2000 for (i = 0; i < channel->nservers; i++)
2002 server = &channel->servers[i];
2003 server->udp_socket = ARES_SOCKET_BAD;
2004 server->tcp_socket = ARES_SOCKET_BAD;
2005 server->tcp_connection_generation = ++channel->tcp_connection_generation;
2006 server->tcp_lenbuf_pos = 0;
2007 server->tcp_buffer_pos = 0;
2008 server->tcp_buffer = NULL;
2009 server->tcp_length = 0;
2010 server->qhead = NULL;
2011 server->qtail = NULL;
2012 ares__init_list_head(&server->queries_to_server);
2013 server->channel = channel;
2014 server->is_broken = 0;