ares_init.c: get_iphlpapi_dns_info() refactoring
[platform/upstream/c-ares.git] / ares_init.c
1
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3  * Copyright (C) 2007-2012 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_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27
28 #ifdef HAVE_SYS_SOCKET_H
29 #include <sys/socket.h>
30 #endif
31
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
34 #endif
35
36 #ifdef HAVE_NETDB_H
37 #include <netdb.h>
38 #endif
39
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
43
44 #ifdef HAVE_ARPA_NAMESER_H
45 #  include <arpa/nameser.h>
46 #else
47 #  include "nameser.h"
48 #endif
49 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
50 #  include <arpa/nameser_compat.h>
51 #endif
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <ctype.h>
61 #include <time.h>
62
63 #if defined(ANDROID) || defined(__ANDROID__)
64 #include <sys/system_properties.h>
65 #endif
66
67 #include "ares.h"
68 #include "inet_ntop.h"
69 #include "inet_net_pton.h"
70 #include "ares_library_init.h"
71 #include "ares_nowarn.h"
72 #include "ares_platform.h"
73 #include "ares_private.h"
74
75 #ifdef WATT32
76 #undef WIN32  /* Redefined in MingW/MSVC headers */
77 #endif
78
79 static int init_by_options(ares_channel channel,
80                            const struct ares_options *options,
81                            int optmask);
82 static int init_by_environment(ares_channel channel);
83 static int init_by_resolv_conf(ares_channel channel);
84 static int init_by_defaults(ares_channel channel);
85
86 #ifndef WATT32
87 static int config_nameserver(struct server_state **servers, int *nservers,
88                              char *str);
89 #endif
90 static int set_search(ares_channel channel, const char *str);
91 static int set_options(ares_channel channel, const char *str);
92 static const char *try_option(const char *p, const char *q, const char *opt);
93 static int init_id_key(rc4_key* key,int key_data_len);
94
95 #if !defined(WIN32) && !defined(WATT32)
96 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
97                           struct apattern *pat);
98 static int ip_addr(const char *s, ssize_t len, struct in_addr *addr);
99 static void natural_mask(struct apattern *pat);
100 #if !defined(ANDROID) && !defined(__ANDROID__)
101 static int config_domain(ares_channel channel, char *str);
102 static int config_lookup(ares_channel channel, const char *str,
103                          const char *bindch, const char *filech);
104 static int config_sortlist(struct apattern **sortlist, int *nsort,
105                            const char *str);
106 static char *try_config(char *s, const char *opt, char scc);
107 #endif
108 #endif
109
110 #define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
111                              x->nservers > -1 && \
112                              x->ndomains > -1 && \
113                              x->ndots > -1 && x->timeout > -1 && \
114                              x->tries > -1)
115
116 int ares_init(ares_channel *channelptr)
117 {
118   return ares_init_options(channelptr, NULL, 0);
119 }
120
121 int ares_init_options(ares_channel *channelptr, struct ares_options *options,
122                       int optmask)
123 {
124   ares_channel channel;
125   int i;
126   int status = ARES_SUCCESS;
127   struct timeval now;
128
129 #ifdef CURLDEBUG
130   const char *env = getenv("CARES_MEMDEBUG");
131
132   if (env)
133     curl_memdebug(env);
134   env = getenv("CARES_MEMLIMIT");
135   if (env) {
136     char *endptr;
137     long num = strtol(env, &endptr, 10);
138     if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
139       curl_memlimit(num);
140   }
141 #endif
142
143   if (ares_library_initialized() != ARES_SUCCESS)
144     return ARES_ENOTINITIALIZED;
145
146   channel = malloc(sizeof(struct ares_channeldata));
147   if (!channel) {
148     *channelptr = NULL;
149     return ARES_ENOMEM;
150   }
151
152   now = ares__tvnow();
153
154   /* Set everything to distinguished values so we know they haven't
155    * been set yet.
156    */
157   channel->flags = -1;
158   channel->timeout = -1;
159   channel->tries = -1;
160   channel->ndots = -1;
161   channel->rotate = -1;
162   channel->udp_port = -1;
163   channel->tcp_port = -1;
164   channel->socket_send_buffer_size = -1;
165   channel->socket_receive_buffer_size = -1;
166   channel->nservers = -1;
167   channel->ndomains = -1;
168   channel->nsort = -1;
169   channel->tcp_connection_generation = 0;
170   channel->lookups = NULL;
171   channel->domains = NULL;
172   channel->sortlist = NULL;
173   channel->servers = NULL;
174   channel->sock_state_cb = NULL;
175   channel->sock_state_cb_data = NULL;
176   channel->sock_create_cb = NULL;
177   channel->sock_create_cb_data = NULL;
178
179   channel->last_server = 0;
180   channel->last_timeout_processed = (time_t)now.tv_sec;
181
182   memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name));
183   channel->local_ip4 = 0;
184   memset(&channel->local_ip6, 0, sizeof(channel->local_ip6));
185
186   /* Initialize our lists of queries */
187   ares__init_list_head(&(channel->all_queries));
188   for (i = 0; i < ARES_QID_TABLE_SIZE; i++)
189     {
190       ares__init_list_head(&(channel->queries_by_qid[i]));
191     }
192   for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++)
193     {
194       ares__init_list_head(&(channel->queries_by_timeout[i]));
195     }
196
197   /* Initialize configuration by each of the four sources, from highest
198    * precedence to lowest.
199    */
200
201   if (status == ARES_SUCCESS) {
202     status = init_by_options(channel, options, optmask);
203     if (status != ARES_SUCCESS)
204       DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
205                      ares_strerror(status)));
206   }
207   if (status == ARES_SUCCESS) {
208     status = init_by_environment(channel);
209     if (status != ARES_SUCCESS)
210       DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
211                      ares_strerror(status)));
212   }
213   if (status == ARES_SUCCESS) {
214     status = init_by_resolv_conf(channel);
215     if (status != ARES_SUCCESS)
216       DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n",
217                      ares_strerror(status)));
218   }
219
220   /*
221    * No matter what failed or succeeded, seed defaults to provide
222    * useful behavior for things that we missed.
223    */
224   status = init_by_defaults(channel);
225   if (status != ARES_SUCCESS)
226     DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
227                    ares_strerror(status)));
228
229   /* Generate random key */
230
231   if (status == ARES_SUCCESS) {
232     status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
233     if (status == ARES_SUCCESS)
234       channel->next_id = ares__generate_new_id(&channel->id_key);
235     else
236       DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
237                      ares_strerror(status)));
238   }
239
240   if (status != ARES_SUCCESS)
241     {
242       /* Something failed; clean up memory we may have allocated. */
243       if (channel->servers)
244         free(channel->servers);
245       if (channel->domains)
246         {
247           for (i = 0; i < channel->ndomains; i++)
248             free(channel->domains[i]);
249           free(channel->domains);
250         }
251       if (channel->sortlist)
252         free(channel->sortlist);
253       if(channel->lookups)
254         free(channel->lookups);
255       free(channel);
256       return status;
257     }
258
259   /* Trim to one server if ARES_FLAG_PRIMARY is set. */
260   if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
261     channel->nservers = 1;
262
263   ares__init_servers_state(channel);
264
265   *channelptr = channel;
266   return ARES_SUCCESS;
267 }
268
269 /* ares_dup() duplicates a channel handle with all its options and returns a
270    new channel handle */
271 int ares_dup(ares_channel *dest, ares_channel src)
272 {
273   struct ares_options opts;
274   struct ares_addr_node *servers;
275   int ipv6_nservers = 0;
276   int i, rc;
277   int optmask;
278
279   *dest = NULL; /* in case of failure return NULL explicitly */
280
281   /* First get the options supported by the old ares_save_options() function,
282      which is most of them */
283   rc = ares_save_options(src, &opts, &optmask);
284   if(rc)
285     return rc;
286
287   /* Then create the new channel with those options */
288   rc = ares_init_options(dest, &opts, optmask);
289
290   /* destroy the options copy to not leak any memory */
291   ares_destroy_options(&opts);
292
293   if(rc)
294     return rc;
295
296   /* Now clone the options that ares_save_options() doesn't support. */
297   (*dest)->sock_create_cb      = src->sock_create_cb;
298   (*dest)->sock_create_cb_data = src->sock_create_cb_data;
299
300   strncpy((*dest)->local_dev_name, src->local_dev_name,
301           sizeof(src->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 when not all are IPv4 */
306   for (i = 0; i < src->nservers; i++)
307     {
308       if (src->servers[i].addr.family != AF_INET) {
309         ipv6_nservers++;
310         break;
311       }
312     }
313   if (ipv6_nservers) {
314     rc = ares_get_servers(src, &servers);
315     if (rc != ARES_SUCCESS)
316       return rc;
317     rc = ares_set_servers(*dest, servers);
318     ares_free_data(servers);
319     if (rc != ARES_SUCCESS)
320       return rc;
321   }
322
323   return ARES_SUCCESS; /* everything went fine */
324 }
325
326 /* Save options from initialized channel */
327 int ares_save_options(ares_channel channel, struct ares_options *options,
328                       int *optmask)
329 {
330   int i, j;
331   int ipv4_nservers = 0;
332
333   /* Zero everything out */
334   memset(options, 0, sizeof(struct ares_options));
335
336   if (!ARES_CONFIG_CHECK(channel))
337     return ARES_ENODATA;
338
339   /* Traditionally the optmask wasn't saved in the channel struct so it was
340      recreated here. ROTATE is the first option that has no struct field of
341      its own in the public config struct */
342   (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS|
343                 ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
344                 ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
345                 ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS) |
346     (channel->optmask & ARES_OPT_ROTATE);
347
348   /* Copy easy stuff */
349   options->flags   = channel->flags;
350
351   /* We return full millisecond resolution but that's only because we don't
352      set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */
353   options->timeout = channel->timeout;
354   options->tries   = channel->tries;
355   options->ndots   = channel->ndots;
356   options->udp_port = (unsigned short)channel->udp_port;
357   options->tcp_port = (unsigned short)channel->tcp_port;
358   options->sock_state_cb     = channel->sock_state_cb;
359   options->sock_state_cb_data = channel->sock_state_cb_data;
360
361   /* Copy IPv4 servers */
362   if (channel->nservers) {
363     for (i = 0; i < channel->nservers; i++)
364     {
365       if (channel->servers[i].addr.family == AF_INET)
366         ipv4_nservers++;
367     }
368     if (ipv4_nservers) {
369       options->servers = malloc(ipv4_nservers * sizeof(struct in_addr));
370       if (!options->servers)
371         return ARES_ENOMEM;
372       for (i = j = 0; i < channel->nservers; i++)
373       {
374         if (channel->servers[i].addr.family == AF_INET)
375           memcpy(&options->servers[j++],
376                  &channel->servers[i].addr.addrV4,
377                  sizeof(channel->servers[i].addr.addrV4));
378       }
379     }
380   }
381   options->nservers = ipv4_nservers;
382
383   /* copy domains */
384   if (channel->ndomains) {
385     options->domains = malloc(channel->ndomains * sizeof(char *));
386     if (!options->domains)
387       return ARES_ENOMEM;
388
389     for (i = 0; i < channel->ndomains; i++)
390     {
391       options->ndomains = i;
392       options->domains[i] = strdup(channel->domains[i]);
393       if (!options->domains[i])
394         return ARES_ENOMEM;
395     }
396   }
397   options->ndomains = channel->ndomains;
398
399   /* copy lookups */
400   if (channel->lookups) {
401     options->lookups = strdup(channel->lookups);
402     if (!options->lookups && channel->lookups)
403       return ARES_ENOMEM;
404   }
405
406   /* copy sortlist */
407   if (channel->nsort) {
408     options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
409     if (!options->sortlist)
410       return ARES_ENOMEM;
411     for (i = 0; i < channel->nsort; i++)
412       options->sortlist[i] = channel->sortlist[i];
413   }
414   options->nsort = channel->nsort;
415
416   return ARES_SUCCESS;
417 }
418
419 static int init_by_options(ares_channel channel,
420                            const struct ares_options *options,
421                            int optmask)
422 {
423   int i;
424
425   /* Easy stuff. */
426   if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
427     channel->flags = options->flags;
428   if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1)
429     channel->timeout = options->timeout;
430   else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
431     channel->timeout = options->timeout * 1000;
432   if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
433     channel->tries = options->tries;
434   if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
435     channel->ndots = options->ndots;
436   if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1)
437     channel->rotate = 1;
438   if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
439     channel->udp_port = htons(options->udp_port);
440   if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
441     channel->tcp_port = htons(options->tcp_port);
442   if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL)
443     {
444       channel->sock_state_cb = options->sock_state_cb;
445       channel->sock_state_cb_data = options->sock_state_cb_data;
446     }
447   if ((optmask & ARES_OPT_SOCK_SNDBUF)
448       && channel->socket_send_buffer_size == -1)
449     channel->socket_send_buffer_size = options->socket_send_buffer_size;
450   if ((optmask & ARES_OPT_SOCK_RCVBUF)
451       && channel->socket_receive_buffer_size == -1)
452     channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
453
454   /* Copy the IPv4 servers, if given. */
455   if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
456     {
457       /* Avoid zero size allocations at any cost */
458       if (options->nservers > 0)
459         {
460           channel->servers =
461             malloc(options->nservers * sizeof(struct server_state));
462           if (!channel->servers)
463             return ARES_ENOMEM;
464           for (i = 0; i < options->nservers; i++)
465             {
466               channel->servers[i].addr.family = AF_INET;
467               memcpy(&channel->servers[i].addr.addrV4,
468                      &options->servers[i],
469                      sizeof(channel->servers[i].addr.addrV4));
470             }
471         }
472       channel->nservers = options->nservers;
473     }
474
475   /* Copy the domains, if given.  Keep channel->ndomains consistent so
476    * we can clean up in case of error.
477    */
478   if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
479     {
480       /* Avoid zero size allocations at any cost */
481       if (options->ndomains > 0)
482       {
483         channel->domains = malloc(options->ndomains * sizeof(char *));
484         if (!channel->domains)
485           return ARES_ENOMEM;
486         for (i = 0; i < options->ndomains; i++)
487           {
488             channel->ndomains = i;
489             channel->domains[i] = strdup(options->domains[i]);
490             if (!channel->domains[i])
491               return ARES_ENOMEM;
492           }
493       }
494       channel->ndomains = options->ndomains;
495     }
496
497   /* Set lookups, if given. */
498   if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
499     {
500       channel->lookups = strdup(options->lookups);
501       if (!channel->lookups)
502         return ARES_ENOMEM;
503     }
504
505   /* copy sortlist */
506   if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1) &&
507       (options->nsort>0)) {
508     channel->sortlist = malloc(options->nsort * sizeof(struct apattern));
509     if (!channel->sortlist)
510       return ARES_ENOMEM;
511     for (i = 0; i < options->nsort; i++)
512       channel->sortlist[i] = options->sortlist[i];
513     channel->nsort = options->nsort;
514   }
515
516   channel->optmask = optmask;
517
518   return ARES_SUCCESS;
519 }
520
521 static int init_by_environment(ares_channel channel)
522 {
523   const char *localdomain, *res_options;
524   int status;
525
526   localdomain = getenv("LOCALDOMAIN");
527   if (localdomain && channel->ndomains == -1)
528     {
529       status = set_search(channel, localdomain);
530       if (status != ARES_SUCCESS)
531         return status;
532     }
533
534   res_options = getenv("RES_OPTIONS");
535   if (res_options)
536     {
537       status = set_options(channel, res_options);
538       if (status != ARES_SUCCESS)
539         return status;
540     }
541
542   return ARES_SUCCESS;
543 }
544
545 #ifdef WIN32
546 /*
547  * Warning: returns a dynamically allocated buffer, the user MUST
548  * use free() if the function returns 1
549  */
550 static int get_res_nt(HKEY hKey, const char *subkey, char **obuf)
551 {
552   /* Test for the size we need */
553   DWORD size = 0;
554   int result;
555
556   result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
557   if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
558     return 0;
559   *obuf = malloc(size+1);
560   if (!*obuf)
561     return 0;
562
563   if (RegQueryValueEx(hKey, subkey, 0, NULL,
564                       (LPBYTE)*obuf, &size) != ERROR_SUCCESS)
565   {
566     free(*obuf);
567     return 0;
568   }
569   if (size == 1)
570   {
571     free(*obuf);
572     return 0;
573   }
574   return 1;
575 }
576
577 static int get_res_interfaces_nt(HKEY hKey, const char *subkey, char **obuf)
578 {
579   char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */
580   DWORD enum_size = 39;
581   int idx = 0;
582   HKEY hVal;
583
584   while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0,
585                       NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
586   {
587     int rc;
588
589     enum_size = 39;
590     if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) !=
591         ERROR_SUCCESS)
592       continue;
593     rc = get_res_nt(hVal, subkey, obuf);
594       RegCloseKey(hVal);
595     if (rc)
596       return 1;
597     }
598   return 0;
599 }
600
601 /* get_iphlpapi_dns_classic() is supported on W98 and newer */
602 static int get_iphlpapi_dns_classic(char *ret_buf, size_t ret_size)
603 {
604   FIXED_INFO       *fi, *newfi;
605   struct ares_addr namesrvr;
606   char             *txtaddr;
607   IP_ADDR_STRING   *ipAddr;
608   size_t           txtlen;
609   HRESULT          res;
610   DWORD            size = sizeof (*fi);
611   char             *endptr = ret_buf;
612   int              count = 0;
613
614   *endptr = '\0';
615
616   fi = malloc(size);
617   if (!fi)
618     return 0;
619
620   res = (*ares_fpGetNetworkParams) (fi, &size);
621   if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
622     goto quit;
623
624   newfi = realloc(fi, size);
625   if (!newfi)
626     goto quit;
627
628   fi = newfi;
629   res = (*ares_fpGetNetworkParams) (fi, &size);
630   if (res != ERROR_SUCCESS)
631     goto quit;
632
633   for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next)
634   {
635     txtaddr = &ipAddr->IpAddress.String[0];
636
637     /* Validate converting textual address to binary format. */
638     if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1)
639     {
640       if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) ||
641           (namesrvr.addrV4.S_un.S_addr == INADDR_NONE))
642         continue;
643     }
644     else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1)
645     {
646       if (memcmp(&namesrvr.addrV6, &ares_in6addr_any,
647                  sizeof(namesrvr.addrV6)) == 0)
648         continue;
649     }
650     else
651       continue;
652
653     txtlen = strlen(txtaddr);
654     if (ret_size >= strlen(ret_buf) + txtlen + 2)
655     {
656       sprintf(endptr, "%s,", txtaddr);
657       endptr += txtlen + 1;
658       count++;
659     }
660   }
661
662 quit:
663   if (fi)
664     free(fi);
665
666   if (endptr != ret_buf)
667     *(endptr - 1) = '\0';
668
669   return count;
670 }
671
672 #define IPAA_INITIAL_BUF_SZ 15 * 1024
673 #define IPAA_MAX_TRIES 3
674
675 static int get_iphlpapi_dns_info(char *ret_buf, size_t ret_size)
676 {
677   IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
678   IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry;
679   ULONG res;
680   ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ;
681   ULONG Bufsz = IPAA_INITIAL_BUF_SZ;
682   ULONG AddrFlags = 0;
683   char *endptr = ret_buf;
684   int trying = IPAA_MAX_TRIES;
685   int count = 0;
686
687   union {
688     struct sockaddr     *sa;
689     struct sockaddr_in  *sa4;
690     struct sockaddr_in6 *sa6;
691   } namesrvr;
692
693   char txtaddr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
694   size_t txtlen;
695
696   /* Unless GetAdaptersAddresses is available, use GetNetworkParams */
697   if (ares_fpGetAdaptersAddresses == ZERO_NULL)
698     return get_iphlpapi_dns_classic(ret_buf, ret_size);
699
700   *endptr = '\0';
701
702   ipaa = malloc(Bufsz);
703   if (!ipaa)
704     return 0;
705
706   /* Usually this call suceeds with initial buffer size */
707   res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
708                                         ipaa, &ReqBufsz);
709   if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
710     goto quit;
711
712   while ((res == ERROR_BUFFER_OVERFLOW) && (--trying))
713   {
714     if (Bufsz < ReqBufsz)
715     {
716       newipaa = realloc(ipaa, ReqBufsz);
717       if (!newipaa)
718         goto quit;
719       Bufsz = ReqBufsz;
720       ipaa = newipaa;
721     }
722     res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
723                                           ipaa, &ReqBufsz);
724     if (res == ERROR_SUCCESS)
725       break;
726   }
727   if (res != ERROR_SUCCESS)
728     goto quit;
729
730   for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next)
731   {
732     for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress;
733          ipaDNSAddr;
734          ipaDNSAddr = ipaDNSAddr->Next)
735     {
736       namesrvr.sa = ipaDNSAddr->Address.lpSockaddr;
737
738       if (namesrvr.sa->sa_family == AF_INET)
739       {
740         if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) ||
741             (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE))
742           continue;
743         if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
744                              txtaddr, sizeof(txtaddr)))
745           continue;
746       }
747       else if (namesrvr.sa->sa_family == AF_INET6)
748       {
749         if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any,
750                    sizeof(namesrvr.sa6->sin6_addr)) == 0)
751           continue;
752         if (! ares_inet_ntop(AF_INET, &namesrvr.sa6->sin6_addr,
753                              txtaddr, sizeof(txtaddr)))
754           continue;
755       }
756       else
757         continue;
758
759       txtlen = strlen(txtaddr);
760       if (ret_size >= strlen(ret_buf) + txtlen + 2)
761       {
762         sprintf(endptr, "%s,", txtaddr);
763         endptr += txtlen + 1;
764         count++;
765       }
766     }
767   }
768
769 quit:
770   if (ipaa)
771     free(ipaa);
772
773   if (endptr != ret_buf)
774     *(endptr - 1) = '\0';
775
776   return count;
777 }
778 #endif
779
780 static int init_by_resolv_conf(ares_channel channel)
781 {
782 #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32)
783   char *line = NULL;
784 #endif
785   int status = -1, nservers = 0, nsort = 0;
786   struct server_state *servers = NULL;
787   struct apattern *sortlist = NULL;
788
789 #ifdef WIN32
790
791     /*
792   NameServer info via IPHLPAPI (IP helper API):
793     GetNetworkParams() should be the trusted source for this.
794     Available in Win-98/2000 and later. If that fail, fall-back to
795     registry information.
796
797   NameServer Registry:
798
799    On Windows 9X, the DNS server can be found in:
800 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP\NameServer
801
802         On Windows NT/2000/XP/2003:
803 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\NameServer
804         or
805 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DhcpNameServer
806         or
807 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
808 NameServer
809         or
810 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
811 DhcpNameServer
812    */
813
814   HKEY mykey;
815   HKEY subkey;
816   DWORD data_type;
817   DWORD bytes;
818   DWORD result;
819   char  buf[512];
820   win_platform platform;
821
822   if (channel->nservers > -1)  /* don't override ARES_OPT_SERVER */
823      return ARES_SUCCESS;
824
825   if (get_iphlpapi_dns_info(buf,sizeof(buf)) > 0)
826   {
827     status = config_nameserver(&servers, &nservers, buf);
828     if (status == ARES_SUCCESS)
829       goto okay;
830   }
831
832   platform = ares__getplatform();
833
834   if (platform == WIN_NT)
835   {
836     if (RegOpenKeyEx(
837           HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
838           KEY_READ, &mykey
839          ) == ERROR_SUCCESS)
840     {
841       RegOpenKeyEx(mykey, "Interfaces", 0,
842                    KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey);
843       if (get_res_nt(mykey, NAMESERVER, &line))
844       {
845         status = config_nameserver(&servers, &nservers, line);
846         free(line);
847       }
848       else if (get_res_nt(mykey, DHCPNAMESERVER, &line))
849       {
850         status = config_nameserver(&servers, &nservers, line);
851         free(line);
852       }
853       /* Try the interfaces */
854       else if (get_res_interfaces_nt(subkey, NAMESERVER, &line))
855       {
856         status = config_nameserver(&servers, &nservers, line);
857         free(line);
858       }
859       else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
860       {
861         status = config_nameserver(&servers, &nservers, line);
862         free(line);
863       }
864       RegCloseKey(subkey);
865       RegCloseKey(mykey);
866     }
867   }
868   else if (platform == WIN_9X)
869   {
870     if (RegOpenKeyEx(
871           HKEY_LOCAL_MACHINE, WIN_NS_9X, 0,
872           KEY_READ, &mykey
873          ) == ERROR_SUCCESS)
874     {
875       if ((result = RegQueryValueEx(
876              mykey, NAMESERVER, NULL, &data_type,
877              NULL, &bytes
878             )
879            ) == ERROR_SUCCESS ||
880           result == ERROR_MORE_DATA)
881       {
882         if (bytes)
883         {
884           line = malloc(bytes+1);
885           if (RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type,
886                               (unsigned char *)line, &bytes) ==
887               ERROR_SUCCESS)
888           {
889             status = config_nameserver(&servers, &nservers, line);
890           }
891           free(line);
892         }
893       }
894     }
895     RegCloseKey(mykey);
896   }
897
898   if (status == ARES_SUCCESS)
899     status = ARES_EOF;
900   else
901     /* Catch the case when all the above checks fail (which happens when there
902        is no network card or the cable is unplugged) */
903     status = ARES_EFILE;
904
905 #elif defined(__riscos__)
906
907   /* Under RISC OS, name servers are listed in the
908      system variable Inet$Resolvers, space separated. */
909
910   line = getenv("Inet$Resolvers");
911   status = ARES_EOF;
912   if (line) {
913     char *resolvers = strdup(line), *pos, *space;
914
915     if (!resolvers)
916       return ARES_ENOMEM;
917
918     pos = resolvers;
919     do {
920       space = strchr(pos, ' ');
921       if (space)
922         *space = '\0';
923       status = config_nameserver(&servers, &nservers, pos);
924       if (status != ARES_SUCCESS)
925         break;
926       pos = space + 1;
927     } while (space);
928
929     if (status == ARES_SUCCESS)
930       status = ARES_EOF;
931
932     free(resolvers);
933   }
934
935 #elif defined(WATT32)
936   int i;
937
938   sock_init();
939   for (i = 0; def_nameservers[i]; i++)
940       ;
941   if (i == 0)
942     return ARES_SUCCESS; /* use localhost DNS server */
943
944   nservers = i;
945   servers = calloc(i, sizeof(struct server_state));
946   if (!servers)
947      return ARES_ENOMEM;
948
949   for (i = 0; def_nameservers[i]; i++)
950   {
951     servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]);
952     servers[i].addr.family = AF_INET;
953   }
954   status = ARES_EOF;
955
956 #elif defined(ANDROID) || defined(__ANDROID__)
957   char value[PROP_VALUE_MAX]="";
958   __system_property_get("net.dns1", value);
959   status = config_nameserver(&servers, &nservers, value);
960   if (status == ARES_SUCCESS)
961     status = ARES_EOF;
962 #else
963   {
964     char *p;
965     FILE *fp;
966     size_t linesize;
967     int error;
968
969     /* Don't read resolv.conf and friends if we don't have to */
970     if (ARES_CONFIG_CHECK(channel))
971         return ARES_SUCCESS;
972
973     fp = fopen(PATH_RESOLV_CONF, "r");
974     if (fp) {
975       while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
976       {
977         if ((p = try_config(line, "domain", ';')))
978           status = config_domain(channel, p);
979         else if ((p = try_config(line, "lookup", ';')) && !channel->lookups)
980           status = config_lookup(channel, p, "bind", "file");
981         else if ((p = try_config(line, "search", ';')))
982           status = set_search(channel, p);
983         else if ((p = try_config(line, "nameserver", ';')) &&
984                  channel->nservers == -1)
985           status = config_nameserver(&servers, &nservers, p);
986         else if ((p = try_config(line, "sortlist", ';')) &&
987                  channel->nsort == -1)
988           status = config_sortlist(&sortlist, &nsort, p);
989         else if ((p = try_config(line, "options", ';')))
990           status = set_options(channel, p);
991         else
992           status = ARES_SUCCESS;
993         if (status != ARES_SUCCESS)
994           break;
995       }
996       fclose(fp);
997     }
998     else {
999       error = ERRNO;
1000       switch(error) {
1001       case ENOENT:
1002       case ESRCH:
1003         status = ARES_EOF;
1004         break;
1005       default:
1006         DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1007                        error, strerror(error)));
1008         DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
1009         status = ARES_EFILE;
1010       }
1011     }
1012
1013     if ((status == ARES_EOF) && (!channel->lookups)) {
1014       /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
1015       fp = fopen("/etc/nsswitch.conf", "r");
1016       if (fp) {
1017         while ((status = ares__read_line(fp, &line, &linesize)) ==
1018                ARES_SUCCESS)
1019         {
1020           if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups)
1021             /* ignore errors */
1022             (void)config_lookup(channel, p, "dns", "files");
1023         }
1024         fclose(fp);
1025       }
1026       else {
1027         error = ERRNO;
1028         switch(error) {
1029         case ENOENT:
1030         case ESRCH:
1031           status = ARES_EOF;
1032           break;
1033         default:
1034           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1035                          error, strerror(error)));
1036           DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1037                          "/etc/nsswitch.conf"));
1038           status = ARES_EFILE;
1039         }
1040       }
1041     }
1042
1043     if ((status == ARES_EOF) && (!channel->lookups)) {
1044       /* Linux / GNU libc 2.x and possibly others have host.conf */
1045       fp = fopen("/etc/host.conf", "r");
1046       if (fp) {
1047         while ((status = ares__read_line(fp, &line, &linesize)) ==
1048                ARES_SUCCESS)
1049         {
1050           if ((p = try_config(line, "order", '\0')) && !channel->lookups)
1051             /* ignore errors */
1052             (void)config_lookup(channel, p, "bind", "hosts");
1053         }
1054         fclose(fp);
1055       }
1056       else {
1057         error = ERRNO;
1058         switch(error) {
1059         case ENOENT:
1060         case ESRCH:
1061           status = ARES_EOF;
1062           break;
1063         default:
1064           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1065                          error, strerror(error)));
1066           DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1067                          "/etc/host.conf"));
1068           status = ARES_EFILE;
1069         }
1070       }
1071     }
1072
1073     if ((status == ARES_EOF) && (!channel->lookups)) {
1074       /* Tru64 uses /etc/svc.conf */
1075       fp = fopen("/etc/svc.conf", "r");
1076       if (fp) {
1077         while ((status = ares__read_line(fp, &line, &linesize)) ==
1078                ARES_SUCCESS)
1079         {
1080           if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups)
1081             /* ignore errors */
1082             (void)config_lookup(channel, p, "bind", "local");
1083         }
1084         fclose(fp);
1085       }
1086       else {
1087         error = ERRNO;
1088         switch(error) {
1089         case ENOENT:
1090         case ESRCH:
1091           status = ARES_EOF;
1092           break;
1093         default:
1094           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1095                          error, strerror(error)));
1096           DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
1097           status = ARES_EFILE;
1098         }
1099       }
1100     }
1101
1102     if(line)
1103       free(line);
1104   }
1105
1106 #endif
1107
1108   /* Handle errors. */
1109   if (status != ARES_EOF)
1110     {
1111       if (servers != NULL)
1112         free(servers);
1113       if (sortlist != NULL)
1114         free(sortlist);
1115       return status;
1116     }
1117
1118   /* If we got any name server entries, fill them in. */
1119 #ifdef WIN32
1120 okay:
1121 #endif
1122   if (servers)
1123     {
1124       channel->servers = servers;
1125       channel->nservers = nservers;
1126     }
1127
1128   /* If we got any sortlist entries, fill them in. */
1129   if (sortlist)
1130     {
1131       channel->sortlist = sortlist;
1132       channel->nsort = nsort;
1133     }
1134
1135   return ARES_SUCCESS;
1136 }
1137
1138 static int init_by_defaults(ares_channel channel)
1139 {
1140   char *hostname = NULL;
1141   int rc = ARES_SUCCESS;
1142 #ifdef HAVE_GETHOSTNAME
1143   char *dot;
1144 #endif
1145
1146   if (channel->flags == -1)
1147     channel->flags = 0;
1148   if (channel->timeout == -1)
1149     channel->timeout = DEFAULT_TIMEOUT;
1150   if (channel->tries == -1)
1151     channel->tries = DEFAULT_TRIES;
1152   if (channel->ndots == -1)
1153     channel->ndots = 1;
1154   if (channel->rotate == -1)
1155     channel->rotate = 0;
1156   if (channel->udp_port == -1)
1157     channel->udp_port = htons(NAMESERVER_PORT);
1158   if (channel->tcp_port == -1)
1159     channel->tcp_port = htons(NAMESERVER_PORT);
1160
1161   if (channel->nservers == -1) {
1162     /* If nobody specified servers, try a local named. */
1163     channel->servers = malloc(sizeof(struct server_state));
1164     if (!channel->servers) {
1165       rc = ARES_ENOMEM;
1166       goto error;
1167     }
1168     channel->servers[0].addr.family = AF_INET;
1169     channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK);
1170     channel->nservers = 1;
1171   }
1172
1173 #if defined(USE_WINSOCK)
1174 #define toolong(x) (x == -1) &&  (SOCKERRNO == WSAEFAULT)
1175 #elif defined(ENAMETOOLONG)
1176 #define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \
1177                                  (SOCKERRNO == EINVAL))
1178 #else
1179 #define toolong(x) (x == -1) &&  (SOCKERRNO == EINVAL)
1180 #endif
1181
1182   if (channel->ndomains == -1) {
1183     /* Derive a default domain search list from the kernel hostname,
1184      * or set it to empty if the hostname isn't helpful.
1185      */
1186 #ifndef HAVE_GETHOSTNAME
1187     channel->ndomains = 0; /* default to none */
1188 #else
1189     GETHOSTNAME_TYPE_ARG2 lenv = 64;
1190     size_t len = 64;
1191     int res;
1192     channel->ndomains = 0; /* default to none */
1193
1194     hostname = malloc(len);
1195     if(!hostname) {
1196       rc = ARES_ENOMEM;
1197       goto error;
1198     }
1199
1200     do {
1201       res = gethostname(hostname, lenv);
1202
1203       if(toolong(res)) {
1204         char *p;
1205         len *= 2;
1206         lenv *= 2;
1207         p = realloc(hostname, len);
1208         if(!p) {
1209           rc = ARES_ENOMEM;
1210           goto error;
1211         }
1212         hostname = p;
1213         continue;
1214       }
1215       else if(res) {
1216         rc = ARES_EBADNAME;
1217         goto error;
1218       }
1219
1220     } WHILE_FALSE;
1221
1222     dot = strchr(hostname, '.');
1223     if (dot) {
1224       /* a dot was found */
1225       channel->domains = malloc(sizeof(char *));
1226       if (!channel->domains) {
1227         rc = ARES_ENOMEM;
1228         goto error;
1229       }
1230       channel->domains[0] = strdup(dot + 1);
1231       if (!channel->domains[0]) {
1232         rc = ARES_ENOMEM;
1233         goto error;
1234       }
1235       channel->ndomains = 1;
1236     }
1237 #endif
1238   }
1239
1240   if (channel->nsort == -1) {
1241     channel->sortlist = NULL;
1242     channel->nsort = 0;
1243   }
1244
1245   if (!channel->lookups) {
1246     channel->lookups = strdup("fb");
1247     if (!channel->lookups)
1248       rc = ARES_ENOMEM;
1249   }
1250
1251   error:
1252   if(rc) {
1253     if(channel->servers) {
1254       free(channel->servers);
1255       channel->servers = NULL;
1256     }
1257
1258     if(channel->domains && channel->domains[0])
1259       free(channel->domains[0]);
1260     if(channel->domains) {
1261       free(channel->domains);
1262       channel->domains = NULL;
1263     }
1264
1265     if(channel->lookups) {
1266       free(channel->lookups);
1267       channel->lookups = NULL;
1268     }
1269   }
1270
1271   if(hostname)
1272     free(hostname);
1273
1274   return rc;
1275 }
1276
1277 #if !defined(WIN32) && !defined(WATT32)
1278 static int config_domain(ares_channel channel, char *str)
1279 {
1280   char *q;
1281
1282   /* Set a single search domain. */
1283   q = str;
1284   while (*q && !ISSPACE(*q))
1285     q++;
1286   *q = '\0';
1287   return set_search(channel, str);
1288 }
1289
1290 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
1291     defined(__OPTIMIZE__) && defined(__unix__) &&  defined(__i386__)
1292   /* workaround icc 9.1 optimizer issue */
1293 # define vqualifier volatile
1294 #else
1295 # define vqualifier
1296 #endif
1297
1298 static int config_lookup(ares_channel channel, const char *str,
1299                          const char *bindch, const char *filech)
1300 {
1301   char lookups[3], *l;
1302   const char *vqualifier p;
1303
1304   /* Set the lookup order.  Only the first letter of each work
1305    * is relevant, and it has to be "b" for DNS or "f" for the
1306    * host file.  Ignore everything else.
1307    */
1308   l = lookups;
1309   p = str;
1310   while (*p)
1311     {
1312       if ((*p == *bindch || *p == *filech) && l < lookups + 2) {
1313         if (*p == *bindch) *l++ = 'b';
1314         else *l++ = 'f';
1315       }
1316       while (*p && !ISSPACE(*p) && (*p != ','))
1317         p++;
1318       while (*p && (ISSPACE(*p) || (*p == ',')))
1319         p++;
1320     }
1321   *l = '\0';
1322   channel->lookups = strdup(lookups);
1323   return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
1324 }
1325 #endif  /* !WIN32 & !WATT32 */
1326
1327 #ifndef WATT32
1328 static int config_nameserver(struct server_state **servers, int *nservers,
1329                              char *str)
1330 {
1331   struct ares_addr host;
1332   struct server_state *newserv;
1333   char *p, *txtaddr;
1334   /* On Windows, there may be more than one nameserver specified in the same
1335    * registry key, so we parse input as a space or comma seperated list.
1336    */
1337   for (p = str; p;)
1338     {
1339       /* Skip whitespace and commas. */
1340       while (*p && (ISSPACE(*p) || (*p == ',')))
1341         p++;
1342       if (!*p)
1343         /* No more input, done. */
1344         break;
1345
1346       /* Pointer to start of IPv4 or IPv6 address part. */
1347       txtaddr = p;
1348
1349       /* Advance past this address. */
1350       while (*p && !ISSPACE(*p) && (*p != ','))
1351         p++;
1352       if (*p)
1353         /* Null terminate this address. */
1354         *p++ = '\0';
1355       else
1356         /* Reached end of input, done when this address is processed. */
1357         p = NULL;
1358
1359       /* Convert textual address to binary format. */
1360       if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
1361         host.family = AF_INET;
1362       else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1)
1363         host.family = AF_INET6;
1364       else
1365         continue;
1366
1367       /* Resize servers state array. */
1368       newserv = realloc(*servers, (*nservers + 1) *
1369                         sizeof(struct server_state));
1370       if (!newserv)
1371         return ARES_ENOMEM;
1372
1373       /* Store address data. */
1374       newserv[*nservers].addr.family = host.family;
1375       if (host.family == AF_INET)
1376         memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
1377                sizeof(host.addrV4));
1378       else
1379         memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
1380                sizeof(host.addrV6));
1381
1382       /* Update arguments. */
1383       *servers = newserv;
1384       *nservers += 1;
1385     }
1386
1387   return ARES_SUCCESS;
1388 }
1389
1390 #ifndef WIN32
1391 static int config_sortlist(struct apattern **sortlist, int *nsort,
1392                            const char *str)
1393 {
1394   struct apattern pat;
1395   const char *q;
1396
1397   /* Add sortlist entries. */
1398   while (*str && *str != ';')
1399     {
1400       int bits;
1401       char ipbuf[16], ipbufpfx[32];
1402       /* Find just the IP */
1403       q = str;
1404       while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
1405         q++;
1406       memcpy(ipbuf, str, q-str);
1407       ipbuf[q-str] = '\0';
1408       /* Find the prefix */
1409       if (*q == '/')
1410         {
1411           const char *str2 = q+1;
1412           while (*q && *q != ';' && !ISSPACE(*q))
1413             q++;
1414           memcpy(ipbufpfx, str, q-str);
1415           ipbufpfx[q-str] = '\0';
1416           str = str2;
1417         }
1418       else
1419         ipbufpfx[0] = '\0';
1420       /* Lets see if it is CIDR */
1421       /* First we'll try IPv6 */
1422       if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf,
1423                                      &pat.addrV6,
1424                                      sizeof(pat.addrV6))) > 0)
1425         {
1426           pat.type = PATTERN_CIDR;
1427           pat.mask.bits = (unsigned short)bits;
1428           pat.family = AF_INET6;
1429           if (!sortlist_alloc(sortlist, nsort, &pat))
1430             return ARES_ENOMEM;
1431         }
1432       else if (ipbufpfx[0] &&
1433                (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4,
1434                                           sizeof(pat.addrV4))) > 0)
1435         {
1436           pat.type = PATTERN_CIDR;
1437           pat.mask.bits = (unsigned short)bits;
1438           pat.family = AF_INET;
1439           if (!sortlist_alloc(sortlist, nsort, &pat))
1440             return ARES_ENOMEM;
1441         }
1442       /* See if it is just a regular IP */
1443       else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0)
1444         {
1445           if (ipbufpfx[0])
1446             {
1447               memcpy(ipbuf, str, q-str);
1448               ipbuf[q-str] = '\0';
1449               if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0)
1450                 natural_mask(&pat);
1451             }
1452           else
1453             natural_mask(&pat);
1454           pat.family = AF_INET;
1455           pat.type = PATTERN_MASK;
1456           if (!sortlist_alloc(sortlist, nsort, &pat))
1457             return ARES_ENOMEM;
1458         }
1459       else
1460         {
1461           while (*q && *q != ';' && !ISSPACE(*q))
1462             q++;
1463         }
1464       str = q;
1465       while (ISSPACE(*str))
1466         str++;
1467     }
1468
1469   return ARES_SUCCESS;
1470 }
1471 #endif  /* !WIN32 */
1472 #endif  /* !WATT32 */
1473
1474 static int set_search(ares_channel channel, const char *str)
1475 {
1476   int n;
1477   const char *p, *q;
1478
1479   if(channel->ndomains != -1) {
1480     /* if we already have some domains present, free them first */
1481     for(n=0; n < channel->ndomains; n++)
1482       free(channel->domains[n]);
1483     free(channel->domains);
1484     channel->domains = NULL;
1485     channel->ndomains = -1;
1486   }
1487
1488   /* Count the domains given. */
1489   n = 0;
1490   p = str;
1491   while (*p)
1492     {
1493       while (*p && !ISSPACE(*p))
1494         p++;
1495       while (ISSPACE(*p))
1496         p++;
1497       n++;
1498     }
1499
1500   if (!n)
1501     {
1502       channel->ndomains = 0;
1503       return ARES_SUCCESS;
1504     }
1505
1506   channel->domains = malloc(n * sizeof(char *));
1507   if (!channel->domains)
1508     return ARES_ENOMEM;
1509
1510   /* Now copy the domains. */
1511   n = 0;
1512   p = str;
1513   while (*p)
1514     {
1515       channel->ndomains = n;
1516       q = p;
1517       while (*q && !ISSPACE(*q))
1518         q++;
1519       channel->domains[n] = malloc(q - p + 1);
1520       if (!channel->domains[n])
1521         return ARES_ENOMEM;
1522       memcpy(channel->domains[n], p, q - p);
1523       channel->domains[n][q - p] = 0;
1524       p = q;
1525       while (ISSPACE(*p))
1526         p++;
1527       n++;
1528     }
1529   channel->ndomains = n;
1530
1531   return ARES_SUCCESS;
1532 }
1533
1534 static int set_options(ares_channel channel, const char *str)
1535 {
1536   const char *p, *q, *val;
1537
1538   p = str;
1539   while (*p)
1540     {
1541       q = p;
1542       while (*q && !ISSPACE(*q))
1543         q++;
1544       val = try_option(p, q, "ndots:");
1545       if (val && channel->ndots == -1)
1546         channel->ndots = aresx_sltosi(strtol(val, NULL, 10));
1547       val = try_option(p, q, "retrans:");
1548       if (val && channel->timeout == -1)
1549         channel->timeout = aresx_sltosi(strtol(val, NULL, 10));
1550       val = try_option(p, q, "retry:");
1551       if (val && channel->tries == -1)
1552         channel->tries = aresx_sltosi(strtol(val, NULL, 10));
1553       val = try_option(p, q, "rotate");
1554       if (val && channel->rotate == -1)
1555         channel->rotate = 1;
1556       p = q;
1557       while (ISSPACE(*p))
1558         p++;
1559     }
1560
1561   return ARES_SUCCESS;
1562 }
1563
1564 static const char *try_option(const char *p, const char *q, const char *opt)
1565 {
1566   size_t len = strlen(opt);
1567   return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL;
1568 }
1569
1570 #if !defined(WIN32) && !defined(WATT32)
1571 static char *try_config(char *s, const char *opt, char scc)
1572 {
1573   size_t len;
1574   char *p;
1575   char *q;
1576
1577   if (!s || !opt)
1578     /* no line or no option */
1579     return NULL;
1580
1581   /* Hash '#' character is always used as primary comment char, additionally
1582      a not-NUL secondary comment char will be considered when specified. */
1583
1584   /* trim line comment */
1585   p = s;
1586   if(scc)
1587     while (*p && (*p != '#') && (*p != scc))
1588       p++;
1589   else
1590     while (*p && (*p != '#'))
1591       p++;
1592   *p = '\0';
1593
1594   /* trim trailing whitespace */
1595   q = p - 1;
1596   while ((q >= s) && ISSPACE(*q))
1597     q--;
1598   *++q = '\0';
1599
1600   /* skip leading whitespace */
1601   p = s;
1602   while (*p && ISSPACE(*p))
1603     p++;
1604
1605   if (!*p)
1606     /* empty line */
1607     return NULL;
1608
1609   if ((len = strlen(opt)) == 0)
1610     /* empty option */
1611     return NULL;
1612
1613   if (strncmp(p, opt, len) != 0)
1614     /* line and option do not match */
1615     return NULL;
1616
1617   /* skip over given option name */
1618   p += len;
1619
1620   if (!*p)
1621     /* no option value */
1622     return NULL;
1623
1624   if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p))
1625     /* whitespace between option name and value is mandatory
1626        for given option names which do not end with ':' or '=' */
1627     return NULL;
1628
1629   /* skip over whitespace */
1630   while (*p && ISSPACE(*p))
1631     p++;
1632
1633   if (!*p)
1634     /* no option value */
1635     return NULL;
1636
1637   /* return pointer to option value */
1638   return p;
1639 }
1640
1641 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
1642                           struct apattern *pat)
1643 {
1644   struct apattern *newsort;
1645   newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
1646   if (!newsort)
1647     return 0;
1648   newsort[*nsort] = *pat;
1649   *sortlist = newsort;
1650   (*nsort)++;
1651   return 1;
1652 }
1653
1654 static int ip_addr(const char *ipbuf, ssize_t len, struct in_addr *addr)
1655 {
1656
1657   /* Four octets and three periods yields at most 15 characters. */
1658   if (len > 15)
1659     return -1;
1660
1661   addr->s_addr = inet_addr(ipbuf);
1662   if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
1663     return -1;
1664   return 0;
1665 }
1666
1667 static void natural_mask(struct apattern *pat)
1668 {
1669   struct in_addr addr;
1670
1671   /* Store a host-byte-order copy of pat in a struct in_addr.  Icky,
1672    * but portable.
1673    */
1674   addr.s_addr = ntohl(pat->addrV4.s_addr);
1675
1676   /* This is out of date in the CIDR world, but some people might
1677    * still rely on it.
1678    */
1679   if (IN_CLASSA(addr.s_addr))
1680     pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET);
1681   else if (IN_CLASSB(addr.s_addr))
1682     pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET);
1683   else
1684     pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET);
1685 }
1686 #endif /* !WIN32 && !WATT32 */
1687
1688 /* initialize an rc4 key. If possible a cryptographically secure random key
1689    is generated using a suitable function (for example win32's RtlGenRandom as
1690    described in
1691    http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
1692    otherwise the code defaults to cross-platform albeit less secure mechanism
1693    using rand
1694 */
1695 static void randomize_key(unsigned char* key,int key_data_len)
1696 {
1697   int randomized = 0;
1698   int counter=0;
1699 #ifdef WIN32
1700   BOOLEAN res;
1701   if (ares_fpSystemFunction036)
1702     {
1703       res = (*ares_fpSystemFunction036) (key, key_data_len);
1704       if (res)
1705         randomized = 1;
1706     }
1707 #else /* !WIN32 */
1708 #ifdef RANDOM_FILE
1709   FILE *f = fopen(RANDOM_FILE, "rb");
1710   if(f) {
1711     counter = aresx_uztosi(fread(key, 1, key_data_len, f));
1712     fclose(f);
1713   }
1714 #endif
1715 #endif /* WIN32 */
1716
1717   if (!randomized) {
1718     for (;counter<key_data_len;counter++)
1719       key[counter]=(unsigned char)(rand() % 256);
1720   }
1721 }
1722
1723 static int init_id_key(rc4_key* key,int key_data_len)
1724 {
1725   unsigned char index1;
1726   unsigned char index2;
1727   unsigned char* state;
1728   short counter;
1729   unsigned char *key_data_ptr = 0;
1730
1731   key_data_ptr = calloc(1,key_data_len);
1732   if (!key_data_ptr)
1733     return ARES_ENOMEM;
1734
1735   state = &key->state[0];
1736   for(counter = 0; counter < 256; counter++)
1737     /* unnecessary AND but it keeps some compilers happier */
1738     state[counter] = (unsigned char)(counter & 0xff);
1739   randomize_key(key->state,key_data_len);
1740   key->x = 0;
1741   key->y = 0;
1742   index1 = 0;
1743   index2 = 0;
1744   for(counter = 0; counter < 256; counter++)
1745   {
1746     index2 = (unsigned char)((key_data_ptr[index1] + state[counter] +
1747                               index2) % 256);
1748     ARES_SWAP_BYTE(&state[counter], &state[index2]);
1749
1750     index1 = (unsigned char)((index1 + 1) % key_data_len);
1751   }
1752   free(key_data_ptr);
1753   return ARES_SUCCESS;
1754 }
1755
1756 unsigned short ares__generate_new_id(rc4_key* key)
1757 {
1758   unsigned short r=0;
1759   ares__rc4(key, (unsigned char *)&r, sizeof(r));
1760   return r;
1761 }
1762
1763 void ares_set_local_ip4(ares_channel channel, unsigned int local_ip)
1764 {
1765   channel->local_ip4 = local_ip;
1766 }
1767
1768 /* local_ip6 should be 16 bytes in length */
1769 void ares_set_local_ip6(ares_channel channel,
1770                         const unsigned char* local_ip6)
1771 {
1772   memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
1773 }
1774
1775 /* local_dev_name should be null terminated. */
1776 void ares_set_local_dev(ares_channel channel,
1777                         const char* local_dev_name)
1778 {
1779   strncpy(channel->local_dev_name, local_dev_name,
1780           sizeof(channel->local_dev_name));
1781   channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
1782 }
1783
1784
1785 void ares_set_socket_callback(ares_channel channel,
1786                               ares_sock_create_callback cb,
1787                               void *data)
1788 {
1789   channel->sock_create_cb = cb;
1790   channel->sock_create_cb_data = data;
1791 }
1792
1793 void ares__init_servers_state(ares_channel channel)
1794 {
1795   struct server_state *server;
1796   int i;
1797
1798   for (i = 0; i < channel->nservers; i++)
1799     {
1800       server = &channel->servers[i];
1801       server->udp_socket = ARES_SOCKET_BAD;
1802       server->tcp_socket = ARES_SOCKET_BAD;
1803       server->tcp_connection_generation = ++channel->tcp_connection_generation;
1804       server->tcp_lenbuf_pos = 0;
1805       server->tcp_buffer_pos = 0;
1806       server->tcp_buffer = NULL;
1807       server->tcp_length = 0;
1808       server->qhead = NULL;
1809       server->qtail = NULL;
1810       ares__init_list_head(&server->queries_to_server);
1811       server->channel = channel;
1812       server->is_broken = 0;
1813     }
1814 }