13bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*	$NetBSD: getaddrinfo.c,v 1.91.6.1 2009/01/26 00:27:34 snj Exp $	*/
23bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*	$KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $	*/
33bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
43bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
53bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
63bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * All rights reserved.
73bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *
83bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Redistribution and use in source and binary forms, with or without
93bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * modification, are permitted provided that the following conditions
103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * are met:
113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * 1. Redistributions of source code must retain the above copyright
123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *    notice, this list of conditions and the following disclaimer.
133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * 2. Redistributions in binary form must reproduce the above copyright
143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *    notice, this list of conditions and the following disclaimer in the
153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *    documentation and/or other materials provided with the distribution.
163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * 3. Neither the name of the project nor the names of its contributors
173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *    may be used to endorse or promote products derived from this software
183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *    without specific prior written permission.
193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *
203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * SUCH DAMAGE.
313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Issues to be discussed:
353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * - Return values.  There are nonstandard return values defined and used
363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   in the source code.  This is because RFC2553 is silent about which error
373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   code must be returned for which situation.
383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * - IPv4 classful (shortened) form.  RFC2553 is silent about it.  XNET 5.2
393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   says to use inet_aton() to convert IPv4 numeric to binary (alows
403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   classful form as a result).
413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   current code - disallow classful form for IPv4 (due to use of inet_pton).
423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * - freeaddrinfo(NULL).  RFC2553 is silent about it.  XNET 5.2 says it is
433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   invalid.
443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   current code - SEGV on freeaddrinfo(NULL)
453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Note:
463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * - The code filters out AFs that are not supported by the kernel,
473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   in ai_flags?
503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   (1) what should we do against numeric hostname (2) what should we do
523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   against NULL hostname (3) what is AI_ADDRCONFIG itself.  AF not ready?
533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *   non-loopback address configured?  global address configured?
543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <sys/cdefs.h>
573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#if defined(LIBC_SCCS) && !defined(lint)
583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy__RCSID("$NetBSD: getaddrinfo.c,v 1.91.6.1 2009/01/26 00:27:34 snj Exp $");
593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif /* LIBC_SCCS and not lint */
603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define INET6   1
623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include "namespace.h"
643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <sys/types.h>
653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <sys/param.h>
663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <sys/socket.h>
673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <net/if.h>
683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <netinet/in.h>
693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <arpa/inet.h>
703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <arpa/nameser.h>
713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <assert.h>
723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <ctype.h>
733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <errno.h>
743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <netdb.h>
753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <resolv.h>
763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <stddef.h>
773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <stdio.h>
783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <stdlib.h>
793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <string.h>
803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <unistd.h>
813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <stdarg.h>
833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <nsswitch.h>
843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <resolv.h>
853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy//#ifdef YP
873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy//#include <rpc/rpc.h>
883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy//#include <rpcsvc/yp_prot.h>
893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy//#include <rpcsvc/ypclnt.h>
903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy//#endif
913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#include <net/servent.h>
933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define endservent_r(svd)   endservent()
953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define nsdispatch(pResult,dtab,database,routine,files,hostname,pai)  NS_NOTFOUND
963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define res_nmkquery(state,op,dname,class,type,data,datalen,newrr_in,buf,buflen)  res_mkquery( op, dname, class, type, data, datalen, newrr_in, buf, buflen )
973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define res_nsend(state,buf,buflen,ans,anssiz)    res_send ( buf, buflen, ans, anssiz )
983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/* Things involving an internal (static) resolver context. */
1003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy__BEGIN_DECLS
1013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define __res_get_state()   (( 0 != _res.nscount ) ? &_res : NULL )
1023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define __res_put_state(state)
1033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define __res_state()   _res
1043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy__END_DECLS
1053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef __weak_alias
1073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy__weak_alias(getaddrinfo,_getaddrinfo)
1083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy__weak_alias(freeaddrinfo,_freeaddrinfo)
1093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy__weak_alias(gai_strerror,_gai_strerror)
1103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
1113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define SUCCESS 0
1133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define ANY 0
1143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define YES 1
1153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define NO  0
1163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const char in_addrany[] = { 0, 0, 0, 0 };
1183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const char in_loopback[] = { 127, 0, 0, 1 };
1193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
1203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const char in6_addrany[] = {
1213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
1233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const char in6_loopback[] = {
1243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
1253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
1263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
1273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const struct afd {
1293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int a_af;
1303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int a_addrlen;
1313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int a_socklen;
1323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int a_off;
1333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *a_addrany;
1343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *a_loopback;
1353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int a_scoped;
1363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy} afdl [] = {
1373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
1383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{PF_INET6, sizeof(struct in6_addr),
1393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 sizeof(struct sockaddr_in6),
1403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 offsetof(struct sockaddr_in6, sin6_addr),
1413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 in6_addrany, in6_loopback, 1},
1423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
1433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{PF_INET, sizeof(struct in_addr),
1443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 sizeof(struct sockaddr_in),
1453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 offsetof(struct sockaddr_in, sin_addr),
1463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 in_addrany, in_loopback, 0},
1473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{0, 0, 0, 0, NULL, NULL, 0},
1483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
1493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystruct explore {
1513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int e_af;
1523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int e_socktype;
1533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int e_protocol;
1543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *e_protostr;
1553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int e_wild;
1563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define WILD_AF(ex)		((ex)->e_wild & 0x01)
1573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
1583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
1593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
1603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const struct explore explore[] = {
1623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#if 0
1633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
1643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
1653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
1663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
1673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
1683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
1693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
1703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
1713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
1723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
1733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
1743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
1753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
1763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ -1, 0, 0, NULL, 0 },
1773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
1783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
1803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define PTON_MAX	16
1813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#else
1823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define PTON_MAX	4
1833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
1843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const ns_src default_dns_files[] = {
1863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ NSSRC_FILES, 	NS_SUCCESS },
1873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ NSSRC_DNS, 	NS_SUCCESS },
1883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	{ 0, 0 }
1893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
1903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define MAXPACKET	(64*1024)
1923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahytypedef union {
1943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	HEADER hdr;
1953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	u_char buf[MAXPACKET];
1963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy} querybuf;
1973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
1983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystruct res_target {
1993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct res_target *next;
2003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *name;	/* domain name */
2013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int qclass, qtype;	/* class and type of query */
2023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	u_char *answer;		/* buffer to put answer */
2033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int anslen;		/* size of answer buffer */
2043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int n;			/* result length */
2053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
2063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int str2number(const char *);
2083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int explore_fqdn(const struct addrinfo *, const char *,
2093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *, struct addrinfo **, struct servent_data *);
2103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int explore_null(const struct addrinfo *,
2113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *, struct addrinfo **, struct servent_data *);
2123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int explore_numeric(const struct addrinfo *, const char *,
2133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *, struct addrinfo **, const char *, struct servent_data *);
2143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int explore_numeric_scope(const struct addrinfo *, const char *,
2153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *, struct addrinfo **, struct servent_data *);
2163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int get_canonname(const struct addrinfo *,
2173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *, const char *);
2183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *get_ai(const struct addrinfo *,
2193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct afd *, const char *);
2203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int get_portmatch(const struct addrinfo *, const char *,
2213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    struct servent_data *);
2223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int get_port(const struct addrinfo *, const char *, int,
2233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    struct servent_data *);
2243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const struct afd *find_afd(int);
2253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
2263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
2273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
2283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *getanswer(const querybuf *, int, const char *, int,
2303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct addrinfo *);
2313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic void aisort(struct addrinfo *s, res_state res);
2323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int _dns_getaddrinfo(void *, void *, va_list);
2333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic void _sethtent(FILE **);
2343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic void _endhtent(FILE **);
2353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *_gethtent(FILE **, const char *,
2363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    const struct addrinfo *);
2373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int _files_getaddrinfo(void *, void *, va_list);
2383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef YP
2393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *_yphostent(char *, const struct addrinfo *);
2403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int _yp_getaddrinfo(void *, void *, va_list);
2413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
2423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int res_queryN(const char *, struct res_target *, res_state);
2443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int res_searchN(const char *, struct res_target *, res_state);
2453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int res_querydomainN(const char *, const char *,
2463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct res_target *, res_state);
2473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const char * const ai_errlist[] = {
2493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Success",
2503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
2513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Temporary failure in name resolution",		/* EAI_AGAIN      */
2523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
2533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
2543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"ai_family not supported",			/* EAI_FAMILY     */
2553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Memory allocation failure", 			/* EAI_MEMORY     */
2563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"No address associated with hostname", 		/* EAI_NODATA     */
2573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
2583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
2593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
2603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"System error returned in errno", 		/* EAI_SYSTEM     */
2613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Invalid value for hints",			/* EAI_BADHINTS	  */
2623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
2633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Argument buffer overflow",			/* EAI_OVERFLOW   */
2643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"Unknown error", 				/* EAI_MAX        */
2653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy};
2663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/* XXX macros that make external reference is BAD. */
2683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define GET_AI(ai, afd, addr) 					\
2703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahydo { 								\
2713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* external reference: pai, error, and label free */ 	\
2723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	(ai) = get_ai(pai, (afd), (addr)); 			\
2733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if ((ai) == NULL) { 					\
2743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = EAI_MEMORY; 				\
2753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto free; 					\
2763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} 							\
2773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy} while (/*CONSTCOND*/0)
2783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define GET_PORT(ai, serv, svd) 				\
2803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahydo { 								\
2813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* external reference: error and label free */ 		\
2823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	error = get_port((ai), (serv), 0, (svd)); 		\
2833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (error != 0) 					\
2843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto free; 					\
2853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy} while (/*CONSTCOND*/0)
2863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define GET_CANONNAME(ai, str) 					\
2883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahydo { 								\
2893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* external reference: pai, error and label free */ 	\
2903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	error = get_canonname(pai, (ai), (str)); 		\
2913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (error != 0) 					\
2923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto free; 					\
2933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy} while (/*CONSTCOND*/0)
2943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
2953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define ERR(err) 						\
2963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahydo { 								\
2973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* external reference: error, and label bad */ 		\
2983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	error = (err); 						\
2993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	goto bad; 						\
3003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*NOTREACHED*/ 						\
3013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy} while (/*CONSTCOND*/0)
3023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define MATCH_FAMILY(x, y, w) 						\
3043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || 	\
3053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	    (y) == PF_UNSPEC)))
3063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define MATCH(x, y, w) 							\
3073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
3083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyconst char *
3103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahygai_strerror(int ecode)
3113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
3123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (ecode < 0 || ecode > EAI_MAX)
3133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ecode = EAI_MAX;
3143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return ai_errlist[ecode];
3153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
3163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyvoid
3183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyfreeaddrinfo(struct addrinfo *ai)
3193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
3203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *next;
3213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(ai != NULL);
3233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	do {
3253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		next = ai->ai_next;
3263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ai->ai_canonname)
3273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			free(ai->ai_canonname);
3283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* no need to free(ai->ai_addr) */
3293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(ai);
3303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ai = next;
3313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} while (ai);
3323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
3333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
3353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystr2number(const char *p)
3363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
3373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *ep;
3383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	unsigned long v;
3393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(p != NULL);
3413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (*p == '\0')
3433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return -1;
3443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ep = NULL;
3453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	errno = 0;
3463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	v = strtoul(p, &ep, 10);
3473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
3483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return v;
3493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	else
3503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return -1;
3513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
3523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyint
3543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahygetaddrinfo(const char *hostname, const char *servname,
3553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    const struct addrinfo *hints, struct addrinfo **res)
3563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
3573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel;
3583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *cur;
3593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int error = 0;
3603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo ai;
3613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo ai0;
3623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *pai;
3633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct explore *ex;
3643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct servent_data svd;
3653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* hostname is allowed to be NULL */
3673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* servname is allowed to be NULL */
3683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* hints is allowed to be NULL */
3693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(res != NULL);
3703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	(void)memset(&svd, 0, sizeof(svd));
3723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&sentinel, 0, sizeof(sentinel));
3733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
3743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&ai, 0, sizeof(ai));
3753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai = &ai;
3763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_flags = 0;
3773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_family = PF_UNSPEC;
3783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_socktype = ANY;
3793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_protocol = ANY;
3803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_addrlen = 0;
3813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_canonname = NULL;
3823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_addr = NULL;
3833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai->ai_next = NULL;
3843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
3853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (hostname == NULL && servname == NULL)
3863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return EAI_NONAME;
3873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (hints) {
3883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* error check for hints */
3893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (hints->ai_addrlen || hints->ai_canonname ||
3903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		    hints->ai_addr || hints->ai_next)
3913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ERR(EAI_BADHINTS); /* xxx */
3923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (hints->ai_flags & ~AI_MASK)
3933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ERR(EAI_BADFLAGS);
3943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		switch (hints->ai_family) {
3953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case PF_UNSPEC:
3963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case PF_INET:
3973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
3983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case PF_INET6:
3993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
4003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
4013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		default:
4023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ERR(EAI_FAMILY);
4033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
4043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		memcpy(pai, hints, sizeof(*pai));
4053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/*
4073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * if both socktype/protocol are specified, check if they
4083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * are meaningful combination.
4093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 */
4103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
4113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			for (ex = explore; ex->e_af >= 0; ex++) {
4123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if (pai->ai_family != ex->e_af)
4133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					continue;
4143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if (ex->e_socktype == ANY)
4153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					continue;
4163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if (ex->e_protocol == ANY)
4173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					continue;
4183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if (pai->ai_socktype == ex->e_socktype
4193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				 && pai->ai_protocol != ex->e_protocol) {
4203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					ERR(EAI_BADHINTS);
4213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				}
4223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
4233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
4243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
4253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
4273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * check for special cases.  (1) numeric servname is disallowed if
4283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * socktype/protocol are left unspecified. (2) servname is disallowed
4293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * for raw and other inet{,6} sockets.
4303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
4313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
4323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef PF_INET6
4333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
4343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
4353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	    ) {
4363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ai0 = *pai;	/* backup *pai */
4373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_family == PF_UNSPEC) {
4393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef PF_INET6
4403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			pai->ai_family = PF_INET6;
4413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#else
4423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			pai->ai_family = PF_INET;
4433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
4443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
4453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = get_portmatch(pai, servname, &svd);
4463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (error)
4473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ERR(error);
4483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*pai = ai0;
4503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
4513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai0 = *pai;
4533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* NULL hostname, or numeric hostname */
4553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	for (ex = explore; ex->e_af >= 0; ex++) {
4563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*pai = ai0;
4573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* PF_UNSPEC entries are prepared for DNS queries only */
4593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ex->e_af == PF_UNSPEC)
4603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
4613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
4633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
4643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
4653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
4663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
4673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
4683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_family == PF_UNSPEC)
4703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			pai->ai_family = ex->e_af;
4713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
4723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			pai->ai_socktype = ex->e_socktype;
4733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
4743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			pai->ai_protocol = ex->e_protocol;
4753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (hostname == NULL)
4773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			error = explore_null(pai, servname, &cur->ai_next,
4783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			    &svd);
4793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		else
4803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			error = explore_numeric_scope(pai, hostname, servname,
4813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			    &cur->ai_next, &svd);
4823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (error)
4843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			goto free;
4853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		while (cur->ai_next)
4873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur = cur->ai_next;
4883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
4893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
4913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * XXX
4923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * If numeric representation of AF1 can be interpreted as FQDN
4933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * representation of AF2, we need to think again about the code below.
4943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
4953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next)
4963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto good;
4973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (hostname == NULL)
4993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ERR(EAI_NODATA);
5003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (pai->ai_flags & AI_NUMERICHOST)
5013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ERR(EAI_NONAME);
5023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
5043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * hostname as alphabetical name.
5053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
5063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * outer loop by AFs.
5073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
5083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	for (ex = explore; ex->e_af >= 0; ex++) {
5093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*pai = ai0;
5103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* require exact match for family field */
5123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_family != ex->e_af)
5133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
5143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!MATCH(pai->ai_socktype, ex->e_socktype,
5163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				WILD_SOCKTYPE(ex))) {
5173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
5183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
5193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!MATCH(pai->ai_protocol, ex->e_protocol,
5203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				WILD_PROTOCOL(ex))) {
5213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
5223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
5233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
5253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			pai->ai_socktype = ex->e_socktype;
5263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
5273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			pai->ai_protocol = ex->e_protocol;
5283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = explore_fqdn(pai, hostname, servname, &cur->ai_next,
5303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		    &svd);
5313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		while (cur && cur->ai_next)
5333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur = cur->ai_next;
5343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
5353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* XXX */
5373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next)
5383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = 0;
5393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (error)
5413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto free;
5423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next) {
5443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy good:
5453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		endservent_r(&svd);
5463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*res = sentinel.ai_next;
5473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return SUCCESS;
5483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} else
5493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = EAI_FAIL;
5503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy free:
5513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy bad:
5523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	endservent_r(&svd);
5533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next)
5543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		freeaddrinfo(sentinel.ai_next);
5553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*res = NULL;
5563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return error;
5573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
5583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
559826f9005c21d61845f64f779bc86c4ca15caa1e6lpleahystatic const ns_dtab dtab[] = {
5607700f0f5c0ab90bf052e33fa0ddd2f2aa7e7893elpleahy  NS_FILES_CB(((nss_method)_files_getaddrinfo), NULL)
5617700f0f5c0ab90bf052e33fa0ddd2f2aa7e7893elpleahy  { NSSRC_DNS, ((nss_method)_dns_getaddrinfo), NULL },  /* force -DHESIOD */
562826f9005c21d61845f64f779bc86c4ca15caa1e6lpleahy  NS_NIS_CB(_yp_getaddrinfo, NULL)
563826f9005c21d61845f64f779bc86c4ca15caa1e6lpleahy  NS_NULL_CB
564826f9005c21d61845f64f779bc86c4ca15caa1e6lpleahy};
565826f9005c21d61845f64f779bc86c4ca15caa1e6lpleahy
5663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
5673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * FQDN hostname, DNS lookup
5683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
5693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
5703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyexplore_fqdn(const struct addrinfo *pai, const char *hostname,
5713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    const char *servname, struct addrinfo **res, struct servent_data *svd)
5723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
5733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *result;
5743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *cur;
5753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int error = 0;
5763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
5783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* hostname may be NULL */
5793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* servname may be NULL */
5803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(res != NULL);
5813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	result = NULL;
5833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
5853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if the servname does not match socktype/protocol, ignore it.
5863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
5873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (get_portmatch(pai, servname, svd) != 0)
5883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
5893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
5903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
5913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			default_dns_files, hostname, pai)) {
5923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case NS_TRYAGAIN:
5933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = EAI_AGAIN;
5943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto free;
5953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case NS_UNAVAIL:
5963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = EAI_FAIL;
5973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto free;
5983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case NS_NOTFOUND:
5993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = EAI_NODATA;
6003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto free;
6013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case NS_SUCCESS:
6023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		error = 0;
6033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		for (cur = result; cur; cur = cur->ai_next) {
6043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			GET_PORT(cur, servname, svd);
6053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			/* canonname should be filled already */
6063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
6073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
6083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
6093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*res = result;
6113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return 0;
6133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyfree:
6153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (result)
6163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		freeaddrinfo(result);
6173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return error;
6183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
6193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
6213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * hostname == NULL.
6223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * passive socket -> anyaddr (0.0.0.0 or ::)
6233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * non-passive socket -> localhost (127.0.0.1 or ::1)
6243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
6253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
6263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyexplore_null(const struct addrinfo *pai, const char *servname,
6273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    struct addrinfo **res, struct servent_data *svd)
6283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
6293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int s;
6303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct afd *afd;
6313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *cur;
6323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel;
6333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int error;
6343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
6363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* servname may be NULL */
6373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(res != NULL);
6383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*res = NULL;
6403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	sentinel.ai_next = NULL;
6413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
6423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
6443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * filter out AFs that are not supported by the kernel
6453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * XXX errno?
6463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
6473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	s = socket(pai->ai_family, SOCK_DGRAM, 0);
6483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (s < 0) {
6493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (errno != EMFILE)
6503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return 0;
6513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} else
6523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		close(s);
6533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
6553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if the servname does not match socktype/protocol, ignore it.
6563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
6573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (get_portmatch(pai, servname, svd) != 0)
6583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
6593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	afd = find_afd(pai->ai_family);
6613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (afd == NULL)
6623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
6633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (pai->ai_flags & AI_PASSIVE) {
6653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		GET_AI(cur->ai_next, afd, afd->a_addrany);
6663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* xxx meaningless?
6673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * GET_CANONNAME(cur->ai_next, "anyaddr");
6683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 */
6693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		GET_PORT(cur->ai_next, servname, svd);
6703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} else {
6713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		GET_AI(cur->ai_next, afd, afd->a_loopback);
6723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* xxx meaningless?
6733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * GET_CANONNAME(cur->ai_next, "localhost");
6743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 */
6753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		GET_PORT(cur->ai_next, servname, svd);
6763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
6773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = cur->ai_next;
6783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*res = sentinel.ai_next;
6803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return 0;
6813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyfree:
6833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next)
6843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		freeaddrinfo(sentinel.ai_next);
6853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return error;
6863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
6873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
6883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
6893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * numeric hostname
6903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
6913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
6923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyexplore_numeric(const struct addrinfo *pai, const char *hostname,
6933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    const char *servname, struct addrinfo **res, const char *canonname,
6943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    struct servent_data *svd)
6953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
6963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct afd *afd;
6973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *cur;
6983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel;
6993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int error;
7003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char pton[PTON_MAX];
7013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
7033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* hostname may be NULL */
7043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* servname may be NULL */
7053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(res != NULL);
7063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*res = NULL;
7083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	sentinel.ai_next = NULL;
7093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
7103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
7123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if the servname does not match socktype/protocol, ignore it.
7133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
7143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (get_portmatch(pai, servname, svd) != 0)
7153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
7163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	afd = find_afd(pai->ai_family);
7183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (afd == NULL)
7193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
7203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	switch (afd->a_af) {
7223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#if 0 /*X/Open spec*/
7233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case AF_INET:
7243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
7253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (pai->ai_family == afd->a_af ||
7263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			    pai->ai_family == PF_UNSPEC /*?*/) {
7273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				GET_AI(cur->ai_next, afd, pton);
7283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				GET_PORT(cur->ai_next, servname, svd);
7293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if ((pai->ai_flags & AI_CANONNAME)) {
7303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					/*
7313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 * Set the numeric address itself as
7323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 * the canonical name, based on a
7333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 * clarification in rfc2553bis-03.
7343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 */
7353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					GET_CANONNAME(cur->ai_next, canonname);
7363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				}
7373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				while (cur && cur->ai_next)
7383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					cur = cur->ai_next;
7393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			} else
7403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				ERR(EAI_FAMILY);	/*xxx*/
7413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
7423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
7433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
7443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	default:
7453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (inet_pton(afd->a_af, hostname, pton) == 1) {
7463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (pai->ai_family == afd->a_af ||
7473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			    pai->ai_family == PF_UNSPEC /*?*/) {
7483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				GET_AI(cur->ai_next, afd, pton);
7493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				GET_PORT(cur->ai_next, servname, svd);
7503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if ((pai->ai_flags & AI_CANONNAME)) {
7513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					/*
7523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 * Set the numeric address itself as
7533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 * the canonical name, based on a
7543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 * clarification in rfc2553bis-03.
7553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					 */
7563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					GET_CANONNAME(cur->ai_next, canonname);
7573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				}
7583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				while (cur->ai_next)
7593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					cur = cur->ai_next;
7603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			} else
7613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				ERR(EAI_FAMILY);	/*xxx*/
7623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
7633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
7643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
7653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*res = sentinel.ai_next;
7673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return 0;
7683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyfree:
7703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahybad:
7713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next)
7723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		freeaddrinfo(sentinel.ai_next);
7733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return error;
7743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
7753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
7773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * numeric hostname with scope
7783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
7793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
7803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyexplore_numeric_scope(const struct addrinfo *pai, const char *hostname,
7813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    const char *servname, struct addrinfo **res, struct servent_data *svd)
7823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
7833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#if !defined(SCOPE_DELIMITER) || !defined(INET6)
7843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return explore_numeric(pai, hostname, servname, res, hostname, svd);
7853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#else
7863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct afd *afd;
7873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *cur;
7883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int error;
7893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *cp, *hostname2 = NULL, *scope, *addr;
7903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct sockaddr_in6 *sin6;
7913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
7933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* hostname may be NULL */
7943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* servname may be NULL */
7953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(res != NULL);
7963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
7973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
7983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if the servname does not match socktype/protocol, ignore it.
7993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
8003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (get_portmatch(pai, servname, svd) != 0)
8013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
8023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	afd = find_afd(pai->ai_family);
8043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (afd == NULL)
8053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
8063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (!afd->a_scoped)
8083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return explore_numeric(pai, hostname, servname, res, hostname,
8093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		    svd);
8103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cp = strchr(hostname, SCOPE_DELIMITER);
8123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (cp == NULL)
8133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return explore_numeric(pai, hostname, servname, res, hostname,
8143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		    svd);
8153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
8173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * Handle special case of <scoped_address><delimiter><scope id>
8183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
8193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hostname2 = strdup(hostname);
8203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (hostname2 == NULL)
8213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return EAI_MEMORY;
8223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* terminate at the delimiter */
8233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hostname2[cp - hostname] = '\0';
8243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	addr = hostname2;
8253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	scope = cp + 1;
8263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	error = explore_numeric(pai, addr, servname, res, hostname, svd);
8283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (error == 0) {
8293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		u_int32_t scopeid;
8303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		for (cur = *res; cur; cur = cur->ai_next) {
8323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (cur->ai_family != AF_INET6)
8333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;
8343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
8353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
8363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				free(hostname2);
8373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				return(EAI_NODATA); /* XXX: is return OK? */
8383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
8393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			sin6->sin6_scope_id = scopeid;
8403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
8413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
8423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	free(hostname2);
8443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return error;
8463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
8473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
8483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
8503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyget_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
8513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
8523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
8543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(ai != NULL);
8553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(str != NULL);
8563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if ((pai->ai_flags & AI_CANONNAME) != 0) {
8583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ai->ai_canonname = strdup(str);
8593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ai->ai_canonname == NULL)
8603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return EAI_MEMORY;
8613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
8623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return 0;
8633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
8643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *
8663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyget_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
8673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
8683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *p;
8693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *ai;
8703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
8723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(afd != NULL);
8733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(addr != NULL);
8743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
8763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		+ (afd->a_socklen));
8773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (ai == NULL)
8783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NULL;
8793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memcpy(ai, pai, sizeof(struct addrinfo));
8813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
8823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
8833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai->ai_addr->sa_len = (uint8_t)afd->a_socklen;
8843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai->ai_addrlen = afd->a_socklen;
8853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai->ai_family = afd->a_af;
8863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai->ai_addr->sa_family = (sa_family_t)ai->ai_family;
8873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	p = (char *)(void *)(ai->ai_addr);
8883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
8893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return ai;
8903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
8913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
8933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyget_portmatch(const struct addrinfo *ai, const char *servname,
8943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    struct servent_data *svd)
8953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
8963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
8973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(ai != NULL);
8983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* servname may be NULL */
8993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return get_port(ai, servname, 1, svd);
9013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
9023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
9043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyget_port(const struct addrinfo *ai, const char *servname, int matchonly,
9053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    struct servent_data *svd)
9063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
9073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *proto;
9083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct servent *sp;
9093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int port;
9103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int allownumeric;
9113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(ai != NULL);
9133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* servname may be NULL */
9143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (servname == NULL)
9163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
9173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	switch (ai->ai_family) {
9183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case AF_INET:
9193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef AF_INET6
9203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case AF_INET6:
9213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
9223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
9233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	default:
9243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
9253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
9263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	switch (ai->ai_socktype) {
9283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case SOCK_RAW:
9293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return EAI_SERVICE;
9303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case SOCK_DGRAM:
9313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case SOCK_STREAM:
9323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		allownumeric = 1;
9333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
9343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case ANY:
9353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/*
9363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * This was 0.  It is now 1 so that queries specifying
9373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * a NULL hint, or hint without socktype (but, hopefully,
9383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * with protocol) and numeric address actually work.
9393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 */
9403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		allownumeric = 1;
9413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
9423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	default:
9433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return EAI_SOCKTYPE;
9443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
9453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	port = str2number(servname);
9473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (port >= 0) {
9483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!allownumeric)
9493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return EAI_SERVICE;
9503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (port < 0 || port > 65535)
9513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return EAI_SERVICE;
9523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		port = htons(port);
9533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} else {
9543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy//		struct servent sv;
9553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ai->ai_flags & AI_NUMERICSERV)
9563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return EAI_NONAME;
9573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		switch (ai->ai_socktype) {
9593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case SOCK_DGRAM:
9603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			proto = "udp";
9613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
9623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case SOCK_STREAM:
9633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			proto = "tcp";
9643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
9653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		default:
9663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			proto = NULL;
9673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
9683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
9693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy//		sp = getservbyname_r(servname, proto, &sv, svd);
9713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    sp = getservbyname ( servname, proto );
9723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (sp == NULL)
9733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return EAI_SERVICE;
9743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		port = sp->s_port;
9753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
9763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (!matchonly) {
9783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		switch (ai->ai_family) {
9793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case AF_INET:
9803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			((struct sockaddr_in *)(void *)
9813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			    ai->ai_addr)->sin_port = (in_port_t)port;
9823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
9833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
9843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case AF_INET6:
9853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			((struct sockaddr_in6 *)(void *)
9863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			    ai->ai_addr)->sin6_port = (in_port_t)port;
9873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
9883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
9893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
9903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
9913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return 0;
9933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
9943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
9953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const struct afd *
9963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyfind_afd(int af)
9973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
9983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct afd *afd;
9993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (af == PF_UNSPEC)
10013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NULL;
10023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	for (afd = afdl; afd->a_af; afd++) {
10033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (afd->a_af == af)
10043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return afd;
10053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
10063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return NULL;
10073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
10083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef INET6
10103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/* convert a string to a scope identifier. XXX: IPv6 specific */
10113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
10123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
10133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
10143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	u_long lscopeid;
10153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct in6_addr *a6;
10163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *ep;
10173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(scope != NULL);
10193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(sin6 != NULL);
10203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(scopeid != NULL);
10213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	a6 = &sin6->sin6_addr;
10233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* empty scopeid portion is invalid */
10253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (*scope == '\0')
10263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return -1;
10273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
10293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/*
10303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * We currently assume a one-to-one mapping between links
10313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * and interfaces, so we simply use interface indices for
10323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * like-local scopes.
10333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 */
10343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
10353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*scopeid = if_nametoindex(scope);
10363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (*scopeid == 0)
10373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			goto trynumeric;
10383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
10393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy*/
10403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return -1;
10413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
10423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* still unclear about literal, allow numeric only - placeholder */
10443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
10453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto trynumeric;
10463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
10473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto trynumeric;
10483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	else
10493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto trynumeric;	/* global */
10503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* try to convert to a numeric id as a last resort */
10523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  trynumeric:
10533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	errno = 0;
10543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	lscopeid = strtoul(scope, &ep, 10);
10553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
10563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
10573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return 0;
10583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	else
10593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return -1;
10603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
10613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
10623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/* code duplicate with gethnamaddr.c */
10643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic const char AskedForGot[] =
10663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
10673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *
10693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahygetanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
10703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    const struct addrinfo *pai)
10713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
10723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel, *cur;
10733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo ai;
10743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct afd *afd;
10753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *canonname;
10763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const HEADER *hp;
10773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const u_char *cp;
10783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int n;
10793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const u_char *eom;
10803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *bp, *ep;
10813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int type, class, ancount, qdcount;
10823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int haveanswer, had_error;
10833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char tbuf[MAXDNAME];
10843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int (*name_ok) (const char *);
10853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	static char hostbuf[8*1024];
10863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(answer != NULL);
10883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(qname != NULL);
10893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
10903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&sentinel, 0, sizeof(sentinel));
10923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
10933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
10943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	canonname = NULL;
10953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	eom = answer->buf + anslen;
10963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	switch (qtype) {
10973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case T_A:
10983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case T_AAAA:
10993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case T_ANY:	/*use T_ANY only for T_A/T_AAAA lookup*/
11003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		name_ok = res_hnok;
11013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
11023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	default:
11033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NULL;	/* XXX should be abort(); */
11043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
11053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
11063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * find first satisfactory answer
11073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
11083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hp = &answer->hdr;
11093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ancount = ntohs(hp->ancount);
11103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	qdcount = ntohs(hp->qdcount);
11113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	bp = hostbuf;
11123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ep = hostbuf + sizeof hostbuf;
11133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cp = answer->buf + HFIXEDSZ;
11143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (qdcount != 1) {
11153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = NO_RECOVERY;
11163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return (NULL);
11173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
11183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
11193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if ((n < 0) || !(*name_ok)(bp)) {
11203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = NO_RECOVERY;
11213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return (NULL);
11223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
11233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cp += n + QFIXEDSZ;
11243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
11253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* res_send() has already verified that the query name is the
11263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * same as the one we sent; this just gets the expanded name
11273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * (i.e., with the succeeding search-domain tacked on).
11283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 */
11293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		n = (int)strlen(bp) + 1;		/* for the \0 */
11303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n >= MAXHOSTNAMELEN) {
11313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = NO_RECOVERY;
11323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return (NULL);
11333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
11343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		canonname = bp;
11353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		bp += n;
11363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* The qname can be abbreviated, but h_name is now absolute. */
11373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		qname = canonname;
11383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
11393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	haveanswer = 0;
11403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	had_error = 0;
11413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	while (ancount-- > 0 && cp < eom && !had_error) {
11423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
11433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if ((n < 0) || !(*name_ok)(bp)) {
11443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			had_error++;
11453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
11463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
11473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		cp += n;			/* name */
11483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		type = _getshort(cp);
11493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy 		cp += INT16SZ;			/* type */
11503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		class = _getshort(cp);
11513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy 		cp += INT16SZ + INT32SZ;	/* class, TTL */
11523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		n = _getshort(cp);
11533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		cp += INT16SZ;			/* len */
11543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (class != C_IN) {
11553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			/* XXX - debug? syslog? */
11563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cp += n;
11573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;		/* XXX - had_error++ ? */
11583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
11593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
11603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		    type == T_CNAME) {
11613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
11623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if ((n < 0) || !(*name_ok)(tbuf)) {
11633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				had_error++;
11643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;
11653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
11663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cp += n;
11673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			/* Get canonical name. */
11683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			n = (int)strlen(tbuf) + 1;	/* for the \0 */
11693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
11703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				had_error++;
11713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;
11723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
11733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			strlcpy(bp, tbuf, (size_t)(ep - bp));
11743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			canonname = bp;
11753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			bp += n;
11763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
11773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
11783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (qtype == T_ANY) {
11793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (!(type == T_A || type == T_AAAA)) {
11803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				cp += n;
11813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;
11823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
11833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		} else if (type != qtype) {
11843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (type != T_KEY && type != T_SIG) {
11853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef _ORG_FREEBSD_
11863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				struct syslog_data sd = SYSLOG_DATA_INIT;
11873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
11883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
11893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				       qname, p_class(C_IN), p_type(qtype),
11903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				       p_type(type));
11913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
11923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
11933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cp += n;
11943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;		/* XXX - had_error++ ? */
11953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
11963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		switch (type) {
11973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case T_A:
11983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case T_AAAA:
11993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (strcasecmp(canonname, bp) != 0) {
12003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef _ORG_FREEBSD_
12013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				struct syslog_data sd = SYSLOG_DATA_INIT;
12023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
12033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				       AskedForGot, canonname, bp);
12043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
12053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				cp += n;
12063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;	/* XXX - had_error++ ? */
12073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
12083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (type == T_A && n != INADDRSZ) {
12093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				cp += n;
12103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;
12113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
12123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (type == T_AAAA && n != IN6ADDRSZ) {
12133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				cp += n;
12143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;
12153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
12163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (type == T_AAAA) {
12173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				struct in6_addr in6;
12183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				memcpy(&in6, cp, IN6ADDRSZ);
12193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
12203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					cp += n;
12213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					continue;
12223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				}
12233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
12243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (!haveanswer) {
12253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				int nn;
12263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				canonname = bp;
12283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				nn = (int)strlen(bp) + 1;	/* for the \0 */
12293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				bp += nn;
12303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
12313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			/* don't overwrite pai */
12333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ai = *pai;
12343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
12353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			afd = find_afd(ai.ai_family);
12363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (afd == NULL) {
12373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				cp += n;
12383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				continue;
12393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
12403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur->ai_next = get_ai(&ai, afd, (const char *)cp);
12413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (cur->ai_next == NULL)
12423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				had_error++;
12433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			while (cur && cur->ai_next)
12443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				cur = cur->ai_next;
12453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cp += n;
12463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
12473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		default:
12483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			abort();
12493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
12503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!had_error)
12513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			haveanswer++;
12523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
12533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (haveanswer) {
12543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!canonname)
12553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			(void)get_canonname(pai, sentinel.ai_next, qname);
12563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		else
12573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			(void)get_canonname(pai, sentinel.ai_next, canonname);
12583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = NETDB_SUCCESS;
12593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return sentinel.ai_next;
12603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
12613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	h_errno = NO_RECOVERY;
12633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return NULL;
12643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
12653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define SORTEDADDR(p)	(((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr)
12673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr)
12683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic void
12703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyaisort(struct addrinfo *s, res_state res)
12713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
12723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo head, *t, *p;
12733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int i;
12743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	head.ai_next = NULL;
12763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	t = &head;
12773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	for (i = 0; i < (int)res->nsort; i++) {
12793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		p = s;
12803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		while (p->ai_next) {
12813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if ((p->ai_next->ai_family != AF_INET)
12823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			|| SORTMATCH(p, res->sort_list[i])) {
12833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				t->ai_next = p->ai_next;
12843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				t = t->ai_next;
12853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				p->ai_next = p->ai_next->ai_next;
12863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			} else {
12873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				p = p->ai_next;
12883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
12893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
12903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
12913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* add rest of list and reset s to the new list*/
12933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	t->ai_next = s->ai_next;
12943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	s->ai_next = head.ai_next;
12953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
12963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
12973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*ARGSUSED*/
12983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
12993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy_dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
13003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
13013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *ai;
13023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	querybuf *buf, *buf2;
13033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *name;
13043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct addrinfo *pai;
13053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel, *cur;
13063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct res_target q, q2;
13073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	res_state res;
13083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
13093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	name = va_arg(ap, char *);
13103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai = va_arg(ap, const struct addrinfo *);
13113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
13123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&q, 0, sizeof(q));
13133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&q2, 0, sizeof(q2));
13143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&sentinel, 0, sizeof(sentinel));
13153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
13163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
13173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	buf = malloc(sizeof(*buf));
13183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (buf == NULL) {
13193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = NETDB_INTERNAL;
13203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_NOTFOUND;
13213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
13223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	buf2 = malloc(sizeof(*buf2));
13233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (buf2 == NULL) {
13243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(buf);
13253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = NETDB_INTERNAL;
13263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_NOTFOUND;
13273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
13283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
13293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	switch (pai->ai_family) {
13303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case AF_UNSPEC:
13313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* prefer IPv6 */
13323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.name = name;
13333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.qclass = C_IN;
13343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.qtype = T_AAAA;
13353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.answer = buf->buf;
13363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.anslen = sizeof(buf->buf);
13373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.next = &q2;
13383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q2.name = name;
13393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q2.qclass = C_IN;
13403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q2.qtype = T_A;
13413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q2.answer = buf2->buf;
13423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q2.anslen = sizeof(buf2->buf);
13433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
13443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case AF_INET:
13453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.name = name;
13463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.qclass = C_IN;
13473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.qtype = T_A;
13483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.answer = buf->buf;
13493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.anslen = sizeof(buf->buf);
13503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
13513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	case AF_INET6:
13523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.name = name;
13533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.qclass = C_IN;
13543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.qtype = T_AAAA;
13553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.answer = buf->buf;
13563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		q.anslen = sizeof(buf->buf);
13573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		break;
13583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	default:
13593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(buf);
13603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(buf2);
13613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_UNAVAIL;
13623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
13633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
13643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	res = __res_get_state();
13653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (res == NULL) {
13663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(buf);
13673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(buf2);
13683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_NOTFOUND;
13693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
13703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
13713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (res_searchN(name, &q, res) < 0) {
13723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		__res_put_state(res);
13733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(buf);
13743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(buf2);
13753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_NOTFOUND;
13763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
13773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ai = getanswer(buf, q.n, q.name, q.qtype, pai);
13783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (ai) {
13793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		cur->ai_next = ai;
13803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		while (cur && cur->ai_next)
13813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur = cur->ai_next;
13823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
13833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (q.next) {
13843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
13853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ai)
13863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur->ai_next = ai;
13873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
13883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	free(buf);
13893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	free(buf2);
13903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next == NULL) {
13913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		__res_put_state(res);
13923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		switch (h_errno) {
13933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case HOST_NOT_FOUND:
13943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return NS_NOTFOUND;
13953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case TRY_AGAIN:
13963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return NS_TRYAGAIN;
13973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		default:
13983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return NS_UNAVAIL;
13993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
14003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
14013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (res->nsort)
14033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		aisort(&sentinel, res);
14043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	__res_put_state(res);
14063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*((struct addrinfo **)rv) = sentinel.ai_next;
14083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return NS_SUCCESS;
14093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
14103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic void
14123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy_sethtent(FILE **hostf)
14133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
14143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (!*hostf)
14163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*hostf = fopen(_PATH_HOSTS, "r" );
14173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	else
14183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		rewind(*hostf);
14193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
14203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic void
14223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy_endhtent(FILE **hostf)
14233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
14243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (*hostf) {
14263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		(void) fclose(*hostf);
14273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*hostf = NULL;
14283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
14293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
14303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *
14323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
14333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
14343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *p;
14353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *cp, *tname, *cname;
14363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo hints, *res0, *res;
14373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int error;
14383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *addr;
14393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	static char hostbuf[8*1024];
14403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(name != NULL);
14423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
14433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (!*hostf && ( NULL == (*hostf = fopen(_PATH_HOSTS, "r" ))))
14453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return (NULL);
14463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy again:
14473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if ( NULL == (p = fgets(hostbuf, sizeof hostbuf, *hostf)))
14483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return (NULL);
14493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (*p == '#')
14503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto again;
14513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if ( NULL == (cp = strpbrk(p, "#\n")))
14523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto again;
14533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*cp = '\0';
14543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if ( NULL == (cp = strpbrk(p, " \t")))
14553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto again;
14563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*cp++ = '\0';
14573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	addr = p;
14583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* if this is not something we're looking for, skip it. */
14593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cname = NULL;
14603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	while (cp && *cp) {
14613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (*cp == ' ' || *cp == '\t') {
14623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cp++;
14633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
14643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
14653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!cname)
14663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cname = cp;
14673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		tname = cp;
14683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if ((cp = strpbrk(cp, " \t")) != NULL)
14693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			*cp++ = '\0';
14703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (strcasecmp(name, tname) == 0)
14713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			goto found;
14723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
14733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	goto again;
14743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyfound:
14763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hints = *pai;
14773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hints.ai_flags = AI_NUMERICHOST;
14783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	error = getaddrinfo(addr, NULL, &hints, &res0);
14793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (error)
14803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto again;
14813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	for (res = res0; res; res = res->ai_next) {
14823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* cover it up */
14833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		res->ai_flags = pai->ai_flags;
14843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (pai->ai_flags & AI_CANONNAME) {
14863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (get_canonname(pai, res, cname) != 0) {
14873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				freeaddrinfo(res0);
14883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				goto again;
14893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
14903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
14913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
14923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return res0;
14933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
14943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
14953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*ARGSUSED*/
14963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
14973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
14983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
14993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *name;
15003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct addrinfo *pai;
15013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel, *cur;
15023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *p;
15033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifndef _REENTRANT
15043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	static
15053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
15063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	FILE *hostf = NULL;
15073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	name = va_arg(ap, char *);
15093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai = va_arg(ap, const struct addrinfo *);
15103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&sentinel, 0, sizeof(sentinel));
15123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
15133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_sethtent(&hostf);
15153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	while ((p = _gethtent(&hostf, name, pai)) != NULL) {
15163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		cur->ai_next = p;
15173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		while (cur && cur->ai_next)
15183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur = cur->ai_next;
15193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
15203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_endhtent(&hostf);
15213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*((struct addrinfo **)rv) = sentinel.ai_next;
15233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next == NULL)
15243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_NOTFOUND;
15253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return NS_SUCCESS;
15263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
15273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef YP
15293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*ARGSUSED*/
15303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic struct addrinfo *
15313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy_yphostent(char *line, const struct addrinfo *pai)
15323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
15333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel, *cur;
15343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo hints, *res, *res0;
15353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int error;
15363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *p;
15373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *addr, *canonname;
15383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *nextline;
15393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *cp;
15403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(line != NULL);
15423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(pai != NULL);
15433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	p = line;
15453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	addr = canonname = NULL;
15463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&sentinel, 0, sizeof(sentinel));
15483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
15493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahynextline:
15513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* terminate line */
15523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cp = strchr(p, '\n');
15533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (cp) {
15543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		*cp++ = '\0';
15553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		nextline = cp;
15563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} else
15573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		nextline = NULL;
15583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cp = strpbrk(p, " \t");
15603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (cp == NULL) {
15613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (canonname == NULL)
15623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return (NULL);
15633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		else
15643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			goto done;
15653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
15663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*cp++ = '\0';
15673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	addr = p;
15693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	while (cp && *cp) {
15713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (*cp == ' ' || *cp == '\t') {
15723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cp++;
15733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
15743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
15753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (!canonname)
15763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			canonname = cp;
15773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if ((cp = strpbrk(cp, " \t")) != NULL)
15783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			*cp++ = '\0';
15793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
15803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hints = *pai;
15823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hints.ai_flags = AI_NUMERICHOST;
15833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	error = getaddrinfo(addr, NULL, &hints, &res0);
15843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (error == 0) {
15853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		for (res = res0; res; res = res->ai_next) {
15863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			/* cover it up */
15873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			res->ai_flags = pai->ai_flags;
15883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
15893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (pai->ai_flags & AI_CANONNAME)
15903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				(void)get_canonname(pai, res, canonname);
15913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
15923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} else
15933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		res0 = NULL;
15943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (res0) {
15953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		cur->ai_next = res0;
15963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		while (cur->ai_next)
15973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur = cur->ai_next;
15983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
15993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (nextline) {
16013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		p = nextline;
16023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		goto nextline;
16033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
16043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahydone:
16063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return sentinel.ai_next;
16073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
16083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*ARGSUSED*/
16103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
16113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy_yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
16123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
16133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo sentinel, *cur;
16143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct addrinfo *ai = NULL;
16153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *ypbuf;
16163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int ypbuflen, r;
16173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *name;
16183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const struct addrinfo *pai;
16193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char *ypdomain;
16203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (_yp_check(&ypdomain) == 0)
16223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_UNAVAIL;
16233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	name = va_arg(ap, char *);
16253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	pai = va_arg(ap, const struct addrinfo *);
16263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	memset(&sentinel, 0, sizeof(sentinel));
16283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	cur = &sentinel;
16293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* hosts.byname is only for IPv4 (Solaris8) */
16313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
16323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		r = yp_match(ypdomain, "hosts.byname", name,
16333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			(int)strlen(name), &ypbuf, &ypbuflen);
16343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (r == 0) {
16353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			struct addrinfo ai4;
16363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ai4 = *pai;
16383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ai4.ai_family = AF_INET;
16393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ai = _yphostent(ypbuf, &ai4);
16403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (ai) {
16413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				cur->ai_next = ai;
16423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				while (cur && cur->ai_next)
16433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					cur = cur->ai_next;
16443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
16453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
16463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(ypbuf);
16473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
16483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* ipnodes.byname can hold both IPv4/v6 */
16503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	r = yp_match(ypdomain, "ipnodes.byname", name,
16513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		(int)strlen(name), &ypbuf, &ypbuflen);
16523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (r == 0) {
16533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ai = _yphostent(ypbuf, pai);
16543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ai)
16553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			cur->ai_next = ai;
16563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		free(ypbuf);
16573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
16583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (sentinel.ai_next == NULL) {
16603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = HOST_NOT_FOUND;
16613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return NS_NOTFOUND;
16623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
16633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	*((struct addrinfo **)rv) = sentinel.ai_next;
16643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return NS_SUCCESS;
16653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
16663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
16673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/* resolver logic */
16693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
16713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Formulate a normal query, send, and await answer.
16723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Returned answer is placed in supplied buffer "answer".
16733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Perform preliminary check of answer, returning success only
16743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * if no error is indicated and the answer count is nonzero.
16753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Return the size of the response on success, -1 on error.
16763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Error number is left in h_errno.
16773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy *
16783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Caller must parse answer and determine whether it answers the question.
16793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
16803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
16813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyres_queryN(const char *name, /* domain name */ struct res_target *target,
16823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    res_state res)
16833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
16843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	static u_char buf[MAXPACKET];
16853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	HEADER *hp;
16863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int n;
16873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	struct res_target *t;
16883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int rcode;
16893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int ancount;
16903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(name != NULL);
16923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* XXX: target may be NULL??? */
16933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	rcode = NOERROR;
16953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	ancount = 0;
16963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
16973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	for (t = target; t; t = t->next) {
16983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		int class, type;
16993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		u_char *answer;
17003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		int anslen;
17013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		hp = (HEADER *)(void *)t->answer;
17033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		hp->rcode = NOERROR;	/* default */
17043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/* make it easier... */
17063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		class = t->qclass;
17073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		type = t->qtype;
17083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		answer = t->answer;
17093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		anslen = t->anslen;
17103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef DEBUG
17113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (res->options & RES_DEBUG)
17123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
17133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
17143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
17163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		    buf, sizeof(buf));
17173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef RES_USE_EDNS0
17183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n > 0 && (res->options & RES_USE_EDNS0) != 0)
17193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			n = res_nopt(res, n, buf, sizeof(buf), anslen);
17203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
17213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n <= 0) {
17223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef DEBUG
17233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (res->options & RES_DEBUG)
17243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				printf(";; res_nquery: mkquery failed\n");
17253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
17263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = NO_RECOVERY;
17273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return n;
17283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
17293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		n = res_nsend(res, buf, n, answer, anslen);
17303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#if 0
17313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n < 0) {
17323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef DEBUG
17333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (res->options & RES_DEBUG)
17343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				printf(";; res_query: send error\n");
17353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
17363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = TRY_AGAIN;
17373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return n;
17383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
17393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
17403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
17423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			rcode = hp->rcode;	/* record most recent error */
17433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef DEBUG
17443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (res->options & RES_DEBUG)
17453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				printf(";; rcode = %u, ancount=%u\n", hp->rcode,
17463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				    ntohs(hp->ancount));
17473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
17483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			continue;
17493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
17503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ancount += ntohs(hp->ancount);
17523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		t->n = n;
17543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
17553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (ancount == 0) {
17573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		switch (rcode) {
17583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case NXDOMAIN:
17593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = HOST_NOT_FOUND;
17603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
17613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case SERVFAIL:
17623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = TRY_AGAIN;
17633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
17643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case NOERROR:
17653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = NO_DATA;
17663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
17673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case FORMERR:
17683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case NOTIMP:
17693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		case REFUSED:
17703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		default:
17713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = NO_RECOVERY;
17723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			break;
17733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
17743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return -1;
17753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
17763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return ancount;
17773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
17783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
17803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Formulate a normal query, send, and retrieve answer in supplied buffer.
17813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Return the size of the response on success, -1 on error.
17823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * If enabled, implement search rules until answer or unrecoverable failure
17833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * is detected.  Error code, if any, is left in h_errno.
17843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
17853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
17863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyres_searchN(const char *name, struct res_target *target, res_state res)
17873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
17883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *cp, * const *domain;
17893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	HEADER *hp;
17903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	u_int dots;
17913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int trailing_dot, ret, saved_herrno;
17923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
17933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(name != NULL);
17953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(target != NULL);
17963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	hp = (HEADER *)(void *)target->answer;	/*XXX*/
17983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
17993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	errno = 0;
18003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	h_errno = HOST_NOT_FOUND;	/* default, if we never query */
18013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	dots = 0;
18023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	for (cp = name; *cp; cp++)
18033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		dots += (*cp == '.');
18043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	trailing_dot = 0;
18053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (cp > name && *--cp == '.')
18063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		trailing_dot++;
18073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
18093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if there aren't any dots, it could be a user-level alias
18103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
18113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (!dots && (cp = __hostalias(name)) != NULL) {
18123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ret = res_queryN(cp, target, res);
18133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		return ret;
18143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
18153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
18173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * If there are dots in the name already, let's just give it a try
18183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * 'as is'.  The threshold can be set with the "ndots" option.
18193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
18203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	saved_herrno = -1;
18213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (dots >= res->ndots) {
18223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ret = res_querydomainN(name, NULL, target, res);
18233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ret > 0)
18243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return (ret);
18253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		saved_herrno = h_errno;
18263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		tried_as_is++;
18273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
18283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
18303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * We do at least one level of search if
18313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 *	- there is no dot and RES_DEFNAME is set, or
18323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 *	- there is at least one dot, there is no trailing dot,
18333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 *	  and RES_DNSRCH is set.
18343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
18353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if ((!dots && (res->options & RES_DEFNAMES)) ||
18363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	    (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
18373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		int done = 0;
18383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		for (domain = (const char * const *)res->dnsrch;
18403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		   *domain && !done;
18413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		   domain++) {
18423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			ret = res_querydomainN(name, *domain, target, res);
18443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (ret > 0)
18453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				return ret;
18463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			/*
18483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * If no server present, give up.
18493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * If name isn't found in this domain,
18503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * keep trying higher domains in the search list
18513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * (if that's enabled).
18523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * On a NO_DATA error, keep trying, otherwise
18533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * a wildcard entry of another type could keep us
18543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * from finding this entry higher in the domain.
18553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * If we get some other error (negative answer or
18563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * server failure), then stop searching up,
18573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * but try the input name below in case it's
18583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * fully-qualified.
18593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 */
18603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (errno == ECONNREFUSED) {
18613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				h_errno = TRY_AGAIN;
18623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				return -1;
18633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
18643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			switch (h_errno) {
18663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			case NO_DATA:
18673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				got_nodata++;
18683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				/* FALLTHROUGH */
18693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			case HOST_NOT_FOUND:
18703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				/* keep trying */
18713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				break;
18723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			case TRY_AGAIN:
18733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				if (hp->rcode == SERVFAIL) {
18743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					/* try next search element, if any */
18753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					got_servfail++;
18763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy					break;
18773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				}
18783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				/* FALLTHROUGH */
18793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			default:
18803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				/* anything else implies that we're done */
18813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy				done++;
18823bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			}
18833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			/*
18843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * if we got here for some reason other than DNSRCH,
18853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 * we only wanted one iteration of the loop, so stop.
18863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			 */
18873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			if (!(res->options & RES_DNSRCH))
18883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			        done++;
18893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
18903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
18913bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
18923bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
18933bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if we have not already tried the name "as is", do that now.
18943bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * note that we do this regardless of how many dots were in the
18953bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * name or whether it ends with a dot.
18963bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
18973bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (!tried_as_is) {
18983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		ret = res_querydomainN(name, NULL, target, res);
18993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (ret > 0)
19003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return ret;
19013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
19023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
19033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/*
19043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if we got here, we didn't satisfy the search.
19053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * if we did an initial full query, return that query's h_errno
19063bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * (note that we wouldn't be here if that query had succeeded).
19073bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * else if we ever got a nodata, send that back as the reason.
19083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * else send back meaningless h_errno, that being the one from
19093bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 * the last DNSRCH we did.
19103bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	 */
19113bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (saved_herrno != -1)
19123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = saved_herrno;
19133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	else if (got_nodata)
19143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = NO_DATA;
19153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	else if (got_servfail)
19163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		h_errno = TRY_AGAIN;
19173bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return -1;
19183bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
19193bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
19203bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy/*
19213bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * Perform a call on res_query on the concatenation of name and domain,
19223bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy * removing a trailing dot from name if domain is NULL.
19233bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy */
19243bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahystatic int
19253bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyres_querydomainN(const char *name, const char *domain,
19263bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    struct res_target *target, res_state res)
19273bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
19283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	char nbuf[MAXDNAME];
19293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	const char *longname = nbuf;
19303bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	size_t n, d;
19313bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
19323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	_DIAGASSERT(name != NULL);
19333bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	/* XXX: target may be NULL??? */
19343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
19353bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#ifdef DEBUG
19363bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (res->options & RES_DEBUG)
19373bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		printf(";; res_querydomain(%s, %s)\n",
19383bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			name, domain?domain:"<Nil>");
19393bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy#endif
19403bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	if (domain == NULL) {
19413bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		/*
19423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * Check for trailing '.';
19433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 * copy without '.' if present.
19443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		 */
19453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		n = strlen(name);
19463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n + 1 > sizeof(nbuf)) {
19473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = NO_RECOVERY;
19483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return -1;
19493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
19503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n > 0 && name[--n] == '.') {
19513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			strncpy(nbuf, name, n);
19523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			nbuf[n] = '\0';
19533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		} else
19543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			longname = name;
19553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	} else {
19563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		n = strlen(name);
19573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		d = strlen(domain);
19583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		if (n + 1 + d + 1 > sizeof(nbuf)) {
19593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			h_errno = NO_RECOVERY;
19603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy			return -1;
19613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		}
19623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy		snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
19633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	}
19643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy	return res_queryN(longname, target, res);
19653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
1966