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