Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libcr / net / getaddrinfo.c
1 /*      $FreeBSD: src/lib/libc/net/getaddrinfo.c,v 1.9.2.14 2002/11/08 17:49:31 ume Exp $       */
2 /*      $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $    */
3
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 /*
34  * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
35  *
36  * Issues to be discussed:
37  * - Thread safe-ness must be checked.
38  * - Return values.  There are nonstandard return values defined and used
39  *   in the source code.  This is because RFC2553 is silent about which error
40  *   code must be returned for which situation.
41  * - freeaddrinfo(NULL).  RFC2553 is silent about it.  XNET 5.2 says it is
42  *   invalid.  current code - SEGV on freeaddrinfo(NULL)
43  *
44  * Note:
45  * - The code filters out AFs that are not supported by the kernel,
46  *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
47  *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
48  *   in ai_flags?
49  * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
50  *   (1) what should we do against numeric hostname (2) what should we do
51  *   against NULL hostname (3) what is AI_ADDRCONFIG itself.  AF not ready?
52  *   non-loopback address configured?  global address configured?
53  *
54  * OS specific notes for netbsd/openbsd/freebsd4/bsdi4:
55  * - To avoid search order issue, we have a big amount of code duplicate
56  *   from gethnamaddr.c and some other places.  The issues that there's no
57  *   lower layer function to lookup "IPv4 or IPv6" record.  Calling
58  *   gethostbyname2 from getaddrinfo will end up in wrong search order, as
59  *   presented above.
60  *
61  * OS specific notes for freebsd4:
62  * - FreeBSD supported $GAI.  The code does not.
63  * - FreeBSD allowed classful IPv4 numeric (127.1), the code does not.
64  */
65
66 #include <sys/types.h>
67 #include <sys/param.h>
68 #include <sys/socket.h>
69 #include <net/if.h>
70 #include <netinet/in.h>
71 #include <arpa/inet.h>
72 #include <arpa/nameser.h>
73 #include <netdb.h>
74 #include <resolv.h>
75 #include <string.h>
76 #include <stdlib.h>
77 #include <stddef.h>
78 #include <ctype.h>
79 #include <unistd.h>
80 #include <stdio.h>
81 #include <errno.h>
82
83 #include "res_config.h"
84
85 #ifdef DEBUG
86 #include <syslog.h>
87 #endif
88
89 #if defined(__KAME__) && defined(INET6)
90 # define FAITH
91 #endif
92
93 #define SUCCESS 0
94 #define ANY 0
95 #define YES 1
96 #define NO  0
97
98 static const char in_addrany[] = { 0, 0, 0, 0 };
99 static const char in_loopback[] = { 127, 0, 0, 1 };
100 #ifdef INET6
101 static const char in6_addrany[] = {
102         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
103 };
104 static const char in6_loopback[] = {
105         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
106 };
107 #endif
108
109 static const struct afd {
110         int a_af;
111         int a_addrlen;
112         int a_socklen;
113         int a_off;
114         const char *a_addrany;
115         const char *a_loopback;
116         int a_scoped;
117 } afdl [] = {
118 #ifdef INET6
119 #define N_INET6 0
120         {PF_INET6, sizeof(struct in6_addr),
121          sizeof(struct sockaddr_in6),
122          offsetof(struct sockaddr_in6, sin6_addr),
123          in6_addrany, in6_loopback, 1},
124 #define N_INET 1
125 #else
126 #define N_INET 0
127 #endif
128         {PF_INET, sizeof(struct in_addr),
129          sizeof(struct sockaddr_in),
130          offsetof(struct sockaddr_in, sin_addr),
131          in_addrany, in_loopback, 0},
132         {0, 0, 0, 0, NULL, NULL, 0},
133 };
134
135 struct explore {
136         int e_af;
137         int e_socktype;
138         int e_protocol;
139         const char *e_protostr;
140         int e_wild;
141 #define WILD_AF(ex)             ((ex)->e_wild & 0x01)
142 #define WILD_SOCKTYPE(ex)       ((ex)->e_wild & 0x02)
143 #define WILD_PROTOCOL(ex)       ((ex)->e_wild & 0x04)
144 };
145
146 static const struct explore explore[] = {
147 #if 0
148         { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
149 #endif
150 #ifdef INET6
151         { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
152         { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
153         { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
154 #endif
155         { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
156         { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
157         { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
158         { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
159         { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
160         { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
161         { -1, 0, 0, NULL, 0 },
162 };
163
164 #ifdef INET6
165 #define PTON_MAX        16
166 #else
167 #define PTON_MAX        4
168 #endif
169
170 #define MAXPACKET       (64*1024)
171
172 typedef union {
173         HEADER hdr;
174         u_char buf[MAXPACKET];
175 } querybuf;
176
177 struct res_target {
178         struct res_target *next;
179         const char *name;       /* domain name */
180         int qclass, qtype;      /* class and type of query */
181         u_char *answer;         /* buffer to put answer */
182         int anslen;             /* size of answer buffer */
183         int n;                  /* result length */
184 };
185
186 static int str_isnumber __P((const char *));
187 static int explore_fqdn __P((const struct addrinfo *, const char *,
188         const char *, struct addrinfo **));
189 static int explore_null __P((const struct addrinfo *,
190         const char *, struct addrinfo **));
191 static int explore_numeric __P((const struct addrinfo *, const char *,
192         const char *, struct addrinfo **));
193 static int explore_numeric_scope __P((const struct addrinfo *, const char *,
194         const char *, struct addrinfo **));
195 static int get_canonname __P((const struct addrinfo *,
196         struct addrinfo *, const char *));
197 static struct addrinfo *get_ai __P((const struct addrinfo *,
198         const struct afd *, const char *));
199 static int get_portmatch __P((const struct addrinfo *, const char *));
200 static int get_port __P((struct addrinfo *, const char *, int));
201 static const struct afd *find_afd __P((int));
202 static int addrconfig __P((struct addrinfo *));
203 #ifdef INET6
204 static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *, u_int32_t *));
205 #endif
206
207 static struct addrinfo *getanswer __P((const querybuf *, int, const char *,
208         int, const struct addrinfo *));
209 static int _dns_getaddrinfo __P((const struct addrinfo *, const char *,
210         struct addrinfo **));
211 static struct addrinfo *_gethtent __P((FILE *fp, const char *,
212         const struct addrinfo *));
213 static int _files_getaddrinfo __P((const struct addrinfo *, const char *,
214         struct addrinfo **));
215 #ifdef YP
216 static int _nis_getaddrinfo __P((const struct addrinfo *, const char *,
217         struct addrinfo **));
218 #endif
219
220 static int res_queryN __P((const char *, struct res_target *));
221 static int res_searchN __P((const char *, struct res_target *));
222 static int res_querydomainN __P((const char *, const char *,
223         struct res_target *));
224
225 static char *ai_errlist[] = {
226         "Success",
227         "Address family for hostname not supported",    /* EAI_ADDRFAMILY */
228         "Temporary failure in name resolution",         /* EAI_AGAIN      */
229         "Invalid value for ai_flags",                   /* EAI_BADFLAGS   */
230         "Non-recoverable failure in name resolution",   /* EAI_FAIL       */
231         "ai_family not supported",                      /* EAI_FAMILY     */
232         "Memory allocation failure",                    /* EAI_MEMORY     */
233         "No address associated with hostname",          /* EAI_NODATA     */
234         "hostname nor servname provided, or not known", /* EAI_NONAME     */
235         "servname not supported for ai_socktype",       /* EAI_SERVICE    */
236         "ai_socktype not supported",                    /* EAI_SOCKTYPE   */
237         "System error returned in errno",               /* EAI_SYSTEM     */
238         "Invalid value for hints",                      /* EAI_BADHINTS   */
239         "Resolved protocol is unknown",                 /* EAI_PROTOCOL   */
240         "Unknown error",                                /* EAI_MAX        */
241 };
242
243 /*
244  * Select order host function.
245  */
246 #define MAXHOSTCONF     4
247
248 #ifndef HOSTCONF
249 #  define       HOSTCONF        "/etc/host.conf"
250 #endif /* !HOSTCONF */
251
252 struct _hostconf {
253         int (*byname)(const struct addrinfo *, const char *,
254                       struct addrinfo **);
255 };
256
257 /* default order */
258 static struct _hostconf _hostconf[MAXHOSTCONF] = {
259         _dns_getaddrinfo,
260         _files_getaddrinfo,
261 #ifdef ICMPNL
262         NULL,
263 #endif /* ICMPNL */
264 };
265
266 static int      _hostconf_init_done;
267 static void     _hostconf_init(void);
268
269 /* Make getaddrinfo() thread-safe in libc for use with kernel threads. */
270 #include "libc_private.h"
271 #include "spinlock.h"
272 /*
273  * XXX: Our res_*() is not thread-safe.  So, we share lock between
274  * getaddrinfo() and getipnodeby*().  Still, we cannot use
275  * getaddrinfo() and getipnodeby*() in conjunction with other
276  * functions which call res_*().
277  */
278 spinlock_t __getaddrinfo_thread_lock = _SPINLOCK_INITIALIZER;
279 #define THREAD_LOCK() \
280         if (__isthreaded) _SPINLOCK(&__getaddrinfo_thread_lock);
281 #define THREAD_UNLOCK() \
282         if (__isthreaded) _SPINUNLOCK(&__getaddrinfo_thread_lock);
283
284 /* XXX macros that make external reference is BAD. */
285
286 #define GET_AI(ai, afd, addr) \
287 do { \
288         /* external reference: pai, error, and label free */ \
289         (ai) = get_ai(pai, (afd), (addr)); \
290         if ((ai) == NULL) { \
291                 error = EAI_MEMORY; \
292                 goto free; \
293         } \
294 } while (/*CONSTCOND*/0)
295
296 #define GET_PORT(ai, serv) \
297 do { \
298         /* external reference: error and label free */ \
299         error = get_port((ai), (serv), 0); \
300         if (error != 0) \
301                 goto free; \
302 } while (/*CONSTCOND*/0)
303
304 #define GET_CANONNAME(ai, str) \
305 do { \
306         /* external reference: pai, error and label free */ \
307         error = get_canonname(pai, (ai), (str)); \
308         if (error != 0) \
309                 goto free; \
310 } while (/*CONSTCOND*/0)
311
312 #define ERR(err) \
313 do { \
314         /* external reference: error, and label bad */ \
315         error = (err); \
316         goto bad; \
317         /*NOTREACHED*/ \
318 } while (/*CONSTCOND*/0)
319
320 #define MATCH_FAMILY(x, y, w) \
321         ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
322 #define MATCH(x, y, w) \
323         ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
324
325 char *
326 gai_strerror(ecode)
327         int ecode;
328 {
329         if (ecode < 0 || ecode > EAI_MAX)
330                 ecode = EAI_MAX;
331         return ai_errlist[ecode];
332 }
333
334 void
335 freeaddrinfo(ai)
336         struct addrinfo *ai;
337 {
338         struct addrinfo *next;
339
340         do {
341                 next = ai->ai_next;
342                 if (ai->ai_canonname)
343                         free(ai->ai_canonname);
344                 /* no need to free(ai->ai_addr) */
345                 free(ai);
346                 ai = next;
347         } while (ai);
348 }
349
350 static int
351 str_isnumber(p)
352         const char *p;
353 {
354         char *ep;
355
356         if (*p == '\0')
357                 return NO;
358         ep = NULL;
359         errno = 0;
360         (void)strtoul(p, &ep, 10);
361         if (errno == 0 && ep && *ep == '\0')
362                 return YES;
363         else
364                 return NO;
365 }
366
367 int
368 getaddrinfo(hostname, servname, hints, res)
369         const char *hostname, *servname;
370         const struct addrinfo *hints;
371         struct addrinfo **res;
372 {
373         struct addrinfo sentinel;
374         struct addrinfo *cur;
375         int error = 0;
376         struct addrinfo ai;
377         struct addrinfo ai0;
378         struct addrinfo *pai;
379         const struct explore *ex;
380
381         memset(&sentinel, 0, sizeof(sentinel));
382         cur = &sentinel;
383         pai = &ai;
384         pai->ai_flags = 0;
385         pai->ai_family = PF_UNSPEC;
386         pai->ai_socktype = ANY;
387         pai->ai_protocol = ANY;
388         pai->ai_addrlen = 0;
389         pai->ai_canonname = NULL;
390         pai->ai_addr = NULL;
391         pai->ai_next = NULL;
392
393         if (hostname == NULL && servname == NULL)
394                 return EAI_NONAME;
395         if (hints) {
396                 /* error check for hints */
397                 if (hints->ai_addrlen || hints->ai_canonname ||
398                     hints->ai_addr || hints->ai_next)
399                         ERR(EAI_BADHINTS); /* xxx */
400                 if (hints->ai_flags & ~AI_MASK)
401                         ERR(EAI_BADFLAGS);
402                 switch (hints->ai_family) {
403                 case PF_UNSPEC:
404                 case PF_INET:
405 #ifdef INET6
406                 case PF_INET6:
407 #endif
408                         break;
409                 default:
410                         ERR(EAI_FAMILY);
411                 }
412                 memcpy(pai, hints, sizeof(*pai));
413
414                 /*
415                  * if both socktype/protocol are specified, check if they
416                  * are meaningful combination.
417                  */
418                 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
419                         for (ex = explore; ex->e_af >= 0; ex++) {
420                                 if (pai->ai_family != ex->e_af)
421                                         continue;
422                                 if (ex->e_socktype == ANY)
423                                         continue;
424                                 if (ex->e_protocol == ANY)
425                                         continue;
426                                 if (pai->ai_socktype == ex->e_socktype &&
427                                     pai->ai_protocol != ex->e_protocol) {
428                                         ERR(EAI_BADHINTS);
429                                 }
430                         }
431                 }
432         }
433
434         /*
435          * post-2553: AI_ALL and AI_V4MAPPED are effective only against
436          * AF_INET6 query.  They need to be ignored if specified in other
437          * occassions.
438          */
439         switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {
440         case AI_V4MAPPED:
441         case AI_ALL | AI_V4MAPPED:
442                 if (pai->ai_family != AF_INET6)
443                         pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
444                 break;
445         case AI_ALL:
446 #if 1
447                 /* illegal */
448                 ERR(EAI_BADFLAGS);
449 #else
450                 pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
451 #endif
452                 break;
453         }
454
455         /*
456          * check for special cases.  (1) numeric servname is disallowed if
457          * socktype/protocol are left unspecified. (2) servname is disallowed
458          * for raw and other inet{,6} sockets.
459          */
460         if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
461 #ifdef PF_INET6
462             || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
463 #endif
464             ) {
465                 ai0 = *pai;     /* backup *pai */
466
467                 if (pai->ai_family == PF_UNSPEC) {
468 #ifdef PF_INET6
469                         pai->ai_family = PF_INET6;
470 #else
471                         pai->ai_family = PF_INET;
472 #endif
473                 }
474                 error = get_portmatch(pai, servname);
475                 if (error)
476                         ERR(error);
477
478                 *pai = ai0;
479         }
480
481         ai0 = *pai;
482
483         /* NULL hostname, or numeric hostname */
484         for (ex = explore; ex->e_af >= 0; ex++) {
485                 *pai = ai0;
486
487                 /* PF_UNSPEC entries are prepared for DNS queries only */
488                 if (ex->e_af == PF_UNSPEC)
489                         continue;
490
491                 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
492                         continue;
493                 if (!MATCH(pai->ai_socktype, ex->e_socktype,
494                            WILD_SOCKTYPE(ex)))
495                         continue;
496                 if (!MATCH(pai->ai_protocol, ex->e_protocol,
497                            WILD_PROTOCOL(ex)))
498                         continue;
499
500                 if (pai->ai_family == PF_UNSPEC)
501                         pai->ai_family = ex->e_af;
502                 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
503                         pai->ai_socktype = ex->e_socktype;
504                 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
505                         pai->ai_protocol = ex->e_protocol;
506
507                 if (hostname == NULL)
508                         error = explore_null(pai, servname, &cur->ai_next);
509                 else
510                         error = explore_numeric_scope(pai, hostname, servname,
511                                                       &cur->ai_next);
512
513                 if (error)
514                         goto free;
515
516                 while (cur && cur->ai_next)
517                         cur = cur->ai_next;
518         }
519
520         /*
521          * XXX
522          * If numreic representation of AF1 can be interpreted as FQDN
523          * representation of AF2, we need to think again about the code below.
524          */
525         if (sentinel.ai_next)
526                 goto good;
527
528         if (pai->ai_flags & AI_NUMERICHOST)
529                 ERR(EAI_NONAME);
530         if (hostname == NULL)
531                 ERR(EAI_NODATA);
532
533         if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))
534                 ERR(EAI_FAIL);
535
536         /*
537          * hostname as alphabetical name.
538          * we would like to prefer AF_INET6 than AF_INET, so we'll make a
539          * outer loop by AFs.
540          */
541         for (ex = explore; ex->e_af >= 0; ex++) {
542                 *pai = ai0;
543
544                 /* require exact match for family field */
545                 if (pai->ai_family != ex->e_af)
546                         continue;
547
548                 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) {
549                         continue;
550                 }
551                 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) {
552                         continue;
553                 }
554
555                 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
556                         pai->ai_socktype = ex->e_socktype;
557                 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
558                         pai->ai_protocol = ex->e_protocol;
559
560                 error = explore_fqdn(pai, hostname, servname, &cur->ai_next);
561
562                 while (cur && cur->ai_next)
563                         cur = cur->ai_next;
564         }
565
566         /* XXX */
567         if (sentinel.ai_next)
568                 error = 0;
569
570         if (error)
571                 goto free;
572         if (error == 0) {
573                 if (sentinel.ai_next) {
574  good:
575                         *res = sentinel.ai_next;
576                         return SUCCESS;
577                 } else
578                         error = EAI_FAIL;
579         }
580  free:
581  bad:
582         if (sentinel.ai_next)
583                 freeaddrinfo(sentinel.ai_next);
584         *res = NULL;
585         return error;
586 }
587
588 static char *
589 _hgetword(char **pp)
590 {
591         char c, *p, *ret;
592         const char *sp;
593         static const char sep[] = "# \t\n";
594
595         ret = NULL;
596         for (p = *pp; (c = *p) != '\0'; p++) {
597                 for (sp = sep; *sp != '\0'; sp++) {
598                         if (c == *sp)
599                                 break;
600                 }
601                 if (c == '#')
602                         p[1] = '\0';    /* ignore rest of line */
603                 if (ret == NULL) {
604                         if (*sp == '\0')
605                                 ret = p;
606                 } else {
607                         if (*sp != '\0') {
608                                 *p++ = '\0';
609                                 break;
610                         }
611                 }
612         }
613         *pp = p;
614         if (ret == NULL || *ret == '\0')
615                 return NULL;
616         return ret;
617 }
618
619 /*
620  * Initialize hostconf structure.
621  */
622
623 static void
624 _hostconf_init(void)
625 {
626         FILE *fp;
627         int n;
628         char *p, *line;
629         char buf[BUFSIZ];
630
631         _hostconf_init_done = 1;
632         n = 0;
633         p = HOSTCONF;
634         if ((fp = fopen(p, "r")) == NULL)
635                 return;
636         while (n < MAXHOSTCONF && fgets(buf, sizeof(buf), fp)) {
637                 line = buf;
638                 if ((p = _hgetword(&line)) == NULL)
639                         continue;
640                 do {
641                         if (strcmp(p, "hosts") == 0
642                         ||  strcmp(p, "local") == 0
643                         ||  strcmp(p, "file") == 0
644                         ||  strcmp(p, "files") == 0)
645                                 _hostconf[n++].byname = _files_getaddrinfo;
646                         else if (strcmp(p, "dns") == 0
647                              ||  strcmp(p, "bind") == 0)
648                                 _hostconf[n++].byname = _dns_getaddrinfo;
649 #ifdef YP
650                         else if (strcmp(p, "nis") == 0)
651                                 _hostconf[n++].byname = _nis_getaddrinfo;
652 #endif
653                 } while ((p = _hgetword(&line)) != NULL);
654         }
655         fclose(fp);
656         if (n < 0) {
657                 /* no keyword found. do not change default configuration */
658                 return;
659         }
660         for (; n < MAXHOSTCONF; n++)
661                 _hostconf[n].byname = NULL;
662 }
663
664 /*
665  * FQDN hostname, DNS lookup
666  */
667 static int
668 explore_fqdn(pai, hostname, servname, res)
669         const struct addrinfo *pai;
670         const char *hostname;
671         const char *servname;
672         struct addrinfo **res;
673 {
674         struct addrinfo *result;
675         struct addrinfo *cur;
676         int error = 0, i;
677
678         result = NULL;
679         *res = NULL;
680
681         THREAD_LOCK();
682
683         /*
684          * if the servname does not match socktype/protocol, ignore it.
685          */
686         if (get_portmatch(pai, servname) != 0) {
687                 THREAD_UNLOCK();
688                 return 0;
689         }
690
691         if (!_hostconf_init_done)
692                 _hostconf_init();
693
694         for (i = 0; i < MAXHOSTCONF; i++) {
695                 if (!_hostconf[i].byname)
696                         continue;
697                 error = (*_hostconf[i].byname)(pai, hostname, &result);
698                 if (error != 0)
699                         continue;
700                 for (cur = result; cur; cur = cur->ai_next) {
701                         GET_PORT(cur, servname);
702                         /* canonname should be filled already */
703                 }
704                 THREAD_UNLOCK();
705                 *res = result;
706                 return 0;
707         }
708
709 free:
710         THREAD_UNLOCK();
711         if (result)
712                 freeaddrinfo(result);
713         return error;
714 }
715
716 /*
717  * hostname == NULL.
718  * passive socket -> anyaddr (0.0.0.0 or ::)
719  * non-passive socket -> localhost (127.0.0.1 or ::1)
720  */
721 static int
722 explore_null(pai, servname, res)
723         const struct addrinfo *pai;
724         const char *servname;
725         struct addrinfo **res;
726 {
727         int s;
728         const struct afd *afd;
729         struct addrinfo *cur;
730         struct addrinfo sentinel;
731         int error;
732
733         *res = NULL;
734         sentinel.ai_next = NULL;
735         cur = &sentinel;
736
737         /*
738          * filter out AFs that are not supported by the kernel
739          * XXX errno?
740          */
741         s = socket(pai->ai_family, SOCK_DGRAM, 0);
742         if (s < 0) {
743                 if (errno != EMFILE)
744                         return 0;
745         } else
746                 _close(s);
747
748         /*
749          * if the servname does not match socktype/protocol, ignore it.
750          */
751         if (get_portmatch(pai, servname) != 0)
752                 return 0;
753
754         afd = find_afd(pai->ai_family);
755         if (afd == NULL)
756                 return 0;
757
758         if (pai->ai_flags & AI_PASSIVE) {
759                 GET_AI(cur->ai_next, afd, afd->a_addrany);
760                 /* xxx meaningless?
761                  * GET_CANONNAME(cur->ai_next, "anyaddr");
762                  */
763                 GET_PORT(cur->ai_next, servname);
764         } else {
765                 GET_AI(cur->ai_next, afd, afd->a_loopback);
766                 /* xxx meaningless?
767                  * GET_CANONNAME(cur->ai_next, "localhost");
768                  */
769                 GET_PORT(cur->ai_next, servname);
770         }
771         cur = cur->ai_next;
772
773         *res = sentinel.ai_next;
774         return 0;
775
776 free:
777         if (sentinel.ai_next)
778                 freeaddrinfo(sentinel.ai_next);
779         return error;
780 }
781
782 /*
783  * numeric hostname
784  */
785 static int
786 explore_numeric(pai, hostname, servname, res)
787         const struct addrinfo *pai;
788         const char *hostname;
789         const char *servname;
790         struct addrinfo **res;
791 {
792         const struct afd *afd;
793         struct addrinfo *cur;
794         struct addrinfo sentinel;
795         int error;
796         char pton[PTON_MAX];
797
798         *res = NULL;
799         sentinel.ai_next = NULL;
800         cur = &sentinel;
801
802         /*
803          * if the servname does not match socktype/protocol, ignore it.
804          */
805         if (get_portmatch(pai, servname) != 0)
806                 return 0;
807
808         afd = find_afd(pai->ai_family);
809         if (afd == NULL)
810                 return 0;
811
812         switch (afd->a_af) {
813 #if 1 /*X/Open spec*/
814         case AF_INET:
815                 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
816                         if (pai->ai_family == afd->a_af ||
817                             pai->ai_family == PF_UNSPEC /*?*/) {
818                                 GET_AI(cur->ai_next, afd, pton);
819                                 GET_PORT(cur->ai_next, servname);
820                                 while (cur && cur->ai_next)
821                                         cur = cur->ai_next;
822                         } else
823                                 ERR(EAI_FAMILY);        /*xxx*/
824                 }
825                 break;
826 #endif
827         default:
828                 if (inet_pton(afd->a_af, hostname, pton) == 1) {
829                         if (pai->ai_family == afd->a_af ||
830                             pai->ai_family == PF_UNSPEC /*?*/) {
831                                 GET_AI(cur->ai_next, afd, pton);
832                                 GET_PORT(cur->ai_next, servname);
833                                 while (cur && cur->ai_next)
834                                         cur = cur->ai_next;
835                         } else
836                                 ERR(EAI_FAMILY);        /* XXX */
837                 }
838                 break;
839         }
840
841         *res = sentinel.ai_next;
842         return 0;
843
844 free:
845 bad:
846         if (sentinel.ai_next)
847                 freeaddrinfo(sentinel.ai_next);
848         return error;
849 }
850
851 /*
852  * numeric hostname with scope
853  */
854 static int
855 explore_numeric_scope(pai, hostname, servname, res)
856         const struct addrinfo *pai;
857         const char *hostname;
858         const char *servname;
859         struct addrinfo **res;
860 {
861 #if !defined(SCOPE_DELIMITER) || !defined(INET6)
862         return explore_numeric(pai, hostname, servname, res);
863 #else
864         const struct afd *afd;
865         struct addrinfo *cur;
866         int error;
867         char *cp, *hostname2 = NULL, *scope, *addr;
868         struct sockaddr_in6 *sin6;
869
870         /*
871          * if the servname does not match socktype/protocol, ignore it.
872          */
873         if (get_portmatch(pai, servname) != 0)
874                 return 0;
875
876         afd = find_afd(pai->ai_family);
877         if (afd == NULL)
878                 return 0;
879         if (!afd->a_scoped)
880                 return explore_numeric(pai, hostname, servname, res);
881
882         cp = strchr(hostname, SCOPE_DELIMITER);
883         if (cp == NULL)
884                 return explore_numeric(pai, hostname, servname, res);
885
886         /*
887          * Handle special case of <scoped_address><delimiter><scope id>
888          */
889         hostname2 = strdup(hostname);
890         if (hostname2 == NULL)
891                 return EAI_MEMORY;
892         /* terminate at the delimiter */
893         hostname2[cp - hostname] = '\0';
894         addr = hostname2;
895         scope = cp + 1;
896
897         error = explore_numeric(pai, addr, servname, res);
898         if (error == 0) {
899                 u_int32_t scopeid;
900
901                 for (cur = *res; cur; cur = cur->ai_next) {
902                         if (cur->ai_family != AF_INET6)
903                                 continue;
904                         sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
905                         if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
906                                 free(hostname2);
907                                 return(EAI_NODATA); /* XXX: is return OK? */
908                         }
909                         sin6->sin6_scope_id = scopeid;
910                 }
911         }
912
913         free(hostname2);
914
915         return error;
916 #endif
917 }
918
919 static int
920 get_canonname(pai, ai, str)
921         const struct addrinfo *pai;
922         struct addrinfo *ai;
923         const char *str;
924 {
925         if ((pai->ai_flags & AI_CANONNAME) != 0) {
926                 ai->ai_canonname = (char *)malloc(strlen(str) + 1);
927                 if (ai->ai_canonname == NULL)
928                         return EAI_MEMORY;
929                 strlcpy(ai->ai_canonname, str, strlen(str) + 1);
930         }
931         return 0;
932 }
933
934 static struct addrinfo *
935 get_ai(pai, afd, addr)
936         const struct addrinfo *pai;
937         const struct afd *afd;
938         const char *addr;
939 {
940         char *p;
941         struct addrinfo *ai;
942 #ifdef FAITH
943         struct in6_addr faith_prefix;
944         char *fp_str;
945         int translate = 0;
946 #endif
947
948 #ifdef FAITH
949         /*
950          * Transfrom an IPv4 addr into a special IPv6 addr format for
951          * IPv6->IPv4 translation gateway. (only TCP is supported now)
952          *
953          * +-----------------------------------+------------+
954          * | faith prefix part (12 bytes)      | embedded   |
955          * |                                   | IPv4 addr part (4 bytes)
956          * +-----------------------------------+------------+
957          *
958          * faith prefix part is specified as ascii IPv6 addr format
959          * in environmental variable GAI.
960          * For FAITH to work correctly, routing to faith prefix must be
961          * setup toward a machine where a FAITH daemon operates.
962          * Also, the machine must enable some mechanizm
963          * (e.g. faith interface hack) to divert those packet with
964          * faith prefixed destination addr to user-land FAITH daemon.
965          */
966         fp_str = getenv("GAI");
967         if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
968             afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
969                 u_int32_t v4a;
970                 u_int8_t v4a_top;
971
972                 memcpy(&v4a, addr, sizeof v4a);
973                 v4a_top = v4a >> IN_CLASSA_NSHIFT;
974                 if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
975                     v4a_top != 0 && v4a != IN_LOOPBACKNET) {
976                         afd = &afdl[N_INET6];
977                         memcpy(&faith_prefix.s6_addr[12], addr,
978                                sizeof(struct in_addr));
979                         translate = 1;
980                 }
981         }
982 #endif
983
984         ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
985                 + (afd->a_socklen));
986         if (ai == NULL)
987                 return NULL;
988
989         memcpy(ai, pai, sizeof(struct addrinfo));
990         ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
991         memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
992         ai->ai_addr->sa_len = afd->a_socklen;
993         ai->ai_addrlen = afd->a_socklen;
994         ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
995         p = (char *)(ai->ai_addr);
996 #ifdef FAITH
997         if (translate == 1)
998                 memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen);
999         else
1000 #endif
1001         memcpy(p + afd->a_off, addr, afd->a_addrlen);
1002
1003         return ai;
1004 }
1005
1006 static int
1007 get_portmatch(ai, servname)
1008         const struct addrinfo *ai;
1009         const char *servname;
1010 {
1011
1012         /* get_port does not touch first argument. when matchonly == 1. */
1013         /* LINTED const cast */
1014         return get_port((struct addrinfo *)ai, servname, 1);
1015 }
1016
1017 static int
1018 get_port(ai, servname, matchonly)
1019         struct addrinfo *ai;
1020         const char *servname;
1021         int matchonly;
1022 {
1023         const char *proto;
1024         struct servent *sp;
1025         int port;
1026         int allownumeric;
1027
1028         if (servname == NULL)
1029                 return 0;
1030         switch (ai->ai_family) {
1031         case AF_INET:
1032 #ifdef AF_INET6
1033         case AF_INET6:
1034 #endif
1035                 break;
1036         default:
1037                 return 0;
1038         }
1039
1040         switch (ai->ai_socktype) {
1041         case SOCK_RAW:
1042                 return EAI_SERVICE;
1043         case SOCK_DGRAM:
1044         case SOCK_STREAM:
1045                 allownumeric = 1;
1046                 break;
1047         case ANY:
1048                 allownumeric = 0;
1049                 break;
1050         default:
1051                 return EAI_SOCKTYPE;
1052         }
1053
1054         if (str_isnumber(servname)) {
1055                 if (!allownumeric)
1056                         return EAI_SERVICE;
1057                 port = atoi(servname);
1058                 if (port < 0 || port > 65535)
1059                         return EAI_SERVICE;
1060                 port = htons(port);
1061         } else {
1062                 switch (ai->ai_socktype) {
1063                 case SOCK_DGRAM:
1064                         proto = "udp";
1065                         break;
1066                 case SOCK_STREAM:
1067                         proto = "tcp";
1068                         break;
1069                 default:
1070                         proto = NULL;
1071                         break;
1072                 }
1073
1074                 if ((sp = getservbyname(servname, proto)) == NULL)
1075                         return EAI_SERVICE;
1076                 port = sp->s_port;
1077         }
1078
1079         if (!matchonly) {
1080                 switch (ai->ai_family) {
1081                 case AF_INET:
1082                         ((struct sockaddr_in *)(void *)
1083                             ai->ai_addr)->sin_port = port;
1084                         break;
1085 #ifdef INET6
1086                 case AF_INET6:
1087                         ((struct sockaddr_in6 *)(void *)
1088                             ai->ai_addr)->sin6_port = port;
1089                         break;
1090 #endif
1091                 }
1092         }
1093
1094         return 0;
1095 }
1096
1097 static const struct afd *
1098 find_afd(af)
1099         int af;
1100 {
1101         const struct afd *afd;
1102
1103         if (af == PF_UNSPEC)
1104                 return NULL;
1105         for (afd = afdl; afd->a_af; afd++) {
1106                 if (afd->a_af == af)
1107                         return afd;
1108         }
1109         return NULL;
1110 }
1111
1112 /*
1113  * post-2553: AI_ADDRCONFIG check.  if we use getipnodeby* as backend, backend
1114  * will take care of it.
1115  * the semantics of AI_ADDRCONFIG is not defined well.  we are not sure
1116  * if the code is right or not.
1117  *
1118  * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
1119  * _dns_getaddrinfo.
1120  */
1121 static int
1122 addrconfig(pai)
1123         struct addrinfo *pai;
1124 {
1125         int s, af;
1126
1127         /*
1128          * TODO:
1129          * Note that implementation dependent test for address
1130          * configuration should be done everytime called
1131          * (or apropriate interval),
1132          * because addresses will be dynamically assigned or deleted.
1133          */
1134         af = pai->ai_family;
1135         if (af == AF_UNSPEC) {
1136                 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
1137                         af = AF_INET;
1138                 else {
1139                         _close(s);
1140                         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1141                                 af = AF_INET6;
1142                         else
1143                                 _close(s);
1144                 }
1145
1146         }
1147         if (af != AF_UNSPEC) {
1148                 if ((s = socket(af, SOCK_DGRAM, 0)) < 0)
1149                         return 0;
1150                 _close(s);
1151         }
1152         pai->ai_family = af;
1153         return 1;
1154 }
1155
1156 #ifdef INET6
1157 /* convert a string to a scope identifier. XXX: IPv6 specific */
1158 static int
1159 ip6_str2scopeid(scope, sin6, scopeid)
1160         char *scope;
1161         struct sockaddr_in6 *sin6;
1162         u_int32_t *scopeid;
1163 {
1164         u_long lscopeid;
1165         struct in6_addr *a6;
1166         char *ep;
1167
1168         a6 = &sin6->sin6_addr;
1169
1170         /* empty scopeid portion is invalid */
1171         if (*scope == '\0')
1172                 return -1;
1173
1174         if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
1175                 /*
1176                  * We currently assume a one-to-one mapping between links
1177                  * and interfaces, so we simply use interface indices for
1178                  * like-local scopes.
1179                  */
1180                 *scopeid = if_nametoindex(scope);
1181                 if (*scopeid == 0)
1182                         goto trynumeric;
1183                 return 0;
1184         }
1185
1186         /* still unclear about literal, allow numeric only - placeholder */
1187         if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1188                 goto trynumeric;
1189         if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1190                 goto trynumeric;
1191         else
1192                 goto trynumeric;        /* global */
1193
1194         /* try to convert to a numeric id as a last resort */
1195   trynumeric:
1196         errno = 0;
1197         lscopeid = strtoul(scope, &ep, 10);
1198         *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1199         if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1200                 return 0;
1201         else
1202                 return -1;
1203 }
1204 #endif
1205
1206 #ifdef RESOLVSORT
1207 struct addr_ptr {
1208         struct addrinfo *ai;
1209         int aval;
1210 };
1211
1212 static int
1213 addr4sort(struct addrinfo *sentinel)
1214 {
1215         struct addrinfo *ai;
1216         struct addr_ptr *addrs, addr;
1217         struct sockaddr_in *sin;
1218         int naddrs, i, j;
1219         int needsort = 0;
1220
1221         if (!sentinel)
1222                 return -1;
1223         naddrs = 0;
1224         for (ai = sentinel->ai_next; ai; ai = ai->ai_next)
1225                 naddrs++;
1226         if (naddrs < 2)
1227                 return 0;               /* We don't need sorting. */
1228         if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL)
1229                 return -1;
1230         i = 0;
1231         for (ai = sentinel->ai_next; ai; ai = ai->ai_next) {
1232                 sin = (struct sockaddr_in *)ai->ai_addr;
1233                 for (j = 0; (unsigned)j < _res.nsort; j++) {
1234                         if (_res.sort_list[j].addr.s_addr == 
1235                             (sin->sin_addr.s_addr & _res.sort_list[j].mask))
1236                                 break;
1237                 }
1238                 addrs[i].ai = ai;
1239                 addrs[i].aval = j;
1240                 if (needsort == 0 && i > 0 && j < addrs[i - 1].aval)
1241                         needsort = i;
1242                 i++;
1243         }
1244         if (!needsort) {
1245                 free(addrs);
1246                 return 0;
1247         }
1248
1249         while (needsort < naddrs) {
1250             for (j = needsort - 1; j >= 0; j--) {
1251                 if (addrs[j].aval > addrs[j+1].aval) {
1252                     addr = addrs[j];
1253                     addrs[j] = addrs[j + 1];
1254                     addrs[j + 1] = addr;
1255                 } else
1256                     break;
1257             }
1258             needsort++;
1259         }
1260
1261         ai = sentinel;
1262         for (i = 0; i < naddrs; ++i) {
1263                 ai->ai_next = addrs[i].ai;
1264                 ai = ai->ai_next;
1265         }
1266         ai->ai_next = NULL;
1267         free(addrs);
1268         return 0;
1269 }
1270 #endif /*RESOLVSORT*/
1271
1272 #ifdef DEBUG
1273 static const char AskedForGot[] =
1274         "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1275 #endif
1276
1277 static struct addrinfo *
1278 getanswer(answer, anslen, qname, qtype, pai)
1279         const querybuf *answer;
1280         int anslen;
1281         const char *qname;
1282         int qtype;
1283         const struct addrinfo *pai;
1284 {
1285         struct addrinfo sentinel, *cur;
1286         struct addrinfo ai;
1287         const struct afd *afd;
1288         char *canonname;
1289         const HEADER *hp;
1290         const u_char *cp;
1291         int n;
1292         const u_char *eom;
1293         char *bp, *ep;
1294         int type, class, ancount, qdcount;
1295         int haveanswer, had_error;
1296         char tbuf[MAXDNAME];
1297         int (*name_ok) __P((const char *));
1298         char hostbuf[8*1024];
1299
1300         memset(&sentinel, 0, sizeof(sentinel));
1301         cur = &sentinel;
1302
1303         canonname = NULL;
1304         eom = answer->buf + anslen;
1305         switch (qtype) {
1306         case T_A:
1307         case T_AAAA:
1308         case T_ANY:     /*use T_ANY only for T_A/T_AAAA lookup*/
1309                 name_ok = res_hnok;
1310                 break;
1311         default:
1312                 return (NULL);  /* XXX should be abort(); */
1313         }
1314         /*
1315          * find first satisfactory answer
1316          */
1317         hp = &answer->hdr;
1318         ancount = ntohs(hp->ancount);
1319         qdcount = ntohs(hp->qdcount);
1320         bp = hostbuf;
1321         ep = hostbuf + sizeof hostbuf;
1322         cp = answer->buf + HFIXEDSZ;
1323         if (qdcount != 1) {
1324                 h_errno = NO_RECOVERY;
1325                 return (NULL);
1326         }
1327         n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1328         if ((n < 0) || !(*name_ok)(bp)) {
1329                 h_errno = NO_RECOVERY;
1330                 return (NULL);
1331         }
1332         cp += n + QFIXEDSZ;
1333         if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1334                 /* res_send() has already verified that the query name is the
1335                  * same as the one we sent; this just gets the expanded name
1336                  * (i.e., with the succeeding search-domain tacked on).
1337                  */
1338                 n = strlen(bp) + 1;             /* for the \0 */
1339                 if (n >= MAXHOSTNAMELEN) {
1340                         h_errno = NO_RECOVERY;
1341                         return (NULL);
1342                 }
1343                 canonname = bp;
1344                 bp += n;
1345                 /* The qname can be abbreviated, but h_name is now absolute. */
1346                 qname = canonname;
1347         }
1348         haveanswer = 0;
1349         had_error = 0;
1350         while (ancount-- > 0 && cp < eom && !had_error) {
1351                 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1352                 if ((n < 0) || !(*name_ok)(bp)) {
1353                         had_error++;
1354                         continue;
1355                 }
1356                 cp += n;                        /* name */
1357                 type = _getshort(cp);
1358                 cp += INT16SZ;                  /* type */
1359                 class = _getshort(cp);
1360                 cp += INT16SZ + INT32SZ;        /* class, TTL */
1361                 n = _getshort(cp);
1362                 cp += INT16SZ;                  /* len */
1363                 if (class != C_IN) {
1364                         /* XXX - debug? syslog? */
1365                         cp += n;
1366                         continue;               /* XXX - had_error++ ? */
1367                 }
1368                 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1369                     type == T_CNAME) {
1370                         n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1371                         if ((n < 0) || !(*name_ok)(tbuf)) {
1372                                 had_error++;
1373                                 continue;
1374                         }
1375                         cp += n;
1376                         /* Get canonical name. */
1377                         n = strlen(tbuf) + 1;   /* for the \0 */
1378                         if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1379                                 had_error++;
1380                                 continue;
1381                         }
1382                         strlcpy(bp, tbuf, ep - bp);
1383                         canonname = bp;
1384                         bp += n;
1385                         continue;
1386                 }
1387                 if (qtype == T_ANY) {
1388                         if (!(type == T_A || type == T_AAAA)) {
1389                                 cp += n;
1390                                 continue;
1391                         }
1392                 } else if (type != qtype) {
1393 #ifdef DEBUG
1394                         if (type != T_KEY && type != T_SIG)
1395                                 syslog(LOG_NOTICE|LOG_AUTH,
1396                "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1397                                        qname, p_class(C_IN), p_type(qtype),
1398                                        p_type(type));
1399 #endif
1400                         cp += n;
1401                         continue;               /* XXX - had_error++ ? */
1402                 }
1403                 switch (type) {
1404                 case T_A:
1405                 case T_AAAA:
1406                         if (strcasecmp(canonname, bp) != 0) {
1407 #ifdef DEBUG
1408                                 syslog(LOG_NOTICE|LOG_AUTH,
1409                                        AskedForGot, canonname, bp);
1410 #endif
1411                                 cp += n;
1412                                 continue;       /* XXX - had_error++ ? */
1413                         }
1414                         if (type == T_A && n != INADDRSZ) {
1415                                 cp += n;
1416                                 continue;
1417                         }
1418                         if (type == T_AAAA && n != IN6ADDRSZ) {
1419                                 cp += n;
1420                                 continue;
1421                         }
1422 #ifdef FILTER_V4MAPPED
1423                         if (type == T_AAAA) {
1424                                 struct in6_addr in6;
1425                                 memcpy(&in6, cp, sizeof(in6));
1426                                 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1427                                         cp += n;
1428                                         continue;
1429                                 }
1430                         }
1431 #endif
1432                         if (!haveanswer) {
1433                                 int nn;
1434
1435                                 canonname = bp;
1436                                 nn = strlen(bp) + 1;    /* for the \0 */
1437                                 bp += nn;
1438                         }
1439
1440                         /* don't overwrite pai */
1441                         ai = *pai;
1442                         ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1443                         afd = find_afd(ai.ai_family);
1444                         if (afd == NULL) {
1445                                 cp += n;
1446                                 continue;
1447                         }
1448                         cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1449                         if (cur->ai_next == NULL)
1450                                 had_error++;
1451                         while (cur && cur->ai_next)
1452                                 cur = cur->ai_next;
1453                         cp += n;
1454                         break;
1455                 default:
1456                         abort();
1457                 }
1458                 if (!had_error)
1459                         haveanswer++;
1460         }
1461         if (haveanswer) {
1462 #if defined(RESOLVSORT)
1463                 /*
1464                  * We support only IPv4 address for backward
1465                  * compatibility against gethostbyname(3).
1466                  */
1467                 if (_res.nsort && qtype == T_A) {
1468                         if (addr4sort(&sentinel) < 0) {
1469                                 freeaddrinfo(sentinel.ai_next);
1470                                 h_errno = NO_RECOVERY;
1471                                 return NULL;
1472                         }
1473                 }
1474 #endif /*RESOLVSORT*/
1475                 if (!canonname)
1476                         (void)get_canonname(pai, sentinel.ai_next, qname);
1477                 else
1478                         (void)get_canonname(pai, sentinel.ai_next, canonname);
1479                 h_errno = NETDB_SUCCESS;
1480                 return sentinel.ai_next;
1481         }
1482
1483         h_errno = NO_RECOVERY;
1484         return NULL;
1485 }
1486
1487 /*ARGSUSED*/
1488 static int
1489 _dns_getaddrinfo(pai, hostname, res)
1490         const struct addrinfo *pai;
1491         const char *hostname;
1492         struct addrinfo **res;
1493 {
1494         struct addrinfo *ai;
1495         querybuf *buf, *buf2;
1496         const char *name;
1497         struct addrinfo sentinel, *cur;
1498         struct res_target q, q2;
1499
1500         memset(&q, 0, sizeof(q2));
1501         memset(&q2, 0, sizeof(q2));
1502         memset(&sentinel, 0, sizeof(sentinel));
1503         cur = &sentinel;
1504
1505         buf = malloc(sizeof(*buf));
1506         if (!buf) {
1507                 h_errno = NETDB_INTERNAL;
1508                 return EAI_MEMORY;
1509         }
1510         buf2 = malloc(sizeof(*buf2));
1511         if (!buf2) {
1512                 free(buf);
1513                 h_errno = NETDB_INTERNAL;
1514                 return EAI_MEMORY;
1515         }
1516
1517         switch (pai->ai_family) {
1518         case AF_UNSPEC:
1519                 /* prefer IPv6 */
1520                 q.name = name;
1521                 q.qclass = C_IN;
1522                 q.qtype = T_AAAA;
1523                 q.answer = buf->buf;
1524                 q.anslen = sizeof(buf->buf);
1525                 q.next = &q2;
1526                 q2.name = name;
1527                 q2.qclass = C_IN;
1528                 q2.qtype = T_A;
1529                 q2.answer = buf2->buf;
1530                 q2.anslen = sizeof(buf2->buf);
1531                 break;
1532         case AF_INET:
1533                 q.name = name;
1534                 q.qclass = C_IN;
1535                 q.qtype = T_A;
1536                 q.answer = buf->buf;
1537                 q.anslen = sizeof(buf->buf);
1538                 break;
1539         case AF_INET6:
1540                 q.name = name;
1541                 q.qclass = C_IN;
1542                 q.qtype = T_AAAA;
1543                 q.answer = buf->buf;
1544                 q.anslen = sizeof(buf->buf);
1545                 break;
1546         default:
1547                 free(buf);
1548                 free(buf2);
1549                 return EAI_FAIL;
1550         }
1551         if (res_searchN(hostname, &q) < 0) {
1552                 free(buf);
1553                 free(buf2);
1554                 return EAI_NODATA;
1555         }
1556         ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1557         if (ai) {
1558                 cur->ai_next = ai;
1559                 while (cur && cur->ai_next)
1560                         cur = cur->ai_next;
1561         }
1562         if (q.next) {
1563                 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1564                 if (ai)
1565                         cur->ai_next = ai;
1566         }
1567         free(buf);
1568         free(buf2);
1569         if (sentinel.ai_next == NULL)
1570                 switch (h_errno) {
1571                 case HOST_NOT_FOUND:
1572                         return EAI_NODATA;
1573                 case TRY_AGAIN:
1574                         return EAI_AGAIN;
1575                 default:
1576                         return EAI_FAIL;
1577                 }
1578         *res = sentinel.ai_next;
1579         return 0;
1580 }
1581
1582 static struct addrinfo *
1583 _gethtent(hostf, name, pai)
1584         FILE *hostf;
1585         const char *name;
1586         const struct addrinfo *pai;
1587 {
1588         char *p;
1589         char *cp, *tname, *cname;
1590         struct addrinfo hints, *res0, *res;
1591         int error;
1592         const char *addr;
1593         char hostbuf[8*1024];
1594
1595 again:
1596         if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1597                 return (NULL);
1598         if (*p == '#')
1599                 goto again;
1600         if (!(cp = strpbrk(p, "#\n")))
1601                 goto again;
1602         *cp = '\0';
1603         if (!(cp = strpbrk(p, " \t")))
1604                 goto again;
1605         *cp++ = '\0';
1606         addr = p;
1607         cname = NULL;
1608         /* if this is not something we're looking for, skip it. */
1609         while (cp && *cp) {
1610                 if (*cp == ' ' || *cp == '\t') {
1611                         cp++;
1612                         continue;
1613                 }
1614                 tname = cp;
1615                 if (cname == NULL)
1616                         cname = cp;
1617                 if ((cp = strpbrk(cp, " \t")) != NULL)
1618                         *cp++ = '\0';
1619                 if (strcasecmp(name, tname) == 0)
1620                         goto found;
1621         }
1622         goto again;
1623
1624 found:
1625         /* we should not glob socktype/protocol here */
1626         memset(&hints, 0, sizeof(hints));
1627         hints.ai_family = pai->ai_family;
1628         hints.ai_socktype = SOCK_DGRAM;
1629         hints.ai_protocol = 0;
1630         hints.ai_flags = AI_NUMERICHOST;
1631         error = getaddrinfo(addr, "0", &hints, &res0);
1632         if (error)
1633                 goto again;
1634 #ifdef FILTER_V4MAPPED
1635         /* XXX should check all items in the chain */
1636         if (res0->ai_family == AF_INET6 &&
1637             IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {
1638                 freeaddrinfo(res0);
1639                 goto again;
1640         }
1641 #endif
1642         for (res = res0; res; res = res->ai_next) {
1643                 /* cover it up */
1644                 res->ai_flags = pai->ai_flags;
1645                 res->ai_socktype = pai->ai_socktype;
1646                 res->ai_protocol = pai->ai_protocol;
1647
1648                 if (pai->ai_flags & AI_CANONNAME) {
1649                         if (get_canonname(pai, res, cname) != 0) {
1650                                 freeaddrinfo(res0);
1651                                 goto again;
1652                         }
1653                 }
1654         }
1655         return res0;
1656 }
1657
1658 /*ARGSUSED*/
1659 static int
1660 _files_getaddrinfo(pai, hostname, res)
1661         const struct addrinfo *pai;
1662         const char *hostname;
1663         struct addrinfo **res;
1664 {
1665         FILE *hostf;
1666         struct addrinfo sentinel, *cur;
1667         struct addrinfo *p;
1668
1669         sentinel.ai_next = NULL;
1670         cur = &sentinel;
1671
1672         if ((hostf = fopen(_PATH_HOSTS, "r")) == NULL)
1673                 return EAI_FAIL;
1674         while ((p = _gethtent(hostf, hostname, pai)) != NULL) {
1675                 cur->ai_next = p;
1676                 while (cur && cur->ai_next)
1677                         cur = cur->ai_next;
1678         }
1679         fclose(hostf);
1680
1681         if (!sentinel.ai_next)
1682                 return EAI_NODATA;
1683
1684         *res = sentinel.ai_next;
1685         return 0;
1686 }
1687
1688 #ifdef YP
1689 /*ARGSUSED*/
1690 static int
1691 _nis_getaddrinfo(pai, hostname, res)
1692         const struct addrinfo *pai;
1693         const char *hostname;
1694         struct addrinfo **res;
1695 {
1696         struct hostent *hp;
1697         int h_error;
1698         int af;
1699         struct addrinfo sentinel, *cur;
1700         int i;
1701         const struct afd *afd;
1702         int error;
1703
1704         sentinel.ai_next = NULL;
1705         cur = &sentinel;
1706
1707         af = (pai->ai_family == AF_UNSPEC) ? AF_INET : pai->ai_family;
1708         if (af != AF_INET)
1709                 return (EAI_ADDRFAMILY);
1710
1711         if ((hp = _gethostbynisname(hostname, af)) == NULL) {
1712                 switch (errno) {
1713                 /* XXX: should be filled in */
1714                 default:
1715                         error = EAI_FAIL;
1716                         break;
1717                 }
1718         } else if (hp->h_name == NULL ||
1719                    hp->h_name[0] == 0 || hp->h_addr_list[0] == NULL) {
1720                 hp = NULL;
1721                 error = EAI_FAIL;
1722         }
1723
1724         if (hp == NULL)
1725                 return error;
1726
1727         for (i = 0; hp->h_addr_list[i] != NULL; i++) {
1728                 if (hp->h_addrtype != af)
1729                         continue;
1730
1731                 afd = find_afd(hp->h_addrtype);
1732                 if (afd == NULL)
1733                         continue;
1734
1735                 GET_AI(cur->ai_next, afd, hp->h_addr_list[i]);
1736                 if ((pai->ai_flags & AI_CANONNAME) != 0) {
1737                         /*
1738                          * RFC2553 says that ai_canonname will be set only for
1739                          * the first element.  we do it for all the elements,
1740                          * just for convenience.
1741                          */
1742                         GET_CANONNAME(cur->ai_next, hp->h_name);
1743                 }
1744
1745                 while (cur && cur->ai_next)
1746                         cur = cur->ai_next;
1747         }
1748
1749         *res = sentinel.ai_next;
1750         return 0;
1751
1752 free:
1753         if (sentinel.ai_next)
1754                 freeaddrinfo(sentinel.ai_next);
1755         return error;
1756 }
1757 #endif
1758
1759 /* resolver logic */
1760
1761 extern const char *__hostalias __P((const char *));
1762 extern int h_errno;
1763
1764 /*
1765  * Formulate a normal query, send, and await answer.
1766  * Returned answer is placed in supplied buffer "answer".
1767  * Perform preliminary check of answer, returning success only
1768  * if no error is indicated and the answer count is nonzero.
1769  * Return the size of the response on success, -1 on error.
1770  * Error number is left in h_errno.
1771  *
1772  * Caller must parse answer and determine whether it answers the question.
1773  */
1774 static int
1775 res_queryN(name, target)
1776         const char *name;       /* domain name */
1777         struct res_target *target;
1778 {
1779         u_char *buf;
1780         HEADER *hp;
1781         int n;
1782         struct res_target *t;
1783         int rcode;
1784         int ancount;
1785
1786         rcode = NOERROR;
1787         ancount = 0;
1788
1789         if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1790                 h_errno = NETDB_INTERNAL;
1791                 return (-1);
1792         }
1793
1794         buf = malloc(MAXPACKET);
1795         if (!buf) {
1796                 h_errno = NETDB_INTERNAL;
1797                 return (-1);
1798         }
1799
1800         for (t = target; t; t = t->next) {
1801                 int class, type;
1802                 u_char *answer;
1803                 int anslen;
1804
1805                 hp = (HEADER *)(void *)t->answer;
1806                 hp->rcode = NOERROR;    /* default */
1807
1808                 /* make it easier... */
1809                 class = t->qclass;
1810                 type = t->qtype;
1811                 answer = t->answer;
1812                 anslen = t->anslen;
1813 #ifdef DEBUG
1814                 if (_res.options & RES_DEBUG)
1815                         printf(";; res_query(%s, %d, %d)\n", name, class, type);
1816 #endif
1817
1818                 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1819                     buf, MAXPACKET);
1820                 if (n > 0 && (_res.options & RES_USE_EDNS0) != 0)
1821                         n = res_opt(n, buf, MAXPACKET, anslen);
1822                 if (n <= 0) {
1823 #ifdef DEBUG
1824                         if (_res.options & RES_DEBUG)
1825                                 printf(";; res_query: mkquery failed\n");
1826 #endif
1827                         free(buf);
1828                         h_errno = NO_RECOVERY;
1829                         return (n);
1830                 }
1831                 n = res_send(buf, n, answer, anslen);
1832 #if 0
1833                 if (n < 0) {
1834 #ifdef DEBUG
1835                         if (_res.options & RES_DEBUG)
1836                                 printf(";; res_query: send error\n");
1837 #endif
1838                         free(buf);
1839                         h_errno = TRY_AGAIN;
1840                         return (n);
1841                 }
1842 #endif
1843
1844                 if (n < 0 || n > anslen)
1845                         hp->rcode = FORMERR; /* XXX not very informative */
1846                 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1847                         rcode = hp->rcode;      /* record most recent error */
1848 #ifdef DEBUG
1849                         if (_res.options & RES_DEBUG)
1850                                 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1851                                     ntohs(hp->ancount));
1852 #endif
1853                         continue;
1854                 }
1855
1856                 ancount += ntohs(hp->ancount);
1857
1858                 t->n = n;
1859         }
1860
1861         free(buf);
1862
1863         if (ancount == 0) {
1864                 switch (rcode) {
1865                 case NXDOMAIN:
1866                         h_errno = HOST_NOT_FOUND;
1867                         break;
1868                 case SERVFAIL:
1869                         h_errno = TRY_AGAIN;
1870                         break;
1871                 case NOERROR:
1872                         h_errno = NO_DATA;
1873                         break;
1874                 case FORMERR:
1875                 case NOTIMP:
1876                 case REFUSED:
1877                 default:
1878                         h_errno = NO_RECOVERY;
1879                         break;
1880                 }
1881                 return (-1);
1882         }
1883         return (ancount);
1884 }
1885
1886 /*
1887  * Formulate a normal query, send, and retrieve answer in supplied buffer.
1888  * Return the size of the response on success, -1 on error.
1889  * If enabled, implement search rules until answer or unrecoverable failure
1890  * is detected.  Error code, if any, is left in h_errno.
1891  */
1892 static int
1893 res_searchN(name, target)
1894         const char *name;       /* domain name */
1895         struct res_target *target;
1896 {
1897         const char *cp, * const *domain;
1898         HEADER *hp = (HEADER *)(void *)target->answer;  /*XXX*/
1899         u_int dots;
1900         int trailing_dot, ret, saved_herrno;
1901         int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1902
1903         if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1904                 h_errno = NETDB_INTERNAL;
1905                 return (-1);
1906         }
1907
1908         errno = 0;
1909         h_errno = HOST_NOT_FOUND;       /* default, if we never query */
1910         dots = 0;
1911         for (cp = name; *cp; cp++)
1912                 dots += (*cp == '.');
1913         trailing_dot = 0;
1914         if (cp > name && *--cp == '.')
1915                 trailing_dot++;
1916
1917         /*
1918          * if there aren't any dots, it could be a user-level alias
1919          */
1920         if (!dots && (cp = __hostalias(name)) != NULL)
1921                 return (res_queryN(cp, target));
1922
1923         /*
1924          * If there are dots in the name already, let's just give it a try
1925          * 'as is'.  The threshold can be set with the "ndots" option.
1926          */
1927         saved_herrno = -1;
1928         if (dots >= _res.ndots) {
1929                 ret = res_querydomainN(name, NULL, target);
1930                 if (ret > 0)
1931                         return (ret);
1932                 saved_herrno = h_errno;
1933                 tried_as_is++;
1934         }
1935
1936         /*
1937          * We do at least one level of search if
1938          *      - there is no dot and RES_DEFNAME is set, or
1939          *      - there is at least one dot, there is no trailing dot,
1940          *        and RES_DNSRCH is set.
1941          */
1942         if ((!dots && (_res.options & RES_DEFNAMES)) ||
1943             (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
1944                 int done = 0;
1945
1946                 for (domain = (const char * const *)_res.dnsrch;
1947                    *domain && !done;
1948                    domain++) {
1949
1950                         ret = res_querydomainN(name, *domain, target);
1951                         if (ret > 0)
1952                                 return (ret);
1953
1954                         /*
1955                          * If no server present, give up.
1956                          * If name isn't found in this domain,
1957                          * keep trying higher domains in the search list
1958                          * (if that's enabled).
1959                          * On a NO_DATA error, keep trying, otherwise
1960                          * a wildcard entry of another type could keep us
1961                          * from finding this entry higher in the domain.
1962                          * If we get some other error (negative answer or
1963                          * server failure), then stop searching up,
1964                          * but try the input name below in case it's
1965                          * fully-qualified.
1966                          */
1967                         if (errno == ECONNREFUSED) {
1968                                 h_errno = TRY_AGAIN;
1969                                 return (-1);
1970                         }
1971
1972                         switch (h_errno) {
1973                         case NO_DATA:
1974                                 got_nodata++;
1975                                 /* FALLTHROUGH */
1976                         case HOST_NOT_FOUND:
1977                                 /* keep trying */
1978                                 break;
1979                         case TRY_AGAIN:
1980                                 if (hp->rcode == SERVFAIL) {
1981                                         /* try next search element, if any */
1982                                         got_servfail++;
1983                                         break;
1984                                 }
1985                                 /* FALLTHROUGH */
1986                         default:
1987                                 /* anything else implies that we're done */
1988                                 done++;
1989                         }
1990                         /*
1991                          * if we got here for some reason other than DNSRCH,
1992                          * we only wanted one iteration of the loop, so stop.
1993                          */
1994                         if (!(_res.options & RES_DNSRCH))
1995                                 done++;
1996                 }
1997         }
1998
1999         /*
2000          * if we have not already tried the name "as is", do that now.
2001          * note that we do this regardless of how many dots were in the
2002          * name or whether it ends with a dot.
2003          */
2004         if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {
2005                 ret = res_querydomainN(name, NULL, target);
2006                 if (ret > 0)
2007                         return (ret);
2008         }
2009
2010         /*
2011          * if we got here, we didn't satisfy the search.
2012          * if we did an initial full query, return that query's h_errno
2013          * (note that we wouldn't be here if that query had succeeded).
2014          * else if we ever got a nodata, send that back as the reason.
2015          * else send back meaningless h_errno, that being the one from
2016          * the last DNSRCH we did.
2017          */
2018         if (saved_herrno != -1)
2019                 h_errno = saved_herrno;
2020         else if (got_nodata)
2021                 h_errno = NO_DATA;
2022         else if (got_servfail)
2023                 h_errno = TRY_AGAIN;
2024         return (-1);
2025 }
2026
2027 /*
2028  * Perform a call on res_query on the concatenation of name and domain,
2029  * removing a trailing dot from name if domain is NULL.
2030  */
2031 static int
2032 res_querydomainN(name, domain, target)
2033         const char *name, *domain;
2034         struct res_target *target;
2035 {
2036         char nbuf[MAXDNAME];
2037         const char *longname = nbuf;
2038         size_t n, d;
2039
2040         if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
2041                 h_errno = NETDB_INTERNAL;
2042                 return (-1);
2043         }
2044 #ifdef DEBUG
2045         if (_res.options & RES_DEBUG)
2046                 printf(";; res_querydomain(%s, %s)\n",
2047                         name, domain?domain:"<Nil>");
2048 #endif
2049         if (domain == NULL) {
2050                 /*
2051                  * Check for trailing '.';
2052                  * copy without '.' if present.
2053                  */
2054                 n = strlen(name);
2055                 if (n >= MAXDNAME) {
2056                         h_errno = NO_RECOVERY;
2057                         return (-1);
2058                 }
2059                 if (n > 0 && name[--n] == '.') {
2060                         strncpy(nbuf, name, n);
2061                         nbuf[n] = '\0';
2062                 } else
2063                         longname = name;
2064         } else {
2065                 n = strlen(name);
2066                 d = strlen(domain);
2067                 if (n + d + 1 >= MAXDNAME) {
2068                         h_errno = NO_RECOVERY;
2069                         return (-1);
2070                 }
2071                 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
2072         }
2073         return (res_queryN(longname, target));
2074 }