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