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