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