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