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