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