xref: /freebsd/lib/libc/net/gethostbydns.c (revision 6c5aff80)
1ca785773SPeter Wemm /*
2ca785773SPeter Wemm  * ++Copyright++ 1985, 1988, 1993
3ca785773SPeter Wemm  * -
41363f04cSPaul Traina  * Copyright (c) 1985, 1988, 1993
51363f04cSPaul Traina  *	The Regents of the University of California.  All rights reserved.
61363f04cSPaul Traina  *
71363f04cSPaul Traina  * Redistribution and use in source and binary forms, with or without
81363f04cSPaul Traina  * modification, are permitted provided that the following conditions
91363f04cSPaul Traina  * are met:
101363f04cSPaul Traina  * 1. Redistributions of source code must retain the above copyright
111363f04cSPaul Traina  *    notice, this list of conditions and the following disclaimer.
121363f04cSPaul Traina  * 2. Redistributions in binary form must reproduce the above copyright
131363f04cSPaul Traina  *    notice, this list of conditions and the following disclaimer in the
141363f04cSPaul Traina  *    documentation and/or other materials provided with the distribution.
151363f04cSPaul Traina  * 3. All advertising materials mentioning features or use of this software
161363f04cSPaul Traina  *    must display the following acknowledgement:
171363f04cSPaul Traina  *	This product includes software developed by the University of
181363f04cSPaul Traina  *	California, Berkeley and its contributors.
191363f04cSPaul Traina  * 4. Neither the name of the University nor the names of its contributors
201363f04cSPaul Traina  *    may be used to endorse or promote products derived from this software
211363f04cSPaul Traina  *    without specific prior written permission.
221363f04cSPaul Traina  *
231363f04cSPaul Traina  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
241363f04cSPaul Traina  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
251363f04cSPaul Traina  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
261363f04cSPaul Traina  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
271363f04cSPaul Traina  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
281363f04cSPaul Traina  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
291363f04cSPaul Traina  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
301363f04cSPaul Traina  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
311363f04cSPaul Traina  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
321363f04cSPaul Traina  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
331363f04cSPaul Traina  * SUCH DAMAGE.
341363f04cSPaul Traina  * -
351363f04cSPaul Traina  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
361363f04cSPaul Traina  *
371363f04cSPaul Traina  * Permission to use, copy, modify, and distribute this software for any
381363f04cSPaul Traina  * purpose with or without fee is hereby granted, provided that the above
391363f04cSPaul Traina  * copyright notice and this permission notice appear in all copies, and that
401363f04cSPaul Traina  * the name of Digital Equipment Corporation not be used in advertising or
411363f04cSPaul Traina  * publicity pertaining to distribution of the document or software without
421363f04cSPaul Traina  * specific, written prior permission.
431363f04cSPaul Traina  *
441363f04cSPaul Traina  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
451363f04cSPaul Traina  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
461363f04cSPaul Traina  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
471363f04cSPaul Traina  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
481363f04cSPaul Traina  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
491363f04cSPaul Traina  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
501363f04cSPaul Traina  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
511363f04cSPaul Traina  * SOFTWARE.
521363f04cSPaul Traina  * -
531363f04cSPaul Traina  * --Copyright--
541363f04cSPaul Traina  */
551363f04cSPaul Traina 
561363f04cSPaul Traina #if defined(LIBC_SCCS) && !defined(lint)
571363f04cSPaul Traina static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
586c5aff80SPeter Wemm static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp";
596c5aff80SPeter Wemm static char rcsid[] = "$Id: gethostbydns.c,v 1.21 1997/03/12 11:02:00 peter Exp $";
601363f04cSPaul Traina #endif /* LIBC_SCCS and not lint */
611363f04cSPaul Traina 
625ce1c533SPeter Wemm #include <sys/types.h>
631363f04cSPaul Traina #include <sys/param.h>
641363f04cSPaul Traina #include <sys/socket.h>
651363f04cSPaul Traina #include <netinet/in.h>
661363f04cSPaul Traina #include <arpa/inet.h>
671363f04cSPaul Traina #include <arpa/nameser.h>
68e5ad4f87SPeter Wemm 
69e5ad4f87SPeter Wemm #include <stdio.h>
70fce61be7SPoul-Henning Kamp #include <unistd.h>
71e5ad4f87SPeter Wemm #include <string.h>
721363f04cSPaul Traina #include <netdb.h>
731363f04cSPaul Traina #include <resolv.h>
741363f04cSPaul Traina #include <ctype.h>
751363f04cSPaul Traina #include <errno.h>
761363f04cSPaul Traina #include <syslog.h>
771363f04cSPaul Traina 
78e6507d61SBruce Evans #include "res_config.h"
791363f04cSPaul Traina 
805ce1c533SPeter Wemm #define SPRINTF(x) ((size_t)sprintf x)
815ce1c533SPeter Wemm 
821363f04cSPaul Traina #define	MAXALIASES	35
831363f04cSPaul Traina #define	MAXADDRS	35
841363f04cSPaul Traina 
851363f04cSPaul Traina static const char AskedForGot[] =
861363f04cSPaul Traina 		"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
871363f04cSPaul Traina 
881363f04cSPaul Traina static char *h_addr_ptrs[MAXADDRS + 1];
891363f04cSPaul Traina 
901363f04cSPaul Traina static struct hostent host;
911363f04cSPaul Traina static char *host_aliases[MAXALIASES];
921363f04cSPaul Traina static char hostbuf[8*1024];
935ce1c533SPeter Wemm static u_char host_addr[16];	/* IPv4 or IPv6 */
941363f04cSPaul Traina 
954faad310SPeter Wemm #ifdef RESOLVSORT
964faad310SPeter Wemm static void addrsort __P((char **, int));
974faad310SPeter Wemm #endif
984faad310SPeter Wemm 
991363f04cSPaul Traina #if PACKETSZ > 1024
1001363f04cSPaul Traina #define	MAXPACKET	PACKETSZ
1011363f04cSPaul Traina #else
1021363f04cSPaul Traina #define	MAXPACKET	1024
1031363f04cSPaul Traina #endif
1041363f04cSPaul Traina 
1051363f04cSPaul Traina typedef union {
1061363f04cSPaul Traina     HEADER hdr;
1071363f04cSPaul Traina     u_char buf[MAXPACKET];
1081363f04cSPaul Traina } querybuf;
1091363f04cSPaul Traina 
1101363f04cSPaul Traina typedef union {
1111363f04cSPaul Traina     int32_t al;
1121363f04cSPaul Traina     char ac;
1131363f04cSPaul Traina } align;
1141363f04cSPaul Traina 
1151363f04cSPaul Traina extern int h_errno;
116df9c30afSPeter Wemm int _dns_ttl_;
1171363f04cSPaul Traina 
118e5ad4f87SPeter Wemm #ifdef DEBUG
119e5ad4f87SPeter Wemm static void
120e5ad4f87SPeter Wemm dprintf(msg, num)
121e5ad4f87SPeter Wemm 	char *msg;
122e5ad4f87SPeter Wemm 	int num;
123e5ad4f87SPeter Wemm {
124e5ad4f87SPeter Wemm 	if (_res.options & RES_DEBUG) {
125e5ad4f87SPeter Wemm 		int save = errno;
126e5ad4f87SPeter Wemm 
127e5ad4f87SPeter Wemm 		printf(msg, num);
128e5ad4f87SPeter Wemm 		errno = save;
129e5ad4f87SPeter Wemm 	}
130e5ad4f87SPeter Wemm }
131e5ad4f87SPeter Wemm #else
132e5ad4f87SPeter Wemm # define dprintf(msg, num) /*nada*/
133e5ad4f87SPeter Wemm #endif
134e5ad4f87SPeter Wemm 
1351363f04cSPaul Traina static struct hostent *
1365ce1c533SPeter Wemm gethostanswer(answer, anslen, qname, qtype)
1371363f04cSPaul Traina 	const querybuf *answer;
1381363f04cSPaul Traina 	int anslen;
1391363f04cSPaul Traina 	const char *qname;
1405ce1c533SPeter Wemm 	int qtype;
1411363f04cSPaul Traina {
1421363f04cSPaul Traina 	register const HEADER *hp;
1431363f04cSPaul Traina 	register const u_char *cp;
1441363f04cSPaul Traina 	register int n;
1451363f04cSPaul Traina 	const u_char *eom;
1461363f04cSPaul Traina 	char *bp, **ap, **hap;
1471363f04cSPaul Traina 	int type, class, buflen, ancount, qdcount;
1481363f04cSPaul Traina 	int haveanswer, had_error;
1491363f04cSPaul Traina 	int toobig = 0;
150ca785773SPeter Wemm 	char tbuf[MAXDNAME];
1514faad310SPeter Wemm 	const char *tname;
1525ce1c533SPeter Wemm 	int (*name_ok) __P((const char *));
1531363f04cSPaul Traina 
1544faad310SPeter Wemm 	tname = qname;
1551363f04cSPaul Traina 	host.h_name = NULL;
1561363f04cSPaul Traina 	eom = answer->buf + anslen;
1575ce1c533SPeter Wemm 	switch (qtype) {
1585ce1c533SPeter Wemm 	case T_A:
1595ce1c533SPeter Wemm 	case T_AAAA:
1605ce1c533SPeter Wemm 		name_ok = res_hnok;
1615ce1c533SPeter Wemm 		break;
1625ce1c533SPeter Wemm 	case T_PTR:
1635ce1c533SPeter Wemm 		name_ok = res_dnok;
1645ce1c533SPeter Wemm 		break;
1655ce1c533SPeter Wemm 	default:
1665ce1c533SPeter Wemm 		h_errno = NO_RECOVERY;
1675ce1c533SPeter Wemm 		return (NULL);	/* XXX should be abort(); */
1685ce1c533SPeter Wemm 	}
1691363f04cSPaul Traina 	/*
1701363f04cSPaul Traina 	 * find first satisfactory answer
1711363f04cSPaul Traina 	 */
1721363f04cSPaul Traina 	hp = &answer->hdr;
1731363f04cSPaul Traina 	ancount = ntohs(hp->ancount);
1741363f04cSPaul Traina 	qdcount = ntohs(hp->qdcount);
1751363f04cSPaul Traina 	bp = hostbuf;
1761363f04cSPaul Traina 	buflen = sizeof hostbuf;
1771363f04cSPaul Traina 	cp = answer->buf + HFIXEDSZ;
1781363f04cSPaul Traina 	if (qdcount != 1) {
1791363f04cSPaul Traina 		h_errno = NO_RECOVERY;
1801363f04cSPaul Traina 		return (NULL);
1811363f04cSPaul Traina 	}
1825ce1c533SPeter Wemm 	n = dn_expand(answer->buf, eom, cp, bp, buflen);
1835ce1c533SPeter Wemm 	if ((n < 0) || !(*name_ok)(bp)) {
1841363f04cSPaul Traina 		h_errno = NO_RECOVERY;
1851363f04cSPaul Traina 		return (NULL);
1861363f04cSPaul Traina 	}
1871363f04cSPaul Traina 	cp += n + QFIXEDSZ;
1885ce1c533SPeter Wemm 	if (qtype == T_A || qtype == T_AAAA) {
1891363f04cSPaul Traina 		/* res_send() has already verified that the query name is the
1901363f04cSPaul Traina 		 * same as the one we sent; this just gets the expanded name
1911363f04cSPaul Traina 		 * (i.e., with the succeeding search-domain tacked on).
1921363f04cSPaul Traina 		 */
1931363f04cSPaul Traina 		n = strlen(bp) + 1;		/* for the \0 */
1946c5aff80SPeter Wemm 		if (n >= MAXHOSTNAMELEN) {
1956c5aff80SPeter Wemm 			h_errno = NO_RECOVERY;
1966c5aff80SPeter Wemm 			return (NULL);
1976c5aff80SPeter Wemm 		}
1981363f04cSPaul Traina 		host.h_name = bp;
1991363f04cSPaul Traina 		bp += n;
2001363f04cSPaul Traina 		buflen -= n;
2011363f04cSPaul Traina 		/* The qname can be abbreviated, but h_name is now absolute. */
2021363f04cSPaul Traina 		qname = host.h_name;
2031363f04cSPaul Traina 	}
2041363f04cSPaul Traina 	ap = host_aliases;
2051363f04cSPaul Traina 	*ap = NULL;
2061363f04cSPaul Traina 	host.h_aliases = host_aliases;
2071363f04cSPaul Traina 	hap = h_addr_ptrs;
2081363f04cSPaul Traina 	*hap = NULL;
2091363f04cSPaul Traina 	host.h_addr_list = h_addr_ptrs;
2101363f04cSPaul Traina 	haveanswer = 0;
2111363f04cSPaul Traina 	had_error = 0;
212df9c30afSPeter Wemm 	_dns_ttl_ = -1;
2131363f04cSPaul Traina 	while (ancount-- > 0 && cp < eom && !had_error) {
2141363f04cSPaul Traina 		n = dn_expand(answer->buf, eom, cp, bp, buflen);
2155ce1c533SPeter Wemm 		if ((n < 0) || !(*name_ok)(bp)) {
2161363f04cSPaul Traina 			had_error++;
2171363f04cSPaul Traina 			continue;
2181363f04cSPaul Traina 		}
2191363f04cSPaul Traina 		cp += n;			/* name */
2201363f04cSPaul Traina 		type = _getshort(cp);
2211363f04cSPaul Traina  		cp += INT16SZ;			/* type */
2221363f04cSPaul Traina 		class = _getshort(cp);
223df9c30afSPeter Wemm  		cp += INT16SZ;			/* class */
224df9c30afSPeter Wemm 		if (qtype == T_A  && type == T_A)
225df9c30afSPeter Wemm 			_dns_ttl_ = _getlong(cp);
226df9c30afSPeter Wemm 		cp += INT32SZ;			/* TTL */
2271363f04cSPaul Traina 		n = _getshort(cp);
2281363f04cSPaul Traina 		cp += INT16SZ;			/* len */
2295ce1c533SPeter Wemm 		if (class != C_IN) {
2301363f04cSPaul Traina 			/* XXX - debug? syslog? */
2311363f04cSPaul Traina 			cp += n;
2321363f04cSPaul Traina 			continue;		/* XXX - had_error++ ? */
2331363f04cSPaul Traina 		}
2345ce1c533SPeter Wemm 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
2351363f04cSPaul Traina 			if (ap >= &host_aliases[MAXALIASES-1])
2361363f04cSPaul Traina 				continue;
2371363f04cSPaul Traina 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
2385ce1c533SPeter Wemm 			if ((n < 0) || !(*name_ok)(tbuf)) {
2391363f04cSPaul Traina 				had_error++;
2401363f04cSPaul Traina 				continue;
2411363f04cSPaul Traina 			}
2421363f04cSPaul Traina 			cp += n;
2431363f04cSPaul Traina 			/* Store alias. */
2441363f04cSPaul Traina 			*ap++ = bp;
2451363f04cSPaul Traina 			n = strlen(bp) + 1;	/* for the \0 */
2466c5aff80SPeter Wemm 			if (n >= MAXHOSTNAMELEN) {
2476c5aff80SPeter Wemm 				had_error++;
2486c5aff80SPeter Wemm 				continue;
2496c5aff80SPeter Wemm 			}
2501363f04cSPaul Traina 			bp += n;
2511363f04cSPaul Traina 			buflen -= n;
2521363f04cSPaul Traina 			/* Get canonical name. */
2531363f04cSPaul Traina 			n = strlen(tbuf) + 1;	/* for the \0 */
2546c5aff80SPeter Wemm 			if (n > buflen || n >= MAXHOSTNAMELEN) {
2551363f04cSPaul Traina 				had_error++;
2561363f04cSPaul Traina 				continue;
2571363f04cSPaul Traina 			}
2581363f04cSPaul Traina 			strcpy(bp, tbuf);
2591363f04cSPaul Traina 			host.h_name = bp;
2601363f04cSPaul Traina 			bp += n;
2611363f04cSPaul Traina 			buflen -= n;
2621363f04cSPaul Traina 			continue;
2631363f04cSPaul Traina 		}
2644faad310SPeter Wemm 		if (qtype == T_PTR && type == T_CNAME) {
2654faad310SPeter Wemm 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
2666c5aff80SPeter Wemm 			if (n < 0 || !res_dnok(tbuf)) {
2674faad310SPeter Wemm 				had_error++;
2684faad310SPeter Wemm 				continue;
2694faad310SPeter Wemm 			}
2704faad310SPeter Wemm 			cp += n;
2714faad310SPeter Wemm 			/* Get canonical name. */
2724faad310SPeter Wemm 			n = strlen(tbuf) + 1;	/* for the \0 */
2736c5aff80SPeter Wemm 			if (n > buflen || n >= MAXHOSTNAMELEN) {
2744faad310SPeter Wemm 				had_error++;
2754faad310SPeter Wemm 				continue;
2764faad310SPeter Wemm 			}
2774faad310SPeter Wemm 			strcpy(bp, tbuf);
2784faad310SPeter Wemm 			tname = bp;
2794faad310SPeter Wemm 			bp += n;
2804faad310SPeter Wemm 			buflen -= n;
2814faad310SPeter Wemm 			continue;
2824faad310SPeter Wemm 		}
2831363f04cSPaul Traina 		if (type != qtype) {
2841363f04cSPaul Traina 			syslog(LOG_NOTICE|LOG_AUTH,
285e5ad4f87SPeter Wemm 	"gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
2865ce1c533SPeter Wemm 			       qname, p_class(C_IN), p_type(qtype),
287e5ad4f87SPeter Wemm 			       p_type(type));
2881363f04cSPaul Traina 			cp += n;
2891363f04cSPaul Traina 			continue;		/* XXX - had_error++ ? */
2901363f04cSPaul Traina 		}
2911363f04cSPaul Traina 		switch (type) {
2921363f04cSPaul Traina 		case T_PTR:
2934faad310SPeter Wemm 			if (strcasecmp(tname, bp) != 0) {
2941363f04cSPaul Traina 				syslog(LOG_NOTICE|LOG_AUTH,
2951363f04cSPaul Traina 				       AskedForGot, qname, bp);
2961363f04cSPaul Traina 				cp += n;
2971363f04cSPaul Traina 				continue;	/* XXX - had_error++ ? */
2981363f04cSPaul Traina 			}
2991363f04cSPaul Traina 			n = dn_expand(answer->buf, eom, cp, bp, buflen);
3005ce1c533SPeter Wemm 			if ((n < 0) || !res_hnok(bp)) {
3011363f04cSPaul Traina 				had_error++;
3021363f04cSPaul Traina 				break;
3031363f04cSPaul Traina 			}
3045ce1c533SPeter Wemm #if MULTI_PTRS_ARE_ALIASES
3051363f04cSPaul Traina 			cp += n;
3061363f04cSPaul Traina 			if (!haveanswer)
3071363f04cSPaul Traina 				host.h_name = bp;
3081363f04cSPaul Traina 			else if (ap < &host_aliases[MAXALIASES-1])
3091363f04cSPaul Traina 				*ap++ = bp;
3101363f04cSPaul Traina 			else
3111363f04cSPaul Traina 				n = -1;
3121363f04cSPaul Traina 			if (n != -1) {
3131363f04cSPaul Traina 				n = strlen(bp) + 1;	/* for the \0 */
3146c5aff80SPeter Wemm 				if (n >= MAXHOSTNAMELEN) {
3156c5aff80SPeter Wemm 					had_error++;
3166c5aff80SPeter Wemm 					break;
3176c5aff80SPeter Wemm 				}
3181363f04cSPaul Traina 				bp += n;
3191363f04cSPaul Traina 				buflen -= n;
3201363f04cSPaul Traina 			}
3211363f04cSPaul Traina 			break;
3221363f04cSPaul Traina #else
3231363f04cSPaul Traina 			host.h_name = bp;
3245ce1c533SPeter Wemm 			if (_res.options & RES_USE_INET6) {
3255ce1c533SPeter Wemm 				n = strlen(bp) + 1;	/* for the \0 */
3266c5aff80SPeter Wemm 				if (n >= MAXHOSTNAMELEN) {
3276c5aff80SPeter Wemm 					had_error++;
3286c5aff80SPeter Wemm 					break;
3296c5aff80SPeter Wemm 				}
3305ce1c533SPeter Wemm 				bp += n;
3315ce1c533SPeter Wemm 				buflen -= n;
3325ce1c533SPeter Wemm 				_map_v4v6_hostent(&host, &bp, &buflen);
3335ce1c533SPeter Wemm 			}
334e5ad4f87SPeter Wemm 			h_errno = NETDB_SUCCESS;
3351363f04cSPaul Traina 			return (&host);
3361363f04cSPaul Traina #endif
3371363f04cSPaul Traina 		case T_A:
3385ce1c533SPeter Wemm 		case T_AAAA:
3391363f04cSPaul Traina 			if (strcasecmp(host.h_name, bp) != 0) {
3401363f04cSPaul Traina 				syslog(LOG_NOTICE|LOG_AUTH,
3411363f04cSPaul Traina 				       AskedForGot, host.h_name, bp);
3421363f04cSPaul Traina 				cp += n;
3431363f04cSPaul Traina 				continue;	/* XXX - had_error++ ? */
3441363f04cSPaul Traina 			}
3451363f04cSPaul Traina 			if (n != host.h_length) {
3461363f04cSPaul Traina 				cp += n;
3471363f04cSPaul Traina 				continue;
3481363f04cSPaul Traina 			}
349beddb20cSPaul Traina 			if (!haveanswer) {
3501363f04cSPaul Traina 				register int nn;
3511363f04cSPaul Traina 
3521363f04cSPaul Traina 				host.h_name = bp;
3531363f04cSPaul Traina 				nn = strlen(bp) + 1;	/* for the \0 */
3541363f04cSPaul Traina 				bp += nn;
3551363f04cSPaul Traina 				buflen -= nn;
3561363f04cSPaul Traina 			}
3571363f04cSPaul Traina 
3581363f04cSPaul Traina 			bp += sizeof(align) - ((u_long)bp % sizeof(align));
3591363f04cSPaul Traina 
3601363f04cSPaul Traina 			if (bp + n >= &hostbuf[sizeof hostbuf]) {
361e5ad4f87SPeter Wemm 				dprintf("size (%d) too big\n", n);
3621363f04cSPaul Traina 				had_error++;
3631363f04cSPaul Traina 				continue;
3641363f04cSPaul Traina 			}
3651363f04cSPaul Traina 			if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
366e5ad4f87SPeter Wemm 				if (!toobig++)
367e5ad4f87SPeter Wemm 					dprintf("Too many addresses (%d)\n",
3681363f04cSPaul Traina 						MAXADDRS);
3691363f04cSPaul Traina 				cp += n;
3701363f04cSPaul Traina 				continue;
3711363f04cSPaul Traina 			}
3721363f04cSPaul Traina 			bcopy(cp, *hap++ = bp, n);
3731363f04cSPaul Traina 			bp += n;
3745ce1c533SPeter Wemm 			buflen -= n;
3751363f04cSPaul Traina 			cp += n;
3761363f04cSPaul Traina 			break;
3771363f04cSPaul Traina 		default:
378e5ad4f87SPeter Wemm 			dprintf("Impossible condition (type=%d)\n", type);
379e5ad4f87SPeter Wemm 			h_errno = NO_RECOVERY;
380e5ad4f87SPeter Wemm 			return (NULL);
381ca785773SPeter Wemm 			/* BIND has abort() here, too risky on bad data */
382ca785773SPeter Wemm 		}
3831363f04cSPaul Traina 		if (!had_error)
3841363f04cSPaul Traina 			haveanswer++;
385ca785773SPeter Wemm 	}
3861363f04cSPaul Traina 	if (haveanswer) {
3871363f04cSPaul Traina 		*ap = NULL;
3881363f04cSPaul Traina 		*hap = NULL;
3891363f04cSPaul Traina # if defined(RESOLVSORT)
3901363f04cSPaul Traina 		/*
3911363f04cSPaul Traina 		 * Note: we sort even if host can take only one address
3921363f04cSPaul Traina 		 * in its return structures - should give it the "best"
3931363f04cSPaul Traina 		 * address in that case, not some random one
3941363f04cSPaul Traina 		 */
3955ce1c533SPeter Wemm 		if (_res.nsort && haveanswer > 1 && qtype == T_A)
3961363f04cSPaul Traina 			addrsort(h_addr_ptrs, haveanswer);
3971363f04cSPaul Traina # endif /*RESOLVSORT*/
3981363f04cSPaul Traina 		if (!host.h_name) {
3991363f04cSPaul Traina 			n = strlen(qname) + 1;	/* for the \0 */
4006c5aff80SPeter Wemm 			if (n > buflen || n >= MAXHOSTNAMELEN)
4016c5aff80SPeter Wemm 				goto no_recovery;
4021363f04cSPaul Traina 			strcpy(bp, qname);
4031363f04cSPaul Traina 			host.h_name = bp;
4045ce1c533SPeter Wemm 			bp += n;
4055ce1c533SPeter Wemm 			buflen -= n;
4061363f04cSPaul Traina 		}
4075ce1c533SPeter Wemm 		if (_res.options & RES_USE_INET6)
4085ce1c533SPeter Wemm 			_map_v4v6_hostent(&host, &bp, &buflen);
409e5ad4f87SPeter Wemm 		h_errno = NETDB_SUCCESS;
4101363f04cSPaul Traina 		return (&host);
4115ce1c533SPeter Wemm 	}
4126c5aff80SPeter Wemm  no_recovery:
4136c5aff80SPeter Wemm 	h_errno = NO_RECOVERY;
4141363f04cSPaul Traina 	return (NULL);
4151363f04cSPaul Traina }
4161363f04cSPaul Traina 
4171363f04cSPaul Traina struct hostent *
418ce8bac1eSBill Paul __dns_getanswer(answer, anslen, qname, qtype)
419ce8bac1eSBill Paul 	const char *answer;
420ce8bac1eSBill Paul 	int anslen;
421ce8bac1eSBill Paul 	const char *qname;
422ce8bac1eSBill Paul 	int qtype;
423ce8bac1eSBill Paul {
4246b73680dSBill Paul 	switch(qtype) {
4256b73680dSBill Paul 	case T_AAAA:
4266b73680dSBill Paul 		host.h_addrtype = AF_INET6;
4276b73680dSBill Paul 		host.h_length = IN6ADDRSZ;
4286b73680dSBill Paul 		break;
4296b73680dSBill Paul 	case T_A:
4306b73680dSBill Paul 	default:
4316b73680dSBill Paul 		host.h_addrtype = AF_INET;
4326b73680dSBill Paul 		host.h_length = INADDRSZ;
4336b73680dSBill Paul 		break;
4346b73680dSBill Paul 	}
4356b73680dSBill Paul 
436ce8bac1eSBill Paul 	return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
437ce8bac1eSBill Paul }
438ce8bac1eSBill Paul 
439ce8bac1eSBill Paul struct hostent *
4405ce1c533SPeter Wemm _gethostbydnsname(name, af)
4411363f04cSPaul Traina 	const char *name;
4425ce1c533SPeter Wemm 	int af;
4431363f04cSPaul Traina {
4441363f04cSPaul Traina 	querybuf buf;
4451363f04cSPaul Traina 	register const char *cp;
4465ce1c533SPeter Wemm 	char *bp;
4475ce1c533SPeter Wemm 	int n, size, type, len;
4481363f04cSPaul Traina 
449e5ad4f87SPeter Wemm 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
450e5ad4f87SPeter Wemm 		h_errno = NETDB_INTERNAL;
451e5ad4f87SPeter Wemm 		return (NULL);
452e5ad4f87SPeter Wemm 	}
453e5ad4f87SPeter Wemm 
4545ce1c533SPeter Wemm 	switch (af) {
4555ce1c533SPeter Wemm 	case AF_INET:
4565ce1c533SPeter Wemm 		size = INADDRSZ;
4575ce1c533SPeter Wemm 		type = T_A;
4585ce1c533SPeter Wemm 		break;
4595ce1c533SPeter Wemm 	case AF_INET6:
4605ce1c533SPeter Wemm 		size = IN6ADDRSZ;
4615ce1c533SPeter Wemm 		type = T_AAAA;
4625ce1c533SPeter Wemm 		break;
4635ce1c533SPeter Wemm 	default:
4645ce1c533SPeter Wemm 		h_errno = NETDB_INTERNAL;
4655ce1c533SPeter Wemm 		errno = EAFNOSUPPORT;
4665ce1c533SPeter Wemm 		return (NULL);
4675ce1c533SPeter Wemm 	}
4685ce1c533SPeter Wemm 
4695ce1c533SPeter Wemm 	host.h_addrtype = af;
4705ce1c533SPeter Wemm 	host.h_length = size;
4715ce1c533SPeter Wemm 
472e5ad4f87SPeter Wemm 	/*
473e5ad4f87SPeter Wemm 	 * if there aren't any dots, it could be a user-level alias.
474e5ad4f87SPeter Wemm 	 * this is also done in res_query() since we are not the only
475e5ad4f87SPeter Wemm 	 * function that looks up host names.
476e5ad4f87SPeter Wemm 	 */
477e5ad4f87SPeter Wemm 	if (!strchr(name, '.') && (cp = __hostalias(name)))
478e5ad4f87SPeter Wemm 		name = cp;
479e5ad4f87SPeter Wemm 
4801363f04cSPaul Traina 	/*
4811363f04cSPaul Traina 	 * disallow names consisting only of digits/dots, unless
4821363f04cSPaul Traina 	 * they end in a dot.
4831363f04cSPaul Traina 	 */
4841363f04cSPaul Traina 	if (isdigit(name[0]))
4851363f04cSPaul Traina 		for (cp = name;; ++cp) {
4861363f04cSPaul Traina 			if (!*cp) {
4871363f04cSPaul Traina 				if (*--cp == '.')
4881363f04cSPaul Traina 					break;
4891363f04cSPaul Traina 				/*
4901363f04cSPaul Traina 				 * All-numeric, no dot at the end.
4911363f04cSPaul Traina 				 * Fake up a hostent as if we'd actually
4921363f04cSPaul Traina 				 * done a lookup.
4931363f04cSPaul Traina 				 */
4945ce1c533SPeter Wemm 				if (inet_pton(af, name, host_addr) <= 0) {
4951363f04cSPaul Traina 					h_errno = HOST_NOT_FOUND;
4961363f04cSPaul Traina 					return (NULL);
4971363f04cSPaul Traina 				}
498e5ad4f87SPeter Wemm 				strncpy(hostbuf, name, MAXDNAME);
499e5ad4f87SPeter Wemm 				hostbuf[MAXDNAME] = '\0';
5005ce1c533SPeter Wemm 				bp = hostbuf + MAXDNAME;
5015ce1c533SPeter Wemm 				len = sizeof hostbuf - MAXDNAME;
502e5ad4f87SPeter Wemm 				host.h_name = hostbuf;
5031363f04cSPaul Traina 				host.h_aliases = host_aliases;
5041363f04cSPaul Traina 				host_aliases[0] = NULL;
5055ce1c533SPeter Wemm 				h_addr_ptrs[0] = (char *)host_addr;
5061363f04cSPaul Traina 				h_addr_ptrs[1] = NULL;
5071363f04cSPaul Traina 				host.h_addr_list = h_addr_ptrs;
5085ce1c533SPeter Wemm 				if (_res.options & RES_USE_INET6)
5095ce1c533SPeter Wemm 					_map_v4v6_hostent(&host, &bp, &len);
5104faad310SPeter Wemm 				h_errno = NETDB_SUCCESS;
5111363f04cSPaul Traina 				return (&host);
5121363f04cSPaul Traina 			}
5131363f04cSPaul Traina 			if (!isdigit(*cp) && *cp != '.')
5141363f04cSPaul Traina 				break;
5151363f04cSPaul Traina 		}
51607a7a2c4SAndrey A. Chernov 	if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
51707a7a2c4SAndrey A. Chernov 	    name[0] == ':')
518ca785773SPeter Wemm 		for (cp = name;; ++cp) {
519ca785773SPeter Wemm 			if (!*cp) {
520ca785773SPeter Wemm 				if (*--cp == '.')
521ca785773SPeter Wemm 					break;
522ca785773SPeter Wemm 				/*
523ca785773SPeter Wemm 				 * All-IPv6-legal, no dot at the end.
524ca785773SPeter Wemm 				 * Fake up a hostent as if we'd actually
525ca785773SPeter Wemm 				 * done a lookup.
526ca785773SPeter Wemm 				 */
527ca785773SPeter Wemm 				if (inet_pton(af, name, host_addr) <= 0) {
528ca785773SPeter Wemm 					h_errno = HOST_NOT_FOUND;
529ca785773SPeter Wemm 					return (NULL);
530ca785773SPeter Wemm 				}
531ca785773SPeter Wemm 				strncpy(hostbuf, name, MAXDNAME);
532ca785773SPeter Wemm 				hostbuf[MAXDNAME] = '\0';
533ca785773SPeter Wemm 				bp = hostbuf + MAXDNAME;
534ca785773SPeter Wemm 				len = sizeof hostbuf - MAXDNAME;
535ca785773SPeter Wemm 				host.h_name = hostbuf;
536ca785773SPeter Wemm 				host.h_aliases = host_aliases;
537ca785773SPeter Wemm 				host_aliases[0] = NULL;
538ca785773SPeter Wemm 				h_addr_ptrs[0] = (char *)host_addr;
539ca785773SPeter Wemm 				h_addr_ptrs[1] = NULL;
540ca785773SPeter Wemm 				host.h_addr_list = h_addr_ptrs;
541ca785773SPeter Wemm 				h_errno = NETDB_SUCCESS;
542ca785773SPeter Wemm 				return (&host);
543ca785773SPeter Wemm 			}
544ca785773SPeter Wemm 			if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
545ca785773SPeter Wemm 				break;
546ca785773SPeter Wemm 		}
54707a7a2c4SAndrey A. Chernov 
5485ce1c533SPeter Wemm 	if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
549e5ad4f87SPeter Wemm 		dprintf("res_search failed (%d)\n", n);
5501363f04cSPaul Traina 		return (NULL);
5511363f04cSPaul Traina 	}
5525ce1c533SPeter Wemm 	return (gethostanswer(&buf, n, name, type));
5531363f04cSPaul Traina }
5541363f04cSPaul Traina 
5551363f04cSPaul Traina struct hostent *
5565ce1c533SPeter Wemm _gethostbydnsaddr(addr, len, af)
5575ce1c533SPeter Wemm 	const char *addr;	/* XXX should have been def'd as u_char! */
5585ce1c533SPeter Wemm 	int len, af;
5591363f04cSPaul Traina {
5605ce1c533SPeter Wemm 	const u_char *uaddr = (const u_char *)addr;
5615ce1c533SPeter Wemm 	static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
5625ce1c533SPeter Wemm 	static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
5635ce1c533SPeter Wemm 	int n, size;
5641363f04cSPaul Traina 	querybuf buf;
5651363f04cSPaul Traina 	register struct hostent *hp;
5665ce1c533SPeter Wemm 	char qbuf[MAXDNAME+1], *qp;
567e5ad4f87SPeter Wemm #ifdef SUNSECURITY
568e5ad4f87SPeter Wemm 	register struct hostent *rhp;
569e5ad4f87SPeter Wemm 	char **haddr;
570e5ad4f87SPeter Wemm 	u_long old_options;
571e5ad4f87SPeter Wemm 	char hname2[MAXDNAME+1];
572e5ad4f87SPeter Wemm #endif /*SUNSECURITY*/
5731363f04cSPaul Traina 
574e5ad4f87SPeter Wemm 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
575e5ad4f87SPeter Wemm 		h_errno = NETDB_INTERNAL;
5761363f04cSPaul Traina 		return (NULL);
577e5ad4f87SPeter Wemm 	}
5785ce1c533SPeter Wemm 	if (af == AF_INET6 && len == IN6ADDRSZ &&
5795ce1c533SPeter Wemm 	    (!bcmp(uaddr, mapped, sizeof mapped) ||
5805ce1c533SPeter Wemm 	     !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
5815ce1c533SPeter Wemm 		/* Unmap. */
5825ce1c533SPeter Wemm 		addr += sizeof mapped;
5835ce1c533SPeter Wemm 		uaddr += sizeof mapped;
5845ce1c533SPeter Wemm 		af = AF_INET;
5855ce1c533SPeter Wemm 		len = INADDRSZ;
5865ce1c533SPeter Wemm 	}
5875ce1c533SPeter Wemm 	switch (af) {
5885ce1c533SPeter Wemm 	case AF_INET:
5895ce1c533SPeter Wemm 		size = INADDRSZ;
5905ce1c533SPeter Wemm 		break;
5915ce1c533SPeter Wemm 	case AF_INET6:
5925ce1c533SPeter Wemm 		size = IN6ADDRSZ;
5935ce1c533SPeter Wemm 		break;
5945ce1c533SPeter Wemm 	default:
595e5ad4f87SPeter Wemm 		errno = EAFNOSUPPORT;
596e5ad4f87SPeter Wemm 		h_errno = NETDB_INTERNAL;
597e5ad4f87SPeter Wemm 		return (NULL);
598e5ad4f87SPeter Wemm 	}
5995ce1c533SPeter Wemm 	if (size != len) {
6005ce1c533SPeter Wemm 		errno = EINVAL;
6015ce1c533SPeter Wemm 		h_errno = NETDB_INTERNAL;
6025ce1c533SPeter Wemm 		return (NULL);
6035ce1c533SPeter Wemm 	}
6045ce1c533SPeter Wemm 	switch (af) {
6055ce1c533SPeter Wemm 	case AF_INET:
6061363f04cSPaul Traina 		(void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
6075ce1c533SPeter Wemm 			       (uaddr[3] & 0xff),
6085ce1c533SPeter Wemm 			       (uaddr[2] & 0xff),
6095ce1c533SPeter Wemm 			       (uaddr[1] & 0xff),
6105ce1c533SPeter Wemm 			       (uaddr[0] & 0xff));
6115ce1c533SPeter Wemm 		break;
6125ce1c533SPeter Wemm 	case AF_INET6:
6135ce1c533SPeter Wemm 		qp = qbuf;
6145ce1c533SPeter Wemm 		for (n = IN6ADDRSZ - 1; n >= 0; n--) {
6155ce1c533SPeter Wemm 			qp += SPRINTF((qp, "%x.%x.",
6165ce1c533SPeter Wemm 				       uaddr[n] & 0xf,
6175ce1c533SPeter Wemm 				       (uaddr[n] >> 4) & 0xf));
6185ce1c533SPeter Wemm 		}
6195ce1c533SPeter Wemm 		strcpy(qp, "ip6.int");
6205ce1c533SPeter Wemm 		break;
6215ce1c533SPeter Wemm 	default:
6225ce1c533SPeter Wemm 		abort();
6235ce1c533SPeter Wemm 	}
6241363f04cSPaul Traina 	n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
6251363f04cSPaul Traina 	if (n < 0) {
626e5ad4f87SPeter Wemm 		dprintf("res_query failed (%d)\n", n);
6271363f04cSPaul Traina 		return (NULL);
6281363f04cSPaul Traina 	}
6295ce1c533SPeter Wemm 	if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
630e5ad4f87SPeter Wemm 		return (NULL);	/* h_errno was set by gethostanswer() */
631e5ad4f87SPeter Wemm #ifdef SUNSECURITY
6325ce1c533SPeter Wemm 	if (af == AF_INET) {
633e5ad4f87SPeter Wemm 	    /*
634e5ad4f87SPeter Wemm 	     * turn off search as the name should be absolute,
635e5ad4f87SPeter Wemm 	     * 'localhost' should be matched by defnames
636e5ad4f87SPeter Wemm 	     */
637e5ad4f87SPeter Wemm 	    strncpy(hname2, hp->h_name, MAXDNAME);
638e5ad4f87SPeter Wemm 	    hname2[MAXDNAME] = '\0';
639e5ad4f87SPeter Wemm 	    old_options = _res.options;
640e5ad4f87SPeter Wemm 	    _res.options &= ~RES_DNSRCH;
641e5ad4f87SPeter Wemm 	    _res.options |= RES_DEFNAMES;
642e5ad4f87SPeter Wemm 	    if (!(rhp = gethostbyname(hname2))) {
643e5ad4f87SPeter Wemm 		syslog(LOG_NOTICE|LOG_AUTH,
644e5ad4f87SPeter Wemm 		       "gethostbyaddr: No A record for %s (verifying [%s])",
645e5ad4f87SPeter Wemm 		       hname2, inet_ntoa(*((struct in_addr *)addr)));
646e5ad4f87SPeter Wemm 		_res.options = old_options;
647e5ad4f87SPeter Wemm 		h_errno = HOST_NOT_FOUND;
6481363f04cSPaul Traina 		return (NULL);
649e5ad4f87SPeter Wemm 	    }
650e5ad4f87SPeter Wemm 	    _res.options = old_options;
651e5ad4f87SPeter Wemm 	    for (haddr = rhp->h_addr_list; *haddr; haddr++)
652e5ad4f87SPeter Wemm 		if (!memcmp(*haddr, addr, INADDRSZ))
653e5ad4f87SPeter Wemm 			break;
654e5ad4f87SPeter Wemm 	    if (!*haddr) {
655e5ad4f87SPeter Wemm 		syslog(LOG_NOTICE|LOG_AUTH,
656e5ad4f87SPeter Wemm 		       "gethostbyaddr: A record of %s != PTR record [%s]",
657e5ad4f87SPeter Wemm 		       hname2, inet_ntoa(*((struct in_addr *)addr)));
658e5ad4f87SPeter Wemm 		h_errno = HOST_NOT_FOUND;
659e5ad4f87SPeter Wemm 		return (NULL);
660e5ad4f87SPeter Wemm 	    }
6615ce1c533SPeter Wemm 	}
662e5ad4f87SPeter Wemm #endif /*SUNSECURITY*/
6635ce1c533SPeter Wemm 	hp->h_addrtype = af;
6641363f04cSPaul Traina 	hp->h_length = len;
6655ce1c533SPeter Wemm 	bcopy(addr, host_addr, len);
6665ce1c533SPeter Wemm 	h_addr_ptrs[0] = (char *)host_addr;
6671363f04cSPaul Traina 	h_addr_ptrs[1] = NULL;
6685ce1c533SPeter Wemm 	if (af == AF_INET && (_res.options & RES_USE_INET6)) {
6695ce1c533SPeter Wemm 		_map_v4v6_address((char*)host_addr, (char*)host_addr);
6705ce1c533SPeter Wemm 		hp->h_addrtype = AF_INET6;
6715ce1c533SPeter Wemm 		hp->h_length = IN6ADDRSZ;
6725ce1c533SPeter Wemm 	}
673e5ad4f87SPeter Wemm 	h_errno = NETDB_SUCCESS;
6741363f04cSPaul Traina 	return (hp);
6751363f04cSPaul Traina }
6761363f04cSPaul Traina 
6774faad310SPeter Wemm #ifdef RESOLVSORT
6784faad310SPeter Wemm static void
6794faad310SPeter Wemm addrsort(ap, num)
6804faad310SPeter Wemm 	char **ap;
6814faad310SPeter Wemm 	int num;
6824faad310SPeter Wemm {
6834faad310SPeter Wemm 	int i, j;
6844faad310SPeter Wemm 	char **p;
6854faad310SPeter Wemm 	short aval[MAXADDRS];
6864faad310SPeter Wemm 	int needsort = 0;
6874faad310SPeter Wemm 
6884faad310SPeter Wemm 	p = ap;
6894faad310SPeter Wemm 	for (i = 0; i < num; i++, p++) {
6904faad310SPeter Wemm 	    for (j = 0 ; (unsigned)j < _res.nsort; j++)
6914faad310SPeter Wemm 		if (_res.sort_list[j].addr.s_addr ==
6924faad310SPeter Wemm 		    (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
6934faad310SPeter Wemm 			break;
6944faad310SPeter Wemm 	    aval[i] = j;
6954faad310SPeter Wemm 	    if (needsort == 0 && i > 0 && j < aval[i-1])
6964faad310SPeter Wemm 		needsort = i;
6974faad310SPeter Wemm 	}
6984faad310SPeter Wemm 	if (!needsort)
6994faad310SPeter Wemm 	    return;
7004faad310SPeter Wemm 
7014faad310SPeter Wemm 	while (needsort < num) {
7024faad310SPeter Wemm 	    for (j = needsort - 1; j >= 0; j--) {
7034faad310SPeter Wemm 		if (aval[j] > aval[j+1]) {
7044faad310SPeter Wemm 		    char *hp;
7054faad310SPeter Wemm 
7064faad310SPeter Wemm 		    i = aval[j];
7074faad310SPeter Wemm 		    aval[j] = aval[j+1];
7084faad310SPeter Wemm 		    aval[j+1] = i;
7094faad310SPeter Wemm 
7104faad310SPeter Wemm 		    hp = ap[j];
7114faad310SPeter Wemm 		    ap[j] = ap[j+1];
7124faad310SPeter Wemm 		    ap[j+1] = hp;
7134faad310SPeter Wemm 
7144faad310SPeter Wemm 		} else
7154faad310SPeter Wemm 		    break;
7164faad310SPeter Wemm 	    }
7174faad310SPeter Wemm 	    needsort++;
7184faad310SPeter Wemm 	}
7194faad310SPeter Wemm }
7204faad310SPeter Wemm #endif
7211363f04cSPaul Traina void
7221363f04cSPaul Traina _sethostdnsent(stayopen)
7231363f04cSPaul Traina 	int stayopen;
7241363f04cSPaul Traina {
7254faad310SPeter Wemm 	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
7264faad310SPeter Wemm 		return;
7271363f04cSPaul Traina 	if (stayopen)
7281363f04cSPaul Traina 		_res.options |= RES_STAYOPEN | RES_USEVC;
7291363f04cSPaul Traina }
7301363f04cSPaul Traina 
7311363f04cSPaul Traina void
7321363f04cSPaul Traina _endhostdnsent()
7331363f04cSPaul Traina {
7341363f04cSPaul Traina 	_res.options &= ~(RES_STAYOPEN | RES_USEVC);
7359547ea9fSPeter Wemm 	res_close();
7361363f04cSPaul Traina }
737