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