Kill some more compiler warnings.
[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_net_pton.h"
69 #include "ares_library_init.h"
70 #include "ares_nowarn.h"
71 #include "ares_platform.h"
72 #include "inet_ntop.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 /**
602  * The desired output for this method is that we set "ret_buf" to
603  * something like:
604  *
605  * 192.168.0.1,dns01.my.domain,fe80::200:f8ff:fe21:67cf
606  *
607  * The only ordering requirement is that primary servers are listed
608  * before secondary. There is no requirement that IPv4 addresses should
609  * necessarily be before IPv6.
610  *
611  * Note that ret_size should ideally be big enough to hold around
612  * 2-3 IPv4 and 2-3 IPv6 addresses.
613  *
614  * Finally, we need to return the total number of DNS servers located.
615  */
616 static int get_iphlpapi_dns_info (char *ret_buf, size_t ret_size)
617 {
618   const size_t  ipv4_size = INET_ADDRSTRLEN  + 1;  /* +1 for ',' at end */
619   const size_t  ipv6_size = INET6_ADDRSTRLEN + 12; /* +12 for "%0123456789," */
620   long          left = ret_size;
621   char         *ret  = ret_buf;
622   int           count = 0;
623
624   /* Use the GetAdaptersAddresses method if it's available, otherwise
625      fall back to GetNetworkParams. */
626   if (ares_fpGetAdaptersAddresses != ZERO_NULL)
627   {
628     const ULONG            working_buf_size = 15000;
629     IP_ADAPTER_ADDRESSES   *pFirstEntry = NULL;
630     IP_ADAPTER_ADDRESSES   *pEntry = NULL;
631     ULONG                  bufSize = 0;
632     ULONG                  result = 0;
633
634     /* According to MSDN, the recommended way to do this is to use a temporary
635        buffer of 15K, to "dramatically reduce the chance that the
636        GetAdaptersAddresses method returns ERROR_BUFFER_OVERFLOW" */
637     pFirstEntry  = (IP_ADAPTER_ADDRESSES *) malloc(working_buf_size);
638     bufSize = working_buf_size;
639     if(!pFirstEntry)
640       return 0;
641
642     /* Call the method one time */
643     result = (*ares_fpGetAdaptersAddresses)(AF_UNSPEC, 0, 0, pFirstEntry,
644                                                &bufSize);
645     if(result == ERROR_BUFFER_OVERFLOW)
646     {
647       /* Reallocate, bufSize should now be set to the required size */
648       pFirstEntry = (IP_ADAPTER_ADDRESSES *) realloc(pFirstEntry, bufSize);
649       if(!pFirstEntry)
650         return 0;
651
652       /* Call the method a second time */
653       result = (*ares_fpGetAdaptersAddresses)(AF_UNSPEC, 0, 0, pFirstEntry,
654                                                 &bufSize);
655       if(result == ERROR_BUFFER_OVERFLOW)
656       {
657         /* Reallocate, bufSize should now be set to the required size */
658         pFirstEntry = (IP_ADAPTER_ADDRESSES *)realloc(pFirstEntry, bufSize);
659         if(!pFirstEntry)
660           return 0;
661
662         /* Call the method a third time. The maximum number of times we're
663            going to do this is 3. Three shall be the number thou shalt count,
664            and the number of the counting shall be three.  Five is right
665            out. */
666         result = (*ares_fpGetAdaptersAddresses)(AF_UNSPEC, 0, 0, pFirstEntry,
667                                                 &bufSize);
668       }
669     }
670
671     /* Check the current result for failure */
672     if(result != ERROR_SUCCESS)
673     {
674       free(pFirstEntry);
675       return 0;
676     }
677
678     /* process the results */
679     for(pEntry = pFirstEntry ; pEntry != NULL ; pEntry = pEntry->Next)
680     {
681       IP_ADAPTER_DNS_SERVER_ADDRESS* pDNSAddr = pEntry->FirstDnsServerAddress;
682       for(; pDNSAddr != NULL ; pDNSAddr = pDNSAddr->Next)
683       {
684         struct sockaddr *pGenericAddr = pDNSAddr->Address.lpSockaddr;
685         size_t stringlen = 0;
686
687         if(pGenericAddr->sa_family == AF_INET && left > ipv4_size)
688         {
689           /* Handle the v4 case */
690           struct sockaddr_in *pIPv4Addr = (struct sockaddr_in *) pGenericAddr;
691
692           ares_inet_ntop(AF_INET, &pIPv4Addr->sin_addr, ret,
693                          ipv4_size - 1); /* -1 for comma */
694
695           /* Append a comma to the end, THEN NULL. Should be OK because we
696              already tested the size at the top of the if statement. */
697           stringlen = strlen(ret);
698           ret[ stringlen ] = ',';
699           ret[ stringlen + 1 ] = '\0';
700           ret += stringlen + 1;
701           left -= stringlen + 1;
702           ++count;
703         }
704         else if(pGenericAddr->sa_family == AF_INET6 && left > ipv6_size)
705         {
706           /* Handle the v6 case */
707           struct sockaddr_in6 *pIPv6Addr = (struct sockaddr_in6 *)pGenericAddr;
708           ares_inet_ntop(AF_INET6, &pIPv6Addr->sin6_addr, ret,
709                          ipv6_size - 1); /* -1 for comma */
710
711           /* Append a comma to the end, THEN NULL. Should be OK because we
712              already tested the size at the top of the if statement. */
713           stringlen = strlen(ret);
714           ret[ stringlen ] = ',';
715           ret[ stringlen + 1 ] = '\0';
716           ret += stringlen + 1;
717           left -= stringlen + 1;
718           ++count;
719
720           /* NB on Windows this also returns stuff in the fec0::/10 range,
721              seems to be hard-coded somehow. Do we need to ignore them? */
722         }
723       }
724     }
725
726     if(pFirstEntry)
727       free(pFirstEntry);
728     if (ret > ret_buf)
729       ret[-1] = '\0';
730     return count;
731   }
732   else
733   {
734     FIXED_INFO    *fi, *newfi;
735     DWORD          size = sizeof (*fi);
736     IP_ADDR_STRING *ipAddr;
737     int            i;
738     int            debug  = 0;
739     HRESULT        res;
740
741     fi = malloc(size);
742     if (!fi)
743       return 0;
744
745     res = (*ares_fpGetNetworkParams) (fi, &size);
746     if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
747       goto quit;
748
749     newfi = realloc(fi, size);
750     if (!newfi)
751       goto quit;
752
753     fi = newfi;
754     res = (*ares_fpGetNetworkParams) (fi, &size);
755     if (res != ERROR_SUCCESS)
756       goto quit;
757
758     if (debug)
759     {
760       printf ("Host Name: %s\n", fi->HostName);
761       printf ("Domain Name: %s\n", fi->DomainName);
762       printf ("DNS Servers:\n"
763               "    %s (primary)\n", fi->DnsServerList.IpAddress.String);
764     }
765     if (strlen(fi->DnsServerList.IpAddress.String) > 0 &&
766         inet_addr(fi->DnsServerList.IpAddress.String) != INADDR_NONE &&
767         left > ipv4_size)
768     {
769       ret += sprintf (ret, "%s,", fi->DnsServerList.IpAddress.String);
770       left -= ret - ret_buf;
771       ++count;
772     }
773
774     for (i = 0, ipAddr = fi->DnsServerList.Next; ipAddr && left > ipv4_size;
775          ipAddr = ipAddr->Next, i++)
776     {
777       if (inet_addr(ipAddr->IpAddress.String) != INADDR_NONE)
778       {
779          ret += sprintf (ret, "%s,", ipAddr->IpAddress.String);
780          left -= ret - ret_buf;
781          ++count;
782       }
783       if (debug)
784          printf ("    %s (secondary %d)\n", ipAddr->IpAddress.String, i+1);
785     }
786
787 quit:
788     if (fi)
789       free(fi);
790
791     if (debug && left <= ipv4_size)
792       printf ("Too many nameservers. Truncating to %d addressess", count);
793     if (ret > ret_buf)
794       ret[-1] = '\0';
795     return count;
796   }
797 }
798 #endif
799
800 static int init_by_resolv_conf(ares_channel channel)
801 {
802 #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32)
803   char *line = NULL;
804 #endif
805   int status = -1, nservers = 0, nsort = 0;
806   struct server_state *servers = NULL;
807   struct apattern *sortlist = NULL;
808
809 #ifdef WIN32
810
811     /*
812   NameServer info via IPHLPAPI (IP helper API):
813     GetNetworkParams() should be the trusted source for this.
814     Available in Win-98/2000 and later. If that fail, fall-back to
815     registry information.
816
817   NameServer Registry:
818
819    On Windows 9X, the DNS server can be found in:
820 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP\NameServer
821
822         On Windows NT/2000/XP/2003:
823 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\NameServer
824         or
825 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DhcpNameServer
826         or
827 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
828 NameServer
829         or
830 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
831 DhcpNameServer
832    */
833
834   HKEY mykey;
835   HKEY subkey;
836   DWORD data_type;
837   DWORD bytes;
838   DWORD result;
839   char  buf[512];
840   win_platform platform;
841
842   if (channel->nservers > -1)  /* don't override ARES_OPT_SERVER */
843      return ARES_SUCCESS;
844
845   if (get_iphlpapi_dns_info(buf,sizeof(buf)) > 0)
846   {
847     status = config_nameserver(&servers, &nservers, buf);
848     if (status == ARES_SUCCESS)
849       goto okay;
850   }
851
852   platform = ares__getplatform();
853
854   if (platform == WIN_NT)
855   {
856     if (RegOpenKeyEx(
857           HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
858           KEY_READ, &mykey
859          ) == ERROR_SUCCESS)
860     {
861       RegOpenKeyEx(mykey, "Interfaces", 0,
862                    KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey);
863       if (get_res_nt(mykey, NAMESERVER, &line))
864       {
865         status = config_nameserver(&servers, &nservers, line);
866         free(line);
867       }
868       else if (get_res_nt(mykey, DHCPNAMESERVER, &line))
869       {
870         status = config_nameserver(&servers, &nservers, line);
871         free(line);
872       }
873       /* Try the interfaces */
874       else if (get_res_interfaces_nt(subkey, NAMESERVER, &line))
875       {
876         status = config_nameserver(&servers, &nservers, line);
877         free(line);
878       }
879       else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
880       {
881         status = config_nameserver(&servers, &nservers, line);
882         free(line);
883       }
884       RegCloseKey(subkey);
885       RegCloseKey(mykey);
886     }
887   }
888   else if (platform == WIN_9X)
889   {
890     if (RegOpenKeyEx(
891           HKEY_LOCAL_MACHINE, WIN_NS_9X, 0,
892           KEY_READ, &mykey
893          ) == ERROR_SUCCESS)
894     {
895       if ((result = RegQueryValueEx(
896              mykey, NAMESERVER, NULL, &data_type,
897              NULL, &bytes
898             )
899            ) == ERROR_SUCCESS ||
900           result == ERROR_MORE_DATA)
901       {
902         if (bytes)
903         {
904           line = malloc(bytes+1);
905           if (RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type,
906                               (unsigned char *)line, &bytes) ==
907               ERROR_SUCCESS)
908           {
909             status = config_nameserver(&servers, &nservers, line);
910           }
911           free(line);
912         }
913       }
914     }
915     RegCloseKey(mykey);
916   }
917
918   if (status == ARES_SUCCESS)
919     status = ARES_EOF;
920   else
921     /* Catch the case when all the above checks fail (which happens when there
922        is no network card or the cable is unplugged) */
923     status = ARES_EFILE;
924
925 #elif defined(__riscos__)
926
927   /* Under RISC OS, name servers are listed in the
928      system variable Inet$Resolvers, space separated. */
929
930   line = getenv("Inet$Resolvers");
931   status = ARES_EOF;
932   if (line) {
933     char *resolvers = strdup(line), *pos, *space;
934
935     if (!resolvers)
936       return ARES_ENOMEM;
937
938     pos = resolvers;
939     do {
940       space = strchr(pos, ' ');
941       if (space)
942         *space = '\0';
943       status = config_nameserver(&servers, &nservers, pos);
944       if (status != ARES_SUCCESS)
945         break;
946       pos = space + 1;
947     } while (space);
948
949     if (status == ARES_SUCCESS)
950       status = ARES_EOF;
951
952     free(resolvers);
953   }
954
955 #elif defined(WATT32)
956   int i;
957
958   sock_init();
959   for (i = 0; def_nameservers[i]; i++)
960       ;
961   if (i == 0)
962     return ARES_SUCCESS; /* use localhost DNS server */
963
964   nservers = i;
965   servers = calloc(i, sizeof(struct server_state));
966   if (!servers)
967      return ARES_ENOMEM;
968
969   for (i = 0; def_nameservers[i]; i++)
970   {
971     servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]);
972     servers[i].addr.family = AF_INET;
973   }
974   status = ARES_EOF;
975
976 #elif defined(ANDROID) || defined(__ANDROID__)
977   char value[PROP_VALUE_MAX]="";
978   __system_property_get("net.dns1", value);
979   status = config_nameserver(&servers, &nservers, value);
980   if (status == ARES_SUCCESS)
981     status = ARES_EOF;
982 #else
983   {
984     char *p;
985     FILE *fp;
986     size_t linesize;
987     int error;
988
989     /* Don't read resolv.conf and friends if we don't have to */
990     if (ARES_CONFIG_CHECK(channel))
991         return ARES_SUCCESS;
992
993     fp = fopen(PATH_RESOLV_CONF, "r");
994     if (fp) {
995       while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
996       {
997         if ((p = try_config(line, "domain", ';')))
998           status = config_domain(channel, p);
999         else if ((p = try_config(line, "lookup", ';')) && !channel->lookups)
1000           status = config_lookup(channel, p, "bind", "file");
1001         else if ((p = try_config(line, "search", ';')))
1002           status = set_search(channel, p);
1003         else if ((p = try_config(line, "nameserver", ';')) &&
1004                  channel->nservers == -1)
1005           status = config_nameserver(&servers, &nservers, p);
1006         else if ((p = try_config(line, "sortlist", ';')) &&
1007                  channel->nsort == -1)
1008           status = config_sortlist(&sortlist, &nsort, p);
1009         else if ((p = try_config(line, "options", ';')))
1010           status = set_options(channel, p);
1011         else
1012           status = ARES_SUCCESS;
1013         if (status != ARES_SUCCESS)
1014           break;
1015       }
1016       fclose(fp);
1017     }
1018     else {
1019       error = ERRNO;
1020       switch(error) {
1021       case ENOENT:
1022       case ESRCH:
1023         status = ARES_EOF;
1024         break;
1025       default:
1026         DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1027                        error, strerror(error)));
1028         DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
1029         status = ARES_EFILE;
1030       }
1031     }
1032
1033     if ((status == ARES_EOF) && (!channel->lookups)) {
1034       /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
1035       fp = fopen("/etc/nsswitch.conf", "r");
1036       if (fp) {
1037         while ((status = ares__read_line(fp, &line, &linesize)) ==
1038                ARES_SUCCESS)
1039         {
1040           if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups)
1041             /* ignore errors */
1042             (void)config_lookup(channel, p, "dns", "files");
1043         }
1044         fclose(fp);
1045       }
1046       else {
1047         error = ERRNO;
1048         switch(error) {
1049         case ENOENT:
1050         case ESRCH:
1051           status = ARES_EOF;
1052           break;
1053         default:
1054           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1055                          error, strerror(error)));
1056           DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1057                          "/etc/nsswitch.conf"));
1058           status = ARES_EFILE;
1059         }
1060       }
1061     }
1062
1063     if ((status == ARES_EOF) && (!channel->lookups)) {
1064       /* Linux / GNU libc 2.x and possibly others have host.conf */
1065       fp = fopen("/etc/host.conf", "r");
1066       if (fp) {
1067         while ((status = ares__read_line(fp, &line, &linesize)) ==
1068                ARES_SUCCESS)
1069         {
1070           if ((p = try_config(line, "order", '\0')) && !channel->lookups)
1071             /* ignore errors */
1072             (void)config_lookup(channel, p, "bind", "hosts");
1073         }
1074         fclose(fp);
1075       }
1076       else {
1077         error = ERRNO;
1078         switch(error) {
1079         case ENOENT:
1080         case ESRCH:
1081           status = ARES_EOF;
1082           break;
1083         default:
1084           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1085                          error, strerror(error)));
1086           DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1087                          "/etc/host.conf"));
1088           status = ARES_EFILE;
1089         }
1090       }
1091     }
1092
1093     if ((status == ARES_EOF) && (!channel->lookups)) {
1094       /* Tru64 uses /etc/svc.conf */
1095       fp = fopen("/etc/svc.conf", "r");
1096       if (fp) {
1097         while ((status = ares__read_line(fp, &line, &linesize)) ==
1098                ARES_SUCCESS)
1099         {
1100           if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups)
1101             /* ignore errors */
1102             (void)config_lookup(channel, p, "bind", "local");
1103         }
1104         fclose(fp);
1105       }
1106       else {
1107         error = ERRNO;
1108         switch(error) {
1109         case ENOENT:
1110         case ESRCH:
1111           status = ARES_EOF;
1112           break;
1113         default:
1114           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1115                          error, strerror(error)));
1116           DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
1117           status = ARES_EFILE;
1118         }
1119       }
1120     }
1121
1122     if(line)
1123       free(line);
1124   }
1125
1126 #endif
1127
1128   /* Handle errors. */
1129   if (status != ARES_EOF)
1130     {
1131       if (servers != NULL)
1132         free(servers);
1133       if (sortlist != NULL)
1134         free(sortlist);
1135       return status;
1136     }
1137
1138   /* If we got any name server entries, fill them in. */
1139 #ifdef WIN32
1140 okay:
1141 #endif
1142   if (servers)
1143     {
1144       channel->servers = servers;
1145       channel->nservers = nservers;
1146     }
1147
1148   /* If we got any sortlist entries, fill them in. */
1149   if (sortlist)
1150     {
1151       channel->sortlist = sortlist;
1152       channel->nsort = nsort;
1153     }
1154
1155   return ARES_SUCCESS;
1156 }
1157
1158 static int init_by_defaults(ares_channel channel)
1159 {
1160   char *hostname = NULL;
1161   int rc = ARES_SUCCESS;
1162 #ifdef HAVE_GETHOSTNAME
1163   char *dot;
1164 #endif
1165
1166   if (channel->flags == -1)
1167     channel->flags = 0;
1168   if (channel->timeout == -1)
1169     channel->timeout = DEFAULT_TIMEOUT;
1170   if (channel->tries == -1)
1171     channel->tries = DEFAULT_TRIES;
1172   if (channel->ndots == -1)
1173     channel->ndots = 1;
1174   if (channel->rotate == -1)
1175     channel->rotate = 0;
1176   if (channel->udp_port == -1)
1177     channel->udp_port = htons(NAMESERVER_PORT);
1178   if (channel->tcp_port == -1)
1179     channel->tcp_port = htons(NAMESERVER_PORT);
1180
1181   if (channel->nservers == -1) {
1182     /* If nobody specified servers, try a local named. */
1183     channel->servers = malloc(sizeof(struct server_state));
1184     if (!channel->servers) {
1185       rc = ARES_ENOMEM;
1186       goto error;
1187     }
1188     channel->servers[0].addr.family = AF_INET;
1189     channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK);
1190     channel->nservers = 1;
1191   }
1192
1193 #if defined(USE_WINSOCK)
1194 #define toolong(x) (x == -1) &&  (SOCKERRNO == WSAEFAULT)
1195 #elif defined(ENAMETOOLONG)
1196 #define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \
1197                                  (SOCKERRNO == EINVAL))
1198 #else
1199 #define toolong(x) (x == -1) &&  (SOCKERRNO == EINVAL)
1200 #endif
1201
1202   if (channel->ndomains == -1) {
1203     /* Derive a default domain search list from the kernel hostname,
1204      * or set it to empty if the hostname isn't helpful.
1205      */
1206 #ifndef HAVE_GETHOSTNAME
1207     channel->ndomains = 0; /* default to none */
1208 #else
1209     GETHOSTNAME_TYPE_ARG2 lenv = 64;
1210     size_t len = 64;
1211     int res;
1212     channel->ndomains = 0; /* default to none */
1213
1214     hostname = malloc(len);
1215     if(!hostname) {
1216       rc = ARES_ENOMEM;
1217       goto error;
1218     }
1219
1220     do {
1221       res = gethostname(hostname, lenv);
1222
1223       if(toolong(res)) {
1224         char *p;
1225         len *= 2;
1226         lenv *= 2;
1227         p = realloc(hostname, len);
1228         if(!p) {
1229           rc = ARES_ENOMEM;
1230           goto error;
1231         }
1232         hostname = p;
1233         continue;
1234       }
1235       else if(res) {
1236         rc = ARES_EBADNAME;
1237         goto error;
1238       }
1239
1240     } WHILE_FALSE;
1241
1242     dot = strchr(hostname, '.');
1243     if (dot) {
1244       /* a dot was found */
1245       channel->domains = malloc(sizeof(char *));
1246       if (!channel->domains) {
1247         rc = ARES_ENOMEM;
1248         goto error;
1249       }
1250       channel->domains[0] = strdup(dot + 1);
1251       if (!channel->domains[0]) {
1252         rc = ARES_ENOMEM;
1253         goto error;
1254       }
1255       channel->ndomains = 1;
1256     }
1257 #endif
1258   }
1259
1260   if (channel->nsort == -1) {
1261     channel->sortlist = NULL;
1262     channel->nsort = 0;
1263   }
1264
1265   if (!channel->lookups) {
1266     channel->lookups = strdup("fb");
1267     if (!channel->lookups)
1268       rc = ARES_ENOMEM;
1269   }
1270
1271   error:
1272   if(rc) {
1273     if(channel->servers) {
1274       free(channel->servers);
1275       channel->servers = NULL;
1276     }
1277
1278     if(channel->domains && channel->domains[0])
1279       free(channel->domains[0]);
1280     if(channel->domains) {
1281       free(channel->domains);
1282       channel->domains = NULL;
1283     }
1284
1285     if(channel->lookups) {
1286       free(channel->lookups);
1287       channel->lookups = NULL;
1288     }
1289   }
1290
1291   if(hostname)
1292     free(hostname);
1293
1294   return rc;
1295 }
1296
1297 #if !defined(WIN32) && !defined(WATT32)
1298 static int config_domain(ares_channel channel, char *str)
1299 {
1300   char *q;
1301
1302   /* Set a single search domain. */
1303   q = str;
1304   while (*q && !ISSPACE(*q))
1305     q++;
1306   *q = '\0';
1307   return set_search(channel, str);
1308 }
1309
1310 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
1311     defined(__OPTIMIZE__) && defined(__unix__) &&  defined(__i386__)
1312   /* workaround icc 9.1 optimizer issue */
1313 # define vqualifier volatile
1314 #else
1315 # define vqualifier
1316 #endif
1317
1318 static int config_lookup(ares_channel channel, const char *str,
1319                          const char *bindch, const char *filech)
1320 {
1321   char lookups[3], *l;
1322   const char *vqualifier p;
1323
1324   /* Set the lookup order.  Only the first letter of each work
1325    * is relevant, and it has to be "b" for DNS or "f" for the
1326    * host file.  Ignore everything else.
1327    */
1328   l = lookups;
1329   p = str;
1330   while (*p)
1331     {
1332       if ((*p == *bindch || *p == *filech) && l < lookups + 2) {
1333         if (*p == *bindch) *l++ = 'b';
1334         else *l++ = 'f';
1335       }
1336       while (*p && !ISSPACE(*p) && (*p != ','))
1337         p++;
1338       while (*p && (ISSPACE(*p) || (*p == ',')))
1339         p++;
1340     }
1341   *l = '\0';
1342   channel->lookups = strdup(lookups);
1343   return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
1344 }
1345 #endif  /* !WIN32 & !WATT32 */
1346
1347 #ifndef WATT32
1348 static int config_nameserver(struct server_state **servers, int *nservers,
1349                              char *str)
1350 {
1351   struct ares_addr host;
1352   struct server_state *newserv;
1353   char *p, *txtaddr;
1354   /* On Windows, there may be more than one nameserver specified in the same
1355    * registry key, so we parse input as a space or comma seperated list.
1356    */
1357   for (p = str; p;)
1358     {
1359       /* Skip whitespace and commas. */
1360       while (*p && (ISSPACE(*p) || (*p == ',')))
1361         p++;
1362       if (!*p)
1363         /* No more input, done. */
1364         break;
1365
1366       /* Pointer to start of IPv4 or IPv6 address part. */
1367       txtaddr = p;
1368
1369       /* Advance past this address. */
1370       while (*p && !ISSPACE(*p) && (*p != ','))
1371         p++;
1372       if (*p)
1373         /* Null terminate this address. */
1374         *p++ = '\0';
1375       else
1376         /* Reached end of input, done when this address is processed. */
1377         p = NULL;
1378
1379       /* Convert textual address to binary format. */
1380       if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
1381         host.family = AF_INET;
1382       else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1)
1383         host.family = AF_INET6;
1384       else
1385         continue;
1386
1387       /* Resize servers state array. */
1388       newserv = realloc(*servers, (*nservers + 1) *
1389                         sizeof(struct server_state));
1390       if (!newserv)
1391         return ARES_ENOMEM;
1392
1393       /* Store address data. */
1394       newserv[*nservers].addr.family = host.family;
1395       if (host.family == AF_INET)
1396         memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
1397                sizeof(host.addrV4));
1398       else
1399         memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
1400                sizeof(host.addrV6));
1401
1402       /* Update arguments. */
1403       *servers = newserv;
1404       *nservers += 1;
1405     }
1406
1407   return ARES_SUCCESS;
1408 }
1409
1410 #ifndef WIN32
1411 static int config_sortlist(struct apattern **sortlist, int *nsort,
1412                            const char *str)
1413 {
1414   struct apattern pat;
1415   const char *q;
1416
1417   /* Add sortlist entries. */
1418   while (*str && *str != ';')
1419     {
1420       int bits;
1421       char ipbuf[16], ipbufpfx[32];
1422       /* Find just the IP */
1423       q = str;
1424       while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
1425         q++;
1426       memcpy(ipbuf, str, q-str);
1427       ipbuf[q-str] = '\0';
1428       /* Find the prefix */
1429       if (*q == '/')
1430         {
1431           const char *str2 = q+1;
1432           while (*q && *q != ';' && !ISSPACE(*q))
1433             q++;
1434           memcpy(ipbufpfx, str, q-str);
1435           ipbufpfx[q-str] = '\0';
1436           str = str2;
1437         }
1438       else
1439         ipbufpfx[0] = '\0';
1440       /* Lets see if it is CIDR */
1441       /* First we'll try IPv6 */
1442       if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf,
1443                                      &pat.addrV6,
1444                                      sizeof(pat.addrV6))) > 0)
1445         {
1446           pat.type = PATTERN_CIDR;
1447           pat.mask.bits = (unsigned short)bits;
1448           pat.family = AF_INET6;
1449           if (!sortlist_alloc(sortlist, nsort, &pat))
1450             return ARES_ENOMEM;
1451         }
1452       else if (ipbufpfx[0] &&
1453                (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4,
1454                                           sizeof(pat.addrV4))) > 0)
1455         {
1456           pat.type = PATTERN_CIDR;
1457           pat.mask.bits = (unsigned short)bits;
1458           pat.family = AF_INET;
1459           if (!sortlist_alloc(sortlist, nsort, &pat))
1460             return ARES_ENOMEM;
1461         }
1462       /* See if it is just a regular IP */
1463       else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0)
1464         {
1465           if (ipbufpfx[0])
1466             {
1467               memcpy(ipbuf, str, q-str);
1468               ipbuf[q-str] = '\0';
1469               if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0)
1470                 natural_mask(&pat);
1471             }
1472           else
1473             natural_mask(&pat);
1474           pat.family = AF_INET;
1475           pat.type = PATTERN_MASK;
1476           if (!sortlist_alloc(sortlist, nsort, &pat))
1477             return ARES_ENOMEM;
1478         }
1479       else
1480         {
1481           while (*q && *q != ';' && !ISSPACE(*q))
1482             q++;
1483         }
1484       str = q;
1485       while (ISSPACE(*str))
1486         str++;
1487     }
1488
1489   return ARES_SUCCESS;
1490 }
1491 #endif  /* !WIN32 */
1492 #endif  /* !WATT32 */
1493
1494 static int set_search(ares_channel channel, const char *str)
1495 {
1496   int n;
1497   const char *p, *q;
1498
1499   if(channel->ndomains != -1) {
1500     /* if we already have some domains present, free them first */
1501     for(n=0; n < channel->ndomains; n++)
1502       free(channel->domains[n]);
1503     free(channel->domains);
1504     channel->domains = NULL;
1505     channel->ndomains = -1;
1506   }
1507
1508   /* Count the domains given. */
1509   n = 0;
1510   p = str;
1511   while (*p)
1512     {
1513       while (*p && !ISSPACE(*p))
1514         p++;
1515       while (ISSPACE(*p))
1516         p++;
1517       n++;
1518     }
1519
1520   if (!n)
1521     {
1522       channel->ndomains = 0;
1523       return ARES_SUCCESS;
1524     }
1525
1526   channel->domains = malloc(n * sizeof(char *));
1527   if (!channel->domains)
1528     return ARES_ENOMEM;
1529
1530   /* Now copy the domains. */
1531   n = 0;
1532   p = str;
1533   while (*p)
1534     {
1535       channel->ndomains = n;
1536       q = p;
1537       while (*q && !ISSPACE(*q))
1538         q++;
1539       channel->domains[n] = malloc(q - p + 1);
1540       if (!channel->domains[n])
1541         return ARES_ENOMEM;
1542       memcpy(channel->domains[n], p, q - p);
1543       channel->domains[n][q - p] = 0;
1544       p = q;
1545       while (ISSPACE(*p))
1546         p++;
1547       n++;
1548     }
1549   channel->ndomains = n;
1550
1551   return ARES_SUCCESS;
1552 }
1553
1554 static int set_options(ares_channel channel, const char *str)
1555 {
1556   const char *p, *q, *val;
1557
1558   p = str;
1559   while (*p)
1560     {
1561       q = p;
1562       while (*q && !ISSPACE(*q))
1563         q++;
1564       val = try_option(p, q, "ndots:");
1565       if (val && channel->ndots == -1)
1566         channel->ndots = aresx_sltosi(strtol(val, NULL, 10));
1567       val = try_option(p, q, "retrans:");
1568       if (val && channel->timeout == -1)
1569         channel->timeout = aresx_sltosi(strtol(val, NULL, 10));
1570       val = try_option(p, q, "retry:");
1571       if (val && channel->tries == -1)
1572         channel->tries = aresx_sltosi(strtol(val, NULL, 10));
1573       val = try_option(p, q, "rotate");
1574       if (val && channel->rotate == -1)
1575         channel->rotate = 1;
1576       p = q;
1577       while (ISSPACE(*p))
1578         p++;
1579     }
1580
1581   return ARES_SUCCESS;
1582 }
1583
1584 static const char *try_option(const char *p, const char *q, const char *opt)
1585 {
1586   size_t len = strlen(opt);
1587   return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL;
1588 }
1589
1590 #if !defined(WIN32) && !defined(WATT32)
1591 static char *try_config(char *s, const char *opt, char scc)
1592 {
1593   size_t len;
1594   char *p;
1595   char *q;
1596
1597   if (!s || !opt)
1598     /* no line or no option */
1599     return NULL;
1600
1601   /* Hash '#' character is always used as primary comment char, additionally
1602      a not-NUL secondary comment char will be considered when specified. */
1603
1604   /* trim line comment */
1605   p = s;
1606   if(scc)
1607     while (*p && (*p != '#') && (*p != scc))
1608       p++;
1609   else
1610     while (*p && (*p != '#'))
1611       p++;
1612   *p = '\0';
1613
1614   /* trim trailing whitespace */
1615   q = p - 1;
1616   while ((q >= s) && ISSPACE(*q))
1617     q--;
1618   *++q = '\0';
1619
1620   /* skip leading whitespace */
1621   p = s;
1622   while (*p && ISSPACE(*p))
1623     p++;
1624
1625   if (!*p)
1626     /* empty line */
1627     return NULL;
1628
1629   if ((len = strlen(opt)) == 0)
1630     /* empty option */
1631     return NULL;
1632
1633   if (strncmp(p, opt, len) != 0)
1634     /* line and option do not match */
1635     return NULL;
1636
1637   /* skip over given option name */
1638   p += len;
1639
1640   if (!*p)
1641     /* no option value */
1642     return NULL;
1643
1644   if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p))
1645     /* whitespace between option name and value is mandatory
1646        for given option names which do not end with ':' or '=' */
1647     return NULL;
1648
1649   /* skip over whitespace */
1650   while (*p && ISSPACE(*p))
1651     p++;
1652
1653   if (!*p)
1654     /* no option value */
1655     return NULL;
1656
1657   /* return pointer to option value */
1658   return p;
1659 }
1660
1661 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
1662                           struct apattern *pat)
1663 {
1664   struct apattern *newsort;
1665   newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
1666   if (!newsort)
1667     return 0;
1668   newsort[*nsort] = *pat;
1669   *sortlist = newsort;
1670   (*nsort)++;
1671   return 1;
1672 }
1673
1674 static int ip_addr(const char *ipbuf, ssize_t len, struct in_addr *addr)
1675 {
1676
1677   /* Four octets and three periods yields at most 15 characters. */
1678   if (len > 15)
1679     return -1;
1680
1681   addr->s_addr = inet_addr(ipbuf);
1682   if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
1683     return -1;
1684   return 0;
1685 }
1686
1687 static void natural_mask(struct apattern *pat)
1688 {
1689   struct in_addr addr;
1690
1691   /* Store a host-byte-order copy of pat in a struct in_addr.  Icky,
1692    * but portable.
1693    */
1694   addr.s_addr = ntohl(pat->addrV4.s_addr);
1695
1696   /* This is out of date in the CIDR world, but some people might
1697    * still rely on it.
1698    */
1699   if (IN_CLASSA(addr.s_addr))
1700     pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET);
1701   else if (IN_CLASSB(addr.s_addr))
1702     pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET);
1703   else
1704     pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET);
1705 }
1706 #endif /* !WIN32 && !WATT32 */
1707
1708 /* initialize an rc4 key. If possible a cryptographically secure random key
1709    is generated using a suitable function (for example win32's RtlGenRandom as
1710    described in
1711    http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
1712    otherwise the code defaults to cross-platform albeit less secure mechanism
1713    using rand
1714 */
1715 static void randomize_key(unsigned char* key,int key_data_len)
1716 {
1717   int randomized = 0;
1718   int counter=0;
1719 #ifdef WIN32
1720   BOOLEAN res;
1721   if (ares_fpSystemFunction036)
1722     {
1723       res = (*ares_fpSystemFunction036) (key, key_data_len);
1724       if (res)
1725         randomized = 1;
1726     }
1727 #else /* !WIN32 */
1728 #ifdef RANDOM_FILE
1729   FILE *f = fopen(RANDOM_FILE, "rb");
1730   if(f) {
1731     counter = aresx_uztosi(fread(key, 1, key_data_len, f));
1732     fclose(f);
1733   }
1734 #endif
1735 #endif /* WIN32 */
1736
1737   if (!randomized) {
1738     for (;counter<key_data_len;counter++)
1739       key[counter]=(unsigned char)(rand() % 256);
1740   }
1741 }
1742
1743 static int init_id_key(rc4_key* key,int key_data_len)
1744 {
1745   unsigned char index1;
1746   unsigned char index2;
1747   unsigned char* state;
1748   short counter;
1749   unsigned char *key_data_ptr = 0;
1750
1751   key_data_ptr = calloc(1,key_data_len);
1752   if (!key_data_ptr)
1753     return ARES_ENOMEM;
1754
1755   state = &key->state[0];
1756   for(counter = 0; counter < 256; counter++)
1757     /* unnecessary AND but it keeps some compilers happier */
1758     state[counter] = (unsigned char)(counter & 0xff);
1759   randomize_key(key->state,key_data_len);
1760   key->x = 0;
1761   key->y = 0;
1762   index1 = 0;
1763   index2 = 0;
1764   for(counter = 0; counter < 256; counter++)
1765   {
1766     index2 = (unsigned char)((key_data_ptr[index1] + state[counter] +
1767                               index2) % 256);
1768     ARES_SWAP_BYTE(&state[counter], &state[index2]);
1769
1770     index1 = (unsigned char)((index1 + 1) % key_data_len);
1771   }
1772   free(key_data_ptr);
1773   return ARES_SUCCESS;
1774 }
1775
1776 unsigned short ares__generate_new_id(rc4_key* key)
1777 {
1778   unsigned short r=0;
1779   ares__rc4(key, (unsigned char *)&r, sizeof(r));
1780   return r;
1781 }
1782
1783 void ares_set_local_ip4(ares_channel channel, unsigned int local_ip)
1784 {
1785   channel->local_ip4 = local_ip;
1786 }
1787
1788 /* local_ip6 should be 16 bytes in length */
1789 void ares_set_local_ip6(ares_channel channel,
1790                         const unsigned char* local_ip6)
1791 {
1792   memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
1793 }
1794
1795 /* local_dev_name should be null terminated. */
1796 void ares_set_local_dev(ares_channel channel,
1797                         const char* local_dev_name)
1798 {
1799   strncpy(channel->local_dev_name, local_dev_name,
1800           sizeof(channel->local_dev_name));
1801   channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
1802 }
1803
1804
1805 void ares_set_socket_callback(ares_channel channel,
1806                               ares_sock_create_callback cb,
1807                               void *data)
1808 {
1809   channel->sock_create_cb = cb;
1810   channel->sock_create_cb_data = data;
1811 }
1812
1813 void ares__init_servers_state(ares_channel channel)
1814 {
1815   struct server_state *server;
1816   int i;
1817
1818   for (i = 0; i < channel->nservers; i++)
1819     {
1820       server = &channel->servers[i];
1821       server->udp_socket = ARES_SOCKET_BAD;
1822       server->tcp_socket = ARES_SOCKET_BAD;
1823       server->tcp_connection_generation = ++channel->tcp_connection_generation;
1824       server->tcp_lenbuf_pos = 0;
1825       server->tcp_buffer_pos = 0;
1826       server->tcp_buffer = NULL;
1827       server->tcp_length = 0;
1828       server->qhead = NULL;
1829       server->qtail = NULL;
1830       ares__init_list_head(&server->queries_to_server);
1831       server->channel = channel;
1832       server->is_broken = 0;
1833     }
1834 }