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