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_NETINET_IN_H
25 #include <netinet/in.h>
32 #ifdef HAVE_ARPA_INET_H
33 #include <arpa/inet.h>
36 #ifdef HAVE_ARPA_NAMESER_H
37 # include <arpa/nameser.h>
41 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
42 # include <arpa/nameser_compat.h>
45 #if defined(ANDROID) || defined(__ANDROID__)
46 #include <sys/system_properties.h>
47 /* From the Bionic sources */
48 #define DNS_PROP_NAME_PREFIX "net.dns"
49 #define MAX_DNS_PROPERTIES 8
53 #include "inet_ntop.h"
54 #include "inet_net_pton.h"
55 #include "ares_library_init.h"
56 #include "ares_nowarn.h"
57 #include "ares_platform.h"
58 #include "ares_private.h"
61 #undef WIN32 /* Redefined in MingW/MSVC headers */
64 static int init_by_options(ares_channel channel,
65 const struct ares_options *options,
67 static int init_by_environment(ares_channel channel);
68 static int init_by_resolv_conf(ares_channel channel);
69 static int init_by_defaults(ares_channel channel);
72 static int config_nameserver(struct server_state **servers, int *nservers,
75 static int set_search(ares_channel channel, const char *str);
76 static int set_options(ares_channel channel, const char *str);
77 static const char *try_option(const char *p, const char *q, const char *opt);
78 static int init_id_key(rc4_key* key,int key_data_len);
80 #if !defined(WIN32) && !defined(WATT32) && \
81 !defined(ANDROID) && !defined(__ANDROID__)
82 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
83 struct apattern *pat);
84 static int ip_addr(const char *s, ssize_t len, struct in_addr *addr);
85 static void natural_mask(struct apattern *pat);
86 static int config_domain(ares_channel channel, char *str);
87 static int config_lookup(ares_channel channel, const char *str,
88 const char *bindch, const char *filech);
89 static int config_sortlist(struct apattern **sortlist, int *nsort,
91 static char *try_config(char *s, const char *opt, char scc);
94 #define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
97 x->ndots > -1 && x->timeout > -1 && \
100 int ares_init(ares_channel *channelptr)
102 return ares_init_options(channelptr, NULL, 0);
105 int ares_init_options(ares_channel *channelptr, struct ares_options *options,
108 ares_channel channel;
110 int status = ARES_SUCCESS;
114 const char *env = getenv("CARES_MEMDEBUG");
118 env = getenv("CARES_MEMLIMIT");
121 long num = strtol(env, &endptr, 10);
122 if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
127 if (ares_library_initialized() != ARES_SUCCESS)
128 return ARES_ENOTINITIALIZED;
130 channel = malloc(sizeof(struct ares_channeldata));
138 /* Set everything to distinguished values so we know they haven't
142 channel->timeout = -1;
145 channel->rotate = -1;
146 channel->udp_port = -1;
147 channel->tcp_port = -1;
148 channel->ednspsz = -1;
149 channel->socket_send_buffer_size = -1;
150 channel->socket_receive_buffer_size = -1;
151 channel->nservers = -1;
152 channel->ndomains = -1;
154 channel->tcp_connection_generation = 0;
155 channel->lookups = NULL;
156 channel->domains = NULL;
157 channel->sortlist = NULL;
158 channel->servers = NULL;
159 channel->sock_state_cb = NULL;
160 channel->sock_state_cb_data = NULL;
161 channel->sock_create_cb = NULL;
162 channel->sock_create_cb_data = NULL;
164 channel->last_server = 0;
165 channel->last_timeout_processed = (time_t)now.tv_sec;
167 memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name));
168 channel->local_ip4 = 0;
169 memset(&channel->local_ip6, 0, sizeof(channel->local_ip6));
171 /* Initialize our lists of queries */
172 ares__init_list_head(&(channel->all_queries));
173 for (i = 0; i < ARES_QID_TABLE_SIZE; i++)
175 ares__init_list_head(&(channel->queries_by_qid[i]));
177 for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++)
179 ares__init_list_head(&(channel->queries_by_timeout[i]));
182 /* Initialize configuration by each of the four sources, from highest
183 * precedence to lowest.
186 if (status == ARES_SUCCESS) {
187 status = init_by_options(channel, options, optmask);
188 if (status != ARES_SUCCESS)
189 DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
190 ares_strerror(status)));
192 if (status == ARES_SUCCESS) {
193 status = init_by_environment(channel);
194 if (status != ARES_SUCCESS)
195 DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
196 ares_strerror(status)));
198 if (status == ARES_SUCCESS) {
199 status = init_by_resolv_conf(channel);
200 if (status != ARES_SUCCESS)
201 DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n",
202 ares_strerror(status)));
206 * No matter what failed or succeeded, seed defaults to provide
207 * useful behavior for things that we missed.
209 status = init_by_defaults(channel);
210 if (status != ARES_SUCCESS)
211 DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
212 ares_strerror(status)));
214 /* Generate random key */
216 if (status == ARES_SUCCESS) {
217 status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
218 if (status == ARES_SUCCESS)
219 channel->next_id = ares__generate_new_id(&channel->id_key);
221 DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
222 ares_strerror(status)));
225 if (status != ARES_SUCCESS)
227 /* Something failed; clean up memory we may have allocated. */
228 if (channel->servers)
229 free(channel->servers);
230 if (channel->domains)
232 for (i = 0; i < channel->ndomains; i++)
233 free(channel->domains[i]);
234 free(channel->domains);
236 if (channel->sortlist)
237 free(channel->sortlist);
239 free(channel->lookups);
244 /* Trim to one server if ARES_FLAG_PRIMARY is set. */
245 if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
246 channel->nservers = 1;
248 ares__init_servers_state(channel);
250 *channelptr = channel;
254 /* ares_dup() duplicates a channel handle with all its options and returns a
255 new channel handle */
256 int ares_dup(ares_channel *dest, ares_channel src)
258 struct ares_options opts;
259 struct ares_addr_node *servers;
260 int ipv6_nservers = 0;
264 *dest = NULL; /* in case of failure return NULL explicitly */
266 /* First get the options supported by the old ares_save_options() function,
267 which is most of them */
268 rc = ares_save_options(src, &opts, &optmask);
272 /* Then create the new channel with those options */
273 rc = ares_init_options(dest, &opts, optmask);
275 /* destroy the options copy to not leak any memory */
276 ares_destroy_options(&opts);
281 /* Now clone the options that ares_save_options() doesn't support. */
282 (*dest)->sock_create_cb = src->sock_create_cb;
283 (*dest)->sock_create_cb_data = src->sock_create_cb_data;
285 strncpy((*dest)->local_dev_name, src->local_dev_name,
286 sizeof(src->local_dev_name));
287 (*dest)->local_ip4 = src->local_ip4;
288 memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
290 /* Full name server cloning required when not all are IPv4 */
291 for (i = 0; i < src->nservers; i++)
293 if (src->servers[i].addr.family != AF_INET) {
299 rc = ares_get_servers(src, &servers);
300 if (rc != ARES_SUCCESS)
302 rc = ares_set_servers(*dest, servers);
303 ares_free_data(servers);
304 if (rc != ARES_SUCCESS)
308 return ARES_SUCCESS; /* everything went fine */
311 /* Save options from initialized channel */
312 int ares_save_options(ares_channel channel, struct ares_options *options,
316 int ipv4_nservers = 0;
318 /* Zero everything out */
319 memset(options, 0, sizeof(struct ares_options));
321 if (!ARES_CONFIG_CHECK(channel))
324 /* Traditionally the optmask wasn't saved in the channel struct so it was
325 recreated here. ROTATE is the first option that has no struct field of
326 its own in the public config struct */
327 (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS|
328 ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
329 ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
330 ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS) |
331 (channel->optmask & ARES_OPT_ROTATE);
333 /* Copy easy stuff */
334 options->flags = channel->flags;
336 /* We return full millisecond resolution but that's only because we don't
337 set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */
338 options->timeout = channel->timeout;
339 options->tries = channel->tries;
340 options->ndots = channel->ndots;
341 options->udp_port = ntohs(aresx_sitous(channel->udp_port));
342 options->tcp_port = ntohs(aresx_sitous(channel->tcp_port));
343 options->sock_state_cb = channel->sock_state_cb;
344 options->sock_state_cb_data = channel->sock_state_cb_data;
346 /* Copy IPv4 servers */
347 if (channel->nservers) {
348 for (i = 0; i < channel->nservers; i++)
350 if (channel->servers[i].addr.family == AF_INET)
354 options->servers = malloc(ipv4_nservers * sizeof(struct in_addr));
355 if (!options->servers)
357 for (i = j = 0; i < channel->nservers; i++)
359 if (channel->servers[i].addr.family == AF_INET)
360 memcpy(&options->servers[j++],
361 &channel->servers[i].addr.addrV4,
362 sizeof(channel->servers[i].addr.addrV4));
366 options->nservers = ipv4_nservers;
369 if (channel->ndomains) {
370 options->domains = malloc(channel->ndomains * sizeof(char *));
371 if (!options->domains)
374 for (i = 0; i < channel->ndomains; i++)
376 options->ndomains = i;
377 options->domains[i] = strdup(channel->domains[i]);
378 if (!options->domains[i])
382 options->ndomains = channel->ndomains;
385 if (channel->lookups) {
386 options->lookups = strdup(channel->lookups);
387 if (!options->lookups && channel->lookups)
392 if (channel->nsort) {
393 options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
394 if (!options->sortlist)
396 for (i = 0; i < channel->nsort; i++)
397 options->sortlist[i] = channel->sortlist[i];
399 options->nsort = channel->nsort;
404 static int init_by_options(ares_channel channel,
405 const struct ares_options *options,
411 if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
412 channel->flags = options->flags;
413 if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1)
414 channel->timeout = options->timeout;
415 else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
416 channel->timeout = options->timeout * 1000;
417 if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
418 channel->tries = options->tries;
419 if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
420 channel->ndots = options->ndots;
421 if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1)
423 if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
424 channel->udp_port = htons(options->udp_port);
425 if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
426 channel->tcp_port = htons(options->tcp_port);
427 if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL)
429 channel->sock_state_cb = options->sock_state_cb;
430 channel->sock_state_cb_data = options->sock_state_cb_data;
432 if ((optmask & ARES_OPT_SOCK_SNDBUF)
433 && channel->socket_send_buffer_size == -1)
434 channel->socket_send_buffer_size = options->socket_send_buffer_size;
435 if ((optmask & ARES_OPT_SOCK_RCVBUF)
436 && channel->socket_receive_buffer_size == -1)
437 channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
439 if ((optmask & ARES_OPT_EDNSPSZ) && channel->ednspsz == -1)
440 channel->ednspsz = options->ednspsz;
442 /* Copy the IPv4 servers, if given. */
443 if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
445 /* Avoid zero size allocations at any cost */
446 if (options->nservers > 0)
449 malloc(options->nservers * sizeof(struct server_state));
450 if (!channel->servers)
452 for (i = 0; i < options->nservers; i++)
454 channel->servers[i].addr.family = AF_INET;
455 memcpy(&channel->servers[i].addr.addrV4,
456 &options->servers[i],
457 sizeof(channel->servers[i].addr.addrV4));
460 channel->nservers = options->nservers;
463 /* Copy the domains, if given. Keep channel->ndomains consistent so
464 * we can clean up in case of error.
466 if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
468 /* Avoid zero size allocations at any cost */
469 if (options->ndomains > 0)
471 channel->domains = malloc(options->ndomains * sizeof(char *));
472 if (!channel->domains)
474 for (i = 0; i < options->ndomains; i++)
476 channel->ndomains = i;
477 channel->domains[i] = strdup(options->domains[i]);
478 if (!channel->domains[i])
482 channel->ndomains = options->ndomains;
485 /* Set lookups, if given. */
486 if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
488 channel->lookups = strdup(options->lookups);
489 if (!channel->lookups)
494 if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1) &&
495 (options->nsort>0)) {
496 channel->sortlist = malloc(options->nsort * sizeof(struct apattern));
497 if (!channel->sortlist)
499 for (i = 0; i < options->nsort; i++)
500 channel->sortlist[i] = options->sortlist[i];
501 channel->nsort = options->nsort;
504 channel->optmask = optmask;
509 static int init_by_environment(ares_channel channel)
511 const char *localdomain, *res_options;
514 localdomain = getenv("LOCALDOMAIN");
515 if (localdomain && channel->ndomains == -1)
517 status = set_search(channel, localdomain);
518 if (status != ARES_SUCCESS)
522 res_options = getenv("RES_OPTIONS");
525 status = set_options(channel, res_options);
526 if (status != ARES_SUCCESS)
537 * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer
538 * to the name of the registry leaf key to be queried, fetch it's string
539 * value and return a pointer in *outptr to a newly allocated memory area
540 * holding it as a null-terminated string.
542 * Returns 0 and nullifies *outptr upon inability to return a string value.
544 * Returns 1 and sets *outptr when returning a dynamically allocated string.
546 * Supported on Windows NT 3.5 and newer.
548 static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
555 /* Find out size of string stored in registry */
556 res = RegQueryValueEx(hKey, leafKeyName, 0, NULL, NULL, &size);
557 if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
560 /* Allocate buffer of indicated size plus one given that string
561 might have been stored without null termination */
562 *outptr = malloc(size+1);
566 /* Get the value for real */
567 res = RegQueryValueEx(hKey, leafKeyName, 0, NULL,
568 (unsigned char *)*outptr, &size);
569 if ((res != ERROR_SUCCESS) || (size == 1))
576 /* Null terminate buffer allways */
577 *(*outptr + size) = '\0';
585 * Functionally identical to get_REG_SZ()
587 * Supported on Windows 95, 98 and ME.
589 static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
597 /* Find out size of string stored in registry */
598 res = RegQueryValueEx(hKey, leafKeyName, 0, &dataType, NULL, &size);
599 if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
602 /* Allocate buffer of indicated size plus one given that string
603 might have been stored without null termination */
604 *outptr = malloc(size+1);
608 /* Get the value for real */
609 res = RegQueryValueEx(hKey, leafKeyName, 0, &dataType,
610 (unsigned char *)*outptr, &size);
611 if ((res != ERROR_SUCCESS) || (size == 1))
618 /* Null terminate buffer allways */
619 *(*outptr + size) = '\0';
627 * Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName'
628 * pointer to the name of the registry leaf key to be queried, parent key
629 * is enumerated searching in child keys for given leaf key name and its
630 * associated string value. When located, this returns a pointer in *outptr
631 * to a newly allocated memory area holding it as a null-terminated string.
633 * Returns 0 and nullifies *outptr upon inability to return a string value.
635 * Returns 1 and sets *outptr when returning a dynamically allocated string.
637 * Supported on Windows NT 3.5 and newer.
639 static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName,
642 char enumKeyName[256];
643 DWORD enumKeyNameBuffSize;
644 DWORD enumKeyIdx = 0;
653 enumKeyNameBuffSize = sizeof(enumKeyName);
654 res = RegEnumKeyEx(hKeyParent, enumKeyIdx++, enumKeyName,
655 &enumKeyNameBuffSize, 0, NULL, NULL, NULL);
656 if (res != ERROR_SUCCESS)
658 res = RegOpenKeyEx(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE,
660 if (res != ERROR_SUCCESS)
662 gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr);
663 RegCloseKey(hKeyEnum);
675 * get_DNS_Registry_9X()
677 * Functionally identical to get_DNS_Registry()
679 * Implementation supports Windows 95, 98 and ME.
681 static int get_DNS_Registry_9X(char **outptr)
689 res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ,
691 if (res != ERROR_SUCCESS)
694 gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr);
695 RegCloseKey(hKey_VxD_MStcp);
697 if (!gotString || !*outptr)
704 * get_DNS_Registry_NT()
706 * Functionally identical to get_DNS_Registry()
708 * Refs: Microsoft Knowledge Base articles KB120642 and KB314053.
710 * Implementation supports Windows NT 3.5 and newer.
712 static int get_DNS_Registry_NT(char **outptr)
714 HKEY hKey_Interfaces = NULL;
715 HKEY hKey_Tcpip_Parameters;
721 res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
722 &hKey_Tcpip_Parameters);
723 if (res != ERROR_SUCCESS)
727 ** Global DNS settings override adapter specific parameters when both
728 ** are set. Additionally static DNS settings override DHCP-configured
729 ** parameters when both are set.
732 /* Global DNS static parameters */
733 gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr);
737 /* Global DNS DHCP-configured parameters */
738 gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr);
742 /* Try adapter specific parameters */
743 res = RegOpenKeyEx(hKey_Tcpip_Parameters, "Interfaces", 0,
744 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
746 if (res != ERROR_SUCCESS)
748 hKey_Interfaces = NULL;
752 /* Adapter specific DNS static parameters */
753 gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr);
757 /* Adapter specific DNS DHCP-configured parameters */
758 gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr);
762 RegCloseKey(hKey_Interfaces);
764 RegCloseKey(hKey_Tcpip_Parameters);
766 if (!gotString || !*outptr)
775 * Locates DNS info in the registry. When located, this returns a pointer
776 * in *outptr to a newly allocated memory area holding a null-terminated
777 * string with a space or comma seperated list of DNS IP addresses.
779 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
781 * Returns 1 and sets *outptr when returning a dynamically allocated string.
783 static int get_DNS_Registry(char **outptr)
785 win_platform platform;
790 platform = ares__getplatform();
792 if (platform == WIN_NT)
793 gotString = get_DNS_Registry_NT(outptr);
794 else if (platform == WIN_9X)
795 gotString = get_DNS_Registry_9X(outptr);
808 static void commajoin(char **dst, const char *src)
814 tmp = malloc(strlen(*dst) + strlen(src) + 2);
817 sprintf(tmp, "%s,%s", *dst, src);
823 *dst = malloc(strlen(src) + 1);
831 * get_DNS_NetworkParams()
833 * Locates DNS info using GetNetworkParams() function from the Internet
834 * Protocol Helper (IP Helper) API. When located, this returns a pointer
835 * in *outptr to a newly allocated memory area holding a null-terminated
836 * string with a space or comma seperated list of DNS IP addresses.
838 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
840 * Returns 1 and sets *outptr when returning a dynamically allocated string.
842 * Implementation supports Windows 98 and newer.
844 * Note: Ancient PSDK required in order to build a W98 target.
846 static int get_DNS_NetworkParams(char **outptr)
848 FIXED_INFO *fi, *newfi;
849 struct ares_addr namesrvr;
851 IP_ADDR_STRING *ipAddr;
853 DWORD size = sizeof (*fi);
857 /* Verify run-time availability of GetNetworkParams() */
858 if (ares_fpGetNetworkParams == ZERO_NULL)
865 res = (*ares_fpGetNetworkParams) (fi, &size);
866 if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
869 newfi = realloc(fi, size);
874 res = (*ares_fpGetNetworkParams) (fi, &size);
875 if (res != ERROR_SUCCESS)
878 for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next)
880 txtaddr = &ipAddr->IpAddress.String[0];
882 /* Validate converting textual address to binary format. */
883 if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1)
885 if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) ||
886 (namesrvr.addrV4.S_un.S_addr == INADDR_NONE))
889 else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1)
891 if (memcmp(&namesrvr.addrV6, &ares_in6addr_any,
892 sizeof(namesrvr.addrV6)) == 0)
898 commajoin(outptr, txtaddr);
915 * get_DNS_AdaptersAddresses()
917 * Locates DNS info using GetAdaptersAddresses() function from the Internet
918 * Protocol Helper (IP Helper) API. When located, this returns a pointer
919 * in *outptr to a newly allocated memory area holding a null-terminated
920 * string with a space or comma seperated list of DNS IP addresses.
922 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
924 * Returns 1 and sets *outptr when returning a dynamically allocated string.
926 * Implementation supports Windows XP and newer.
928 #define IPAA_INITIAL_BUF_SZ 15 * 1024
929 #define IPAA_MAX_TRIES 3
930 static int get_DNS_AdaptersAddresses(char **outptr)
932 IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
933 IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry;
934 ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ;
935 ULONG Bufsz = IPAA_INITIAL_BUF_SZ;
937 int trying = IPAA_MAX_TRIES;
942 struct sockaddr_in *sa4;
943 struct sockaddr_in6 *sa6;
946 char txtaddr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
950 /* Verify run-time availability of GetAdaptersAddresses() */
951 if (ares_fpGetAdaptersAddresses == ZERO_NULL)
954 ipaa = malloc(Bufsz);
958 /* Usually this call suceeds with initial buffer size */
959 res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
961 if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
964 while ((res == ERROR_BUFFER_OVERFLOW) && (--trying))
966 if (Bufsz < ReqBufsz)
968 newipaa = realloc(ipaa, ReqBufsz);
974 res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
976 if (res == ERROR_SUCCESS)
979 if (res != ERROR_SUCCESS)
982 for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next)
984 for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress;
986 ipaDNSAddr = ipaDNSAddr->Next)
988 namesrvr.sa = ipaDNSAddr->Address.lpSockaddr;
990 if (namesrvr.sa->sa_family == AF_INET)
992 if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) ||
993 (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE))
995 if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
996 txtaddr, sizeof(txtaddr)))
999 else if (namesrvr.sa->sa_family == AF_INET6)
1001 if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any,
1002 sizeof(namesrvr.sa6->sin6_addr)) == 0)
1004 if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr,
1005 txtaddr, sizeof(txtaddr)))
1011 commajoin(outptr, txtaddr);
1031 * Locates DNS info from Windows employing most suitable methods available at
1032 * run-time no matter which Windows version it is. When located, this returns
1033 * a pointer in *outptr to a newly allocated memory area holding a string with
1034 * a space or comma seperated list of DNS IP addresses, null-terminated.
1036 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
1038 * Returns 1 and sets *outptr when returning a dynamically allocated string.
1040 * Implementation supports Windows 95 and newer.
1042 static int get_DNS_Windows(char **outptr)
1044 /* Try using IP helper API GetAdaptersAddresses() */
1045 if (get_DNS_AdaptersAddresses(outptr))
1048 /* Try using IP helper API GetNetworkParams() */
1049 if (get_DNS_NetworkParams(outptr))
1052 /* Fall-back to registry information */
1053 return get_DNS_Registry(outptr);
1057 static int init_by_resolv_conf(ares_channel channel)
1059 #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32)
1062 int status = -1, nservers = 0, nsort = 0;
1063 struct server_state *servers = NULL;
1064 struct apattern *sortlist = NULL;
1068 if (channel->nservers > -1) /* don't override ARES_OPT_SERVER */
1069 return ARES_SUCCESS;
1071 if (get_DNS_Windows(&line))
1073 status = config_nameserver(&servers, &nservers, line);
1077 if (status == ARES_SUCCESS)
1080 /* Catch the case when all the above checks fail (which happens when there
1081 is no network card or the cable is unplugged) */
1082 status = ARES_EFILE;
1084 #elif defined(__riscos__)
1086 /* Under RISC OS, name servers are listed in the
1087 system variable Inet$Resolvers, space separated. */
1089 line = getenv("Inet$Resolvers");
1092 char *resolvers = strdup(line), *pos, *space;
1099 space = strchr(pos, ' ');
1102 status = config_nameserver(&servers, &nservers, pos);
1103 if (status != ARES_SUCCESS)
1108 if (status == ARES_SUCCESS)
1114 #elif defined(WATT32)
1118 for (i = 0; def_nameservers[i]; i++)
1121 return ARES_SUCCESS; /* use localhost DNS server */
1124 servers = calloc(i, sizeof(struct server_state));
1128 for (i = 0; def_nameservers[i]; i++)
1130 servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]);
1131 servers[i].addr.family = AF_INET;
1135 #elif defined(ANDROID) || defined(__ANDROID__)
1137 char propname[PROP_NAME_MAX];
1138 char propvalue[PROP_VALUE_MAX]="";
1140 for (i = 1; i <= MAX_DNS_PROPERTIES; i++) {
1141 snprintf(propname, sizeof(propname), "%s%u", DNS_PROP_NAME_PREFIX, i);
1142 if (__system_property_get(propname, propvalue) < 1) {
1146 status = config_nameserver(&servers, &nservers, propvalue);
1147 if (status != ARES_SUCCESS)
1158 /* Don't read resolv.conf and friends if we don't have to */
1159 if (ARES_CONFIG_CHECK(channel))
1160 return ARES_SUCCESS;
1162 fp = fopen(PATH_RESOLV_CONF, "r");
1164 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
1166 if ((p = try_config(line, "domain", ';')))
1167 status = config_domain(channel, p);
1168 else if ((p = try_config(line, "lookup", ';')) && !channel->lookups)
1169 status = config_lookup(channel, p, "bind", "file");
1170 else if ((p = try_config(line, "search", ';')))
1171 status = set_search(channel, p);
1172 else if ((p = try_config(line, "nameserver", ';')) &&
1173 channel->nservers == -1)
1174 status = config_nameserver(&servers, &nservers, p);
1175 else if ((p = try_config(line, "sortlist", ';')) &&
1176 channel->nsort == -1)
1177 status = config_sortlist(&sortlist, &nsort, p);
1178 else if ((p = try_config(line, "options", ';')))
1179 status = set_options(channel, p);
1181 status = ARES_SUCCESS;
1182 if (status != ARES_SUCCESS)
1195 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1196 error, strerror(error)));
1197 DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
1198 status = ARES_EFILE;
1202 if ((status == ARES_EOF) && (!channel->lookups)) {
1203 /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
1204 fp = fopen("/etc/nsswitch.conf", "r");
1206 while ((status = ares__read_line(fp, &line, &linesize)) ==
1209 if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups)
1211 (void)config_lookup(channel, p, "dns", "files");
1223 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1224 error, strerror(error)));
1225 DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1226 "/etc/nsswitch.conf"));
1227 status = ARES_EFILE;
1232 if ((status == ARES_EOF) && (!channel->lookups)) {
1233 /* Linux / GNU libc 2.x and possibly others have host.conf */
1234 fp = fopen("/etc/host.conf", "r");
1236 while ((status = ares__read_line(fp, &line, &linesize)) ==
1239 if ((p = try_config(line, "order", '\0')) && !channel->lookups)
1241 (void)config_lookup(channel, p, "bind", "hosts");
1253 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1254 error, strerror(error)));
1255 DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1257 status = ARES_EFILE;
1262 if ((status == ARES_EOF) && (!channel->lookups)) {
1263 /* Tru64 uses /etc/svc.conf */
1264 fp = fopen("/etc/svc.conf", "r");
1266 while ((status = ares__read_line(fp, &line, &linesize)) ==
1269 if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups)
1271 (void)config_lookup(channel, p, "bind", "local");
1283 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1284 error, strerror(error)));
1285 DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
1286 status = ARES_EFILE;
1297 /* Handle errors. */
1298 if (status != ARES_EOF)
1300 if (servers != NULL)
1302 if (sortlist != NULL)
1307 /* If we got any name server entries, fill them in. */
1310 channel->servers = servers;
1311 channel->nservers = nservers;
1314 /* If we got any sortlist entries, fill them in. */
1317 channel->sortlist = sortlist;
1318 channel->nsort = nsort;
1321 return ARES_SUCCESS;
1324 static int init_by_defaults(ares_channel channel)
1326 char *hostname = NULL;
1327 int rc = ARES_SUCCESS;
1328 #ifdef HAVE_GETHOSTNAME
1332 if (channel->flags == -1)
1334 if (channel->timeout == -1)
1335 channel->timeout = DEFAULT_TIMEOUT;
1336 if (channel->tries == -1)
1337 channel->tries = DEFAULT_TRIES;
1338 if (channel->ndots == -1)
1340 if (channel->rotate == -1)
1341 channel->rotate = 0;
1342 if (channel->udp_port == -1)
1343 channel->udp_port = htons(NAMESERVER_PORT);
1344 if (channel->tcp_port == -1)
1345 channel->tcp_port = htons(NAMESERVER_PORT);
1347 if (channel->ednspsz == -1)
1348 channel->ednspsz = EDNSPACKETSZ;
1350 if (channel->nservers == -1) {
1351 /* If nobody specified servers, try a local named. */
1352 channel->servers = malloc(sizeof(struct server_state));
1353 if (!channel->servers) {
1357 channel->servers[0].addr.family = AF_INET;
1358 channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK);
1359 channel->nservers = 1;
1362 #if defined(USE_WINSOCK)
1363 #define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT)
1364 #elif defined(ENAMETOOLONG)
1365 #define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \
1366 (SOCKERRNO == EINVAL))
1368 #define toolong(x) (x == -1) && (SOCKERRNO == EINVAL)
1371 if (channel->ndomains == -1) {
1372 /* Derive a default domain search list from the kernel hostname,
1373 * or set it to empty if the hostname isn't helpful.
1375 #ifndef HAVE_GETHOSTNAME
1376 channel->ndomains = 0; /* default to none */
1378 GETHOSTNAME_TYPE_ARG2 lenv = 64;
1381 channel->ndomains = 0; /* default to none */
1383 hostname = malloc(len);
1390 res = gethostname(hostname, lenv);
1396 p = realloc(hostname, len);
1411 dot = strchr(hostname, '.');
1413 /* a dot was found */
1414 channel->domains = malloc(sizeof(char *));
1415 if (!channel->domains) {
1419 channel->domains[0] = strdup(dot + 1);
1420 if (!channel->domains[0]) {
1424 channel->ndomains = 1;
1429 if (channel->nsort == -1) {
1430 channel->sortlist = NULL;
1434 if (!channel->lookups) {
1435 channel->lookups = strdup("fb");
1436 if (!channel->lookups)
1442 if(channel->servers) {
1443 free(channel->servers);
1444 channel->servers = NULL;
1447 if(channel->domains && channel->domains[0])
1448 free(channel->domains[0]);
1449 if(channel->domains) {
1450 free(channel->domains);
1451 channel->domains = NULL;
1454 if(channel->lookups) {
1455 free(channel->lookups);
1456 channel->lookups = NULL;
1466 #if !defined(WIN32) && !defined(WATT32) && \
1467 !defined(ANDROID) && !defined(__ANDROID__)
1468 static int config_domain(ares_channel channel, char *str)
1472 /* Set a single search domain. */
1474 while (*q && !ISSPACE(*q))
1477 return set_search(channel, str);
1480 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
1481 defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
1482 /* workaround icc 9.1 optimizer issue */
1483 # define vqualifier volatile
1488 static int config_lookup(ares_channel channel, const char *str,
1489 const char *bindch, const char *filech)
1491 char lookups[3], *l;
1492 const char *vqualifier p;
1494 /* Set the lookup order. Only the first letter of each work
1495 * is relevant, and it has to be "b" for DNS or "f" for the
1496 * host file. Ignore everything else.
1502 if ((*p == *bindch || *p == *filech) && l < lookups + 2) {
1503 if (*p == *bindch) *l++ = 'b';
1506 while (*p && !ISSPACE(*p) && (*p != ','))
1508 while (*p && (ISSPACE(*p) || (*p == ',')))
1512 channel->lookups = strdup(lookups);
1513 return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
1515 #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */
1518 static int config_nameserver(struct server_state **servers, int *nservers,
1521 struct ares_addr host;
1522 struct server_state *newserv;
1524 /* On Windows, there may be more than one nameserver specified in the same
1525 * registry key, so we parse input as a space or comma seperated list.
1529 /* Skip whitespace and commas. */
1530 while (*p && (ISSPACE(*p) || (*p == ',')))
1533 /* No more input, done. */
1536 /* Pointer to start of IPv4 or IPv6 address part. */
1539 /* Advance past this address. */
1540 while (*p && !ISSPACE(*p) && (*p != ','))
1543 /* Null terminate this address. */
1546 /* Reached end of input, done when this address is processed. */
1549 /* Convert textual address to binary format. */
1550 if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
1551 host.family = AF_INET;
1552 else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1)
1553 host.family = AF_INET6;
1557 /* Resize servers state array. */
1558 newserv = realloc(*servers, (*nservers + 1) *
1559 sizeof(struct server_state));
1563 /* Store address data. */
1564 newserv[*nservers].addr.family = host.family;
1565 if (host.family == AF_INET)
1566 memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
1567 sizeof(host.addrV4));
1569 memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
1570 sizeof(host.addrV6));
1572 /* Update arguments. */
1577 return ARES_SUCCESS;
1580 #if !defined(WIN32) && !defined(ANDROID) && !defined(__ANDROID__)
1581 static int config_sortlist(struct apattern **sortlist, int *nsort,
1584 struct apattern pat;
1587 /* Add sortlist entries. */
1588 while (*str && *str != ';')
1591 char ipbuf[16], ipbufpfx[32];
1592 /* Find just the IP */
1594 while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
1596 memcpy(ipbuf, str, q-str);
1597 ipbuf[q-str] = '\0';
1598 /* Find the prefix */
1601 const char *str2 = q+1;
1602 while (*q && *q != ';' && !ISSPACE(*q))
1604 memcpy(ipbufpfx, str, q-str);
1605 ipbufpfx[q-str] = '\0';
1610 /* Lets see if it is CIDR */
1611 /* First we'll try IPv6 */
1612 if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf,
1614 sizeof(pat.addrV6))) > 0)
1616 pat.type = PATTERN_CIDR;
1617 pat.mask.bits = (unsigned short)bits;
1618 pat.family = AF_INET6;
1619 if (!sortlist_alloc(sortlist, nsort, &pat))
1622 else if (ipbufpfx[0] &&
1623 (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4,
1624 sizeof(pat.addrV4))) > 0)
1626 pat.type = PATTERN_CIDR;
1627 pat.mask.bits = (unsigned short)bits;
1628 pat.family = AF_INET;
1629 if (!sortlist_alloc(sortlist, nsort, &pat))
1632 /* See if it is just a regular IP */
1633 else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0)
1637 memcpy(ipbuf, str, q-str);
1638 ipbuf[q-str] = '\0';
1639 if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0)
1644 pat.family = AF_INET;
1645 pat.type = PATTERN_MASK;
1646 if (!sortlist_alloc(sortlist, nsort, &pat))
1651 while (*q && *q != ';' && !ISSPACE(*q))
1655 while (ISSPACE(*str))
1659 return ARES_SUCCESS;
1661 #endif /* !WIN32 & !ANDROID & !__ANDROID__ */
1662 #endif /* !WATT32 */
1664 static int set_search(ares_channel channel, const char *str)
1669 if(channel->ndomains != -1) {
1670 /* if we already have some domains present, free them first */
1671 for(n=0; n < channel->ndomains; n++)
1672 free(channel->domains[n]);
1673 free(channel->domains);
1674 channel->domains = NULL;
1675 channel->ndomains = -1;
1678 /* Count the domains given. */
1683 while (*p && !ISSPACE(*p))
1692 channel->ndomains = 0;
1693 return ARES_SUCCESS;
1696 channel->domains = malloc(n * sizeof(char *));
1697 if (!channel->domains)
1700 /* Now copy the domains. */
1705 channel->ndomains = n;
1707 while (*q && !ISSPACE(*q))
1709 channel->domains[n] = malloc(q - p + 1);
1710 if (!channel->domains[n])
1712 memcpy(channel->domains[n], p, q - p);
1713 channel->domains[n][q - p] = 0;
1719 channel->ndomains = n;
1721 return ARES_SUCCESS;
1724 static int set_options(ares_channel channel, const char *str)
1726 const char *p, *q, *val;
1732 while (*q && !ISSPACE(*q))
1734 val = try_option(p, q, "ndots:");
1735 if (val && channel->ndots == -1)
1736 channel->ndots = aresx_sltosi(strtol(val, NULL, 10));
1737 val = try_option(p, q, "retrans:");
1738 if (val && channel->timeout == -1)
1739 channel->timeout = aresx_sltosi(strtol(val, NULL, 10));
1740 val = try_option(p, q, "retry:");
1741 if (val && channel->tries == -1)
1742 channel->tries = aresx_sltosi(strtol(val, NULL, 10));
1743 val = try_option(p, q, "rotate");
1744 if (val && channel->rotate == -1)
1745 channel->rotate = 1;
1751 return ARES_SUCCESS;
1754 static const char *try_option(const char *p, const char *q, const char *opt)
1756 size_t len = strlen(opt);
1757 return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL;
1760 #if !defined(WIN32) && !defined(WATT32) && \
1761 !defined(ANDROID) && !defined(__ANDROID__)
1762 static char *try_config(char *s, const char *opt, char scc)
1769 /* no line or no option */
1772 /* Hash '#' character is always used as primary comment char, additionally
1773 a not-NUL secondary comment char will be considered when specified. */
1775 /* trim line comment */
1778 while (*p && (*p != '#') && (*p != scc))
1781 while (*p && (*p != '#'))
1785 /* trim trailing whitespace */
1787 while ((q >= s) && ISSPACE(*q))
1791 /* skip leading whitespace */
1793 while (*p && ISSPACE(*p))
1800 if ((len = strlen(opt)) == 0)
1804 if (strncmp(p, opt, len) != 0)
1805 /* line and option do not match */
1808 /* skip over given option name */
1812 /* no option value */
1815 if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p))
1816 /* whitespace between option name and value is mandatory
1817 for given option names which do not end with ':' or '=' */
1820 /* skip over whitespace */
1821 while (*p && ISSPACE(*p))
1825 /* no option value */
1828 /* return pointer to option value */
1832 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
1833 struct apattern *pat)
1835 struct apattern *newsort;
1836 newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
1839 newsort[*nsort] = *pat;
1840 *sortlist = newsort;
1845 static int ip_addr(const char *ipbuf, ssize_t len, struct in_addr *addr)
1848 /* Four octets and three periods yields at most 15 characters. */
1852 addr->s_addr = inet_addr(ipbuf);
1853 if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
1858 static void natural_mask(struct apattern *pat)
1860 struct in_addr addr;
1862 /* Store a host-byte-order copy of pat in a struct in_addr. Icky,
1865 addr.s_addr = ntohl(pat->addrV4.s_addr);
1867 /* This is out of date in the CIDR world, but some people might
1870 if (IN_CLASSA(addr.s_addr))
1871 pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET);
1872 else if (IN_CLASSB(addr.s_addr))
1873 pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET);
1875 pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET);
1877 #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */
1879 /* initialize an rc4 key. If possible a cryptographically secure random key
1880 is generated using a suitable function (for example win32's RtlGenRandom as
1882 http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
1883 otherwise the code defaults to cross-platform albeit less secure mechanism
1886 static void randomize_key(unsigned char* key,int key_data_len)
1892 if (ares_fpSystemFunction036)
1894 res = (*ares_fpSystemFunction036) (key, key_data_len);
1900 FILE *f = fopen(RANDOM_FILE, "rb");
1902 counter = aresx_uztosi(fread(key, 1, key_data_len, f));
1909 for (;counter<key_data_len;counter++)
1910 key[counter]=(unsigned char)(rand() % 256);
1914 static int init_id_key(rc4_key* key,int key_data_len)
1916 unsigned char index1;
1917 unsigned char index2;
1918 unsigned char* state;
1920 unsigned char *key_data_ptr = 0;
1922 key_data_ptr = calloc(1,key_data_len);
1926 state = &key->state[0];
1927 for(counter = 0; counter < 256; counter++)
1928 /* unnecessary AND but it keeps some compilers happier */
1929 state[counter] = (unsigned char)(counter & 0xff);
1930 randomize_key(key->state,key_data_len);
1935 for(counter = 0; counter < 256; counter++)
1937 index2 = (unsigned char)((key_data_ptr[index1] + state[counter] +
1939 ARES_SWAP_BYTE(&state[counter], &state[index2]);
1941 index1 = (unsigned char)((index1 + 1) % key_data_len);
1944 return ARES_SUCCESS;
1947 unsigned short ares__generate_new_id(rc4_key* key)
1950 ares__rc4(key, (unsigned char *)&r, sizeof(r));
1954 void ares_set_local_ip4(ares_channel channel, unsigned int local_ip)
1956 channel->local_ip4 = local_ip;
1959 /* local_ip6 should be 16 bytes in length */
1960 void ares_set_local_ip6(ares_channel channel,
1961 const unsigned char* local_ip6)
1963 memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
1966 /* local_dev_name should be null terminated. */
1967 void ares_set_local_dev(ares_channel channel,
1968 const char* local_dev_name)
1970 strncpy(channel->local_dev_name, local_dev_name,
1971 sizeof(channel->local_dev_name));
1972 channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
1976 void ares_set_socket_callback(ares_channel channel,
1977 ares_sock_create_callback cb,
1980 channel->sock_create_cb = cb;
1981 channel->sock_create_cb_data = data;
1984 void ares__init_servers_state(ares_channel channel)
1986 struct server_state *server;
1989 for (i = 0; i < channel->nservers; i++)
1991 server = &channel->servers[i];
1992 server->udp_socket = ARES_SOCKET_BAD;
1993 server->tcp_socket = ARES_SOCKET_BAD;
1994 server->tcp_connection_generation = ++channel->tcp_connection_generation;
1995 server->tcp_lenbuf_pos = 0;
1996 server->tcp_buffer_pos = 0;
1997 server->tcp_buffer = NULL;
1998 server->tcp_length = 0;
1999 server->qhead = NULL;
2000 server->qtail = NULL;
2001 ares__init_list_head(&server->queries_to_server);
2002 server->channel = channel;
2003 server->is_broken = 0;