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