Cleanup
[platform/upstream/c-ares.git] / ares_init.c
1 /* Copyright 1998 by the Massachusetts Institute of Technology.
2  *
3  * Permission to use, copy, modify, and distribute this
4  * software and its documentation for any purpose and without
5  * fee is hereby granted, provided that the above copyright
6  * notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting
8  * documentation, and that the name of M.I.T. not be used in
9  * advertising or publicity pertaining to distribution of the
10  * software without specific, written prior permission.
11  * M.I.T. makes no representations about the suitability of
12  * this software for any purpose.  It is provided "as is"
13  * without express or implied warranty.
14  */
15
16 #include "setup.h"
17 #include <sys/types.h>
18
19 #if defined(WIN32) && !defined(WATT32)
20 #include "nameser.h"
21 #include <iphlpapi.h>
22 #include <malloc.h>
23
24 #else
25 #include <sys/param.h>
26 #ifdef HAVE_SYS_TIME_H
27 #include <sys/time.h>
28 #endif
29
30 #ifdef HAVE_SYS_SOCKET_H
31 #include <sys/socket.h>
32 #endif
33
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #include <arpa/nameser.h>
38 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
39 #include <arpa/nameser_compat.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #endif
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <ctype.h>
50 #include <time.h>
51 #include <errno.h>
52 #include "ares.h"
53 #include "ares_private.h"
54 #include "inet_net_pton.h"
55
56 #ifdef WATT32
57 #undef WIN32  /* Redefined in MingW/MSVC headers */
58 #endif
59
60 static int init_by_options(ares_channel channel, struct ares_options *options,
61                            int optmask);
62 static int init_by_environment(ares_channel channel);
63 static int init_by_resolv_conf(ares_channel channel);
64 static int init_by_defaults(ares_channel channel);
65
66 static int config_nameserver(struct server_state **servers, int *nservers,
67                              char *str);
68 static int set_search(ares_channel channel, const char *str);
69 static int set_options(ares_channel channel, const char *str);
70 static const char *try_option(const char *p, const char *q, const char *opt);
71 #ifndef WIN32
72 static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat);
73 static int ip_addr(const char *s, int len, struct in_addr *addr);
74 static void natural_mask(struct apattern *pat);
75 static int config_domain(ares_channel channel, char *str);
76 static int config_lookup(ares_channel channel, const char *str,
77                          const char *bindch, const char *filech);
78 static int config_sortlist(struct apattern **sortlist, int *nsort,
79                            const char *str);
80 static char *try_config(char *s, const char *opt);
81 #endif
82
83 int ares_init(ares_channel *channelptr)
84 {
85   return ares_init_options(channelptr, NULL, 0);
86 }
87
88 int ares_init_options(ares_channel *channelptr, struct ares_options *options,
89                       int optmask)
90 {
91   ares_channel channel;
92   int i, status;
93   struct server_state *server;
94   struct timeval tv;
95
96   channel = malloc(sizeof(struct ares_channeldata));
97   if (!channel)
98     return ARES_ENOMEM;
99
100   /* Set everything to distinguished values so we know they haven't
101    * been set yet.
102    */
103   channel->flags = -1;
104   channel->timeout = -1;
105   channel->tries = -1;
106   channel->ndots = -1;
107   channel->udp_port = -1;
108   channel->tcp_port = -1;
109   channel->nservers = -1;
110   channel->ndomains = -1;
111   channel->nsort = -1;
112   channel->lookups = NULL;
113   channel->queries = NULL;
114   channel->domains = NULL;
115   channel->sortlist = NULL;
116
117   /* Initialize configuration by each of the four sources, from highest
118    * precedence to lowest.
119    */
120   status = init_by_options(channel, options, optmask);
121   if (status == ARES_SUCCESS)
122     status = init_by_environment(channel);
123   if (status == ARES_SUCCESS)
124     status = init_by_resolv_conf(channel);
125   if (status == ARES_SUCCESS)
126     status = init_by_defaults(channel);
127   if (status != ARES_SUCCESS)
128     {
129       /* Something failed; clean up memory we may have allocated. */
130       if (channel->nservers != -1)
131         free(channel->servers);
132       if (channel->domains)
133         {
134           for (i = 0; i < channel->ndomains; i++)
135             free(channel->domains[i]);
136           free(channel->domains);
137         }
138       if (channel->sortlist)
139         free(channel->sortlist);
140       if(channel->lookups)
141         free(channel->lookups);
142       free(channel);
143       return status;
144     }
145
146   /* Trim to one server if ARES_FLAG_PRIMARY is set. */
147   if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
148     channel->nservers = 1;
149
150   /* Initialize server states. */
151   for (i = 0; i < channel->nservers; i++)
152     {
153       server = &channel->servers[i];
154       server->udp_socket = ARES_SOCKET_BAD;
155       server->tcp_socket = ARES_SOCKET_BAD;
156       server->tcp_lenbuf_pos = 0;
157       server->tcp_buffer = NULL;
158       server->qhead = NULL;
159       server->qtail = NULL;
160     }
161
162   /* Choose a somewhat random query ID.  The main point is to avoid
163    * collisions with stale queries.  An attacker trying to spoof a DNS
164    * answer also has to guess the query ID, but it's only a 16-bit
165    * field, so there's not much to be done about that.
166    */
167   gettimeofday(&tv, NULL);
168   channel->next_id = (unsigned short)
169     (tv.tv_sec ^ tv.tv_usec ^ getpid()) & 0xffff;
170
171   channel->queries = NULL;
172
173   *channelptr = channel;
174   return ARES_SUCCESS;
175 }
176
177 static int init_by_options(ares_channel channel, struct ares_options *options,
178                            int optmask)
179 {
180   int i;
181
182   /* Easy stuff. */
183   if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
184     channel->flags = options->flags;
185   if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
186     channel->timeout = options->timeout;
187   if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
188     channel->tries = options->tries;
189   if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
190     channel->ndots = options->ndots;
191   if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
192     channel->udp_port = options->udp_port;
193   if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
194     channel->tcp_port = options->tcp_port;
195
196   /* Copy the servers, if given. */
197   if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
198     {
199       channel->servers =
200         malloc(options->nservers * sizeof(struct server_state));
201       if (!channel->servers && options->nservers != 0)
202         return ARES_ENOMEM;
203       for (i = 0; i < options->nservers; i++)
204         channel->servers[i].addr = options->servers[i];
205       channel->nservers = options->nservers;
206     }
207
208   /* Copy the domains, if given.  Keep channel->ndomains consistent so
209    * we can clean up in case of error.
210    */
211   if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
212     {
213       channel->domains = malloc(options->ndomains * sizeof(char *));
214       if (!channel->domains && options->ndomains != 0)
215         return ARES_ENOMEM;
216       for (i = 0; i < options->ndomains; i++)
217         {
218           channel->ndomains = i;
219           channel->domains[i] = strdup(options->domains[i]);
220           if (!channel->domains[i])
221             return ARES_ENOMEM;
222         }
223       channel->ndomains = options->ndomains;
224     }
225
226   /* Set lookups, if given. */
227   if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
228     {
229       channel->lookups = strdup(options->lookups);
230       if (!channel->lookups)
231         return ARES_ENOMEM;
232     }
233
234   return ARES_SUCCESS;
235 }
236
237 static int init_by_environment(ares_channel channel)
238 {
239   const char *localdomain, *res_options;
240   int status;
241
242   localdomain = getenv("LOCALDOMAIN");
243   if (localdomain && channel->ndomains == -1)
244     {
245       status = set_search(channel, localdomain);
246       if (status != ARES_SUCCESS)
247         return status;
248     }
249
250   res_options = getenv("RES_OPTIONS");
251   if (res_options)
252     {
253       status = set_options(channel, res_options);
254       if (status != ARES_SUCCESS)
255         return status;
256     }
257
258   return ARES_SUCCESS;
259 }
260
261 #ifdef WIN32
262 /*
263  * Warning: returns a dynamically allocated buffer, the user MUST
264  * use free() if the function returns 1
265  */
266 static int get_res_nt(HKEY hKey, const char *subkey, char **obuf)
267 {
268   /* Test for the size we need */
269   DWORD size = 0;
270   int result;
271
272   result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
273   if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
274     return 0;
275   *obuf = malloc(size+1);
276   if (!*obuf)
277     return 0;
278
279   if (RegQueryValueEx(hKey, subkey, 0, NULL,
280                       (LPBYTE)*obuf, &size) != ERROR_SUCCESS)
281   {
282     free(*obuf);
283     return 0;
284   }
285   if (size == 1)
286   {
287     free(*obuf);
288     return 0;
289   }
290   return 1;
291 }
292
293 static int get_res_interfaces_nt(HKEY hKey, const char *subkey, char **obuf)
294 {
295   char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */
296   DWORD enum_size = 39;
297   int idx = 0;
298   HKEY hVal;
299
300   while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0,
301                       NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
302   {
303     int rc;
304
305     enum_size = 39;
306     if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) !=
307         ERROR_SUCCESS)
308       continue;
309     rc = get_res_nt(hVal, subkey, obuf);
310       RegCloseKey(hVal);
311     if (rc)
312       return 1;
313     }
314   return 0;
315 }
316
317 static int get_iphlpapi_dns_info (char *ret_buf, size_t ret_size)
318 {
319   FIXED_INFO    *fi   = alloca (sizeof(*fi));
320   DWORD          size = sizeof (*fi);
321   typedef DWORD (WINAPI* get_net_param_func) (FIXED_INFO*, DWORD*);
322   get_net_param_func GetNetworkParams;  /* available only on Win-98/2000+ */
323   HMODULE        handle;
324   IP_ADDR_STRING *ipAddr;
325   int            i, count = 0;
326   int            debug  = 0;
327   size_t         ip_size = sizeof("255.255.255.255,")-1;
328   size_t         left = ret_size;
329   char          *ret = ret_buf;
330   HRESULT        res;
331
332   if (!fi)
333      return (0);
334
335   handle = LoadLibrary ("iphlpapi.dll");
336   if (!handle)
337      return (0);
338
339   GetNetworkParams = (get_net_param_func) GetProcAddress (handle, "GetNetworkParams");
340   if (!GetNetworkParams)
341      goto quit;
342
343   res = (*GetNetworkParams) (fi, &size);
344   if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
345      goto quit;
346
347   fi = alloca (size);
348   if (!fi || (*GetNetworkParams) (fi, &size) != ERROR_SUCCESS)
349      goto quit;
350
351   if (debug)
352   {
353     printf ("Host Name: %s\n", fi->HostName);
354     printf ("Domain Name: %s\n", fi->DomainName);
355     printf ("DNS Servers:\n"
356             "    %s (primary)\n", fi->DnsServerList.IpAddress.String);
357   }
358   if (inet_addr(fi->DnsServerList.IpAddress.String) != INADDR_NONE &&
359       left > ip_size)
360   {
361     ret += sprintf (ret, "%s,", fi->DnsServerList.IpAddress.String);
362     left -= ret - ret_buf;
363     count++;
364   }
365
366   for (i = 0, ipAddr = fi->DnsServerList.Next; ipAddr && left > ip_size;
367        ipAddr = ipAddr->Next, i++)
368   {
369     if (inet_addr(ipAddr->IpAddress.String) != INADDR_NONE)
370     {
371        ret += sprintf (ret, "%s,", ipAddr->IpAddress.String);
372        left -= ret - ret_buf;
373        count++;
374     }
375     if (debug)
376        printf ("    %s (secondary %d)\n", ipAddr->IpAddress.String, i+1);
377   }
378
379 quit:
380   if (handle)
381      FreeLibrary (handle);
382
383   if (debug && left <= ip_size)
384      printf ("Too many nameservers. Truncating to %d addressess", count);
385   if (ret > ret_buf)
386      ret[-1] = '\0';
387   return (count);
388 }
389 #endif
390
391 static int init_by_resolv_conf(ares_channel channel)
392 {
393   char *line = NULL;
394   int status = -1, nservers = 0, nsort = 0;
395   struct server_state *servers = NULL;
396   struct apattern *sortlist = NULL;
397
398 #ifdef WIN32
399
400     /*
401   NameServer info via IPHLPAPI (IP helper API):
402     GetNetworkParams() should be the trusted source for this.
403     Available in Win-98/2000 and later. If that fail, fall-back to
404     registry information.
405
406   NameServer Registry:
407
408    On Windows 9X, the DNS server can be found in:
409 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP\NameServer
410
411         On Windows NT/2000/XP/2003:
412 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\NameServer
413         or
414 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DhcpNameServer
415         or
416 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
417 NameServer
418         or
419 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
420 DhcpNameServer
421    */
422
423   HKEY mykey;
424   HKEY subkey;
425   DWORD data_type;
426   DWORD bytes;
427   DWORD result;
428   char  buf[256];
429
430   if (channel->nservers > -1)  /* don't override ARES_OPT_SERVER */
431      return ARES_SUCCESS;
432
433   if (get_iphlpapi_dns_info(buf,sizeof(buf)) > 0)
434   {
435     status = config_nameserver(&servers, &nservers, buf);
436     if (status == ARES_SUCCESS)
437       goto okay;
438   }
439
440   if (IS_NT())
441   {
442     if (RegOpenKeyEx(
443           HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
444           KEY_READ, &mykey
445           ) == ERROR_SUCCESS)
446     {
447       RegOpenKeyEx(mykey, "Interfaces", 0,
448                    KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey);
449       if (get_res_nt(mykey, NAMESERVER, &line))
450       {
451         status = config_nameserver(&servers, &nservers, line);
452         free(line);
453       }
454       else if (get_res_nt(mykey, DHCPNAMESERVER, &line))
455       {
456         status = config_nameserver(&servers, &nservers, line);
457         free(line);
458       }
459       /* Try the interfaces */
460       else if (get_res_interfaces_nt(subkey, NAMESERVER, &line))
461       {
462         status = config_nameserver(&servers, &nservers, line);
463         free(line);
464       }
465       else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
466       {
467         status = config_nameserver(&servers, &nservers, line);
468         free(line);
469       }
470       RegCloseKey(subkey);
471       RegCloseKey(mykey);
472     }
473   }
474   else
475   {
476     if (RegOpenKeyEx(
477           HKEY_LOCAL_MACHINE, WIN_NS_9X, 0,
478           KEY_READ, &mykey
479           ) == ERROR_SUCCESS)
480     {
481       if ((result = RegQueryValueEx(
482              mykey, NAMESERVER, NULL, &data_type,
483              NULL, &bytes
484              )
485             ) == ERROR_SUCCESS ||
486           result == ERROR_MORE_DATA)
487       {
488         if (bytes)
489         {
490           line = (char *)malloc(bytes+1);
491           if (RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type,
492                               (unsigned char *)line, &bytes) ==
493               ERROR_SUCCESS)
494           {
495             status = config_nameserver(&servers, &nservers, line);
496           }
497           free(line);
498         }
499       }
500     }
501     RegCloseKey(mykey);
502   }
503
504   if (status == ARES_SUCCESS)
505     status = ARES_EOF;
506
507 #elif defined(riscos)
508
509   /* Under RISC OS, name servers are listed in the
510      system variable Inet$Resolvers, space separated. */
511
512   line = getenv("Inet$Resolvers");
513   status = ARES_EOF;
514   if (line) {
515     char *resolvers = strdup(line), *pos, *space;
516
517     if (!resolvers)
518       return ARES_ENOMEM;
519
520     pos = resolvers;
521     do {
522       space = strchr(pos, ' ');
523       if (space)
524         *space = 0;
525       status = config_nameserver(&servers, &nservers, pos);
526       if (status != ARES_SUCCESS)
527         break;
528       pos = space + 1;
529     } while (space);
530
531     if (status == ARES_SUCCESS)
532       status = ARES_EOF;
533
534     free(resolvers);
535   }
536
537 #elif defined(WATT32)
538   int i;
539
540   sock_init();
541   for (i = 0; def_nameservers[i]; i++)
542       ;
543   if (i == 0)
544     return ARES_SUCCESS; /* use localhost DNS server */
545
546   nservers = i;
547   servers = calloc(sizeof(*servers), i);
548   if (!servers)
549      return ARES_ENOMEM;
550
551   for (i = 0; def_nameservers[i]; i++)
552       servers[i].addr.s_addr = htonl(def_nameservers[i]);
553   status = ARES_EOF;
554
555 #else
556   {
557     char *p;
558     FILE *fp;
559     int linesize;
560
561     fp = fopen(PATH_RESOLV_CONF, "r");
562     if (!fp)
563       return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
564     while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
565     {
566       if ((p = try_config(line, "domain")))
567         status = config_domain(channel, p);
568       else if ((p = try_config(line, "lookup")) && !channel->lookups)
569         status = config_lookup(channel, p, "bind", "file");
570       else if ((p = try_config(line, "search")))
571         status = set_search(channel, p);
572       else if ((p = try_config(line, "nameserver")) && channel->nservers == -1)
573         status = config_nameserver(&servers, &nservers, p);
574       else if ((p = try_config(line, "sortlist")) && channel->nsort == -1)
575         status = config_sortlist(&sortlist, &nsort, p);
576       else if ((p = try_config(line, "options")))
577         status = set_options(channel, p);
578       else
579         status = ARES_SUCCESS;
580       if (status != ARES_SUCCESS)
581         break;
582     }
583     fclose(fp);
584
585     if (!channel->lookups) {
586       /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
587       fp = fopen("/etc/nsswitch.conf", "r");
588       if (fp) {
589         while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
590         {
591           if ((p = try_config(line, "hosts:")) && !channel->lookups)
592             status = config_lookup(channel, p, "dns", "files");
593         }
594         fclose(fp);
595       }
596     }
597
598     if (!channel->lookups) {
599       /* Linux / GNU libc 2.x and possibly others have host.conf */
600       fp = fopen("/etc/host.conf", "r");
601       if (fp) {
602         while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
603         {
604           if ((p = try_config(line, "order")) && !channel->lookups)
605             status = config_lookup(channel, p, "bind", "hosts");
606         }
607         fclose(fp);
608       }
609     }
610
611     if (!channel->lookups) {
612       /* Tru64 uses /etc/svc.conf */
613       fp = fopen("/etc/svc.conf", "r");
614       if (fp) {
615         while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
616         {
617           if ((p = try_config(line, "hosts=")) && !channel->lookups)
618             status = config_lookup(channel, p, "bind", "local");
619         }
620         fclose(fp);
621       }
622     }
623
624     if(line)
625       free(line);
626   }
627
628 #endif
629
630   /* Handle errors. */
631   if (status != ARES_EOF)
632     {
633       if (servers != NULL)
634         free(servers);
635       if (sortlist != NULL)
636         free(sortlist);
637       return status;
638     }
639
640   /* If we got any name server entries, fill them in. */
641 #ifdef WIN32
642 okay:
643 #endif
644   if (servers)
645     {
646       channel->servers = servers;
647       channel->nservers = nservers;
648     }
649
650   /* If we got any sortlist entries, fill them in. */
651   if (sortlist)
652     {
653       channel->sortlist = sortlist;
654       channel->nsort = nsort;
655     }
656
657   return ARES_SUCCESS;
658 }
659
660 static int init_by_defaults(ares_channel channel)
661 {
662   char hostname[MAXHOSTNAMELEN + 1];
663
664   if (channel->flags == -1)
665     channel->flags = 0;
666   if (channel->timeout == -1)
667     channel->timeout = DEFAULT_TIMEOUT;
668   if (channel->tries == -1)
669     channel->tries = DEFAULT_TRIES;
670   if (channel->ndots == -1)
671     channel->ndots = 1;
672   if (channel->udp_port == -1)
673     channel->udp_port = htons(NAMESERVER_PORT);
674   if (channel->tcp_port == -1)
675     channel->tcp_port = htons(NAMESERVER_PORT);
676
677   if (channel->nservers == -1)
678     {
679       /* If nobody specified servers, try a local named. */
680       channel->servers = malloc(sizeof(struct server_state));
681       if (!channel->servers)
682         return ARES_ENOMEM;
683       channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK);
684       channel->nservers = 1;
685     }
686
687   if (channel->ndomains == -1)
688     {
689       /* Derive a default domain search list from the kernel hostname,
690        * or set it to empty if the hostname isn't helpful.
691        */
692       if (gethostname(hostname, sizeof(hostname)) == -1
693           || !strchr(hostname, '.'))
694         {
695           channel->domains = malloc(0);
696           channel->ndomains = 0;
697         }
698       else
699         {
700           channel->domains = malloc(sizeof(char *));
701           if (!channel->domains)
702             return ARES_ENOMEM;
703           channel->ndomains = 0;
704           channel->domains[0] = strdup(strchr(hostname, '.') + 1);
705           if (!channel->domains[0])
706             return ARES_ENOMEM;
707           channel->ndomains = 1;
708         }
709     }
710
711   if (channel->nsort == -1)
712     {
713       channel->sortlist = NULL;
714       channel->nsort = 0;
715     }
716
717   if (!channel->lookups)
718     {
719       channel->lookups = strdup("fb");
720       if (!channel->lookups)
721         return ARES_ENOMEM;
722     }
723
724   return ARES_SUCCESS;
725 }
726
727 #ifndef WIN32
728 static int config_domain(ares_channel channel, char *str)
729 {
730   char *q;
731
732   /* Set a single search domain. */
733   q = str;
734   while (*q && !isspace((unsigned char)*q))
735     q++;
736   *q = 0;
737   return set_search(channel, str);
738 }
739
740 static int config_lookup(ares_channel channel, const char *str,
741                          const char *bindch, const char *filech)
742 {
743   char lookups[3], *l;
744   const char *p;
745
746   /* Set the lookup order.  Only the first letter of each work
747    * is relevant, and it has to be "b" for DNS or "f" for the
748    * host file.  Ignore everything else.
749    */
750   l = lookups;
751   p = str;
752   while (*p)
753     {
754       if ((*p == *bindch || *p == *filech) && l < lookups + 2) {
755         if (*p == *bindch) *l++ = 'b';
756         else *l++ = 'f';
757       }
758       while (*p && !isspace((unsigned char)*p) && (*p != ','))
759         p++;
760       while (*p && (isspace((unsigned char)*p) || (*p == ',')))
761         p++;
762     }
763   *l = 0;
764   channel->lookups = strdup(lookups);
765   return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
766 }
767
768 #endif
769
770 static int config_nameserver(struct server_state **servers, int *nservers,
771                              char *str)
772 {
773   struct in_addr addr;
774   struct server_state *newserv;
775   /* On Windows, there may be more than one nameserver specified in the same
776    * registry key, so we parse it as a space or comma seperated list.
777    */
778 #ifdef WIN32
779   char *p = str;
780   char *begin = str;
781   int more = 1;
782   while (more)
783   {
784     more = 0;
785     while (*p && !isspace(*p) && *p != ',')
786       p++;
787
788     if (*p)
789     {
790       *p = 0;
791       more = 1;
792     }
793
794     /* Skip multiple spaces or trailing spaces */
795     if (!*begin)
796     {
797       begin = ++p;
798       continue;
799     }
800
801     /* This is the part that actually sets the nameserver */
802     addr.s_addr = inet_addr(begin);
803     if (addr.s_addr == INADDR_NONE)
804       continue;
805     newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
806     if (!newserv)
807       return ARES_ENOMEM;
808     newserv[*nservers].addr = addr;
809     *servers = newserv;
810     (*nservers)++;
811
812     if (!more)
813       break;
814     begin = ++p;
815   }
816 #else
817   /* Add a nameserver entry, if this is a valid address. */
818   addr.s_addr = inet_addr(str);
819   if (addr.s_addr == INADDR_NONE)
820     return ARES_SUCCESS;
821   newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
822   if (!newserv)
823     return ARES_ENOMEM;
824   newserv[*nservers].addr = addr;
825   *servers = newserv;
826   (*nservers)++;
827 #endif
828   return ARES_SUCCESS;
829 }
830
831 #ifndef WIN32
832 static int config_sortlist(struct apattern **sortlist, int *nsort,
833                            const char *str)
834 {
835   struct apattern pat;
836   const char *q;
837
838   /* Add sortlist entries. */
839   while (*str && *str != ';')
840     {
841       int bits;
842       char ipbuf[16], ipbufpfx[32];
843       /* Find just the IP */
844       q = str;
845       while (*q && *q != '/' && *q != ';' && !isspace((unsigned char)*q))
846         q++;
847       memcpy(ipbuf, str, (int)(q-str));
848       ipbuf[(int)(q-str)] = 0;
849       /* Find the prefix */
850       if (*q == '/')
851         {
852           const char *str2 = q+1;
853           while (*q && *q != ';' && !isspace((unsigned char)*q))
854             q++;
855           memcpy(ipbufpfx, str, (int)(q-str));
856           ipbufpfx[(int)(q-str)] = 0;
857           str = str2;
858         }
859       else
860         ipbufpfx[0] = 0;
861       /* Lets see if it is CIDR */
862       /* First we'll try IPv6 */
863       if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx ? ipbufpfx : ipbuf,
864                                      &pat.addr.addr6,
865                                      sizeof(pat.addr.addr6))) > 0)
866         {
867           pat.type = PATTERN_CIDR;
868           pat.mask.bits = bits;
869           pat.family = AF_INET6;
870           if (!sortlist_alloc(sortlist, nsort, &pat))
871             return ARES_ENOMEM;
872         }
873       if (ipbufpfx &&
874           (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addr.addr4,
875                                      sizeof(pat.addr.addr4))) > 0)
876         {
877           pat.type = PATTERN_CIDR;
878           pat.mask.bits = bits;
879           pat.family = AF_INET;
880           if (!sortlist_alloc(sortlist, nsort, &pat))
881             return ARES_ENOMEM;
882         }
883       /* See if it is just a regular IP */
884       else if (ip_addr(ipbuf, (int)(q-str), &pat.addr.addr4) == 0)
885         {
886           if (ipbufpfx)
887             {
888               memcpy(ipbuf, str, (int)(q-str));
889               ipbuf[(int)(q-str)] = 0;
890               if (ip_addr(ipbuf, (int)(q - str), &pat.mask.addr.addr4) != 0)
891                 natural_mask(&pat);
892             }
893           else
894             natural_mask(&pat);
895           pat.family = AF_INET;
896           pat.type = PATTERN_MASK;
897           if (!sortlist_alloc(sortlist, nsort, &pat))
898             return ARES_ENOMEM;
899         }
900       else
901         {
902           while (*q && *q != ';' && !isspace((unsigned char)*q))
903             q++;
904         }
905       str = q;
906       while (isspace((unsigned char)*str))
907         str++;
908     }
909
910   return ARES_SUCCESS;
911 }
912 #endif
913
914 static int set_search(ares_channel channel, const char *str)
915 {
916   int n;
917   const char *p, *q;
918
919   if(channel->ndomains != -1) {
920     /* if we already have some domains present, free them first */
921     for(n=0; n < channel->ndomains; n++)
922       free(channel->domains[n]);
923     free(channel->domains);
924     channel->ndomains = -1;
925   }
926
927   /* Count the domains given. */
928   n = 0;
929   p = str;
930   while (*p)
931     {
932       while (*p && !isspace((unsigned char)*p))
933         p++;
934       while (isspace((unsigned char)*p))
935         p++;
936       n++;
937     }
938
939   channel->domains = malloc(n * sizeof(char *));
940   if (!channel->domains && n)
941     return ARES_ENOMEM;
942
943   /* Now copy the domains. */
944   n = 0;
945   p = str;
946   while (*p)
947     {
948       channel->ndomains = n;
949       q = p;
950       while (*q && !isspace((unsigned char)*q))
951         q++;
952       channel->domains[n] = malloc(q - p + 1);
953       if (!channel->domains[n])
954         return ARES_ENOMEM;
955       memcpy(channel->domains[n], p, q - p);
956       channel->domains[n][q - p] = 0;
957       p = q;
958       while (isspace((unsigned char)*p))
959         p++;
960       n++;
961     }
962   channel->ndomains = n;
963
964   return ARES_SUCCESS;
965 }
966
967 static int set_options(ares_channel channel, const char *str)
968 {
969   const char *p, *q, *val;
970
971   p = str;
972   while (*p)
973     {
974       q = p;
975       while (*q && !isspace((unsigned char)*q))
976         q++;
977       val = try_option(p, q, "ndots:");
978       if (val && channel->ndots == -1)
979         channel->ndots = atoi(val);
980       val = try_option(p, q, "retrans:");
981       if (val && channel->timeout == -1)
982         channel->timeout = atoi(val);
983       val = try_option(p, q, "retry:");
984       if (val && channel->tries == -1)
985         channel->tries = atoi(val);
986       p = q;
987       while (isspace((unsigned char)*p))
988         p++;
989     }
990
991   return ARES_SUCCESS;
992 }
993
994 #ifndef WIN32
995 static char *try_config(char *s, const char *opt)
996 {
997   size_t len;
998
999   len = strlen(opt);
1000   if (strncmp(s, opt, len) != 0 || !isspace((unsigned char)s[len]))
1001     return NULL;
1002   s += len;
1003   while (isspace((unsigned char)*s))
1004     s++;
1005   return s;
1006 }
1007
1008 #endif
1009
1010 static const char *try_option(const char *p, const char *q, const char *opt)
1011 {
1012   size_t len = strlen(opt);
1013   return ((size_t)(q - p) > len && !strncmp(p, opt, len)) ? &p[len] : NULL;
1014 }
1015
1016 #ifndef WIN32
1017 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
1018                           struct apattern *pat)
1019 {
1020   struct apattern *newsort;
1021   newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
1022   if (!newsort)
1023     return 0;
1024   newsort[*nsort] = *pat;
1025   *sortlist = newsort;
1026   (*nsort)++;
1027   return 1;
1028 }
1029
1030 static int ip_addr(const char *ipbuf, int len, struct in_addr *addr)
1031 {
1032
1033   /* Four octets and three periods yields at most 15 characters. */
1034   if (len > 15)
1035     return -1;
1036
1037   addr->s_addr = inet_addr(ipbuf);
1038   if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
1039     return -1;
1040   return 0;
1041 }
1042
1043 static void natural_mask(struct apattern *pat)
1044 {
1045   struct in_addr addr;
1046
1047   /* Store a host-byte-order copy of pat in a struct in_addr.  Icky,
1048    * but portable.
1049    */
1050   addr.s_addr = ntohl(pat->addr.addr4.s_addr);
1051
1052   /* This is out of date in the CIDR world, but some people might
1053    * still rely on it.
1054    */
1055   if (IN_CLASSA(addr.s_addr))
1056     pat->mask.addr.addr4.s_addr = htonl(IN_CLASSA_NET);
1057   else if (IN_CLASSB(addr.s_addr))
1058     pat->mask.addr.addr4.s_addr = htonl(IN_CLASSB_NET);
1059   else
1060     pat->mask.addr.addr4.s_addr = htonl(IN_CLASSC_NET);
1061 }
1062 #endif