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