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