10Sstevel@tonic-gate /* 2*11038SRao.Shoaib@Sun.COM * Portions Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC") 3*11038SRao.Shoaib@Sun.COM * Portions Copyright (C) 1996-2003 Internet Software Consortium. 4*11038SRao.Shoaib@Sun.COM * 5*11038SRao.Shoaib@Sun.COM * Permission to use, copy, modify, and/or distribute this software for any 6*11038SRao.Shoaib@Sun.COM * purpose with or without fee is hereby granted, provided that the above 7*11038SRao.Shoaib@Sun.COM * copyright notice and this permission notice appear in all copies. 8*11038SRao.Shoaib@Sun.COM * 9*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10*11038SRao.Shoaib@Sun.COM * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11*11038SRao.Shoaib@Sun.COM * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12*11038SRao.Shoaib@Sun.COM * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13*11038SRao.Shoaib@Sun.COM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14*11038SRao.Shoaib@Sun.COM * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15*11038SRao.Shoaib@Sun.COM * PERFORMANCE OF THIS SOFTWARE. 160Sstevel@tonic-gate */ 170Sstevel@tonic-gate 180Sstevel@tonic-gate /* 190Sstevel@tonic-gate * Copyright (c) 1985, 1988, 1993 200Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 21*11038SRao.Shoaib@Sun.COM * 220Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 230Sstevel@tonic-gate * modification, are permitted provided that the following conditions 240Sstevel@tonic-gate * are met: 250Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 260Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 270Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 280Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 290Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 300Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 310Sstevel@tonic-gate * must display the following acknowledgement: 320Sstevel@tonic-gate * This product includes software developed by the University of 330Sstevel@tonic-gate * California, Berkeley and its contributors. 340Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 350Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 360Sstevel@tonic-gate * without specific prior written permission. 37*11038SRao.Shoaib@Sun.COM * 380Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 390Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 400Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 410Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 420Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 430Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 440Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 450Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 460Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 470Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 480Sstevel@tonic-gate * SUCH DAMAGE. 490Sstevel@tonic-gate */ 500Sstevel@tonic-gate 510Sstevel@tonic-gate /* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ 520Sstevel@tonic-gate /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ 530Sstevel@tonic-gate 540Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 55*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: dns_ho.c,v 1.23 2008/11/14 02:36:51 marka Exp $"; 560Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 570Sstevel@tonic-gate 580Sstevel@tonic-gate /* Imports. */ 590Sstevel@tonic-gate 600Sstevel@tonic-gate #include "port_before.h" 610Sstevel@tonic-gate 620Sstevel@tonic-gate #include <sys/types.h> 630Sstevel@tonic-gate #include <sys/param.h> 640Sstevel@tonic-gate #include <sys/socket.h> 650Sstevel@tonic-gate 660Sstevel@tonic-gate #include <netinet/in.h> 670Sstevel@tonic-gate #include <arpa/inet.h> 680Sstevel@tonic-gate #include <arpa/nameser.h> 690Sstevel@tonic-gate 700Sstevel@tonic-gate #include <ctype.h> 710Sstevel@tonic-gate #include <errno.h> 720Sstevel@tonic-gate #include <stdlib.h> 730Sstevel@tonic-gate #include <netdb.h> 740Sstevel@tonic-gate #include <resolv.h> 750Sstevel@tonic-gate #include <stdio.h> 760Sstevel@tonic-gate #include <string.h> 770Sstevel@tonic-gate #include <syslog.h> 780Sstevel@tonic-gate 790Sstevel@tonic-gate #include <isc/memcluster.h> 800Sstevel@tonic-gate #include <irs.h> 810Sstevel@tonic-gate 820Sstevel@tonic-gate #include "port_after.h" 830Sstevel@tonic-gate 840Sstevel@tonic-gate #include "irs_p.h" 850Sstevel@tonic-gate #include "dns_p.h" 860Sstevel@tonic-gate 870Sstevel@tonic-gate #ifdef SPRINTF_CHAR 880Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x) 890Sstevel@tonic-gate #else 900Sstevel@tonic-gate # define SPRINTF(x) sprintf x 910Sstevel@tonic-gate #endif 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* Definitions. */ 940Sstevel@tonic-gate 950Sstevel@tonic-gate #define MAXALIASES 35 960Sstevel@tonic-gate #define MAXADDRS 35 970Sstevel@tonic-gate 98*11038SRao.Shoaib@Sun.COM #define MAXPACKET (65535) /*%< Maximum TCP message size */ 990Sstevel@tonic-gate #define BOUNDS_CHECK(ptr, count) \ 1000Sstevel@tonic-gate if ((ptr) + (count) > eom) { \ 1010Sstevel@tonic-gate had_error++; \ 1020Sstevel@tonic-gate continue; \ 1030Sstevel@tonic-gate } else (void)0 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate typedef union { 1060Sstevel@tonic-gate HEADER hdr; 1070Sstevel@tonic-gate u_char buf[MAXPACKET]; 1080Sstevel@tonic-gate } querybuf; 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate struct dns_res_target { 1110Sstevel@tonic-gate struct dns_res_target *next; 112*11038SRao.Shoaib@Sun.COM querybuf qbuf; /*%< query buffer */ 113*11038SRao.Shoaib@Sun.COM u_char *answer; /*%< buffer to put answer */ 114*11038SRao.Shoaib@Sun.COM int anslen; /*%< size of answer buffer */ 115*11038SRao.Shoaib@Sun.COM int qclass, qtype; /*%< class and type of query */ 116*11038SRao.Shoaib@Sun.COM int action; /*%< condition whether query is really issued */ 117*11038SRao.Shoaib@Sun.COM char qname[MAXDNAME +1]; /*%< domain name */ 1180Sstevel@tonic-gate #if 0 119*11038SRao.Shoaib@Sun.COM int n; /*%< result length */ 1200Sstevel@tonic-gate #endif 1210Sstevel@tonic-gate }; 1220Sstevel@tonic-gate enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE}; 1230Sstevel@tonic-gate enum {RESQRY_SUCCESS, RESQRY_FAIL}; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate struct pvt { 1260Sstevel@tonic-gate struct hostent host; 1270Sstevel@tonic-gate char * h_addr_ptrs[MAXADDRS + 1]; 1280Sstevel@tonic-gate char * host_aliases[MAXALIASES]; 1290Sstevel@tonic-gate char hostbuf[8*1024]; 130*11038SRao.Shoaib@Sun.COM u_char host_addr[16]; /*%< IPv4 or IPv6 */ 1310Sstevel@tonic-gate struct __res_state *res; 1320Sstevel@tonic-gate void (*free_res)(void *); 1330Sstevel@tonic-gate }; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate typedef union { 1360Sstevel@tonic-gate int32_t al; 1370Sstevel@tonic-gate char ac; 1380Sstevel@tonic-gate } align; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; 1410Sstevel@tonic-gate static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; 1420Sstevel@tonic-gate /* Note: the IPv6 loopback address is in the "tunnel" space */ 143*11038SRao.Shoaib@Sun.COM static const u_char v6local[] = { 0,0, 0,1 }; /*%< last 4 bytes of IPv6 addr */ 1440Sstevel@tonic-gate /* Forwards. */ 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate static void ho_close(struct irs_ho *this); 1470Sstevel@tonic-gate static struct hostent * ho_byname(struct irs_ho *this, const char *name); 1480Sstevel@tonic-gate static struct hostent * ho_byname2(struct irs_ho *this, const char *name, 1490Sstevel@tonic-gate int af); 1500Sstevel@tonic-gate static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, 1510Sstevel@tonic-gate int len, int af); 1520Sstevel@tonic-gate static struct hostent * ho_next(struct irs_ho *this); 1530Sstevel@tonic-gate static void ho_rewind(struct irs_ho *this); 1540Sstevel@tonic-gate static void ho_minimize(struct irs_ho *this); 1550Sstevel@tonic-gate static struct __res_state * ho_res_get(struct irs_ho *this); 1560Sstevel@tonic-gate static void ho_res_set(struct irs_ho *this, 1570Sstevel@tonic-gate struct __res_state *res, 1580Sstevel@tonic-gate void (*free_res)(void *)); 1590Sstevel@tonic-gate static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, 1600Sstevel@tonic-gate const struct addrinfo *pai); 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate static void map_v4v6_hostent(struct hostent *hp, char **bp, 1630Sstevel@tonic-gate char *ep); 1640Sstevel@tonic-gate static void addrsort(res_state, char **, int); 1650Sstevel@tonic-gate static struct hostent * gethostans(struct irs_ho *this, 1660Sstevel@tonic-gate const u_char *ansbuf, int anslen, 1670Sstevel@tonic-gate const char *qname, int qtype, 1680Sstevel@tonic-gate int af, int size, 1690Sstevel@tonic-gate struct addrinfo **ret_aip, 1700Sstevel@tonic-gate const struct addrinfo *pai); 1710Sstevel@tonic-gate static int add_hostent(struct pvt *pvt, char *bp, char **hap, 1720Sstevel@tonic-gate struct addrinfo *ai); 1730Sstevel@tonic-gate static int init(struct irs_ho *this); 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* Exports. */ 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate struct irs_ho * 1780Sstevel@tonic-gate irs_dns_ho(struct irs_acc *this) { 1790Sstevel@tonic-gate struct irs_ho *ho; 1800Sstevel@tonic-gate struct pvt *pvt; 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate UNUSED(this); 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate if (!(pvt = memget(sizeof *pvt))) { 1850Sstevel@tonic-gate errno = ENOMEM; 1860Sstevel@tonic-gate return (NULL); 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate memset(pvt, 0, sizeof *pvt); 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate if (!(ho = memget(sizeof *ho))) { 1910Sstevel@tonic-gate memput(pvt, sizeof *pvt); 1920Sstevel@tonic-gate errno = ENOMEM; 1930Sstevel@tonic-gate return (NULL); 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate memset(ho, 0x5e, sizeof *ho); 1960Sstevel@tonic-gate ho->private = pvt; 1970Sstevel@tonic-gate ho->close = ho_close; 1980Sstevel@tonic-gate ho->byname = ho_byname; 1990Sstevel@tonic-gate ho->byname2 = ho_byname2; 2000Sstevel@tonic-gate ho->byaddr = ho_byaddr; 2010Sstevel@tonic-gate ho->next = ho_next; 2020Sstevel@tonic-gate ho->rewind = ho_rewind; 2030Sstevel@tonic-gate ho->minimize = ho_minimize; 2040Sstevel@tonic-gate ho->res_get = ho_res_get; 2050Sstevel@tonic-gate ho->res_set = ho_res_set; 2060Sstevel@tonic-gate ho->addrinfo = ho_addrinfo; 2070Sstevel@tonic-gate return (ho); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate /* Methods. */ 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate static void 2130Sstevel@tonic-gate ho_close(struct irs_ho *this) { 2140Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate ho_minimize(this); 2170Sstevel@tonic-gate if (pvt->res && pvt->free_res) 2180Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 219*11038SRao.Shoaib@Sun.COM memput(pvt, sizeof *pvt); 2200Sstevel@tonic-gate memput(this, sizeof *this); 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate static struct hostent * 2240Sstevel@tonic-gate ho_byname(struct irs_ho *this, const char *name) { 2250Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2260Sstevel@tonic-gate struct hostent *hp; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate if (init(this) == -1) 2290Sstevel@tonic-gate return (NULL); 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) { 2320Sstevel@tonic-gate hp = ho_byname2(this, name, AF_INET6); 2330Sstevel@tonic-gate if (hp) 2340Sstevel@tonic-gate return (hp); 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate return (ho_byname2(this, name, AF_INET)); 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate static struct hostent * 2400Sstevel@tonic-gate ho_byname2(struct irs_ho *this, const char *name, int af) 2410Sstevel@tonic-gate { 2420Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2430Sstevel@tonic-gate struct hostent *hp = NULL; 2440Sstevel@tonic-gate int n, size; 2450Sstevel@tonic-gate char tmp[NS_MAXDNAME]; 2460Sstevel@tonic-gate const char *cp; 2470Sstevel@tonic-gate struct addrinfo ai; 2480Sstevel@tonic-gate struct dns_res_target *q, *p; 2490Sstevel@tonic-gate int querystate = RESQRY_FAIL; 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate if (init(this) == -1) 2520Sstevel@tonic-gate return (NULL); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate q = memget(sizeof(*q)); 2550Sstevel@tonic-gate if (q == NULL) { 2560Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2570Sstevel@tonic-gate errno = ENOMEM; 2580Sstevel@tonic-gate goto cleanup; 2590Sstevel@tonic-gate } 260*11038SRao.Shoaib@Sun.COM memset(q, 0, sizeof(*q)); 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate switch (af) { 2630Sstevel@tonic-gate case AF_INET: 2640Sstevel@tonic-gate size = INADDRSZ; 2650Sstevel@tonic-gate q->qclass = C_IN; 2660Sstevel@tonic-gate q->qtype = T_A; 2670Sstevel@tonic-gate q->answer = q->qbuf.buf; 2680Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 2690Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 2700Sstevel@tonic-gate break; 2710Sstevel@tonic-gate case AF_INET6: 2720Sstevel@tonic-gate size = IN6ADDRSZ; 2730Sstevel@tonic-gate q->qclass = C_IN; 2740Sstevel@tonic-gate q->qtype = T_AAAA; 2750Sstevel@tonic-gate q->answer = q->qbuf.buf; 2760Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 2770Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 2780Sstevel@tonic-gate break; 2790Sstevel@tonic-gate default: 2800Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2810Sstevel@tonic-gate errno = EAFNOSUPPORT; 2820Sstevel@tonic-gate hp = NULL; 2830Sstevel@tonic-gate goto cleanup; 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate /* 2870Sstevel@tonic-gate * if there aren't any dots, it could be a user-level alias. 2880Sstevel@tonic-gate * this is also done in res_nquery() since we are not the only 2890Sstevel@tonic-gate * function that looks up host names. 2900Sstevel@tonic-gate */ 2910Sstevel@tonic-gate if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, 2920Sstevel@tonic-gate tmp, sizeof tmp))) 2930Sstevel@tonic-gate name = cp; 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate for (p = q; p; p = p->next) { 2960Sstevel@tonic-gate switch(p->action) { 2970Sstevel@tonic-gate case RESTGT_DOALWAYS: 2980Sstevel@tonic-gate break; 2990Sstevel@tonic-gate case RESTGT_AFTERFAILURE: 3000Sstevel@tonic-gate if (querystate == RESQRY_SUCCESS) 3010Sstevel@tonic-gate continue; 3020Sstevel@tonic-gate break; 3030Sstevel@tonic-gate case RESTGT_IGNORE: 3040Sstevel@tonic-gate continue; 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, 3080Sstevel@tonic-gate p->answer, p->anslen)) < 0) { 3090Sstevel@tonic-gate querystate = RESQRY_FAIL; 3100Sstevel@tonic-gate continue; 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate memset(&ai, 0, sizeof(ai)); 3140Sstevel@tonic-gate ai.ai_family = af; 3150Sstevel@tonic-gate if ((hp = gethostans(this, p->answer, n, name, p->qtype, 3160Sstevel@tonic-gate af, size, NULL, 3170Sstevel@tonic-gate (const struct addrinfo *)&ai)) != NULL) 318*11038SRao.Shoaib@Sun.COM goto cleanup; /*%< no more loop is necessary */ 3190Sstevel@tonic-gate querystate = RESQRY_FAIL; 3200Sstevel@tonic-gate continue; 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate cleanup: 3240Sstevel@tonic-gate if (q != NULL) 3250Sstevel@tonic-gate memput(q, sizeof(*q)); 3260Sstevel@tonic-gate return(hp); 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate static struct hostent * 3300Sstevel@tonic-gate ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) 3310Sstevel@tonic-gate { 3320Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 3330Sstevel@tonic-gate const u_char *uaddr = addr; 3340Sstevel@tonic-gate char *qp; 3350Sstevel@tonic-gate struct hostent *hp = NULL; 3360Sstevel@tonic-gate struct addrinfo ai; 3370Sstevel@tonic-gate struct dns_res_target *q, *q2, *p; 3380Sstevel@tonic-gate int n, size, i; 3390Sstevel@tonic-gate int querystate = RESQRY_FAIL; 340*11038SRao.Shoaib@Sun.COM 3410Sstevel@tonic-gate if (init(this) == -1) 3420Sstevel@tonic-gate return (NULL); 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate q = memget(sizeof(*q)); 3450Sstevel@tonic-gate q2 = memget(sizeof(*q2)); 3460Sstevel@tonic-gate if (q == NULL || q2 == NULL) { 3470Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 3480Sstevel@tonic-gate errno = ENOMEM; 3490Sstevel@tonic-gate goto cleanup; 3500Sstevel@tonic-gate } 351*11038SRao.Shoaib@Sun.COM memset(q, 0, sizeof(*q)); 352*11038SRao.Shoaib@Sun.COM memset(q2, 0, sizeof(*q2)); 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate if (af == AF_INET6 && len == IN6ADDRSZ && 3550Sstevel@tonic-gate (!memcmp(uaddr, mapped, sizeof mapped) || 356*11038SRao.Shoaib@Sun.COM (!memcmp(uaddr, tunnelled, sizeof tunnelled) && 357*11038SRao.Shoaib@Sun.COM memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) { 3580Sstevel@tonic-gate /* Unmap. */ 3590Sstevel@tonic-gate addr = (const char *)addr + sizeof mapped; 3600Sstevel@tonic-gate uaddr += sizeof mapped; 3610Sstevel@tonic-gate af = AF_INET; 3620Sstevel@tonic-gate len = INADDRSZ; 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate switch (af) { 3650Sstevel@tonic-gate case AF_INET: 3660Sstevel@tonic-gate size = INADDRSZ; 3670Sstevel@tonic-gate q->qclass = C_IN; 3680Sstevel@tonic-gate q->qtype = T_PTR; 3690Sstevel@tonic-gate q->answer = q->qbuf.buf; 3700Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 3710Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 3720Sstevel@tonic-gate break; 3730Sstevel@tonic-gate case AF_INET6: 3740Sstevel@tonic-gate size = IN6ADDRSZ; 3750Sstevel@tonic-gate q->qclass = C_IN; 3760Sstevel@tonic-gate q->qtype = T_PTR; 3770Sstevel@tonic-gate q->answer = q->qbuf.buf; 3780Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 3790Sstevel@tonic-gate q->next = q2; 3800Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 3810Sstevel@tonic-gate q2->qclass = C_IN; 3820Sstevel@tonic-gate q2->qtype = T_PTR; 3830Sstevel@tonic-gate q2->answer = q2->qbuf.buf; 3840Sstevel@tonic-gate q2->anslen = sizeof(q2->qbuf); 385*11038SRao.Shoaib@Sun.COM if ((pvt->res->options & RES_NO_NIBBLE2) != 0U) 3860Sstevel@tonic-gate q2->action = RESTGT_IGNORE; 3870Sstevel@tonic-gate else 3880Sstevel@tonic-gate q2->action = RESTGT_AFTERFAILURE; 3890Sstevel@tonic-gate break; 3900Sstevel@tonic-gate default: 3910Sstevel@tonic-gate errno = EAFNOSUPPORT; 3920Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 3930Sstevel@tonic-gate hp = NULL; 3940Sstevel@tonic-gate goto cleanup; 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate if (size > len) { 3970Sstevel@tonic-gate errno = EINVAL; 3980Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 3990Sstevel@tonic-gate hp = NULL; 4000Sstevel@tonic-gate goto cleanup; 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate switch (af) { 4030Sstevel@tonic-gate case AF_INET: 4040Sstevel@tonic-gate qp = q->qname; 4050Sstevel@tonic-gate (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa", 4060Sstevel@tonic-gate (uaddr[3] & 0xff), 4070Sstevel@tonic-gate (uaddr[2] & 0xff), 4080Sstevel@tonic-gate (uaddr[1] & 0xff), 4090Sstevel@tonic-gate (uaddr[0] & 0xff)); 4100Sstevel@tonic-gate break; 4110Sstevel@tonic-gate case AF_INET6: 4120Sstevel@tonic-gate if (q->action != RESTGT_IGNORE) { 413*11038SRao.Shoaib@Sun.COM const char *nibsuff = res_get_nibblesuffix(pvt->res); 4140Sstevel@tonic-gate qp = q->qname; 4150Sstevel@tonic-gate for (n = IN6ADDRSZ - 1; n >= 0; n--) { 4160Sstevel@tonic-gate i = SPRINTF((qp, "%x.%x.", 4170Sstevel@tonic-gate uaddr[n] & 0xf, 4180Sstevel@tonic-gate (uaddr[n] >> 4) & 0xf)); 419*11038SRao.Shoaib@Sun.COM if (i != 4) 4200Sstevel@tonic-gate abort(); 4210Sstevel@tonic-gate qp += i; 4220Sstevel@tonic-gate } 423*11038SRao.Shoaib@Sun.COM if (strlen(q->qname) + strlen(nibsuff) + 1 > 424*11038SRao.Shoaib@Sun.COM sizeof q->qname) { 425*11038SRao.Shoaib@Sun.COM errno = ENAMETOOLONG; 426*11038SRao.Shoaib@Sun.COM RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 427*11038SRao.Shoaib@Sun.COM hp = NULL; 428*11038SRao.Shoaib@Sun.COM goto cleanup; 429*11038SRao.Shoaib@Sun.COM } 430*11038SRao.Shoaib@Sun.COM strcpy(qp, nibsuff); /* (checked) */ 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate if (q2->action != RESTGT_IGNORE) { 433*11038SRao.Shoaib@Sun.COM const char *nibsuff2 = res_get_nibblesuffix2(pvt->res); 4340Sstevel@tonic-gate qp = q2->qname; 4350Sstevel@tonic-gate for (n = IN6ADDRSZ - 1; n >= 0; n--) { 4360Sstevel@tonic-gate i = SPRINTF((qp, "%x.%x.", 4370Sstevel@tonic-gate uaddr[n] & 0xf, 4380Sstevel@tonic-gate (uaddr[n] >> 4) & 0xf)); 439*11038SRao.Shoaib@Sun.COM if (i != 4) 4400Sstevel@tonic-gate abort(); 4410Sstevel@tonic-gate qp += i; 4420Sstevel@tonic-gate } 443*11038SRao.Shoaib@Sun.COM if (strlen(q2->qname) + strlen(nibsuff2) + 1 > 444*11038SRao.Shoaib@Sun.COM sizeof q2->qname) { 445*11038SRao.Shoaib@Sun.COM errno = ENAMETOOLONG; 446*11038SRao.Shoaib@Sun.COM RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 447*11038SRao.Shoaib@Sun.COM hp = NULL; 448*11038SRao.Shoaib@Sun.COM goto cleanup; 449*11038SRao.Shoaib@Sun.COM } 450*11038SRao.Shoaib@Sun.COM strcpy(qp, nibsuff2); /* (checked) */ 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate break; 4530Sstevel@tonic-gate default: 4540Sstevel@tonic-gate abort(); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate for (p = q; p; p = p->next) { 4580Sstevel@tonic-gate switch(p->action) { 4590Sstevel@tonic-gate case RESTGT_DOALWAYS: 4600Sstevel@tonic-gate break; 4610Sstevel@tonic-gate case RESTGT_AFTERFAILURE: 4620Sstevel@tonic-gate if (querystate == RESQRY_SUCCESS) 4630Sstevel@tonic-gate continue; 4640Sstevel@tonic-gate break; 4650Sstevel@tonic-gate case RESTGT_IGNORE: 4660Sstevel@tonic-gate continue; 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate if ((n = res_nquery(pvt->res, p->qname, p->qclass, p->qtype, 4700Sstevel@tonic-gate p->answer, p->anslen)) < 0) { 4710Sstevel@tonic-gate querystate = RESQRY_FAIL; 4720Sstevel@tonic-gate continue; 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate memset(&ai, 0, sizeof(ai)); 4760Sstevel@tonic-gate ai.ai_family = af; 4770Sstevel@tonic-gate hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size, 4780Sstevel@tonic-gate NULL, (const struct addrinfo *)&ai); 4790Sstevel@tonic-gate if (!hp) { 4800Sstevel@tonic-gate querystate = RESQRY_FAIL; 4810Sstevel@tonic-gate continue; 4820Sstevel@tonic-gate } 483*11038SRao.Shoaib@Sun.COM 4840Sstevel@tonic-gate memcpy(pvt->host_addr, addr, len); 4850Sstevel@tonic-gate pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; 4860Sstevel@tonic-gate pvt->h_addr_ptrs[1] = NULL; 4870Sstevel@tonic-gate if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { 4880Sstevel@tonic-gate map_v4v6_address((char*)pvt->host_addr, 4890Sstevel@tonic-gate (char*)pvt->host_addr); 4900Sstevel@tonic-gate pvt->host.h_addrtype = AF_INET6; 4910Sstevel@tonic-gate pvt->host.h_length = IN6ADDRSZ; 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 495*11038SRao.Shoaib@Sun.COM goto cleanup; /*%< no more loop is necessary. */ 4960Sstevel@tonic-gate } 497*11038SRao.Shoaib@Sun.COM hp = NULL; /*%< H_ERRNO was set by subroutines */ 4980Sstevel@tonic-gate cleanup: 4990Sstevel@tonic-gate if (q != NULL) 5000Sstevel@tonic-gate memput(q, sizeof(*q)); 5010Sstevel@tonic-gate if (q2 != NULL) 5020Sstevel@tonic-gate memput(q2, sizeof(*q2)); 5030Sstevel@tonic-gate return(hp); 5040Sstevel@tonic-gate } 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate static struct hostent * 5070Sstevel@tonic-gate ho_next(struct irs_ho *this) { 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate UNUSED(this); 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate return (NULL); 5120Sstevel@tonic-gate } 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate static void 5150Sstevel@tonic-gate ho_rewind(struct irs_ho *this) { 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate UNUSED(this); 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate /* NOOP */ 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate static void 5230Sstevel@tonic-gate ho_minimize(struct irs_ho *this) { 5240Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate if (pvt->res) 5270Sstevel@tonic-gate res_nclose(pvt->res); 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate static struct __res_state * 5310Sstevel@tonic-gate ho_res_get(struct irs_ho *this) { 5320Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate if (!pvt->res) { 5350Sstevel@tonic-gate struct __res_state *res; 5360Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 5370Sstevel@tonic-gate if (!res) { 5380Sstevel@tonic-gate errno = ENOMEM; 5390Sstevel@tonic-gate return (NULL); 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate memset(res, 0, sizeof *res); 5420Sstevel@tonic-gate ho_res_set(this, res, free); 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate return (pvt->res); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate /* XXX */ 5490Sstevel@tonic-gate extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *, 5500Sstevel@tonic-gate const char *)); 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate static struct addrinfo * 5530Sstevel@tonic-gate ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) 5540Sstevel@tonic-gate { 5550Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5560Sstevel@tonic-gate int n; 5570Sstevel@tonic-gate char tmp[NS_MAXDNAME]; 5580Sstevel@tonic-gate const char *cp; 5590Sstevel@tonic-gate struct dns_res_target *q, *q2, *p; 5600Sstevel@tonic-gate struct addrinfo sentinel, *cur; 5610Sstevel@tonic-gate int querystate = RESQRY_FAIL; 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate if (init(this) == -1) 5640Sstevel@tonic-gate return (NULL); 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel)); 5670Sstevel@tonic-gate cur = &sentinel; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate q = memget(sizeof(*q)); 5700Sstevel@tonic-gate q2 = memget(sizeof(*q2)); 5710Sstevel@tonic-gate if (q == NULL || q2 == NULL) { 5720Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 5730Sstevel@tonic-gate errno = ENOMEM; 5740Sstevel@tonic-gate goto cleanup; 5750Sstevel@tonic-gate } 576*11038SRao.Shoaib@Sun.COM memset(q, 0, sizeof(*q2)); 577*11038SRao.Shoaib@Sun.COM memset(q2, 0, sizeof(*q2)); 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate switch (pai->ai_family) { 5800Sstevel@tonic-gate case AF_UNSPEC: 5810Sstevel@tonic-gate /* prefer IPv6 */ 5820Sstevel@tonic-gate q->qclass = C_IN; 5830Sstevel@tonic-gate q->qtype = T_AAAA; 5840Sstevel@tonic-gate q->answer = q->qbuf.buf; 5850Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 5860Sstevel@tonic-gate q->next = q2; 5870Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 5880Sstevel@tonic-gate q2->qclass = C_IN; 5890Sstevel@tonic-gate q2->qtype = T_A; 5900Sstevel@tonic-gate q2->answer = q2->qbuf.buf; 5910Sstevel@tonic-gate q2->anslen = sizeof(q2->qbuf); 5920Sstevel@tonic-gate q2->action = RESTGT_DOALWAYS; 5930Sstevel@tonic-gate break; 5940Sstevel@tonic-gate case AF_INET: 5950Sstevel@tonic-gate q->qclass = C_IN; 5960Sstevel@tonic-gate q->qtype = T_A; 5970Sstevel@tonic-gate q->answer = q->qbuf.buf; 5980Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 5990Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 6000Sstevel@tonic-gate break; 6010Sstevel@tonic-gate case AF_INET6: 6020Sstevel@tonic-gate q->qclass = C_IN; 6030Sstevel@tonic-gate q->qtype = T_AAAA; 6040Sstevel@tonic-gate q->answer = q->qbuf.buf; 6050Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 6060Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 6070Sstevel@tonic-gate break; 6080Sstevel@tonic-gate default: 609*11038SRao.Shoaib@Sun.COM RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /*%< better error? */ 6100Sstevel@tonic-gate goto cleanup; 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* 6140Sstevel@tonic-gate * if there aren't any dots, it could be a user-level alias. 6150Sstevel@tonic-gate * this is also done in res_nquery() since we are not the only 6160Sstevel@tonic-gate * function that looks up host names. 6170Sstevel@tonic-gate */ 6180Sstevel@tonic-gate if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, 6190Sstevel@tonic-gate tmp, sizeof tmp))) 6200Sstevel@tonic-gate name = cp; 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate for (p = q; p; p = p->next) { 6230Sstevel@tonic-gate struct addrinfo *ai; 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate switch(p->action) { 6260Sstevel@tonic-gate case RESTGT_DOALWAYS: 6270Sstevel@tonic-gate break; 6280Sstevel@tonic-gate case RESTGT_AFTERFAILURE: 6290Sstevel@tonic-gate if (querystate == RESQRY_SUCCESS) 6300Sstevel@tonic-gate continue; 6310Sstevel@tonic-gate break; 6320Sstevel@tonic-gate case RESTGT_IGNORE: 6330Sstevel@tonic-gate continue; 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, 6370Sstevel@tonic-gate p->answer, p->anslen)) < 0) { 6380Sstevel@tonic-gate querystate = RESQRY_FAIL; 6390Sstevel@tonic-gate continue; 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate (void)gethostans(this, p->answer, n, name, p->qtype, 642*11038SRao.Shoaib@Sun.COM pai->ai_family, /*%< XXX: meaningless */ 6430Sstevel@tonic-gate 0, &ai, pai); 6440Sstevel@tonic-gate if (ai) { 6450Sstevel@tonic-gate querystate = RESQRY_SUCCESS; 6460Sstevel@tonic-gate cur->ai_next = ai; 647*11038SRao.Shoaib@Sun.COM while (cur->ai_next) 6480Sstevel@tonic-gate cur = cur->ai_next; 649*11038SRao.Shoaib@Sun.COM } else 6500Sstevel@tonic-gate querystate = RESQRY_FAIL; 6510Sstevel@tonic-gate } 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate cleanup: 6540Sstevel@tonic-gate if (q != NULL) 6550Sstevel@tonic-gate memput(q, sizeof(*q)); 6560Sstevel@tonic-gate if (q2 != NULL) 6570Sstevel@tonic-gate memput(q2, sizeof(*q2)); 6580Sstevel@tonic-gate return(sentinel.ai_next); 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate static void 6620Sstevel@tonic-gate ho_res_set(struct irs_ho *this, struct __res_state *res, 6630Sstevel@tonic-gate void (*free_res)(void *)) { 6640Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate if (pvt->res && pvt->free_res) { 6670Sstevel@tonic-gate res_nclose(pvt->res); 6680Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate pvt->res = res; 6720Sstevel@tonic-gate pvt->free_res = free_res; 6730Sstevel@tonic-gate } 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate /* Private. */ 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate static struct hostent * 6780Sstevel@tonic-gate gethostans(struct irs_ho *this, 6790Sstevel@tonic-gate const u_char *ansbuf, int anslen, const char *qname, int qtype, 680*11038SRao.Shoaib@Sun.COM int af, int size, /*!< meaningless for addrinfo cases */ 6810Sstevel@tonic-gate struct addrinfo **ret_aip, const struct addrinfo *pai) 6820Sstevel@tonic-gate { 6830Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 6840Sstevel@tonic-gate int type, class, ancount, qdcount, n, haveanswer, had_error; 685*11038SRao.Shoaib@Sun.COM int error = NETDB_SUCCESS; 6860Sstevel@tonic-gate int (*name_ok)(const char *); 6870Sstevel@tonic-gate const HEADER *hp; 6880Sstevel@tonic-gate const u_char *eom; 6890Sstevel@tonic-gate const u_char *eor; 6900Sstevel@tonic-gate const u_char *cp; 6910Sstevel@tonic-gate const char *tname; 6920Sstevel@tonic-gate const char *hname; 6930Sstevel@tonic-gate char *bp, *ep, **ap, **hap; 6940Sstevel@tonic-gate char tbuf[MAXDNAME+1]; 6950Sstevel@tonic-gate struct addrinfo sentinel, *cur, ai; 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate if (pai == NULL) abort(); 6980Sstevel@tonic-gate if (ret_aip != NULL) 6990Sstevel@tonic-gate *ret_aip = NULL; 7000Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel)); 7010Sstevel@tonic-gate cur = &sentinel; 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate tname = qname; 7040Sstevel@tonic-gate eom = ansbuf + anslen; 7050Sstevel@tonic-gate switch (qtype) { 7060Sstevel@tonic-gate case T_A: 7070Sstevel@tonic-gate case T_AAAA: 708*11038SRao.Shoaib@Sun.COM case T_ANY: /*%< use T_ANY only for T_A/T_AAAA lookup */ 7090Sstevel@tonic-gate name_ok = res_hnok; 7100Sstevel@tonic-gate break; 7110Sstevel@tonic-gate case T_PTR: 7120Sstevel@tonic-gate name_ok = res_dnok; 7130Sstevel@tonic-gate break; 7140Sstevel@tonic-gate default: 7150Sstevel@tonic-gate abort(); 7160Sstevel@tonic-gate } 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate pvt->host.h_addrtype = af; 7190Sstevel@tonic-gate pvt->host.h_length = size; 7200Sstevel@tonic-gate hname = pvt->host.h_name = NULL; 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate /* 7230Sstevel@tonic-gate * Find first satisfactory answer. 7240Sstevel@tonic-gate */ 7250Sstevel@tonic-gate if (ansbuf + HFIXEDSZ > eom) { 7260Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7270Sstevel@tonic-gate return (NULL); 7280Sstevel@tonic-gate } 7290Sstevel@tonic-gate hp = (const HEADER *)ansbuf; 7300Sstevel@tonic-gate ancount = ntohs(hp->ancount); 7310Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 7320Sstevel@tonic-gate bp = pvt->hostbuf; 7330Sstevel@tonic-gate ep = pvt->hostbuf + sizeof(pvt->hostbuf); 7340Sstevel@tonic-gate cp = ansbuf + HFIXEDSZ; 7350Sstevel@tonic-gate if (qdcount != 1) { 7360Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7370Sstevel@tonic-gate return (NULL); 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate n = dn_expand(ansbuf, eom, cp, bp, ep - bp); 7400Sstevel@tonic-gate if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { 7410Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7420Sstevel@tonic-gate return (NULL); 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate cp += n + QFIXEDSZ; 7450Sstevel@tonic-gate if (cp > eom) { 7460Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7470Sstevel@tonic-gate return (NULL); 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 7500Sstevel@tonic-gate /* res_nsend() has already verified that the query name is the 7510Sstevel@tonic-gate * same as the one we sent; this just gets the expanded name 7520Sstevel@tonic-gate * (i.e., with the succeeding search-domain tacked on). 7530Sstevel@tonic-gate */ 754*11038SRao.Shoaib@Sun.COM n = strlen(bp) + 1; /*%< for the \\0 */ 7550Sstevel@tonic-gate if (n > MAXHOSTNAMELEN) { 7560Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7570Sstevel@tonic-gate return (NULL); 7580Sstevel@tonic-gate } 7590Sstevel@tonic-gate pvt->host.h_name = bp; 7600Sstevel@tonic-gate hname = bp; 7610Sstevel@tonic-gate bp += n; 7620Sstevel@tonic-gate /* The qname can be abbreviated, but hname is now absolute. */ 7630Sstevel@tonic-gate qname = pvt->host.h_name; 7640Sstevel@tonic-gate } 7650Sstevel@tonic-gate ap = pvt->host_aliases; 7660Sstevel@tonic-gate *ap = NULL; 7670Sstevel@tonic-gate pvt->host.h_aliases = pvt->host_aliases; 7680Sstevel@tonic-gate hap = pvt->h_addr_ptrs; 7690Sstevel@tonic-gate *hap = NULL; 7700Sstevel@tonic-gate pvt->host.h_addr_list = pvt->h_addr_ptrs; 7710Sstevel@tonic-gate haveanswer = 0; 7720Sstevel@tonic-gate had_error = 0; 7730Sstevel@tonic-gate while (ancount-- > 0 && cp < eom && !had_error) { 7740Sstevel@tonic-gate n = dn_expand(ansbuf, eom, cp, bp, ep - bp); 7750Sstevel@tonic-gate if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { 7760Sstevel@tonic-gate had_error++; 7770Sstevel@tonic-gate continue; 7780Sstevel@tonic-gate } 779*11038SRao.Shoaib@Sun.COM cp += n; /*%< name */ 7800Sstevel@tonic-gate BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 7810Sstevel@tonic-gate type = ns_get16(cp); 782*11038SRao.Shoaib@Sun.COM cp += INT16SZ; /*%< type */ 7830Sstevel@tonic-gate class = ns_get16(cp); 784*11038SRao.Shoaib@Sun.COM cp += INT16SZ + INT32SZ; /*%< class, TTL */ 7850Sstevel@tonic-gate n = ns_get16(cp); 786*11038SRao.Shoaib@Sun.COM cp += INT16SZ; /*%< len */ 7870Sstevel@tonic-gate BOUNDS_CHECK(cp, n); 7880Sstevel@tonic-gate if (class != C_IN) { 7890Sstevel@tonic-gate cp += n; 7900Sstevel@tonic-gate continue; 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate eor = cp + n; 7930Sstevel@tonic-gate if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 7940Sstevel@tonic-gate type == T_CNAME) { 7950Sstevel@tonic-gate if (haveanswer) { 7960Sstevel@tonic-gate int level = LOG_CRIT; 7970Sstevel@tonic-gate #ifdef LOG_SECURITY 7980Sstevel@tonic-gate level |= LOG_SECURITY; 7990Sstevel@tonic-gate #endif 8000Sstevel@tonic-gate syslog(level, 8010Sstevel@tonic-gate "gethostans: possible attempt to exploit buffer overflow while looking up %s", 8020Sstevel@tonic-gate *qname ? qname : "."); 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); 8050Sstevel@tonic-gate if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { 8060Sstevel@tonic-gate had_error++; 8070Sstevel@tonic-gate continue; 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate cp += n; 8100Sstevel@tonic-gate /* Store alias. */ 8110Sstevel@tonic-gate if (ap >= &pvt->host_aliases[MAXALIASES-1]) 8120Sstevel@tonic-gate continue; 8130Sstevel@tonic-gate *ap++ = bp; 814*11038SRao.Shoaib@Sun.COM n = strlen(bp) + 1; /*%< for the \\0 */ 8150Sstevel@tonic-gate bp += n; 8160Sstevel@tonic-gate /* Get canonical name. */ 817*11038SRao.Shoaib@Sun.COM n = strlen(tbuf) + 1; /*%< for the \\0 */ 8180Sstevel@tonic-gate if (n > (ep - bp) || n > MAXHOSTNAMELEN) { 8190Sstevel@tonic-gate had_error++; 8200Sstevel@tonic-gate continue; 8210Sstevel@tonic-gate } 822*11038SRao.Shoaib@Sun.COM strcpy(bp, tbuf); /* (checked) */ 8230Sstevel@tonic-gate pvt->host.h_name = bp; 8240Sstevel@tonic-gate hname = bp; 8250Sstevel@tonic-gate bp += n; 8260Sstevel@tonic-gate continue; 8270Sstevel@tonic-gate } 8280Sstevel@tonic-gate if (qtype == T_PTR && type == T_CNAME) { 8290Sstevel@tonic-gate n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); 8300Sstevel@tonic-gate if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { 8310Sstevel@tonic-gate had_error++; 8320Sstevel@tonic-gate continue; 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate cp += n; 8350Sstevel@tonic-gate #ifdef RES_USE_DNAME 836*11038SRao.Shoaib@Sun.COM if ((pvt->res->options & RES_USE_DNAME) != 0U) 8370Sstevel@tonic-gate #endif 8380Sstevel@tonic-gate { 8390Sstevel@tonic-gate /* 8400Sstevel@tonic-gate * We may be able to check this regardless 8410Sstevel@tonic-gate * of the USE_DNAME bit, but we add the check 8420Sstevel@tonic-gate * for now since the DNAME support is 8430Sstevel@tonic-gate * experimental. 8440Sstevel@tonic-gate */ 8450Sstevel@tonic-gate if (ns_samename(tname, bp) != 1) 8460Sstevel@tonic-gate continue; 8470Sstevel@tonic-gate } 8480Sstevel@tonic-gate /* Get canonical name. */ 849*11038SRao.Shoaib@Sun.COM n = strlen(tbuf) + 1; /*%< for the \\0 */ 8500Sstevel@tonic-gate if (n > (ep - bp)) { 8510Sstevel@tonic-gate had_error++; 8520Sstevel@tonic-gate continue; 8530Sstevel@tonic-gate } 854*11038SRao.Shoaib@Sun.COM strcpy(bp, tbuf); /* (checked) */ 8550Sstevel@tonic-gate tname = bp; 8560Sstevel@tonic-gate bp += n; 8570Sstevel@tonic-gate continue; 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate if (qtype == T_ANY) { 8600Sstevel@tonic-gate if (!(type == T_A || type == T_AAAA)) { 8610Sstevel@tonic-gate cp += n; 8620Sstevel@tonic-gate continue; 8630Sstevel@tonic-gate } 8640Sstevel@tonic-gate } else if (type != qtype) { 8650Sstevel@tonic-gate cp += n; 8660Sstevel@tonic-gate continue; 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate switch (type) { 8690Sstevel@tonic-gate case T_PTR: 8700Sstevel@tonic-gate if (ret_aip != NULL) { 8710Sstevel@tonic-gate /* addrinfo never needs T_PTR */ 8720Sstevel@tonic-gate cp += n; 8730Sstevel@tonic-gate continue; 8740Sstevel@tonic-gate } 8750Sstevel@tonic-gate if (ns_samename(tname, bp) != 1) { 8760Sstevel@tonic-gate cp += n; 8770Sstevel@tonic-gate continue; 8780Sstevel@tonic-gate } 8790Sstevel@tonic-gate n = dn_expand(ansbuf, eor, cp, bp, ep - bp); 8800Sstevel@tonic-gate if (n < 0 || !maybe_hnok(pvt->res, bp) || 8810Sstevel@tonic-gate n >= MAXHOSTNAMELEN) { 8820Sstevel@tonic-gate had_error++; 8830Sstevel@tonic-gate break; 8840Sstevel@tonic-gate } 8850Sstevel@tonic-gate cp += n; 8860Sstevel@tonic-gate if (!haveanswer) { 8870Sstevel@tonic-gate pvt->host.h_name = bp; 8880Sstevel@tonic-gate hname = bp; 8890Sstevel@tonic-gate } 8900Sstevel@tonic-gate else if (ap < &pvt->host_aliases[MAXALIASES-1]) 8910Sstevel@tonic-gate *ap++ = bp; 8920Sstevel@tonic-gate else 8930Sstevel@tonic-gate n = -1; 8940Sstevel@tonic-gate if (n != -1) { 895*11038SRao.Shoaib@Sun.COM n = strlen(bp) + 1; /*%< for the \\0 */ 8960Sstevel@tonic-gate bp += n; 8970Sstevel@tonic-gate } 8980Sstevel@tonic-gate break; 8990Sstevel@tonic-gate case T_A: 9000Sstevel@tonic-gate case T_AAAA: 9010Sstevel@tonic-gate if (ns_samename(hname, bp) != 1) { 9020Sstevel@tonic-gate cp += n; 9030Sstevel@tonic-gate continue; 9040Sstevel@tonic-gate } 9050Sstevel@tonic-gate if (type == T_A && n != INADDRSZ) { 9060Sstevel@tonic-gate cp += n; 9070Sstevel@tonic-gate continue; 9080Sstevel@tonic-gate } 9090Sstevel@tonic-gate if (type == T_AAAA && n != IN6ADDRSZ) { 9100Sstevel@tonic-gate cp += n; 9110Sstevel@tonic-gate continue; 9120Sstevel@tonic-gate } 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate /* make addrinfo. don't overwrite constant PAI */ 9150Sstevel@tonic-gate ai = *pai; 9160Sstevel@tonic-gate ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET; 9170Sstevel@tonic-gate cur->ai_next = addr2addrinfo( 9180Sstevel@tonic-gate (const struct addrinfo *)&ai, 9190Sstevel@tonic-gate (const char *)cp); 9200Sstevel@tonic-gate if (cur->ai_next == NULL) 9210Sstevel@tonic-gate had_error++; 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate if (!haveanswer) { 9240Sstevel@tonic-gate int nn; 9250Sstevel@tonic-gate 926*11038SRao.Shoaib@Sun.COM nn = strlen(bp) + 1; /*%< for the \\0 */ 9270Sstevel@tonic-gate if (nn >= MAXHOSTNAMELEN) { 9280Sstevel@tonic-gate cp += n; 9290Sstevel@tonic-gate had_error++; 9300Sstevel@tonic-gate continue; 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate pvt->host.h_name = bp; 9330Sstevel@tonic-gate hname = bp; 9340Sstevel@tonic-gate bp += nn; 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate /* Ensure alignment. */ 9370Sstevel@tonic-gate bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & 9380Sstevel@tonic-gate ~(sizeof(align) - 1)); 9390Sstevel@tonic-gate /* Avoid overflows. */ 940*11038SRao.Shoaib@Sun.COM if (bp + n > &pvt->hostbuf[sizeof(pvt->hostbuf) - 1]) { 9410Sstevel@tonic-gate had_error++; 9420Sstevel@tonic-gate continue; 9430Sstevel@tonic-gate } 944*11038SRao.Shoaib@Sun.COM if (ret_aip) { /*%< need addrinfo. keep it. */ 945*11038SRao.Shoaib@Sun.COM while (cur->ai_next) 9460Sstevel@tonic-gate cur = cur->ai_next; 947*11038SRao.Shoaib@Sun.COM } else if (cur->ai_next) { /*%< need hostent */ 9480Sstevel@tonic-gate struct addrinfo *aip = cur->ai_next; 9490Sstevel@tonic-gate 9500Sstevel@tonic-gate for (aip = cur->ai_next; aip; 9510Sstevel@tonic-gate aip = aip->ai_next) { 9520Sstevel@tonic-gate int m; 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate m = add_hostent(pvt, bp, hap, aip); 9550Sstevel@tonic-gate if (m < 0) { 9560Sstevel@tonic-gate had_error++; 9570Sstevel@tonic-gate break; 9580Sstevel@tonic-gate } 9590Sstevel@tonic-gate if (m == 0) 9600Sstevel@tonic-gate continue; 9619433SStacey.Marshall@Sun.COM if (hap < &pvt->h_addr_ptrs[MAXADDRS]) 9620Sstevel@tonic-gate hap++; 9630Sstevel@tonic-gate *hap = NULL; 9640Sstevel@tonic-gate bp += m; 9650Sstevel@tonic-gate } 9660Sstevel@tonic-gate 9670Sstevel@tonic-gate freeaddrinfo(cur->ai_next); 9680Sstevel@tonic-gate cur->ai_next = NULL; 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate cp += n; 9710Sstevel@tonic-gate break; 9720Sstevel@tonic-gate default: 9730Sstevel@tonic-gate abort(); 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate if (!had_error) 9760Sstevel@tonic-gate haveanswer++; 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate if (haveanswer) { 9790Sstevel@tonic-gate if (ret_aip == NULL) { 9800Sstevel@tonic-gate *ap = NULL; 9810Sstevel@tonic-gate *hap = NULL; 9820Sstevel@tonic-gate 9839433SStacey.Marshall@Sun.COM if (pvt->res->nsort && hap != pvt->h_addr_ptrs && 9849433SStacey.Marshall@Sun.COM qtype == T_A) 9850Sstevel@tonic-gate addrsort(pvt->res, pvt->h_addr_ptrs, 9869433SStacey.Marshall@Sun.COM hap - pvt->h_addr_ptrs); 9870Sstevel@tonic-gate if (pvt->host.h_name == NULL) { 988*11038SRao.Shoaib@Sun.COM n = strlen(qname) + 1; /*%< for the \\0 */ 9890Sstevel@tonic-gate if (n > (ep - bp) || n >= MAXHOSTNAMELEN) 9900Sstevel@tonic-gate goto no_recovery; 991*11038SRao.Shoaib@Sun.COM strcpy(bp, qname); /* (checked) */ 9920Sstevel@tonic-gate pvt->host.h_name = bp; 9930Sstevel@tonic-gate bp += n; 9940Sstevel@tonic-gate } 9950Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) 9960Sstevel@tonic-gate map_v4v6_hostent(&pvt->host, &bp, ep); 9970Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 9980Sstevel@tonic-gate return (&pvt->host); 9990Sstevel@tonic-gate } else { 10000Sstevel@tonic-gate if ((pai->ai_flags & AI_CANONNAME) != 0) { 10010Sstevel@tonic-gate if (pvt->host.h_name == NULL) { 10020Sstevel@tonic-gate sentinel.ai_next->ai_canonname = 10030Sstevel@tonic-gate strdup(qname); 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate else { 10060Sstevel@tonic-gate sentinel.ai_next->ai_canonname = 10070Sstevel@tonic-gate strdup(pvt->host.h_name); 10080Sstevel@tonic-gate } 10090Sstevel@tonic-gate } 10100Sstevel@tonic-gate *ret_aip = sentinel.ai_next; 10110Sstevel@tonic-gate return(NULL); 10120Sstevel@tonic-gate } 10130Sstevel@tonic-gate } 10140Sstevel@tonic-gate no_recovery: 10150Sstevel@tonic-gate if (sentinel.ai_next) { 10160Sstevel@tonic-gate /* this should be impossible, but check it for safety */ 10170Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next); 10180Sstevel@tonic-gate } 10190Sstevel@tonic-gate if (error == NETDB_SUCCESS) 10200Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 10210Sstevel@tonic-gate else 10220Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, error); 10230Sstevel@tonic-gate return(NULL); 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate static int 10270Sstevel@tonic-gate add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) 10280Sstevel@tonic-gate { 10290Sstevel@tonic-gate int addrlen; 10300Sstevel@tonic-gate char *addrp; 10310Sstevel@tonic-gate const char **tap; 10320Sstevel@tonic-gate char *obp = bp; 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate switch(ai->ai_addr->sa_family) { 10350Sstevel@tonic-gate case AF_INET6: 10360Sstevel@tonic-gate addrlen = IN6ADDRSZ; 10370Sstevel@tonic-gate addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; 10380Sstevel@tonic-gate break; 10390Sstevel@tonic-gate case AF_INET: 10400Sstevel@tonic-gate addrlen = INADDRSZ; 10410Sstevel@tonic-gate addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr; 10420Sstevel@tonic-gate break; 10430Sstevel@tonic-gate default: 1044*11038SRao.Shoaib@Sun.COM return(-1); /*%< abort? */ 10450Sstevel@tonic-gate } 10460Sstevel@tonic-gate 10470Sstevel@tonic-gate /* Ensure alignment. */ 10480Sstevel@tonic-gate bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & 10490Sstevel@tonic-gate ~(sizeof(align) - 1)); 10500Sstevel@tonic-gate /* Avoid overflows. */ 1051*11038SRao.Shoaib@Sun.COM if (bp + addrlen > &pvt->hostbuf[sizeof(pvt->hostbuf) - 1]) 10520Sstevel@tonic-gate return(-1); 10539433SStacey.Marshall@Sun.COM if (hap >= &pvt->h_addr_ptrs[MAXADDRS]) 1054*11038SRao.Shoaib@Sun.COM return(0); /*%< fail, but not treat it as an error. */ 10550Sstevel@tonic-gate /* Suppress duplicates. */ 10560Sstevel@tonic-gate for (tap = (const char **)pvt->h_addr_ptrs; 10570Sstevel@tonic-gate *tap != NULL; 10580Sstevel@tonic-gate tap++) 10590Sstevel@tonic-gate if (memcmp(*tap, addrp, addrlen) == 0) 10600Sstevel@tonic-gate break; 10610Sstevel@tonic-gate if (*tap != NULL) 10620Sstevel@tonic-gate return (0); 10630Sstevel@tonic-gate 10640Sstevel@tonic-gate memcpy(*hap = bp, addrp, addrlen); 10650Sstevel@tonic-gate return((bp + addrlen) - obp); 10660Sstevel@tonic-gate } 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate static void 10690Sstevel@tonic-gate map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) { 10700Sstevel@tonic-gate char **ap; 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) 10730Sstevel@tonic-gate return; 10740Sstevel@tonic-gate hp->h_addrtype = AF_INET6; 10750Sstevel@tonic-gate hp->h_length = IN6ADDRSZ; 10760Sstevel@tonic-gate for (ap = hp->h_addr_list; *ap; ap++) { 10770Sstevel@tonic-gate int i = (u_long)*bpp % sizeof(align); 10780Sstevel@tonic-gate 10790Sstevel@tonic-gate if (i != 0) 10800Sstevel@tonic-gate i = sizeof(align) - i; 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate if ((ep - *bpp) < (i + IN6ADDRSZ)) { 10830Sstevel@tonic-gate /* Out of memory. Truncate address list here. */ 10840Sstevel@tonic-gate *ap = NULL; 10850Sstevel@tonic-gate return; 10860Sstevel@tonic-gate } 10870Sstevel@tonic-gate *bpp += i; 10880Sstevel@tonic-gate map_v4v6_address(*ap, *bpp); 10890Sstevel@tonic-gate *ap = *bpp; 10900Sstevel@tonic-gate *bpp += IN6ADDRSZ; 10910Sstevel@tonic-gate } 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate static void 10950Sstevel@tonic-gate addrsort(res_state statp, char **ap, int num) { 10960Sstevel@tonic-gate int i, j, needsort = 0, aval[MAXADDRS]; 10970Sstevel@tonic-gate char **p; 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate p = ap; 11000Sstevel@tonic-gate for (i = 0; i < num; i++, p++) { 11010Sstevel@tonic-gate for (j = 0 ; (unsigned)j < statp->nsort; j++) 1102*11038SRao.Shoaib@Sun.COM if (statp->sort_list[j].addr.s_addr == 11030Sstevel@tonic-gate (((struct in_addr *)(*p))->s_addr & 11040Sstevel@tonic-gate statp->sort_list[j].mask)) 11050Sstevel@tonic-gate break; 11060Sstevel@tonic-gate aval[i] = j; 11070Sstevel@tonic-gate if (needsort == 0 && i > 0 && j < aval[i-1]) 11080Sstevel@tonic-gate needsort = i; 11090Sstevel@tonic-gate } 11100Sstevel@tonic-gate if (!needsort) 11110Sstevel@tonic-gate return; 11120Sstevel@tonic-gate 11130Sstevel@tonic-gate while (needsort < num) { 11140Sstevel@tonic-gate for (j = needsort - 1; j >= 0; j--) { 11150Sstevel@tonic-gate if (aval[j] > aval[j+1]) { 11160Sstevel@tonic-gate char *hp; 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate i = aval[j]; 11190Sstevel@tonic-gate aval[j] = aval[j+1]; 11200Sstevel@tonic-gate aval[j+1] = i; 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate hp = ap[j]; 11230Sstevel@tonic-gate ap[j] = ap[j+1]; 11240Sstevel@tonic-gate ap[j+1] = hp; 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate } else 11270Sstevel@tonic-gate break; 11280Sstevel@tonic-gate } 11290Sstevel@tonic-gate needsort++; 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate static int 11340Sstevel@tonic-gate init(struct irs_ho *this) { 11350Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 1136*11038SRao.Shoaib@Sun.COM 11370Sstevel@tonic-gate if (!pvt->res && !ho_res_get(this)) 11380Sstevel@tonic-gate return (-1); 1139*11038SRao.Shoaib@Sun.COM if (((pvt->res->options & RES_INIT) == 0U) && 11400Sstevel@tonic-gate res_ninit(pvt->res) == -1) 11410Sstevel@tonic-gate return (-1); 11420Sstevel@tonic-gate return (0); 11430Sstevel@tonic-gate } 1144