Home | History | Annotate | Download | only in BsdSocketLib
      1 /*
      2  * ++Copyright++ 1985, 1988, 1993
      3  * -
      4  * Copyright (c) 1985, 1988, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  * -
     35  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
     36  *
     37  * Permission to use, copy, modify, and distribute this software for any
     38  * purpose with or without fee is hereby granted, provided that the above
     39  * copyright notice and this permission notice appear in all copies, and that
     40  * the name of Digital Equipment Corporation not be used in advertising or
     41  * publicity pertaining to distribution of the document or software without
     42  * specific, written prior permission.
     43  *
     44  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
     45  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
     46  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
     47  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     48  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
     49  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
     50  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     51  * SOFTWARE.
     52  * -
     53  * --Copyright--
     54  */
     55 
     56 /*
     57  * Portions copyright (c) 1999, 2000
     58  * Intel Corporation.
     59  * All rights reserved.
     60  *
     61  * Redistribution and use in source and binary forms, with or without
     62  * modification, are permitted provided that the following conditions
     63  * are met:
     64  *
     65  * 1. Redistributions of source code must retain the above copyright
     66  *    notice, this list of conditions and the following disclaimer.
     67  *
     68  * 2. Redistributions in binary form must reproduce the above copyright
     69  *    notice, this list of conditions and the following disclaimer in the
     70  *    documentation and/or other materials provided with the distribution.
     71  *
     72  * 3. All advertising materials mentioning features or use of this software
     73  *    must display the following acknowledgement:
     74  *
     75  *    This product includes software developed by Intel Corporation and
     76  *    its contributors.
     77  *
     78  * 4. Neither the name of Intel Corporation or its contributors may be
     79  *    used to endorse or promote products derived from this software
     80  *    without specific prior written permission.
     81  *
     82  * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
     83  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     84  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     85  * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
     86  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     87  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     88  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     89  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     90  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     91  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     92  * THE POSSIBILITY OF SUCH DAMAGE.
     93  *
     94  */
     95 
     96 #if defined(LIBC_SCCS) && !defined(lint)
     97 static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
     98 static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
     99 static char rcsid[] = "$Id: gethostbydns.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
    100 #endif /* LIBC_SCCS and not lint */
    101 
    102 #include <sys/types.h>
    103 #include <sys/param.h>
    104 #include <sys/socket.h>
    105 #include <netinet/in.h>
    106 #include <arpa/inet.h>
    107 #include <arpa/nameser.h>
    108 
    109 #include <stdio.h>
    110 #include <unistd.h>
    111 #include <string.h>
    112 #include <netdb.h>
    113 #include <resolv.h>
    114 #include <ctype.h>
    115 #include <errno.h>
    116 #ifdef _ORG_FREEBSD_
    117 #include <syslog.h>
    118 #else
    119 #include <stdlib.h>
    120 u_int32_t _getlong(const u_char *src);
    121 u_int16_t _getshort(const u_char *src);
    122 #endif
    123 
    124 #include "res_config.h"
    125 #include "Socklib_internals.h"
    126 
    127 #define SPRINTF(x) ((size_t)sprintf x)
    128 
    129 #define	MAXALIASES	35
    130 #define	MAXADDRS	35
    131 
    132 static const char AskedForGot[] =
    133 		"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
    134 
    135 static char *h_addr_ptrs[MAXADDRS + 1];
    136 
    137 static struct hostent host;
    138 static char *host_aliases[MAXALIASES];
    139 static char hostbuf[8*1024];
    140 static u_char host_addr[16];	/* IPv4 or IPv6 */
    141 
    142 #ifdef RESOLVSORT
    143 static void addrsort(char **, int);
    144 #endif
    145 
    146 #if PACKETSZ > 1024
    147 #define	MAXPACKET	PACKETSZ
    148 #else
    149 #define	MAXPACKET	1024
    150 #endif
    151 
    152 typedef union {
    153     HEADER hdr;
    154     u_char buf[MAXPACKET];
    155 } querybuf;
    156 
    157 typedef union {
    158     int32_t al;
    159     char ac;
    160 } align;
    161 
    162 extern int h_errno;
    163 int _dns_ttl_;
    164 
    165 #ifdef DEBUG_RES
    166 static void
    167 dprintf(char *msg, int num)
    168 {
    169 	if (_res.options & RES_DEBUG) {
    170 		int save = errno;
    171 
    172 		printf(msg, num);
    173 		errno = save;
    174 	}
    175 }
    176 #else
    177 # define dprintf(msg, num) /*nada*/
    178 #endif
    179 
    180 #define BOUNDED_INCR(x) \
    181 	do { \
    182 		cp += x; \
    183 		if (cp > eom) { \
    184 			h_errno = NO_RECOVERY; \
    185 			return (NULL); \
    186 		} \
    187 	} while (0)
    188 
    189 #define BOUNDS_CHECK(ptr, count) \
    190 	do { \
    191 		if ((ptr) + (count) > eom) { \
    192 			h_errno = NO_RECOVERY; \
    193 			return (NULL); \
    194 		} \
    195 	} while (0)
    196 
    197 static struct hostent *
    198 gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
    199 {
    200 	register const HEADER *hp;
    201 	register const u_char *cp;
    202 	register int n;
    203 	const u_char *eom, *erdata;
    204 	char *bp, **ap, **hap;
    205 	int type, class, buflen, ancount, qdcount;
    206 	int haveanswer, had_error;
    207 	int toobig = 0;
    208 	char tbuf[MAXDNAME];
    209 	const char *tname;
    210 	int (*name_ok)(const char *);
    211 
    212 	tname = qname;
    213 	host.h_name = NULL;
    214 	eom = answer->buf + anslen;
    215 	switch (qtype) {
    216 	case T_A:
    217 	case T_AAAA:
    218 		name_ok = res_hnok;
    219 		break;
    220 	case T_PTR:
    221 		name_ok = res_dnok;
    222 		break;
    223 	default:
    224 		h_errno = NO_RECOVERY;
    225 		return (NULL);	/* XXX should be abort(); */
    226 	}
    227 	/*
    228 	 * find first satisfactory answer
    229 	 */
    230 	hp = &answer->hdr;
    231 	ancount = ntohs(hp->ancount);
    232 	qdcount = ntohs(hp->qdcount);
    233 	bp = hostbuf;
    234 	buflen = sizeof hostbuf;
    235 	cp = answer->buf;
    236 	BOUNDED_INCR(HFIXEDSZ);
    237 	if (qdcount != 1) {
    238 		h_errno = NO_RECOVERY;
    239 		return (NULL);
    240 	}
    241 	n = dn_expand(answer->buf, eom, cp, bp, buflen);
    242 	if ((n < 0) || !(*name_ok)(bp)) {
    243 		h_errno = NO_RECOVERY;
    244 		return (NULL);
    245 	}
    246 	BOUNDED_INCR(n + QFIXEDSZ);
    247 	if (qtype == T_A || qtype == T_AAAA) {
    248 		/* res_send() has already verified that the query name is the
    249 		 * same as the one we sent; this just gets the expanded name
    250 		 * (i.e., with the succeeding search-domain tacked on).
    251 		 */
    252 		n = (int)strlen(bp) + 1;		/* for the \0 */
    253 		if (n >= MAXHOSTNAMELEN) {
    254 			h_errno = NO_RECOVERY;
    255 			return (NULL);
    256 		}
    257 		host.h_name = bp;
    258 		bp += n;
    259 		buflen -= n;
    260 		/* The qname can be abbreviated, but h_name is now absolute. */
    261 		qname = host.h_name;
    262 	}
    263 	ap = host_aliases;
    264 	*ap = NULL;
    265 	host.h_aliases = host_aliases;
    266 	hap = h_addr_ptrs;
    267 	*hap = NULL;
    268 	host.h_addr_list = h_addr_ptrs;
    269 	haveanswer = 0;
    270 	had_error = 0;
    271 	_dns_ttl_ = -1;
    272 	while (ancount-- > 0 && cp < eom && !had_error) {
    273 		n = dn_expand(answer->buf, eom, cp, bp, buflen);
    274 		if ((n < 0) || !(*name_ok)(bp)) {
    275 			had_error++;
    276 			continue;
    277 		}
    278 		cp += n;			/* name */
    279 		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
    280 		type = _getshort(cp);
    281  		cp += INT16SZ;			/* type */
    282 		class = _getshort(cp);
    283  		cp += INT16SZ;			/* class */
    284 		if (qtype == T_A  && type == T_A)
    285 			_dns_ttl_ = _getlong(cp);
    286 		cp += INT32SZ;			/* TTL */
    287 		n = _getshort(cp);
    288 		cp += INT16SZ;			/* len */
    289 		BOUNDS_CHECK(cp, n);
    290 		erdata = cp + n;
    291 		if (class != C_IN) {
    292 			/* XXX - debug? syslog? */
    293 			cp += n;
    294 			continue;		/* XXX - had_error++ ? */
    295 		}
    296 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
    297 			if (ap >= &host_aliases[MAXALIASES-1])
    298 				continue;
    299 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
    300 			if ((n < 0) || !(*name_ok)(tbuf)) {
    301 				had_error++;
    302 				continue;
    303 			}
    304 			cp += n;
    305 			if (cp != erdata) {
    306 				h_errno = NO_RECOVERY;
    307 				return (NULL);
    308 			}
    309 			/* Store alias. */
    310 			*ap++ = bp;
    311 			n = (int)strlen(bp) + 1;	/* for the \0 */
    312 			if (n >= MAXHOSTNAMELEN) {
    313 				had_error++;
    314 				continue;
    315 			}
    316 			bp += n;
    317 			buflen -= n;
    318 			/* Get canonical name. */
    319 			n = (int)strlen(tbuf) + 1;	/* for the \0 */
    320 			if (n > buflen || n >= MAXHOSTNAMELEN) {
    321 				had_error++;
    322 				continue;
    323 			}
    324 			strcpy(bp, tbuf);
    325 			host.h_name = bp;
    326 			bp += n;
    327 			buflen -= n;
    328 			continue;
    329 		}
    330 		if (qtype == T_PTR && type == T_CNAME) {
    331 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
    332 			if (n < 0 || !res_dnok(tbuf)) {
    333 				had_error++;
    334 				continue;
    335 			}
    336 			cp += n;
    337 			if (cp != erdata) {
    338 				h_errno = NO_RECOVERY;
    339 				return (NULL);
    340 			}
    341 			/* Get canonical name. */
    342 			n = (int)strlen(tbuf) + 1;	/* for the \0 */
    343 			if (n > buflen || n >= MAXHOSTNAMELEN) {
    344 				had_error++;
    345 				continue;
    346 			}
    347 			strcpy(bp, tbuf);
    348 			tname = bp;
    349 			bp += n;
    350 			buflen -= n;
    351 			continue;
    352 		}
    353 		if (type != qtype) {
    354 #ifdef _ORG_FREEBSD_
    355 			syslog(LOG_NOTICE|LOG_AUTH,
    356 	"gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
    357 			       qname, p_class(C_IN), p_type(qtype),
    358 			       p_type(type));
    359 #endif
    360 			cp += n;
    361 			continue;		/* XXX - had_error++ ? */
    362 		}
    363 		switch (type) {
    364 		case T_PTR:
    365 			if (strcasecmp(tname, bp) != 0) {
    366 #ifdef _ORG_FREEBSD_
    367 				syslog(LOG_NOTICE|LOG_AUTH,
    368 				       AskedForGot, qname, bp);
    369 #endif
    370 				cp += n;
    371 				continue;	/* XXX - had_error++ ? */
    372 			}
    373 			n = dn_expand(answer->buf, eom, cp, bp, buflen);
    374 			if ((n < 0) || !res_hnok(bp)) {
    375 				had_error++;
    376 				break;
    377 			}
    378 #if MULTI_PTRS_ARE_ALIASES
    379 			cp += n;
    380 			if (cp != erdata) {
    381 				h_errno = NO_RECOVERY;
    382 				return (NULL);
    383 			}
    384 			if (!haveanswer)
    385 				host.h_name = bp;
    386 			else if (ap < &host_aliases[MAXALIASES-1])
    387 				*ap++ = bp;
    388 			else
    389 				n = -1;
    390 			if (n != -1) {
    391 				n = (int)strlen(bp) + 1;	/* for the \0 */
    392 				if (n >= MAXHOSTNAMELEN) {
    393 					had_error++;
    394 					break;
    395 				}
    396 				bp += n;
    397 				buflen -= n;
    398 			}
    399 			break;
    400 #else
    401 			host.h_name = bp;
    402 			if (_res.options & RES_USE_INET6) {
    403 				n = strlen(bp) + 1;	/* for the \0 */
    404 				if (n >= MAXHOSTNAMELEN) {
    405 					had_error++;
    406 					break;
    407 				}
    408 				bp += n;
    409 				buflen -= n;
    410 				_map_v4v6_hostent(&host, &bp, &buflen);
    411 			}
    412 			h_errno = NETDB_SUCCESS;
    413 			return (&host);
    414 #endif
    415 		case T_A:
    416 		case T_AAAA:
    417 			if (strcasecmp(host.h_name, bp) != 0) {
    418 #ifdef _ORG_FREEBSD_
    419 				syslog(LOG_NOTICE|LOG_AUTH,
    420 				       AskedForGot, host.h_name, bp);
    421 #endif
    422 				cp += n;
    423 				continue;	/* XXX - had_error++ ? */
    424 			}
    425 			if (n != host.h_length) {
    426 				cp += n;
    427 				continue;
    428 			}
    429 			if (!haveanswer) {
    430 				register int nn;
    431 
    432 				host.h_name = bp;
    433 				nn = (int)strlen(bp) + 1;	/* for the \0 */
    434 				bp += nn;
    435 				buflen -= nn;
    436 			}
    437 
    438 			bp += sizeof(align) - ((size_t)bp % sizeof(align));
    439 
    440 			if (bp + n >= &hostbuf[sizeof hostbuf]) {
    441 				dprintf("size (%d) too big\n", n);
    442 				had_error++;
    443 				continue;
    444 			}
    445 			if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
    446 				if (!toobig++)
    447 					dprintf("Too many addresses (%d)\n",
    448 						MAXADDRS);
    449 				cp += n;
    450 				continue;
    451 			}
    452       *hap++ = bp;
    453 			bcopy(cp, bp, n);
    454 			bp += n;
    455 			buflen -= n;
    456 			cp += n;
    457 			if (cp != erdata) {
    458 				h_errno = NO_RECOVERY;
    459 				return (NULL);
    460 			}
    461 			break;
    462 		default:
    463 			dprintf("Impossible condition (type=%d)\n", type);
    464 			h_errno = NO_RECOVERY;
    465 			return (NULL);
    466 			/* BIND has abort() here, too risky on bad data */
    467 		}
    468 		if (!had_error)
    469 			haveanswer++;
    470 	}
    471 	if (haveanswer) {
    472 		*ap = NULL;
    473 		*hap = NULL;
    474 # if defined(RESOLVSORT)
    475 		/*
    476 		 * Note: we sort even if host can take only one address
    477 		 * in its return structures - should give it the "best"
    478 		 * address in that case, not some random one
    479 		 */
    480 		if (_res.nsort && haveanswer > 1 && qtype == T_A)
    481 			addrsort(h_addr_ptrs, haveanswer);
    482 # endif /*RESOLVSORT*/
    483 		if (!host.h_name) {
    484 			n = (int)strlen(qname) + 1;	/* for the \0 */
    485 			if (n > buflen || n >= MAXHOSTNAMELEN)
    486 				goto no_recovery;
    487 			strcpy(bp, qname);
    488 			host.h_name = bp;
    489 			bp += n;
    490 			buflen -= n;
    491 		}
    492 		if (_res.options & RES_USE_INET6)
    493 			_map_v4v6_hostent(&host, &bp, &buflen);
    494 		h_errno = NETDB_SUCCESS;
    495 		return (&host);
    496 	}
    497  no_recovery:
    498 	h_errno = NO_RECOVERY;
    499 	return (NULL);
    500 }
    501 
    502 struct hostent *
    503 __dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
    504 {
    505 	switch(qtype) {
    506 	case T_AAAA:
    507 		host.h_addrtype = AF_INET6;
    508 		host.h_length = IN6ADDRSZ;
    509 		break;
    510 	case T_A:
    511 	default:
    512 		host.h_addrtype = AF_INET;
    513 		host.h_length = INADDRSZ;
    514 		break;
    515 	}
    516 
    517 	return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
    518 }
    519 
    520 struct hostent *
    521 _gethostbydnsname(const char *name, int af)
    522 {
    523 	querybuf buf;
    524 	register const char *cp;
    525 	char *bp;
    526 	int n, size, type, len;
    527 
    528 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    529 		h_errno = NETDB_INTERNAL;
    530 		return (NULL);
    531 	}
    532 
    533 	switch (af) {
    534 	case AF_INET:
    535 		size = INADDRSZ;
    536 		type = T_A;
    537 		break;
    538 	case AF_INET6:
    539 		size = IN6ADDRSZ;
    540 		type = T_AAAA;
    541 		break;
    542 	default:
    543 		h_errno = NETDB_INTERNAL;
    544 		errno = EAFNOSUPPORT;
    545 		return (NULL);
    546 	}
    547 
    548 	host.h_addrtype = af;
    549 	host.h_length = size;
    550 
    551 	/*
    552 	 * if there aren't any dots, it could be a user-level alias.
    553 	 * this is also done in res_query() since we are not the only
    554 	 * function that looks up host names.
    555 	 */
    556 	if (!strchr(name, '.') && ( NULL != (cp = __hostalias(name))))
    557 		name = cp;
    558 
    559 	/*
    560 	 * disallow names consisting only of digits/dots, unless
    561 	 * they end in a dot.
    562 	 */
    563 	if (isdigit(name[0]))
    564 		for (cp = name;; ++cp) {
    565 			if (!*cp) {
    566 				if (*--cp == '.')
    567 					break;
    568 				/*
    569 				 * All-numeric, no dot at the end.
    570 				 * Fake up a hostent as if we'd actually
    571 				 * done a lookup.
    572 				 */
    573 				if (inet_pton(af, name, host_addr) <= 0) {
    574 					h_errno = HOST_NOT_FOUND;
    575 					return (NULL);
    576 				}
    577 				strncpy(hostbuf, name, MAXDNAME);
    578 				hostbuf[MAXDNAME] = '\0';
    579 				bp = hostbuf + MAXDNAME;
    580 				len = sizeof hostbuf - MAXDNAME;
    581 				host.h_name = hostbuf;
    582 				host.h_aliases = host_aliases;
    583 				host_aliases[0] = NULL;
    584 				h_addr_ptrs[0] = (char *)host_addr;
    585 				h_addr_ptrs[1] = NULL;
    586 				host.h_addr_list = h_addr_ptrs;
    587 				if (_res.options & RES_USE_INET6)
    588 					_map_v4v6_hostent(&host, &bp, &len);
    589 				h_errno = NETDB_SUCCESS;
    590 				return (&host);
    591 			}
    592 			if (!isdigit(*cp) && *cp != '.')
    593 				break;
    594 		}
    595 	if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
    596 	    name[0] == ':')
    597 		for (cp = name;; ++cp) {
    598 			if (!*cp) {
    599 				if (*--cp == '.')
    600 					break;
    601 				/*
    602 				 * All-IPv6-legal, no dot at the end.
    603 				 * Fake up a hostent as if we'd actually
    604 				 * done a lookup.
    605 				 */
    606 				if (inet_pton(af, name, host_addr) <= 0) {
    607 					h_errno = HOST_NOT_FOUND;
    608 					return (NULL);
    609 				}
    610 				strncpy(hostbuf, name, MAXDNAME);
    611 				hostbuf[MAXDNAME] = '\0';
    612 				bp = hostbuf + MAXDNAME;
    613 				len = sizeof hostbuf - MAXDNAME;
    614 				host.h_name = hostbuf;
    615 				host.h_aliases = host_aliases;
    616 				host_aliases[0] = NULL;
    617 				h_addr_ptrs[0] = (char *)host_addr;
    618 				h_addr_ptrs[1] = NULL;
    619 				host.h_addr_list = h_addr_ptrs;
    620 				h_errno = NETDB_SUCCESS;
    621 				return (&host);
    622 			}
    623 			if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
    624 				break;
    625 		}
    626 
    627 	if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
    628 		dprintf("res_search failed (%d)\n", n);
    629 		return (NULL);
    630 	}
    631 	return (gethostanswer(&buf, n, name, type));
    632 }
    633 
    634 struct hostent *
    635 _gethostbydnsaddr(const char *addr, int len, int af)
    636 {
    637 	const u_char *uaddr = (const u_char *)addr;
    638 	static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
    639 	static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
    640 	int n, size;
    641 	querybuf buf;
    642 	register struct hostent *hp;
    643 	char qbuf[MAXDNAME+1], *qp;
    644 #ifdef SUNSECURITY
    645 	register struct hostent *rhp;
    646 	char **haddr;
    647 	u_long old_options;
    648 	char hname2[MAXDNAME+1];
    649 #endif /*SUNSECURITY*/
    650 
    651 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    652 		h_errno = NETDB_INTERNAL;
    653 		return (NULL);
    654 	}
    655 	if (af == AF_INET6 && len == IN6ADDRSZ &&
    656 	    (!bcmp(uaddr, mapped, sizeof mapped) ||
    657 	     !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
    658 		/* Unmap. */
    659 		addr += sizeof mapped;
    660 		uaddr += sizeof mapped;
    661 		af = AF_INET;
    662 		len = INADDRSZ;
    663 	}
    664 	switch (af) {
    665 	case AF_INET:
    666 		size = INADDRSZ;
    667 		break;
    668 	case AF_INET6:
    669 		size = IN6ADDRSZ;
    670 		break;
    671 	default:
    672 		errno = EAFNOSUPPORT;
    673 		h_errno = NETDB_INTERNAL;
    674 		return (NULL);
    675 	}
    676 	if (size != len) {
    677 		errno = EINVAL;
    678 		h_errno = NETDB_INTERNAL;
    679 		return (NULL);
    680 	}
    681 	switch (af) {
    682 	case AF_INET:
    683 		(void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
    684 			       (uaddr[3] & 0xff),
    685 			       (uaddr[2] & 0xff),
    686 			       (uaddr[1] & 0xff),
    687 			       (uaddr[0] & 0xff));
    688 		break;
    689 	case AF_INET6:
    690 		qp = qbuf;
    691 		for (n = IN6ADDRSZ - 1; n >= 0; n--) {
    692 			qp += SPRINTF((qp, "%x.%x.",
    693 				       uaddr[n] & 0xf,
    694 				       (uaddr[n] >> 4) & 0xf));
    695 		}
    696 		strcpy(qp, "ip6.int");
    697 		break;
    698 	default:
    699 		abort();
    700 	}
    701 	n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
    702 	if (n < 0) {
    703 		dprintf("res_query failed (%d)\n", n);
    704 		return (NULL);
    705 	}
    706 	if ( NULL == (hp = gethostanswer(&buf, n, qbuf, T_PTR)))
    707 		return (NULL);	/* h_errno was set by gethostanswer() */
    708 #ifdef SUNSECURITY
    709 	if (af == AF_INET) {
    710 	    /*
    711 	     * turn off search as the name should be absolute,
    712 	     * 'localhost' should be matched by defnames
    713 	     */
    714 	    strncpy(hname2, hp->h_name, MAXDNAME);
    715 	    hname2[MAXDNAME] = '\0';
    716 	    old_options = _res.options;
    717 	    _res.options &= ~RES_DNSRCH;
    718 	    _res.options |= RES_DEFNAMES;
    719 	    if (!(rhp = gethostbyname(hname2))) {
    720 #ifdef _ORG_FREEBSD_
    721 		syslog(LOG_NOTICE|LOG_AUTH,
    722 		       "gethostbyaddr: No A record for %s (verifying [%s])",
    723 		       hname2, inet_ntoa(*((struct in_addr *)addr)));
    724 #endif
    725 		_res.options = old_options;
    726 		h_errno = HOST_NOT_FOUND;
    727 		return (NULL);
    728 	    }
    729 	    _res.options = old_options;
    730 	    for (haddr = rhp->h_addr_list; *haddr; haddr++)
    731 		if (!memcmp(*haddr, addr, INADDRSZ))
    732 			break;
    733 	    if (!*haddr) {
    734 #ifdef _ORG_FREEBSD_
    735 		syslog(LOG_NOTICE|LOG_AUTH,
    736 		       "gethostbyaddr: A record of %s != PTR record [%s]",
    737 		       hname2, inet_ntoa(*((struct in_addr *)addr)));
    738 #endif
    739 		h_errno = HOST_NOT_FOUND;
    740 		return (NULL);
    741 	    }
    742 	}
    743 #endif /*SUNSECURITY*/
    744 	hp->h_addrtype = af;
    745 	hp->h_length = len;
    746 	bcopy(addr, host_addr, len);
    747 	h_addr_ptrs[0] = (char *)host_addr;
    748 	h_addr_ptrs[1] = NULL;
    749 	if (af == AF_INET && (_res.options & RES_USE_INET6)) {
    750 		_map_v4v6_address((char*)host_addr, (char*)host_addr);
    751 		hp->h_addrtype = AF_INET6;
    752 		hp->h_length = IN6ADDRSZ;
    753 	}
    754 	h_errno = NETDB_SUCCESS;
    755 	return (hp);
    756 }
    757 
    758 #ifdef RESOLVSORT
    759 static void
    760 addrsort(char **ap, int num)
    761 {
    762 	short i, j;
    763 	char **p;
    764 	short aval[MAXADDRS];
    765 	short needsort = 0;
    766 
    767 	p = ap;
    768 	for (i = 0; i < num; i++, p++) {
    769 	    for (j = 0 ; (unsigned)j < _res.nsort; j++)
    770 		if (_res.sort_list[j].addr.s_addr ==
    771 		    (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
    772 			break;
    773 	    aval[i] = j;
    774 	    if (needsort == 0 && i > 0 && j < aval[i-1])
    775 		needsort = i;
    776 	}
    777 	if (!needsort)
    778 	    return;
    779 
    780 	while (needsort < num) {
    781 	    for (j = needsort - 1; j >= 0; j--) {
    782 		if (aval[j] > aval[j+1]) {
    783 		    char *hp;
    784 
    785 		    i = aval[j];
    786 		    aval[j] = aval[j+1];
    787 		    aval[j+1] = i;
    788 
    789 		    hp = ap[j];
    790 		    ap[j] = ap[j+1];
    791 		    ap[j+1] = hp;
    792 
    793 		} else
    794 		    break;
    795 	    }
    796 	    needsort++;
    797 	}
    798 }
    799 #endif
    800 void
    801 _sethostdnsent(int stayopen)
    802 {
    803 	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
    804 		return;
    805 	if (stayopen)
    806 		_res.options |= RES_STAYOPEN | RES_USEVC;
    807 }
    808 
    809 void
    810 _endhostdnsent()
    811 {
    812 	_res.options &= ~(RES_STAYOPEN | RES_USEVC);
    813 	res_close();
    814 }
    815