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