• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3  * Copyright (C) 2007-2013 by Daniel Stenberg
4  *
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.
16  */
17 
18 #include "ares_setup.h"
19 
20 #ifdef HAVE_SYS_PARAM_H
21 #include <sys/param.h>
22 #endif
23 
24 #ifdef HAVE_NETINET_IN_H
25 #include <netinet/in.h>
26 #endif
27 
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
31 
32 #ifdef HAVE_ARPA_INET_H
33 #include <arpa/inet.h>
34 #endif
35 
36 #ifdef HAVE_ARPA_NAMESER_H
37 #  include <arpa/nameser.h>
38 #else
39 #  include "nameser.h"
40 #endif
41 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
42 #  include <arpa/nameser_compat.h>
43 #endif
44 
45 #if defined(ANDROID) || defined(__ANDROID__)
46 #include <sys/system_properties.h>
47 #include "ares_android.h"
48 /* From the Bionic sources */
49 #define DNS_PROP_NAME_PREFIX  "net.dns"
50 #define MAX_DNS_PROPERTIES    8
51 #endif
52 
53 #if defined(CARES_USE_LIBRESOLV)
54 #include <resolv.h>
55 #endif
56 
57 #include "ares.h"
58 #include "ares_inet_net_pton.h"
59 #include "ares_library_init.h"
60 #include "ares_nowarn.h"
61 #include "ares_platform.h"
62 #include "ares_private.h"
63 
64 #ifdef WATT32
65 #undef WIN32  /* Redefined in MingW/MSVC headers */
66 #endif
67 
68 static int init_by_options(ares_channel channel,
69                            const struct ares_options *options,
70                            int optmask);
71 static int init_by_environment(ares_channel channel);
72 static int init_by_resolv_conf(ares_channel channel);
73 static int init_by_defaults(ares_channel channel);
74 
75 #ifndef WATT32
76 static int config_nameserver(struct server_state **servers, int *nservers,
77                              char *str);
78 #endif
79 static int set_search(ares_channel channel, const char *str);
80 static int set_options(ares_channel channel, const char *str);
81 static const char *try_option(const char *p, const char *q, const char *opt);
82 static int init_id_key(rc4_key* key,int key_data_len);
83 
84 static int config_sortlist(struct apattern **sortlist, int *nsort,
85                            const char *str);
86 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
87                           struct apattern *pat);
88 static int ip_addr(const char *s, ares_ssize_t len, struct in_addr *addr);
89 static void natural_mask(struct apattern *pat);
90 #if !defined(WIN32) && !defined(WATT32) && \
91     !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
92 static int config_domain(ares_channel channel, char *str);
93 static int config_lookup(ares_channel channel, const char *str,
94                          const char *bindch, const char *altbindch,
95                          const char *filech);
96 static char *try_config(char *s, const char *opt, char scc);
97 #endif
98 
99 #define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
100                              x->nservers > -1 && \
101                              x->ndomains > -1 && \
102                              x->ndots > -1 && x->timeout > -1 && \
103                              x->tries > -1)
104 
ares_init(ares_channel * channelptr)105 int ares_init(ares_channel *channelptr)
106 {
107   return ares_init_options(channelptr, NULL, 0);
108 }
109 
ares_init_options(ares_channel * channelptr,struct ares_options * options,int optmask)110 int ares_init_options(ares_channel *channelptr, struct ares_options *options,
111                       int optmask)
112 {
113   ares_channel channel;
114   int i;
115   int status = ARES_SUCCESS;
116   struct timeval now;
117 
118 #ifdef CURLDEBUG
119   const char *env = getenv("CARES_MEMDEBUG");
120 
121   if (env)
122     curl_memdebug(env);
123   env = getenv("CARES_MEMLIMIT");
124   if (env) {
125     char *endptr;
126     long num = strtol(env, &endptr, 10);
127     if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
128       curl_memlimit(num);
129   }
130 #endif
131 
132   if (ares_library_initialized() != ARES_SUCCESS)
133     return ARES_ENOTINITIALIZED;  /* LCOV_EXCL_LINE: n/a on non-WinSock */
134 
135   channel = ares_malloc(sizeof(struct ares_channeldata));
136   if (!channel) {
137     *channelptr = NULL;
138     return ARES_ENOMEM;
139   }
140 
141   now = ares__tvnow();
142 
143   /* Set everything to distinguished values so we know they haven't
144    * been set yet.
145    */
146   channel->flags = -1;
147   channel->timeout = -1;
148   channel->tries = -1;
149   channel->ndots = -1;
150   channel->rotate = -1;
151   channel->udp_port = -1;
152   channel->tcp_port = -1;
153   channel->ednspsz = -1;
154   channel->socket_send_buffer_size = -1;
155   channel->socket_receive_buffer_size = -1;
156   channel->nservers = -1;
157   channel->ndomains = -1;
158   channel->nsort = -1;
159   channel->tcp_connection_generation = 0;
160   channel->lookups = NULL;
161   channel->domains = NULL;
162   channel->sortlist = NULL;
163   channel->servers = NULL;
164   channel->sock_state_cb = NULL;
165   channel->sock_state_cb_data = NULL;
166   channel->sock_create_cb = NULL;
167   channel->sock_create_cb_data = NULL;
168   channel->sock_config_cb = NULL;
169   channel->sock_config_cb_data = NULL;
170   channel->sock_funcs = NULL;
171   channel->sock_func_cb_data = NULL;
172   channel->resolvconf_path = NULL;
173 
174   channel->last_server = 0;
175   channel->last_timeout_processed = (time_t)now.tv_sec;
176 
177   memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name));
178   channel->local_ip4 = 0;
179   memset(&channel->local_ip6, 0, sizeof(channel->local_ip6));
180 
181   /* Initialize our lists of queries */
182   ares__init_list_head(&(channel->all_queries));
183   for (i = 0; i < ARES_QID_TABLE_SIZE; i++)
184     {
185       ares__init_list_head(&(channel->queries_by_qid[i]));
186     }
187   for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++)
188     {
189       ares__init_list_head(&(channel->queries_by_timeout[i]));
190     }
191 
192   /* Initialize configuration by each of the four sources, from highest
193    * precedence to lowest.
194    */
195 
196   status = init_by_options(channel, options, optmask);
197   if (status != ARES_SUCCESS) {
198     DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
199                    ares_strerror(status)));
200     /* If we fail to apply user-specified options, fail the whole init process */
201     goto done;
202   }
203   status = init_by_environment(channel);
204   if (status != ARES_SUCCESS)
205     DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
206                    ares_strerror(status)));
207   if (status == ARES_SUCCESS) {
208     status = init_by_resolv_conf(channel);
209     if (status != ARES_SUCCESS)
210       DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n",
211                      ares_strerror(status)));
212   }
213 
214   /*
215    * No matter what failed or succeeded, seed defaults to provide
216    * useful behavior for things that we missed.
217    */
218   status = init_by_defaults(channel);
219   if (status != ARES_SUCCESS)
220     DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
221                    ares_strerror(status)));
222 
223   /* Generate random key */
224 
225   if (status == ARES_SUCCESS) {
226     status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
227     if (status == ARES_SUCCESS)
228       channel->next_id = ares__generate_new_id(&channel->id_key);
229     else
230       DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
231                      ares_strerror(status)));
232   }
233 
234 done:
235   if (status != ARES_SUCCESS)
236     {
237       /* Something failed; clean up memory we may have allocated. */
238       if (channel->servers)
239         ares_free(channel->servers);
240       if (channel->ndomains != -1)
241         ares_strsplit_free(channel->domains, channel->ndomains);
242       if (channel->sortlist)
243         ares_free(channel->sortlist);
244       if(channel->lookups)
245         ares_free(channel->lookups);
246       if(channel->resolvconf_path)
247         ares_free(channel->resolvconf_path);
248       ares_free(channel);
249       return status;
250     }
251 
252   /* Trim to one server if ARES_FLAG_PRIMARY is set. */
253   if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
254     channel->nservers = 1;
255 
256   ares__init_servers_state(channel);
257 
258   *channelptr = channel;
259   return ARES_SUCCESS;
260 }
261 
262 /* ares_dup() duplicates a channel handle with all its options and returns a
263    new channel handle */
ares_dup(ares_channel * dest,ares_channel src)264 int ares_dup(ares_channel *dest, ares_channel src)
265 {
266   struct ares_options opts;
267   struct ares_addr_port_node *servers;
268   int non_v4_default_port = 0;
269   int i, rc;
270   int optmask;
271 
272   *dest = NULL; /* in case of failure return NULL explicitly */
273 
274   /* First get the options supported by the old ares_save_options() function,
275      which is most of them */
276   rc = ares_save_options(src, &opts, &optmask);
277   if(rc)
278   {
279     ares_destroy_options(&opts);
280     return rc;
281   }
282 
283   /* Then create the new channel with those options */
284   rc = ares_init_options(dest, &opts, optmask);
285 
286   /* destroy the options copy to not leak any memory */
287   ares_destroy_options(&opts);
288 
289   if(rc)
290     return rc;
291 
292   /* Now clone the options that ares_save_options() doesn't support. */
293   (*dest)->sock_create_cb      = src->sock_create_cb;
294   (*dest)->sock_create_cb_data = src->sock_create_cb_data;
295   (*dest)->sock_config_cb      = src->sock_config_cb;
296   (*dest)->sock_config_cb_data = src->sock_config_cb_data;
297   (*dest)->sock_funcs          = src->sock_funcs;
298   (*dest)->sock_func_cb_data   = src->sock_func_cb_data;
299 
300   strncpy((*dest)->local_dev_name, src->local_dev_name,
301           sizeof((*dest)->local_dev_name));
302   (*dest)->local_ip4 = src->local_ip4;
303   memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
304 
305   /* Full name server cloning required if there is a non-IPv4, or non-default port, nameserver */
306   for (i = 0; i < src->nservers; i++)
307     {
308       if ((src->servers[i].addr.family != AF_INET) ||
309           (src->servers[i].addr.udp_port != 0) ||
310           (src->servers[i].addr.tcp_port != 0)) {
311         non_v4_default_port++;
312         break;
313       }
314     }
315   if (non_v4_default_port) {
316     rc = ares_get_servers_ports(src, &servers);
317     if (rc != ARES_SUCCESS) {
318       ares_destroy(*dest);
319       *dest = NULL;
320       return rc;
321     }
322     rc = ares_set_servers_ports(*dest, servers);
323     ares_free_data(servers);
324     if (rc != ARES_SUCCESS) {
325       ares_destroy(*dest);
326       *dest = NULL;
327       return rc;
328     }
329   }
330 
331   return ARES_SUCCESS; /* everything went fine */
332 }
333 
334 /* Save options from initialized channel */
ares_save_options(ares_channel channel,struct ares_options * options,int * optmask)335 int ares_save_options(ares_channel channel, struct ares_options *options,
336                       int *optmask)
337 {
338   int i, j;
339   int ipv4_nservers = 0;
340 
341   /* Zero everything out */
342   memset(options, 0, sizeof(struct ares_options));
343 
344   if (!ARES_CONFIG_CHECK(channel))
345     return ARES_ENODATA;
346 
347   /* Traditionally the optmask wasn't saved in the channel struct so it was
348      recreated here. ROTATE is the first option that has no struct field of
349      its own in the public config struct */
350   (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS|
351                 ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
352                 ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
353                 ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS);
354   (*optmask) |= (channel->rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE);
355 
356   if (channel->resolvconf_path)
357     (*optmask) |= ARES_OPT_RESOLVCONF;
358 
359   /* Copy easy stuff */
360   options->flags   = channel->flags;
361 
362   /* We return full millisecond resolution but that's only because we don't
363      set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */
364   options->timeout = channel->timeout;
365   options->tries   = channel->tries;
366   options->ndots   = channel->ndots;
367   options->udp_port = ntohs(aresx_sitous(channel->udp_port));
368   options->tcp_port = ntohs(aresx_sitous(channel->tcp_port));
369   options->sock_state_cb     = channel->sock_state_cb;
370   options->sock_state_cb_data = channel->sock_state_cb_data;
371 
372   /* Copy IPv4 servers that use the default port */
373   if (channel->nservers) {
374     for (i = 0; i < channel->nservers; i++)
375     {
376       if ((channel->servers[i].addr.family == AF_INET) &&
377           (channel->servers[i].addr.udp_port == 0) &&
378           (channel->servers[i].addr.tcp_port == 0))
379         ipv4_nservers++;
380     }
381     if (ipv4_nservers) {
382       options->servers = ares_malloc(ipv4_nservers * sizeof(struct in_addr));
383       if (!options->servers)
384         return ARES_ENOMEM;
385       for (i = j = 0; i < channel->nservers; i++)
386       {
387         if ((channel->servers[i].addr.family == AF_INET) &&
388             (channel->servers[i].addr.udp_port == 0) &&
389             (channel->servers[i].addr.tcp_port == 0))
390           memcpy(&options->servers[j++],
391                  &channel->servers[i].addr.addrV4,
392                  sizeof(channel->servers[i].addr.addrV4));
393       }
394     }
395   }
396   options->nservers = ipv4_nservers;
397 
398   /* copy domains */
399   if (channel->ndomains) {
400     options->domains = ares_malloc(channel->ndomains * sizeof(char *));
401     if (!options->domains)
402       return ARES_ENOMEM;
403 
404     for (i = 0; i < channel->ndomains; i++)
405     {
406       options->ndomains = i;
407       options->domains[i] = ares_strdup(channel->domains[i]);
408       if (!options->domains[i])
409         return ARES_ENOMEM;
410     }
411   }
412   options->ndomains = channel->ndomains;
413 
414   /* copy lookups */
415   if (channel->lookups) {
416     options->lookups = ares_strdup(channel->lookups);
417     if (!options->lookups && channel->lookups)
418       return ARES_ENOMEM;
419   }
420 
421   /* copy sortlist */
422   if (channel->nsort) {
423     options->sortlist = ares_malloc(channel->nsort * sizeof(struct apattern));
424     if (!options->sortlist)
425       return ARES_ENOMEM;
426     for (i = 0; i < channel->nsort; i++)
427       options->sortlist[i] = channel->sortlist[i];
428   }
429   options->nsort = channel->nsort;
430 
431   /* copy path for resolv.conf file */
432   if (channel->resolvconf_path) {
433     options->resolvconf_path = ares_strdup(channel->resolvconf_path);
434     if (!options->resolvconf_path)
435       return ARES_ENOMEM;
436   }
437 
438   return ARES_SUCCESS;
439 }
440 
init_by_options(ares_channel channel,const struct ares_options * options,int optmask)441 static int init_by_options(ares_channel channel,
442                            const struct ares_options *options,
443                            int optmask)
444 {
445   int i;
446 
447   /* Easy stuff. */
448   if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
449     channel->flags = options->flags;
450   if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1)
451     channel->timeout = options->timeout;
452   else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
453     channel->timeout = options->timeout * 1000;
454   if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
455     channel->tries = options->tries;
456   if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
457     channel->ndots = options->ndots;
458   if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1)
459     channel->rotate = 1;
460   if ((optmask & ARES_OPT_NOROTATE) && channel->rotate == -1)
461     channel->rotate = 0;
462   if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
463     channel->udp_port = htons(options->udp_port);
464   if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
465     channel->tcp_port = htons(options->tcp_port);
466   if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL)
467     {
468       channel->sock_state_cb = options->sock_state_cb;
469       channel->sock_state_cb_data = options->sock_state_cb_data;
470     }
471   if ((optmask & ARES_OPT_SOCK_SNDBUF)
472       && channel->socket_send_buffer_size == -1)
473     channel->socket_send_buffer_size = options->socket_send_buffer_size;
474   if ((optmask & ARES_OPT_SOCK_RCVBUF)
475       && channel->socket_receive_buffer_size == -1)
476     channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
477 
478   if ((optmask & ARES_OPT_EDNSPSZ) && channel->ednspsz == -1)
479     channel->ednspsz = options->ednspsz;
480 
481   /* Copy the IPv4 servers, if given. */
482   if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
483     {
484       /* Avoid zero size allocations at any cost */
485       if (options->nservers > 0)
486         {
487           channel->servers =
488             ares_malloc(options->nservers * sizeof(struct server_state));
489           if (!channel->servers)
490             return ARES_ENOMEM;
491           for (i = 0; i < options->nservers; i++)
492             {
493               channel->servers[i].addr.family = AF_INET;
494               channel->servers[i].addr.udp_port = 0;
495               channel->servers[i].addr.tcp_port = 0;
496               memcpy(&channel->servers[i].addr.addrV4,
497                      &options->servers[i],
498                      sizeof(channel->servers[i].addr.addrV4));
499             }
500         }
501       channel->nservers = options->nservers;
502     }
503 
504   /* Copy the domains, if given.  Keep channel->ndomains consistent so
505    * we can clean up in case of error.
506    */
507   if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
508     {
509       /* Avoid zero size allocations at any cost */
510       if (options->ndomains > 0)
511       {
512         channel->domains = ares_malloc(options->ndomains * sizeof(char *));
513         if (!channel->domains)
514           return ARES_ENOMEM;
515         for (i = 0; i < options->ndomains; i++)
516           {
517             channel->ndomains = i;
518             channel->domains[i] = ares_strdup(options->domains[i]);
519             if (!channel->domains[i])
520               return ARES_ENOMEM;
521           }
522       }
523       channel->ndomains = options->ndomains;
524     }
525 
526   /* Set lookups, if given. */
527   if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
528     {
529       channel->lookups = ares_strdup(options->lookups);
530       if (!channel->lookups)
531         return ARES_ENOMEM;
532     }
533 
534   /* copy sortlist */
535   if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1)) {
536     if (options->nsort > 0) {
537       channel->sortlist = ares_malloc(options->nsort * sizeof(struct apattern));
538       if (!channel->sortlist)
539         return ARES_ENOMEM;
540       for (i = 0; i < options->nsort; i++)
541         channel->sortlist[i] = options->sortlist[i];
542     }
543     channel->nsort = options->nsort;
544   }
545 
546   /* Set path for resolv.conf file, if given. */
547   if ((optmask & ARES_OPT_RESOLVCONF) && !channel->resolvconf_path)
548     {
549       channel->resolvconf_path = ares_strdup(options->resolvconf_path);
550       if (!channel->resolvconf_path && options->resolvconf_path)
551         return ARES_ENOMEM;
552     }
553 
554   channel->optmask = optmask;
555 
556   return ARES_SUCCESS;
557 }
558 
init_by_environment(ares_channel channel)559 static int init_by_environment(ares_channel channel)
560 {
561   const char *localdomain, *res_options;
562   int status;
563 
564   localdomain = getenv("LOCALDOMAIN");
565   if (localdomain && channel->ndomains == -1)
566     {
567       status = set_search(channel, localdomain);
568       if (status != ARES_SUCCESS)
569         return status;
570     }
571 
572   res_options = getenv("RES_OPTIONS");
573   if (res_options)
574     {
575       status = set_options(channel, res_options);
576       if (status != ARES_SUCCESS)
577         return status;  /* LCOV_EXCL_LINE: set_options() never fails */
578     }
579 
580   return ARES_SUCCESS;
581 }
582 
583 #ifdef WIN32
584 /*
585  * get_REG_SZ()
586  *
587  * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer
588  * to the name of the registry leaf key to be queried, fetch it's string
589  * value and return a pointer in *outptr to a newly allocated memory area
590  * holding it as a null-terminated string.
591  *
592  * Returns 0 and nullifies *outptr upon inability to return a string value.
593  *
594  * Returns 1 and sets *outptr when returning a dynamically allocated string.
595  *
596  * Supported on Windows NT 3.5 and newer.
597  */
get_REG_SZ(HKEY hKey,const char * leafKeyName,char ** outptr)598 static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
599 {
600   DWORD size = 0;
601   int   res;
602 
603   *outptr = NULL;
604 
605   /* Find out size of string stored in registry */
606   res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, NULL, &size);
607   if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
608     return 0;
609 
610   /* Allocate buffer of indicated size plus one given that string
611      might have been stored without null termination */
612   *outptr = ares_malloc(size+1);
613   if (!*outptr)
614     return 0;
615 
616   /* Get the value for real */
617   res = RegQueryValueExA(hKey, leafKeyName, 0, NULL,
618                         (unsigned char *)*outptr, &size);
619   if ((res != ERROR_SUCCESS) || (size == 1))
620   {
621     ares_free(*outptr);
622     *outptr = NULL;
623     return 0;
624   }
625 
626   /* Null terminate buffer allways */
627   *(*outptr + size) = '\0';
628 
629   return 1;
630 }
631 
632 /*
633  * get_REG_SZ_9X()
634  *
635  * Functionally identical to get_REG_SZ()
636  *
637  * Supported on Windows 95, 98 and ME.
638  */
get_REG_SZ_9X(HKEY hKey,const char * leafKeyName,char ** outptr)639 static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
640 {
641   DWORD dataType = 0;
642   DWORD size = 0;
643   int   res;
644 
645   *outptr = NULL;
646 
647   /* Find out size of string stored in registry */
648   res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, NULL, &size);
649   if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
650     return 0;
651 
652   /* Allocate buffer of indicated size plus one given that string
653      might have been stored without null termination */
654   *outptr = ares_malloc(size+1);
655   if (!*outptr)
656     return 0;
657 
658   /* Get the value for real */
659   res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType,
660                         (unsigned char *)*outptr, &size);
661   if ((res != ERROR_SUCCESS) || (size == 1))
662   {
663     ares_free(*outptr);
664     *outptr = NULL;
665     return 0;
666   }
667 
668   /* Null terminate buffer allways */
669   *(*outptr + size) = '\0';
670 
671   return 1;
672 }
673 
674 /*
675  * get_enum_REG_SZ()
676  *
677  * Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName'
678  * pointer to the name of the registry leaf key to be queried, parent key
679  * is enumerated searching in child keys for given leaf key name and its
680  * associated string value. When located, this returns a pointer in *outptr
681  * to a newly allocated memory area holding it as a null-terminated string.
682  *
683  * Returns 0 and nullifies *outptr upon inability to return a string value.
684  *
685  * Returns 1 and sets *outptr when returning a dynamically allocated string.
686  *
687  * Supported on Windows NT 3.5 and newer.
688  */
get_enum_REG_SZ(HKEY hKeyParent,const char * leafKeyName,char ** outptr)689 static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName,
690                            char **outptr)
691 {
692   char  enumKeyName[256];
693   DWORD enumKeyNameBuffSize;
694   DWORD enumKeyIdx = 0;
695   HKEY  hKeyEnum;
696   int   gotString;
697   int   res;
698 
699   *outptr = NULL;
700 
701   for(;;)
702   {
703     enumKeyNameBuffSize = sizeof(enumKeyName);
704     res = RegEnumKeyExA(hKeyParent, enumKeyIdx++, enumKeyName,
705                        &enumKeyNameBuffSize, 0, NULL, NULL, NULL);
706     if (res != ERROR_SUCCESS)
707       break;
708     res = RegOpenKeyExA(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE,
709                        &hKeyEnum);
710     if (res != ERROR_SUCCESS)
711       continue;
712     gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr);
713     RegCloseKey(hKeyEnum);
714     if (gotString)
715       break;
716   }
717 
718   if (!*outptr)
719     return 0;
720 
721   return 1;
722 }
723 
724 /*
725  * get_DNS_Registry_9X()
726  *
727  * Functionally identical to get_DNS_Registry()
728  *
729  * Implementation supports Windows 95, 98 and ME.
730  */
get_DNS_Registry_9X(char ** outptr)731 static int get_DNS_Registry_9X(char **outptr)
732 {
733   HKEY hKey_VxD_MStcp;
734   int  gotString;
735   int  res;
736 
737   *outptr = NULL;
738 
739   res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ,
740                      &hKey_VxD_MStcp);
741   if (res != ERROR_SUCCESS)
742     return 0;
743 
744   gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr);
745   RegCloseKey(hKey_VxD_MStcp);
746 
747   if (!gotString || !*outptr)
748     return 0;
749 
750   return 1;
751 }
752 
753 /*
754  * get_DNS_Registry_NT()
755  *
756  * Functionally identical to get_DNS_Registry()
757  *
758  * Refs: Microsoft Knowledge Base articles KB120642 and KB314053.
759  *
760  * Implementation supports Windows NT 3.5 and newer.
761  */
get_DNS_Registry_NT(char ** outptr)762 static int get_DNS_Registry_NT(char **outptr)
763 {
764   HKEY hKey_Interfaces = NULL;
765   HKEY hKey_Tcpip_Parameters;
766   int  gotString;
767   int  res;
768 
769   *outptr = NULL;
770 
771   res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
772                      &hKey_Tcpip_Parameters);
773   if (res != ERROR_SUCCESS)
774     return 0;
775 
776   /*
777   ** Global DNS settings override adapter specific parameters when both
778   ** are set. Additionally static DNS settings override DHCP-configured
779   ** parameters when both are set.
780   */
781 
782   /* Global DNS static parameters */
783   gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr);
784   if (gotString)
785     goto done;
786 
787   /* Global DNS DHCP-configured parameters */
788   gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr);
789   if (gotString)
790     goto done;
791 
792   /* Try adapter specific parameters */
793   res = RegOpenKeyExA(hKey_Tcpip_Parameters, "Interfaces", 0,
794                      KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
795                      &hKey_Interfaces);
796   if (res != ERROR_SUCCESS)
797   {
798     hKey_Interfaces = NULL;
799     goto done;
800   }
801 
802   /* Adapter specific DNS static parameters */
803   gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr);
804   if (gotString)
805     goto done;
806 
807   /* Adapter specific DNS DHCP-configured parameters */
808   gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr);
809 
810 done:
811   if (hKey_Interfaces)
812     RegCloseKey(hKey_Interfaces);
813 
814   RegCloseKey(hKey_Tcpip_Parameters);
815 
816   if (!gotString || !*outptr)
817     return 0;
818 
819   return 1;
820 }
821 
822 /*
823  * get_DNS_Registry()
824  *
825  * Locates DNS info in the registry. When located, this returns a pointer
826  * in *outptr to a newly allocated memory area holding a null-terminated
827  * string with a space or comma seperated list of DNS IP addresses.
828  *
829  * Returns 0 and nullifies *outptr upon inability to return DNSes string.
830  *
831  * Returns 1 and sets *outptr when returning a dynamically allocated string.
832  */
get_DNS_Registry(char ** outptr)833 static int get_DNS_Registry(char **outptr)
834 {
835   win_platform platform;
836   int gotString = 0;
837 
838   *outptr = NULL;
839 
840   platform = ares__getplatform();
841 
842   if (platform == WIN_NT)
843     gotString = get_DNS_Registry_NT(outptr);
844   else if (platform == WIN_9X)
845     gotString = get_DNS_Registry_9X(outptr);
846 
847   if (!gotString)
848     return 0;
849 
850   return 1;
851 }
852 
commanjoin(char ** dst,const char * const src,const size_t len)853 static void commanjoin(char** dst, const char* const src, const size_t len)
854 {
855   char *newbuf;
856   size_t newsize;
857 
858   /* 1 for terminating 0 and 2 for , and terminating 0 */
859   newsize = len + (*dst ? (strlen(*dst) + 2) : 1);
860   newbuf = ares_realloc(*dst, newsize);
861   if (!newbuf)
862     return;
863   if (*dst == NULL)
864     *newbuf = '\0';
865   *dst = newbuf;
866   if (strlen(*dst) != 0)
867     strcat(*dst, ",");
868   strncat(*dst, src, len);
869 }
870 
871 /*
872  * commajoin()
873  *
874  * RTF code.
875  */
commajoin(char ** dst,const char * src)876 static void commajoin(char **dst, const char *src)
877 {
878   commanjoin(dst, src, strlen(src));
879 }
880 
881 /*
882  * get_DNS_NetworkParams()
883  *
884  * Locates DNS info using GetNetworkParams() function from the Internet
885  * Protocol Helper (IP Helper) API. When located, this returns a pointer
886  * in *outptr to a newly allocated memory area holding a null-terminated
887  * string with a space or comma seperated list of DNS IP addresses.
888  *
889  * Returns 0 and nullifies *outptr upon inability to return DNSes string.
890  *
891  * Returns 1 and sets *outptr when returning a dynamically allocated string.
892  *
893  * Implementation supports Windows 98 and newer.
894  *
895  * Note: Ancient PSDK required in order to build a W98 target.
896  */
get_DNS_NetworkParams(char ** outptr)897 static int get_DNS_NetworkParams(char **outptr)
898 {
899   FIXED_INFO       *fi, *newfi;
900   struct ares_addr namesrvr;
901   char             *txtaddr;
902   IP_ADDR_STRING   *ipAddr;
903   int              res;
904   DWORD            size = sizeof (*fi);
905 
906   *outptr = NULL;
907 
908   /* Verify run-time availability of GetNetworkParams() */
909   if (ares_fpGetNetworkParams == ZERO_NULL)
910     return 0;
911 
912   fi = ares_malloc(size);
913   if (!fi)
914     return 0;
915 
916   res = (*ares_fpGetNetworkParams) (fi, &size);
917   if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
918     goto done;
919 
920   newfi = ares_realloc(fi, size);
921   if (!newfi)
922     goto done;
923 
924   fi = newfi;
925   res = (*ares_fpGetNetworkParams) (fi, &size);
926   if (res != ERROR_SUCCESS)
927     goto done;
928 
929   for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next)
930   {
931     txtaddr = &ipAddr->IpAddress.String[0];
932 
933     /* Validate converting textual address to binary format. */
934     if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1)
935     {
936       if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) ||
937           (namesrvr.addrV4.S_un.S_addr == INADDR_NONE))
938         continue;
939     }
940     else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1)
941     {
942       if (memcmp(&namesrvr.addrV6, &ares_in6addr_any,
943                  sizeof(namesrvr.addrV6)) == 0)
944         continue;
945     }
946     else
947       continue;
948 
949     commajoin(outptr, txtaddr);
950 
951     if (!*outptr)
952       break;
953   }
954 
955 done:
956   if (fi)
957     ares_free(fi);
958 
959   if (!*outptr)
960     return 0;
961 
962   return 1;
963 }
964 
ares_IsWindowsVistaOrGreater(void)965 static BOOL ares_IsWindowsVistaOrGreater(void)
966 {
967   OSVERSIONINFO vinfo;
968   memset(&vinfo, 0, sizeof(vinfo));
969   vinfo.dwOSVersionInfoSize = sizeof(vinfo);
970 #ifdef _MSC_VER
971 #pragma warning(push)
972 #pragma warning(disable:4996) /* warning C4996: 'GetVersionExW': was declared deprecated */
973 #endif
974   if (!GetVersionEx(&vinfo) || vinfo.dwMajorVersion < 6)
975     return FALSE;
976   return TRUE;
977 #ifdef _MSC_VER
978 #pragma warning(pop)
979 #endif
980 }
981 
982 /* A structure to hold the string form of IPv4 and IPv6 addresses so we can
983  * sort them by a metric.
984  */
985 typedef struct
986 {
987   /* The metric we sort them by. */
988   ULONG metric;
989 
990   /* Original index of the item, used as a secondary sort parameter to make
991    * qsort() stable if the metrics are equal */
992   size_t orig_idx;
993 
994   /* Room enough for the string form of any IPv4 or IPv6 address that
995    * ares_inet_ntop() will create.  Based on the existing c-ares practice.
996    */
997   char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
998 } Address;
999 
1000 /* Sort Address values \a left and \a right by metric, returning the usual
1001  * indicators for qsort().
1002  */
compareAddresses(const void * arg1,const void * arg2)1003 static int compareAddresses(const void *arg1,
1004                             const void *arg2)
1005 {
1006   const Address * const left = arg1;
1007   const Address * const right = arg2;
1008   /* Lower metric the more preferred */
1009   if(left->metric < right->metric) return -1;
1010   if(left->metric > right->metric) return 1;
1011   /* If metrics are equal, lower original index more preferred */
1012   if(left->orig_idx < right->orig_idx) return -1;
1013   if(left->orig_idx > right->orig_idx) return 1;
1014   return 0;
1015 }
1016 
1017 /* There can be multiple routes to "the Internet".  And there can be different
1018  * DNS servers associated with each of the interfaces that offer those routes.
1019  * We have to assume that any DNS server can serve any request.  But, some DNS
1020  * servers may only respond if requested over their associated interface.  But
1021  * we also want to use "the preferred route to the Internet" whenever possible
1022  * (and not use DNS servers on a non-preferred route even by forcing request
1023  * to go out on the associated non-preferred interface).  i.e. We want to use
1024  * the DNS servers associated with the same interface that we would use to
1025  * make a general request to anything else.
1026  *
1027  * But, Windows won't sort the DNS servers by the metrics associated with the
1028  * routes and interfaces _even_ though it obviously sends IP packets based on
1029  * those same routes and metrics.  So, we must do it ourselves.
1030  *
1031  * So, we sort the DNS servers by the same metric values used to determine how
1032  * an outgoing IP packet will go, thus effectively using the DNS servers
1033  * associated with the interface that the DNS requests themselves will
1034  * travel.  This gives us optimal routing and avoids issues where DNS servers
1035  * won't respond to requests that don't arrive via some specific subnetwork
1036  * (and thus some specific interface).
1037  *
1038  * This function computes the metric we use to sort.  On the interface
1039  * identified by \a luid, it determines the best route to \a dest and combines
1040  * that route's metric with \a interfaceMetric to compute a metric for the
1041  * destination address on that interface.  This metric can be used as a weight
1042  * to sort the DNS server addresses associated with each interface (lower is
1043  * better).
1044  *
1045  * Note that by restricting the route search to the specific interface with
1046  * which the DNS servers are associated, this function asks the question "What
1047  * is the metric for sending IP packets to this DNS server?" which allows us
1048  * to sort the DNS servers correctly.
1049  */
getBestRouteMetric(IF_LUID * const luid,const SOCKADDR_INET * const dest,const ULONG interfaceMetric)1050 static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
1051                                 const SOCKADDR_INET * const dest,
1052                                 const ULONG interfaceMetric)
1053 {
1054   /* On this interface, get the best route to that destination. */
1055   MIB_IPFORWARD_ROW2 row;
1056   SOCKADDR_INET ignored;
1057   if(!ares_fpGetBestRoute2 ||
1058      ares_fpGetBestRoute2(/* The interface to use.  The index is ignored since we are
1059                            * passing a LUID.
1060                            */
1061                            luid, 0,
1062                            /* No specific source address. */
1063                            NULL,
1064                            /* Our destination address. */
1065                            dest,
1066                            /* No options. */
1067                            0,
1068                            /* The route row. */
1069                            &row,
1070                            /* The best source address, which we don't need. */
1071                            &ignored) != NO_ERROR
1072      /* If the metric is "unused" (-1) or too large for us to add the two
1073       * metrics, use the worst possible, thus sorting this last.
1074       */
1075      || row.Metric == (ULONG)-1
1076      || row.Metric > ((ULONG)-1) - interfaceMetric) {
1077     /* Return the worst possible metric. */
1078     return (ULONG)-1;
1079   }
1080 
1081   /* Return the metric value from that row, plus the interface metric.
1082    *
1083    * See
1084    * http://msdn.microsoft.com/en-us/library/windows/desktop/aa814494(v=vs.85).aspx
1085    * which describes the combination as a "sum".
1086    */
1087   return row.Metric + interfaceMetric;
1088 }
1089 
1090 /*
1091  * get_DNS_AdaptersAddresses()
1092  *
1093  * Locates DNS info using GetAdaptersAddresses() function from the Internet
1094  * Protocol Helper (IP Helper) API. When located, this returns a pointer
1095  * in *outptr to a newly allocated memory area holding a null-terminated
1096  * string with a space or comma seperated list of DNS IP addresses.
1097  *
1098  * Returns 0 and nullifies *outptr upon inability to return DNSes string.
1099  *
1100  * Returns 1 and sets *outptr when returning a dynamically allocated string.
1101  *
1102  * Implementation supports Windows XP and newer.
1103  */
1104 #define IPAA_INITIAL_BUF_SZ 15 * 1024
1105 #define IPAA_MAX_TRIES 3
get_DNS_AdaptersAddresses(char ** outptr)1106 static int get_DNS_AdaptersAddresses(char **outptr)
1107 {
1108   IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
1109   IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry;
1110   ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ;
1111   ULONG Bufsz = IPAA_INITIAL_BUF_SZ;
1112   ULONG AddrFlags = 0;
1113   int trying = IPAA_MAX_TRIES;
1114   int res;
1115 
1116   /* The capacity of addresses, in elements. */
1117   size_t addressesSize;
1118   /* The number of elements in addresses. */
1119   size_t addressesIndex = 0;
1120   /* The addresses we will sort. */
1121   Address *addresses;
1122 
1123   union {
1124     struct sockaddr     *sa;
1125     struct sockaddr_in  *sa4;
1126     struct sockaddr_in6 *sa6;
1127   } namesrvr;
1128 
1129   *outptr = NULL;
1130 
1131   /* Verify run-time availability of GetAdaptersAddresses() */
1132   if (ares_fpGetAdaptersAddresses == ZERO_NULL)
1133     return 0;
1134 
1135   ipaa = ares_malloc(Bufsz);
1136   if (!ipaa)
1137     return 0;
1138 
1139   /* Start with enough room for a few DNS server addresses and we'll grow it
1140    * as we encounter more.
1141    */
1142   addressesSize = 4;
1143   addresses = (Address*)ares_malloc(sizeof(Address) * addressesSize);
1144   if(addresses == NULL) {
1145     /* We need room for at least some addresses to function. */
1146     ares_free(ipaa);
1147     return 0;
1148   }
1149 
1150   /* Usually this call suceeds with initial buffer size */
1151   res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
1152                                         ipaa, &ReqBufsz);
1153   if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
1154     goto done;
1155 
1156   while ((res == ERROR_BUFFER_OVERFLOW) && (--trying))
1157   {
1158     if (Bufsz < ReqBufsz)
1159     {
1160       newipaa = ares_realloc(ipaa, ReqBufsz);
1161       if (!newipaa)
1162         goto done;
1163       Bufsz = ReqBufsz;
1164       ipaa = newipaa;
1165     }
1166     res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
1167                                           ipaa, &ReqBufsz);
1168     if (res == ERROR_SUCCESS)
1169       break;
1170   }
1171   if (res != ERROR_SUCCESS)
1172     goto done;
1173 
1174   for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next)
1175   {
1176     if(ipaaEntry->OperStatus != IfOperStatusUp)
1177         continue;
1178 
1179     /* For each interface, find any associated DNS servers as IPv4 or IPv6
1180      * addresses.  For each found address, find the best route to that DNS
1181      * server address _on_ _that_ _interface_ (at this moment in time) and
1182      * compute the resulting total metric, just as Windows routing will do.
1183      * Then, sort all the addresses found by the metric.
1184      */
1185     for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress;
1186          ipaDNSAddr;
1187          ipaDNSAddr = ipaDNSAddr->Next)
1188     {
1189       namesrvr.sa = ipaDNSAddr->Address.lpSockaddr;
1190 
1191       if (namesrvr.sa->sa_family == AF_INET)
1192       {
1193         if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) ||
1194             (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE))
1195           continue;
1196 
1197         /* Allocate room for another address, if necessary, else skip. */
1198         if(addressesIndex == addressesSize) {
1199           const size_t newSize = addressesSize + 4;
1200           Address * const newMem =
1201             (Address*)ares_realloc(addresses, sizeof(Address) * newSize);
1202           if(newMem == NULL) {
1203             continue;
1204           }
1205           addresses = newMem;
1206           addressesSize = newSize;
1207         }
1208 
1209         /* Vista required for Luid or Ipv4Metric */
1210         if (ares_IsWindowsVistaOrGreater())
1211         {
1212           /* Save the address as the next element in addresses. */
1213           addresses[addressesIndex].metric =
1214             getBestRouteMetric(&ipaaEntry->Luid,
1215                                (SOCKADDR_INET*)(namesrvr.sa),
1216                                ipaaEntry->Ipv4Metric);
1217         }
1218         else
1219         {
1220           addresses[addressesIndex].metric = (ULONG)-1;
1221         }
1222 
1223         /* Record insertion index to make qsort stable */
1224         addresses[addressesIndex].orig_idx = addressesIndex;
1225 
1226         if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
1227                              addresses[addressesIndex].text,
1228                              sizeof(addresses[0].text))) {
1229           continue;
1230         }
1231         ++addressesIndex;
1232       }
1233       else if (namesrvr.sa->sa_family == AF_INET6)
1234       {
1235         if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any,
1236                    sizeof(namesrvr.sa6->sin6_addr)) == 0)
1237           continue;
1238 
1239         /* Allocate room for another address, if necessary, else skip. */
1240         if(addressesIndex == addressesSize) {
1241           const size_t newSize = addressesSize + 4;
1242           Address * const newMem =
1243             (Address*)ares_realloc(addresses, sizeof(Address) * newSize);
1244           if(newMem == NULL) {
1245             continue;
1246           }
1247           addresses = newMem;
1248           addressesSize = newSize;
1249         }
1250 
1251         /* Vista required for Luid or Ipv4Metric */
1252         if (ares_IsWindowsVistaOrGreater())
1253         {
1254           /* Save the address as the next element in addresses. */
1255           addresses[addressesIndex].metric =
1256             getBestRouteMetric(&ipaaEntry->Luid,
1257                                (SOCKADDR_INET*)(namesrvr.sa),
1258                                ipaaEntry->Ipv6Metric);
1259         }
1260         else
1261         {
1262           addresses[addressesIndex].metric = (ULONG)-1;
1263         }
1264 
1265         /* Record insertion index to make qsort stable */
1266         addresses[addressesIndex].orig_idx = addressesIndex;
1267 
1268         if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr,
1269                              addresses[addressesIndex].text,
1270                              sizeof(addresses[0].text))) {
1271           continue;
1272         }
1273         ++addressesIndex;
1274       }
1275       else {
1276         /* Skip non-IPv4/IPv6 addresses completely. */
1277         continue;
1278       }
1279     }
1280   }
1281 
1282   /* Sort all of the textual addresses by their metric (and original index if
1283    * metrics are equal). */
1284   qsort(addresses, addressesIndex, sizeof(*addresses), compareAddresses);
1285 
1286   /* Join them all into a single string, removing duplicates. */
1287   {
1288     size_t i;
1289     for(i = 0; i < addressesIndex; ++i) {
1290       size_t j;
1291       /* Look for this address text appearing previously in the results. */
1292       for(j = 0; j < i; ++j) {
1293         if(strcmp(addresses[j].text, addresses[i].text) == 0) {
1294           break;
1295         }
1296       }
1297       /* Iff we didn't emit this address already, emit it now. */
1298       if(j == i) {
1299         /* Add that to outptr (if we can). */
1300         commajoin(outptr, addresses[i].text);
1301       }
1302     }
1303   }
1304 
1305 done:
1306   ares_free(addresses);
1307 
1308   if (ipaa)
1309     ares_free(ipaa);
1310 
1311   if (!*outptr) {
1312     return 0;
1313   }
1314 
1315   return 1;
1316 }
1317 
1318 /*
1319  * get_DNS_Windows()
1320  *
1321  * Locates DNS info from Windows employing most suitable methods available at
1322  * run-time no matter which Windows version it is. When located, this returns
1323  * a pointer in *outptr to a newly allocated memory area holding a string with
1324  * a space or comma seperated list of DNS IP addresses, null-terminated.
1325  *
1326  * Returns 0 and nullifies *outptr upon inability to return DNSes string.
1327  *
1328  * Returns 1 and sets *outptr when returning a dynamically allocated string.
1329  *
1330  * Implementation supports Windows 95 and newer.
1331  */
get_DNS_Windows(char ** outptr)1332 static int get_DNS_Windows(char **outptr)
1333 {
1334   /* Try using IP helper API GetAdaptersAddresses(). IPv4 + IPv6, also sorts
1335    * DNS servers by interface route metrics to try to use the best DNS server. */
1336   if (get_DNS_AdaptersAddresses(outptr))
1337     return 1;
1338 
1339   /* Try using IP helper API GetNetworkParams(). IPv4 only. */
1340   if (get_DNS_NetworkParams(outptr))
1341     return 1;
1342 
1343   /* Fall-back to registry information */
1344   return get_DNS_Registry(outptr);
1345 }
1346 
1347 /*
1348  * get_SuffixList_Windows()
1349  *
1350  * Reads the "DNS Suffix Search List" from registry and writes the list items
1351  * whitespace separated to outptr. If the Search List is empty, the
1352  * "Primary Dns Suffix" is written to outptr.
1353  *
1354  * Returns 0 and nullifies *outptr upon inability to return the suffix list.
1355  *
1356  * Returns 1 and sets *outptr when returning a dynamically allocated string.
1357  *
1358  * Implementation supports Windows Server 2003 and newer
1359  */
get_SuffixList_Windows(char ** outptr)1360 static int get_SuffixList_Windows(char **outptr)
1361 {
1362   HKEY hKey, hKeyEnum;
1363   char  keyName[256];
1364   DWORD keyNameBuffSize;
1365   DWORD keyIdx = 0;
1366   char *p = NULL;
1367 
1368   *outptr = NULL;
1369 
1370   if (ares__getplatform() != WIN_NT)
1371     return 0;
1372 
1373   /* 1. Global DNS Suffix Search List */
1374   if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
1375       KEY_READ, &hKey) == ERROR_SUCCESS)
1376   {
1377     get_REG_SZ(hKey, SEARCHLIST_KEY, outptr);
1378     if (get_REG_SZ(hKey, DOMAIN_KEY, &p))
1379     {
1380       commajoin(outptr, p);
1381       ares_free(p);
1382       p = NULL;
1383     }
1384     RegCloseKey(hKey);
1385   }
1386 
1387   if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NT_DNSCLIENT, 0,
1388       KEY_READ, &hKey) == ERROR_SUCCESS)
1389   {
1390     if (get_REG_SZ(hKey, SEARCHLIST_KEY, &p))
1391     {
1392       commajoin(outptr, p);
1393       ares_free(p);
1394       p = NULL;
1395     }
1396     RegCloseKey(hKey);
1397   }
1398 
1399   /* 2. Connection Specific Search List composed of:
1400    *  a. Primary DNS Suffix */
1401   if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_DNSCLIENT, 0,
1402       KEY_READ, &hKey) == ERROR_SUCCESS)
1403   {
1404     if (get_REG_SZ(hKey, PRIMARYDNSSUFFIX_KEY, &p))
1405     {
1406       commajoin(outptr, p);
1407       ares_free(p);
1408       p = NULL;
1409     }
1410     RegCloseKey(hKey);
1411   }
1412 
1413   /*  b. Interface SearchList, Domain, DhcpDomain */
1414   if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY "\\" INTERFACES_KEY, 0,
1415       KEY_READ, &hKey) == ERROR_SUCCESS)
1416   {
1417     for(;;)
1418     {
1419       keyNameBuffSize = sizeof(keyName);
1420       if (RegEnumKeyExA(hKey, keyIdx++, keyName, &keyNameBuffSize,
1421           0, NULL, NULL, NULL)
1422           != ERROR_SUCCESS)
1423         break;
1424       if (RegOpenKeyExA(hKey, keyName, 0, KEY_QUERY_VALUE, &hKeyEnum)
1425           != ERROR_SUCCESS)
1426         continue;
1427       /* p can be comma separated (SearchList) */
1428       if (get_REG_SZ(hKeyEnum, SEARCHLIST_KEY, &p))
1429       {
1430         commajoin(outptr, p);
1431         ares_free(p);
1432         p = NULL;
1433       }
1434       if (get_REG_SZ(hKeyEnum, DOMAIN_KEY, &p))
1435       {
1436         commajoin(outptr, p);
1437         ares_free(p);
1438         p = NULL;
1439       }
1440       if (get_REG_SZ(hKeyEnum, DHCPDOMAIN_KEY, &p))
1441       {
1442         commajoin(outptr, p);
1443         ares_free(p);
1444         p = NULL;
1445       }
1446       RegCloseKey(hKeyEnum);
1447     }
1448     RegCloseKey(hKey);
1449   }
1450 
1451   return *outptr != NULL;
1452 }
1453 
1454 #endif
1455 
init_by_resolv_conf(ares_channel channel)1456 static int init_by_resolv_conf(ares_channel channel)
1457 {
1458 #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32) && \
1459     !defined(CARES_USE_LIBRESOLV)
1460   char *line = NULL;
1461 #endif
1462   int status = -1, nservers = 0, nsort = 0;
1463   struct server_state *servers = NULL;
1464   struct apattern *sortlist = NULL;
1465 
1466 #ifdef WIN32
1467 
1468   if (channel->nservers > -1)  /* don't override ARES_OPT_SERVER */
1469      return ARES_SUCCESS;
1470 
1471   if (get_DNS_Windows(&line))
1472   {
1473     status = config_nameserver(&servers, &nservers, line);
1474     ares_free(line);
1475   }
1476 
1477   if (channel->ndomains == -1 && get_SuffixList_Windows(&line))
1478   {
1479       status = set_search(channel, line);
1480       ares_free(line);
1481   }
1482 
1483   if (status == ARES_SUCCESS)
1484     status = ARES_EOF;
1485   else
1486     /* Catch the case when all the above checks fail (which happens when there
1487        is no network card or the cable is unplugged) */
1488     status = ARES_EFILE;
1489 
1490 #elif defined(__riscos__)
1491 
1492   /* Under RISC OS, name servers are listed in the
1493      system variable Inet$Resolvers, space separated. */
1494 
1495   line = getenv("Inet$Resolvers");
1496   status = ARES_EOF;
1497   if (line) {
1498     char *resolvers = ares_strdup(line), *pos, *space;
1499 
1500     if (!resolvers)
1501       return ARES_ENOMEM;
1502 
1503     pos = resolvers;
1504     do {
1505       space = strchr(pos, ' ');
1506       if (space)
1507         *space = '\0';
1508       status = config_nameserver(&servers, &nservers, pos);
1509       if (status != ARES_SUCCESS)
1510         break;
1511       pos = space + 1;
1512     } while (space);
1513 
1514     if (status == ARES_SUCCESS)
1515       status = ARES_EOF;
1516 
1517     ares_free(resolvers);
1518   }
1519 
1520 #elif defined(WATT32)
1521   int i;
1522 
1523   sock_init();
1524   for (i = 0; def_nameservers[i]; i++)
1525       ;
1526   if (i == 0)
1527     return ARES_SUCCESS; /* use localhost DNS server */
1528 
1529   nservers = i;
1530   servers = ares_malloc(sizeof(struct server_state));
1531   if (!servers)
1532      return ARES_ENOMEM;
1533   memset(servers, 0, sizeof(struct server_state));
1534 
1535   for (i = 0; def_nameservers[i]; i++)
1536   {
1537     servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]);
1538     servers[i].addr.family = AF_INET;
1539     servers[i].addr.udp_port = 0;
1540     servers[i].addr.tcp_port = 0;
1541   }
1542   status = ARES_EOF;
1543 
1544 #elif defined(ANDROID) || defined(__ANDROID__)
1545   unsigned int i;
1546   char **dns_servers;
1547   char *domains;
1548   size_t num_servers;
1549 
1550   /* Use the Android connectivity manager to get a list
1551    * of DNS servers. As of Android 8 (Oreo) net.dns#
1552    * system properties are no longer available. Google claims this
1553    * improves privacy. Apps now need the ACCESS_NETWORK_STATE
1554    * permission and must use the ConnectivityManager which
1555    * is Java only. */
1556   dns_servers = ares_get_android_server_list(MAX_DNS_PROPERTIES, &num_servers);
1557   if (dns_servers != NULL)
1558   {
1559     for (i = 0; i < num_servers; i++)
1560     {
1561       status = config_nameserver(&servers, &nservers, dns_servers[i]);
1562       if (status != ARES_SUCCESS)
1563         break;
1564       status = ARES_EOF;
1565     }
1566     for (i = 0; i < num_servers; i++)
1567     {
1568       ares_free(dns_servers[i]);
1569     }
1570     ares_free(dns_servers);
1571   }
1572   if (channel->ndomains == -1)
1573   {
1574     domains = ares_get_android_search_domains_list();
1575     set_search(channel, domains);
1576     ares_free(domains);
1577   }
1578 
1579 #  ifdef HAVE___SYSTEM_PROPERTY_GET
1580   /* Old way using the system property still in place as
1581    * a fallback. Older android versions can still use this.
1582    * it's possible for older apps not not have added the new
1583    * permission and we want to try to avoid breaking those.
1584    *
1585    * We'll only run this if we don't have any dns servers
1586    * because this will get the same ones (if it works). */
1587   if (status != ARES_EOF) {
1588     char propname[PROP_NAME_MAX];
1589     char propvalue[PROP_VALUE_MAX]="";
1590     for (i = 1; i <= MAX_DNS_PROPERTIES; i++) {
1591       snprintf(propname, sizeof(propname), "%s%u", DNS_PROP_NAME_PREFIX, i);
1592       if (__system_property_get(propname, propvalue) < 1) {
1593         status = ARES_EOF;
1594         break;
1595       }
1596 
1597       status = config_nameserver(&servers, &nservers, propvalue);
1598       if (status != ARES_SUCCESS)
1599         break;
1600       status = ARES_EOF;
1601     }
1602   }
1603 #  endif /* HAVE___SYSTEM_PROPERTY_GET */
1604 #elif defined(CARES_USE_LIBRESOLV)
1605   struct __res_state res;
1606   memset(&res, 0, sizeof(res));
1607   int result = res_ninit(&res);
1608   if (result == 0 && (res.options & RES_INIT)) {
1609     status = ARES_EOF;
1610 
1611     if (channel->nservers == -1) {
1612       union res_sockaddr_union addr[MAXNS];
1613       int nscount = res_getservers(&res, addr, MAXNS);
1614       for (int i = 0; i < nscount; ++i) {
1615         char str[INET6_ADDRSTRLEN];
1616         int config_status;
1617         sa_family_t family = addr[i].sin.sin_family;
1618         if (family == AF_INET) {
1619           ares_inet_ntop(family, &addr[i].sin.sin_addr, str, sizeof(str));
1620         } else if (family == AF_INET6) {
1621           ares_inet_ntop(family, &addr[i].sin6.sin6_addr, str, sizeof(str));
1622         } else {
1623           continue;
1624         }
1625 
1626         config_status = config_nameserver(&servers, &nservers, str);
1627         if (config_status != ARES_SUCCESS) {
1628           status = config_status;
1629           break;
1630         }
1631       }
1632     }
1633     if (channel->ndomains == -1) {
1634       int entries = 0;
1635       while ((entries < MAXDNSRCH) && res.dnsrch[entries])
1636         entries++;
1637 
1638       channel->domains = ares_malloc(entries * sizeof(char *));
1639       if (!channel->domains) {
1640         status = ARES_ENOMEM;
1641       } else {
1642         channel->ndomains = entries;
1643         for (int i = 0; i < channel->ndomains; ++i) {
1644           channel->domains[i] = ares_strdup(res.dnsrch[i]);
1645           if (!channel->domains[i])
1646             status = ARES_ENOMEM;
1647         }
1648       }
1649     }
1650     if (channel->ndots == -1)
1651       channel->ndots = res.ndots;
1652     if (channel->tries == -1)
1653       channel->tries = res.retry;
1654     if (channel->rotate == -1)
1655       channel->rotate = res.options & RES_ROTATE;
1656     if (channel->timeout == -1)
1657       channel->timeout = res.retrans * 1000;
1658 
1659     res_ndestroy(&res);
1660   }
1661 #else
1662   {
1663     char *p;
1664     FILE *fp;
1665     size_t linesize;
1666     int error;
1667     int update_domains;
1668     const char *resolvconf_path;
1669 
1670     /* Don't read resolv.conf and friends if we don't have to */
1671     if (ARES_CONFIG_CHECK(channel))
1672         return ARES_SUCCESS;
1673 
1674     /* Only update search domains if they're not already specified */
1675     update_domains = (channel->ndomains == -1);
1676 
1677     /* Support path for resolvconf filename set by ares_init_options */
1678     if(channel->resolvconf_path) {
1679       resolvconf_path = channel->resolvconf_path;
1680     } else {
1681       resolvconf_path = PATH_RESOLV_CONF;
1682     }
1683 
1684     fp = fopen(resolvconf_path, "r");
1685     if (fp) {
1686       while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
1687       {
1688         if ((p = try_config(line, "domain", ';')) && update_domains)
1689           status = config_domain(channel, p);
1690         else if ((p = try_config(line, "lookup", ';')) && !channel->lookups)
1691           status = config_lookup(channel, p, "bind", NULL, "file");
1692         else if ((p = try_config(line, "search", ';')) && update_domains)
1693           status = set_search(channel, p);
1694         else if ((p = try_config(line, "nameserver", ';')) &&
1695                 channel->nservers == -1)
1696           status = config_nameserver(&servers, &nservers, p);
1697         else if ((p = try_config(line, "sortlist", ';')) &&
1698                 channel->nsort == -1)
1699           status = config_sortlist(&sortlist, &nsort, p);
1700         else if ((p = try_config(line, "options", ';')))
1701           status = set_options(channel, p);
1702         else
1703           status = ARES_SUCCESS;
1704         if (status != ARES_SUCCESS)
1705           break;
1706       }
1707       fclose(fp);
1708     }
1709     else {
1710       error = ERRNO;
1711       switch(error) {
1712       case ENOENT:
1713       case ESRCH:
1714         status = ARES_EOF;
1715         break;
1716       default:
1717         DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1718                       error, strerror(error)));
1719         DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
1720         status = ARES_EFILE;
1721       }
1722     }
1723 
1724     if ((status == ARES_EOF) && (!channel->lookups)) {
1725       /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
1726       fp = fopen("/etc/nsswitch.conf", "r");
1727       if (fp) {
1728         while ((status = ares__read_line(fp, &line, &linesize)) ==
1729                ARES_SUCCESS)
1730         {
1731           if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups)
1732             (void)config_lookup(channel, p, "dns", "resolve", "files");
1733         }
1734         fclose(fp);
1735       }
1736       else {
1737         error = ERRNO;
1738         switch(error) {
1739         case ENOENT:
1740         case ESRCH:
1741           break;
1742         default:
1743           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1744                          error, strerror(error)));
1745           DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1746                          "/etc/nsswitch.conf"));
1747         }
1748 
1749         /* ignore error, maybe we will get luck in next if clause */
1750         status = ARES_EOF;
1751       }
1752     }
1753 
1754     if ((status == ARES_EOF) && (!channel->lookups)) {
1755       /* Linux / GNU libc 2.x and possibly others have host.conf */
1756       fp = fopen("/etc/host.conf", "r");
1757       if (fp) {
1758         while ((status = ares__read_line(fp, &line, &linesize)) ==
1759                ARES_SUCCESS)
1760         {
1761           if ((p = try_config(line, "order", '\0')) && !channel->lookups)
1762             /* ignore errors */
1763             (void)config_lookup(channel, p, "bind", NULL, "hosts");
1764         }
1765         fclose(fp);
1766       }
1767       else {
1768         error = ERRNO;
1769         switch(error) {
1770         case ENOENT:
1771         case ESRCH:
1772           break;
1773         default:
1774           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1775                          error, strerror(error)));
1776           DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1777                          "/etc/host.conf"));
1778         }
1779 
1780         /* ignore error, maybe we will get luck in next if clause */
1781         status = ARES_EOF;
1782       }
1783     }
1784 
1785     if ((status == ARES_EOF) && (!channel->lookups)) {
1786       /* Tru64 uses /etc/svc.conf */
1787       fp = fopen("/etc/svc.conf", "r");
1788       if (fp) {
1789         while ((status = ares__read_line(fp, &line, &linesize)) ==
1790                ARES_SUCCESS)
1791         {
1792           if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups)
1793             /* ignore errors */
1794             (void)config_lookup(channel, p, "bind", NULL, "local");
1795         }
1796         fclose(fp);
1797       }
1798       else {
1799         error = ERRNO;
1800         switch(error) {
1801         case ENOENT:
1802         case ESRCH:
1803           break;
1804         default:
1805           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1806                          error, strerror(error)));
1807           DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
1808         }
1809 
1810         /* ignore error, default value will be chosen for `channel->lookups` */
1811         status = ARES_EOF;
1812       }
1813     }
1814 
1815     if(line)
1816       ares_free(line);
1817   }
1818 
1819 #endif
1820 
1821   /* Handle errors. */
1822   if (status != ARES_EOF)
1823     {
1824       if (servers != NULL)
1825         ares_free(servers);
1826       if (sortlist != NULL)
1827         ares_free(sortlist);
1828       return status;
1829     }
1830 
1831   /* If we got any name server entries, fill them in. */
1832   if (servers)
1833     {
1834       channel->servers = servers;
1835       channel->nservers = nservers;
1836     }
1837 
1838   /* If we got any sortlist entries, fill them in. */
1839   if (sortlist)
1840     {
1841       channel->sortlist = sortlist;
1842       channel->nsort = nsort;
1843     }
1844 
1845   return ARES_SUCCESS;
1846 }
1847 
init_by_defaults(ares_channel channel)1848 static int init_by_defaults(ares_channel channel)
1849 {
1850   char *hostname = NULL;
1851   int rc = ARES_SUCCESS;
1852 #ifdef HAVE_GETHOSTNAME
1853   char *dot;
1854 #endif
1855 
1856   if (channel->flags == -1)
1857     channel->flags = 0;
1858   if (channel->timeout == -1)
1859     channel->timeout = DEFAULT_TIMEOUT;
1860   if (channel->tries == -1)
1861     channel->tries = DEFAULT_TRIES;
1862   if (channel->ndots == -1)
1863     channel->ndots = 1;
1864   if (channel->rotate == -1)
1865     channel->rotate = 0;
1866   if (channel->udp_port == -1)
1867     channel->udp_port = htons(NAMESERVER_PORT);
1868   if (channel->tcp_port == -1)
1869     channel->tcp_port = htons(NAMESERVER_PORT);
1870 
1871   if (channel->ednspsz == -1)
1872     channel->ednspsz = EDNSPACKETSZ;
1873 
1874   if (channel->nservers == -1) {
1875     /* If nobody specified servers, try a local named. */
1876     channel->servers = ares_malloc(sizeof(struct server_state));
1877     if (!channel->servers) {
1878       rc = ARES_ENOMEM;
1879       goto error;
1880     }
1881     channel->servers[0].addr.family = AF_INET;
1882     channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK);
1883     channel->servers[0].addr.udp_port = 0;
1884     channel->servers[0].addr.tcp_port = 0;
1885     channel->nservers = 1;
1886   }
1887 
1888 #if defined(USE_WINSOCK)
1889 #define toolong(x) (x == -1) &&  (SOCKERRNO == WSAEFAULT)
1890 #elif defined(ENAMETOOLONG)
1891 #define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \
1892                                  (SOCKERRNO == EINVAL))
1893 #else
1894 #define toolong(x) (x == -1) &&  (SOCKERRNO == EINVAL)
1895 #endif
1896 
1897   if (channel->ndomains == -1) {
1898     /* Derive a default domain search list from the kernel hostname,
1899      * or set it to empty if the hostname isn't helpful.
1900      */
1901 #ifndef HAVE_GETHOSTNAME
1902     channel->ndomains = 0; /* default to none */
1903 #else
1904     GETHOSTNAME_TYPE_ARG2 lenv = 64;
1905     size_t len = 64;
1906     int res;
1907     channel->ndomains = 0; /* default to none */
1908 
1909     hostname = ares_malloc(len);
1910     if(!hostname) {
1911       rc = ARES_ENOMEM;
1912       goto error;
1913     }
1914 
1915     do {
1916       res = gethostname(hostname, lenv);
1917 
1918       if(toolong(res)) {
1919         char *p;
1920         len *= 2;
1921         lenv *= 2;
1922         p = ares_realloc(hostname, len);
1923         if(!p) {
1924           rc = ARES_ENOMEM;
1925           goto error;
1926         }
1927         hostname = p;
1928         continue;
1929       }
1930       else if(res) {
1931         /* Lets not treat a gethostname failure as critical, since we
1932          * are ok if gethostname doesn't even exist */
1933         *hostname = '\0';
1934         break;
1935       }
1936 
1937     } while (res != 0);
1938 
1939     dot = strchr(hostname, '.');
1940     if (dot) {
1941       /* a dot was found */
1942       channel->domains = ares_malloc(sizeof(char *));
1943       if (!channel->domains) {
1944         rc = ARES_ENOMEM;
1945         goto error;
1946       }
1947       channel->domains[0] = ares_strdup(dot + 1);
1948       if (!channel->domains[0]) {
1949         rc = ARES_ENOMEM;
1950         goto error;
1951       }
1952       channel->ndomains = 1;
1953     }
1954 #endif
1955   }
1956 
1957   if (channel->nsort == -1) {
1958     channel->sortlist = NULL;
1959     channel->nsort = 0;
1960   }
1961 
1962   if (!channel->lookups) {
1963     channel->lookups = ares_strdup("fb");
1964     if (!channel->lookups)
1965       rc = ARES_ENOMEM;
1966   }
1967 
1968   error:
1969   if(rc) {
1970     if(channel->servers) {
1971       ares_free(channel->servers);
1972       channel->servers = NULL;
1973     }
1974 
1975     if(channel->domains && channel->domains[0])
1976       ares_free(channel->domains[0]);
1977     if(channel->domains) {
1978       ares_free(channel->domains);
1979       channel->domains = NULL;
1980     }
1981 
1982     if(channel->lookups) {
1983       ares_free(channel->lookups);
1984       channel->lookups = NULL;
1985     }
1986 
1987     if(channel->resolvconf_path) {
1988       ares_free(channel->resolvconf_path);
1989       channel->resolvconf_path = NULL;
1990     }
1991   }
1992 
1993   if(hostname)
1994     ares_free(hostname);
1995 
1996   return rc;
1997 }
1998 
1999 #if !defined(WIN32) && !defined(WATT32) && \
2000     !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
config_domain(ares_channel channel,char * str)2001 static int config_domain(ares_channel channel, char *str)
2002 {
2003   char *q;
2004 
2005   /* Set a single search domain. */
2006   q = str;
2007   while (*q && !ISSPACE(*q))
2008     q++;
2009   *q = '\0';
2010   return set_search(channel, str);
2011 }
2012 
2013 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
2014     defined(__OPTIMIZE__) && defined(__unix__) &&  defined(__i386__)
2015   /* workaround icc 9.1 optimizer issue */
2016 # define vqualifier volatile
2017 #else
2018 # define vqualifier
2019 #endif
2020 
config_lookup(ares_channel channel,const char * str,const char * bindch,const char * altbindch,const char * filech)2021 static int config_lookup(ares_channel channel, const char *str,
2022                          const char *bindch, const char *altbindch,
2023                          const char *filech)
2024 {
2025   char lookups[3], *l;
2026   const char *vqualifier p;
2027   int found;
2028 
2029   if (altbindch == NULL)
2030     altbindch = bindch;
2031 
2032   /* Set the lookup order.  Only the first letter of each work
2033    * is relevant, and it has to be "b" for DNS or "f" for the
2034    * host file.  Ignore everything else.
2035    */
2036   l = lookups;
2037   p = str;
2038   found = 0;
2039   while (*p)
2040     {
2041       if ((*p == *bindch || *p == *altbindch || *p == *filech) && l < lookups + 2) {
2042         if (*p == *bindch || *p == *altbindch) *l++ = 'b';
2043         else *l++ = 'f';
2044         found = 1;
2045       }
2046       while (*p && !ISSPACE(*p) && (*p != ','))
2047         p++;
2048       while (*p && (ISSPACE(*p) || (*p == ',')))
2049         p++;
2050     }
2051   if (!found)
2052     return ARES_ENOTINITIALIZED;
2053   *l = '\0';
2054   channel->lookups = ares_strdup(lookups);
2055   return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
2056 }
2057 #endif  /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ & !CARES_USE_LIBRESOLV */
2058 
2059 #ifndef WATT32
2060 /* Validate that the ip address matches the subnet (network base and network
2061  * mask) specified. Addresses are specified in standard Network Byte Order as
2062  * 16 bytes, and the netmask is 0 to 128 (bits).
2063  */
ares_ipv6_subnet_matches(const unsigned char netbase[16],unsigned char netmask,const unsigned char ipaddr[16])2064 static int ares_ipv6_subnet_matches(const unsigned char netbase[16],
2065                                     unsigned char netmask,
2066                                     const unsigned char ipaddr[16])
2067 {
2068   unsigned char mask[16] = { 0 };
2069   unsigned char i;
2070 
2071   /* Misuse */
2072   if (netmask > 128)
2073     return 0;
2074 
2075   /* Quickly set whole bytes */
2076   memset(mask, 0xFF, netmask / 8);
2077 
2078   /* Set remaining bits */
2079   if(netmask % 8) {
2080     mask[netmask / 8] = (unsigned char)(0xff << (8 - (netmask % 8)));
2081   }
2082 
2083   for (i=0; i<16; i++) {
2084     if ((netbase[i] & mask[i]) != (ipaddr[i] & mask[i]))
2085       return 0;
2086   }
2087 
2088   return 1;
2089 }
2090 
2091 /* Return true iff the IPv6 ipaddr is blacklisted. */
ares_ipv6_server_blacklisted(const unsigned char ipaddr[16])2092 static int ares_ipv6_server_blacklisted(const unsigned char ipaddr[16])
2093 {
2094   /* A list of blacklisted IPv6 subnets. */
2095   const struct {
2096     const unsigned char netbase[16];
2097     unsigned char netmask;
2098   } blacklist[] = {
2099     /* fec0::/10 was deprecated by [RFC3879] in September 2004. Formerly a
2100      * Site-Local scoped address prefix.  These are never valid DNS servers,
2101      * but are known to be returned at least sometimes on Windows and Android.
2102      */
2103     {
2104       {
2105         0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2106         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2107       },
2108       10
2109     }
2110   };
2111   size_t i;
2112 
2113   /* See if ipaddr matches any of the entries in the blacklist. */
2114   for (i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); ++i) {
2115     if (ares_ipv6_subnet_matches(
2116           blacklist[i].netbase, blacklist[i].netmask, ipaddr))
2117       return 1;
2118   }
2119   return 0;
2120 }
2121 
2122 /* Add the IPv4 or IPv6 nameservers in str (separated by commas) to the
2123  * servers list, updating servers and nservers as required.
2124  *
2125  * This will silently ignore blacklisted IPv6 nameservers as detected by
2126  * ares_ipv6_server_blacklisted().
2127  *
2128  * Returns an error code on failure, else ARES_SUCCESS.
2129  */
config_nameserver(struct server_state ** servers,int * nservers,char * str)2130 static int config_nameserver(struct server_state **servers, int *nservers,
2131                              char *str)
2132 {
2133   struct ares_addr host;
2134   struct server_state *newserv;
2135   char *p, *txtaddr;
2136   /* On Windows, there may be more than one nameserver specified in the same
2137    * registry key, so we parse input as a space or comma seperated list.
2138    */
2139   for (p = str; p;)
2140     {
2141       /* Skip whitespace and commas. */
2142       while (*p && (ISSPACE(*p) || (*p == ',')))
2143         p++;
2144       if (!*p)
2145         /* No more input, done. */
2146         break;
2147 
2148       /* Pointer to start of IPv4 or IPv6 address part. */
2149       txtaddr = p;
2150 
2151       /* Advance past this address. */
2152       while (*p && !ISSPACE(*p) && (*p != ','))
2153         p++;
2154       if (*p)
2155         /* Null terminate this address. */
2156         *p++ = '\0';
2157       else
2158         /* Reached end of input, done when this address is processed. */
2159         p = NULL;
2160 
2161       /* Convert textual address to binary format. */
2162       if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
2163         host.family = AF_INET;
2164       else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1
2165                /* Silently skip blacklisted IPv6 servers. */
2166                && !ares_ipv6_server_blacklisted(
2167                     (const unsigned char *)&host.addrV6))
2168         host.family = AF_INET6;
2169       else
2170         continue;
2171 
2172       /* Resize servers state array. */
2173       newserv = ares_realloc(*servers, (*nservers + 1) *
2174                              sizeof(struct server_state));
2175       if (!newserv)
2176         return ARES_ENOMEM;
2177 
2178       /* Store address data. */
2179       newserv[*nservers].addr.family = host.family;
2180       newserv[*nservers].addr.udp_port = 0;
2181       newserv[*nservers].addr.tcp_port = 0;
2182       if (host.family == AF_INET)
2183         memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
2184                sizeof(host.addrV4));
2185       else
2186         memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
2187                sizeof(host.addrV6));
2188 
2189       /* Update arguments. */
2190       *servers = newserv;
2191       *nservers += 1;
2192     }
2193 
2194   return ARES_SUCCESS;
2195 }
2196 #endif  /* !WATT32 */
2197 
config_sortlist(struct apattern ** sortlist,int * nsort,const char * str)2198 static int config_sortlist(struct apattern **sortlist, int *nsort,
2199                            const char *str)
2200 {
2201   struct apattern pat;
2202   const char *q;
2203 
2204   /* Add sortlist entries. */
2205   while (*str && *str != ';')
2206     {
2207       int bits;
2208       char ipbuf[16], ipbufpfx[32];
2209       /* Find just the IP */
2210       q = str;
2211       while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
2212         q++;
2213       memcpy(ipbuf, str, q-str);
2214       ipbuf[q-str] = '\0';
2215       /* Find the prefix */
2216       if (*q == '/')
2217         {
2218           const char *str2 = q+1;
2219           while (*q && *q != ';' && !ISSPACE(*q))
2220             q++;
2221           memcpy(ipbufpfx, str, q-str);
2222           ipbufpfx[q-str] = '\0';
2223           str = str2;
2224         }
2225       else
2226         ipbufpfx[0] = '\0';
2227       /* Lets see if it is CIDR */
2228       /* First we'll try IPv6 */
2229       if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf,
2230                                      &pat.addrV6,
2231                                      sizeof(pat.addrV6))) > 0)
2232         {
2233           pat.type = PATTERN_CIDR;
2234           pat.mask.bits = (unsigned short)bits;
2235           pat.family = AF_INET6;
2236           if (!sortlist_alloc(sortlist, nsort, &pat)) {
2237             ares_free(*sortlist);
2238             *sortlist = NULL;
2239             return ARES_ENOMEM;
2240           }
2241         }
2242       else if (ipbufpfx[0] &&
2243                (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4,
2244                                           sizeof(pat.addrV4))) > 0)
2245         {
2246           pat.type = PATTERN_CIDR;
2247           pat.mask.bits = (unsigned short)bits;
2248           pat.family = AF_INET;
2249           if (!sortlist_alloc(sortlist, nsort, &pat)) {
2250             ares_free(*sortlist);
2251             *sortlist = NULL;
2252             return ARES_ENOMEM;
2253           }
2254         }
2255       /* See if it is just a regular IP */
2256       else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0)
2257         {
2258           if (ipbufpfx[0])
2259             {
2260               memcpy(ipbuf, str, q-str);
2261               ipbuf[q-str] = '\0';
2262               if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0)
2263                 natural_mask(&pat);
2264             }
2265           else
2266             natural_mask(&pat);
2267           pat.family = AF_INET;
2268           pat.type = PATTERN_MASK;
2269           if (!sortlist_alloc(sortlist, nsort, &pat)) {
2270             ares_free(*sortlist);
2271             *sortlist = NULL;
2272             return ARES_ENOMEM;
2273           }
2274         }
2275       else
2276         {
2277           while (*q && *q != ';' && !ISSPACE(*q))
2278             q++;
2279         }
2280       str = q;
2281       while (ISSPACE(*str))
2282         str++;
2283     }
2284 
2285   return ARES_SUCCESS;
2286 }
2287 
set_search(ares_channel channel,const char * str)2288 static int set_search(ares_channel channel, const char *str)
2289 {
2290   size_t cnt;
2291 
2292   if(channel->ndomains != -1) {
2293     /* LCOV_EXCL_START: all callers check ndomains == -1 */
2294     /* if we already have some domains present, free them first */
2295     ares_strsplit_free(channel->domains, channel->ndomains);
2296     channel->domains = NULL;
2297     channel->ndomains = -1;
2298   } /* LCOV_EXCL_STOP */
2299 
2300   channel->domains  = ares_strsplit(str, ", ", 1, &cnt);
2301   channel->ndomains = (int)cnt;
2302   if (channel->domains == NULL || channel->ndomains == 0) {
2303     channel->domains  = NULL;
2304     channel->ndomains = -1;
2305   }
2306 
2307   return ARES_SUCCESS;
2308 }
2309 
set_options(ares_channel channel,const char * str)2310 static int set_options(ares_channel channel, const char *str)
2311 {
2312   const char *p, *q, *val;
2313 
2314   p = str;
2315   while (*p)
2316     {
2317       q = p;
2318       while (*q && !ISSPACE(*q))
2319         q++;
2320       val = try_option(p, q, "ndots:");
2321       if (val && channel->ndots == -1)
2322         channel->ndots = aresx_sltosi(strtol(val, NULL, 10));
2323       val = try_option(p, q, "retrans:");
2324       if (val && channel->timeout == -1)
2325         channel->timeout = aresx_sltosi(strtol(val, NULL, 10));
2326       val = try_option(p, q, "retry:");
2327       if (val && channel->tries == -1)
2328         channel->tries = aresx_sltosi(strtol(val, NULL, 10));
2329       val = try_option(p, q, "rotate");
2330       if (val && channel->rotate == -1)
2331         channel->rotate = 1;
2332       p = q;
2333       while (ISSPACE(*p))
2334         p++;
2335     }
2336 
2337   return ARES_SUCCESS;
2338 }
2339 
try_option(const char * p,const char * q,const char * opt)2340 static const char *try_option(const char *p, const char *q, const char *opt)
2341 {
2342   size_t len = strlen(opt);
2343   return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL;
2344 }
2345 
2346 #if !defined(WIN32) && !defined(WATT32) && \
2347     !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
try_config(char * s,const char * opt,char scc)2348 static char *try_config(char *s, const char *opt, char scc)
2349 {
2350   size_t len;
2351   char *p;
2352   char *q;
2353 
2354   if (!s || !opt)
2355     /* no line or no option */
2356     return NULL;  /* LCOV_EXCL_LINE */
2357 
2358   /* Hash '#' character is always used as primary comment char, additionally
2359      a not-NUL secondary comment char will be considered when specified. */
2360 
2361   /* trim line comment */
2362   p = s;
2363   if(scc)
2364     while (*p && (*p != '#') && (*p != scc))
2365       p++;
2366   else
2367     while (*p && (*p != '#'))
2368       p++;
2369   *p = '\0';
2370 
2371   /* trim trailing whitespace */
2372   q = p - 1;
2373   while ((q >= s) && ISSPACE(*q))
2374     q--;
2375   *++q = '\0';
2376 
2377   /* skip leading whitespace */
2378   p = s;
2379   while (*p && ISSPACE(*p))
2380     p++;
2381 
2382   if (!*p)
2383     /* empty line */
2384     return NULL;
2385 
2386   if ((len = strlen(opt)) == 0)
2387     /* empty option */
2388     return NULL;  /* LCOV_EXCL_LINE */
2389 
2390   if (strncmp(p, opt, len) != 0)
2391     /* line and option do not match */
2392     return NULL;
2393 
2394   /* skip over given option name */
2395   p += len;
2396 
2397   if (!*p)
2398     /* no option value */
2399     return NULL;  /* LCOV_EXCL_LINE */
2400 
2401   if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p))
2402     /* whitespace between option name and value is mandatory
2403        for given option names which do not end with ':' or '=' */
2404     return NULL;
2405 
2406   /* skip over whitespace */
2407   while (*p && ISSPACE(*p))
2408     p++;
2409 
2410   if (!*p)
2411     /* no option value */
2412     return NULL;
2413 
2414   /* return pointer to option value */
2415   return p;
2416 }
2417 #endif  /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */
2418 
ip_addr(const char * ipbuf,ares_ssize_t len,struct in_addr * addr)2419 static int ip_addr(const char *ipbuf, ares_ssize_t len, struct in_addr *addr)
2420 {
2421 
2422   /* Four octets and three periods yields at most 15 characters. */
2423   if (len > 15)
2424     return -1;
2425 
2426   if (ares_inet_pton(AF_INET, ipbuf, addr) < 1)
2427     return -1;
2428 
2429   return 0;
2430 }
2431 
natural_mask(struct apattern * pat)2432 static void natural_mask(struct apattern *pat)
2433 {
2434   struct in_addr addr;
2435 
2436   /* Store a host-byte-order copy of pat in a struct in_addr.  Icky,
2437    * but portable.
2438    */
2439   addr.s_addr = ntohl(pat->addrV4.s_addr);
2440 
2441   /* This is out of date in the CIDR world, but some people might
2442    * still rely on it.
2443    */
2444   if (IN_CLASSA(addr.s_addr))
2445     pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET);
2446   else if (IN_CLASSB(addr.s_addr))
2447     pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET);
2448   else
2449     pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET);
2450 }
2451 
sortlist_alloc(struct apattern ** sortlist,int * nsort,struct apattern * pat)2452 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
2453                           struct apattern *pat)
2454 {
2455   struct apattern *newsort;
2456   newsort = ares_realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
2457   if (!newsort)
2458     return 0;
2459   newsort[*nsort] = *pat;
2460   *sortlist = newsort;
2461   (*nsort)++;
2462   return 1;
2463 }
2464 
2465 /* initialize an rc4 key. If possible a cryptographically secure random key
2466    is generated using a suitable function (for example win32's RtlGenRandom as
2467    described in
2468    http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
2469    otherwise the code defaults to cross-platform albeit less secure mechanism
2470    using rand
2471 */
randomize_key(unsigned char * key,int key_data_len)2472 static void randomize_key(unsigned char* key,int key_data_len)
2473 {
2474   int randomized = 0;
2475   int counter=0;
2476 #ifdef WIN32
2477   BOOLEAN res;
2478   if (ares_fpSystemFunction036)
2479     {
2480       res = (*ares_fpSystemFunction036) (key, key_data_len);
2481       if (res)
2482         randomized = 1;
2483     }
2484 #else /* !WIN32 */
2485 #ifdef RANDOM_FILE
2486   FILE *f = fopen(RANDOM_FILE, "rb");
2487   if(f) {
2488     counter = aresx_uztosi(fread(key, 1, key_data_len, f));
2489     fclose(f);
2490   }
2491 #endif
2492 #endif /* WIN32 */
2493 
2494   if (!randomized) {
2495     for (;counter<key_data_len;counter++)
2496       key[counter]=(unsigned char)(rand() % 256);  /* LCOV_EXCL_LINE */
2497   }
2498 }
2499 
init_id_key(rc4_key * key,int key_data_len)2500 static int init_id_key(rc4_key* key,int key_data_len)
2501 {
2502   unsigned char index1;
2503   unsigned char index2;
2504   unsigned char* state;
2505   short counter;
2506   unsigned char *key_data_ptr = 0;
2507 
2508   key_data_ptr = ares_malloc(key_data_len);
2509   if (!key_data_ptr)
2510     return ARES_ENOMEM;
2511   memset(key_data_ptr, 0, key_data_len);
2512 
2513   state = &key->state[0];
2514   for(counter = 0; counter < 256; counter++)
2515     /* unnecessary AND but it keeps some compilers happier */
2516     state[counter] = (unsigned char)(counter & 0xff);
2517   randomize_key(key->state,key_data_len);
2518   key->x = 0;
2519   key->y = 0;
2520   index1 = 0;
2521   index2 = 0;
2522   for(counter = 0; counter < 256; counter++)
2523   {
2524     index2 = (unsigned char)((key_data_ptr[index1] + state[counter] +
2525                               index2) % 256);
2526     ARES_SWAP_BYTE(&state[counter], &state[index2]);
2527 
2528     index1 = (unsigned char)((index1 + 1) % key_data_len);
2529   }
2530   ares_free(key_data_ptr);
2531   return ARES_SUCCESS;
2532 }
2533 
ares_set_local_ip4(ares_channel channel,unsigned int local_ip)2534 void ares_set_local_ip4(ares_channel channel, unsigned int local_ip)
2535 {
2536   channel->local_ip4 = local_ip;
2537 }
2538 
2539 /* local_ip6 should be 16 bytes in length */
ares_set_local_ip6(ares_channel channel,const unsigned char * local_ip6)2540 void ares_set_local_ip6(ares_channel channel,
2541                         const unsigned char* local_ip6)
2542 {
2543   memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
2544 }
2545 
2546 /* local_dev_name should be null terminated. */
ares_set_local_dev(ares_channel channel,const char * local_dev_name)2547 void ares_set_local_dev(ares_channel channel,
2548                         const char* local_dev_name)
2549 {
2550   strncpy(channel->local_dev_name, local_dev_name,
2551           sizeof(channel->local_dev_name));
2552   channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
2553 }
2554 
2555 
ares_set_socket_callback(ares_channel channel,ares_sock_create_callback cb,void * data)2556 void ares_set_socket_callback(ares_channel channel,
2557                               ares_sock_create_callback cb,
2558                               void *data)
2559 {
2560   channel->sock_create_cb = cb;
2561   channel->sock_create_cb_data = data;
2562 }
2563 
ares_set_socket_configure_callback(ares_channel channel,ares_sock_config_callback cb,void * data)2564 void ares_set_socket_configure_callback(ares_channel channel,
2565                                         ares_sock_config_callback cb,
2566                                         void *data)
2567 {
2568   channel->sock_config_cb = cb;
2569   channel->sock_config_cb_data = data;
2570 }
2571 
ares_set_socket_functions(ares_channel channel,const struct ares_socket_functions * funcs,void * data)2572 void ares_set_socket_functions(ares_channel channel,
2573                                const struct ares_socket_functions * funcs,
2574                                void *data)
2575 {
2576   channel->sock_funcs = funcs;
2577   channel->sock_func_cb_data = data;
2578 }
2579 
ares_set_sortlist(ares_channel channel,const char * sortstr)2580 int ares_set_sortlist(ares_channel channel, const char *sortstr)
2581 {
2582   int nsort = 0;
2583   struct apattern *sortlist = NULL;
2584   int status;
2585 
2586   if (!channel)
2587     return ARES_ENODATA;
2588 
2589   status = config_sortlist(&sortlist, &nsort, sortstr);
2590   if (status == ARES_SUCCESS && sortlist) {
2591     if (channel->sortlist)
2592       ares_free(channel->sortlist);
2593     channel->sortlist = sortlist;
2594     channel->nsort = nsort;
2595   }
2596   return status;
2597 }
2598 
ares__init_servers_state(ares_channel channel)2599 void ares__init_servers_state(ares_channel channel)
2600 {
2601   struct server_state *server;
2602   int i;
2603 
2604   for (i = 0; i < channel->nservers; i++)
2605     {
2606       server = &channel->servers[i];
2607       server->udp_socket = ARES_SOCKET_BAD;
2608       server->tcp_socket = ARES_SOCKET_BAD;
2609       server->tcp_connection_generation = ++channel->tcp_connection_generation;
2610       server->tcp_lenbuf_pos = 0;
2611       server->tcp_buffer_pos = 0;
2612       server->tcp_buffer = NULL;
2613       server->tcp_length = 0;
2614       server->qhead = NULL;
2615       server->qtail = NULL;
2616       ares__init_list_head(&server->queries_to_server);
2617       server->channel = channel;
2618       server->is_broken = 0;
2619     }
2620 }
2621