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