17c478bd9Sstevel@tonic-gate /* 2*9525b14bSRao Shoaib * Portions Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC") 3*9525b14bSRao Shoaib * Portions Copyright (C) 1996-2003 Internet Software Consortium. 4*9525b14bSRao Shoaib * 5*9525b14bSRao Shoaib * Permission to use, copy, modify, and/or distribute this software for any 6*9525b14bSRao Shoaib * purpose with or without fee is hereby granted, provided that the above 7*9525b14bSRao Shoaib * copyright notice and this permission notice appear in all copies. 8*9525b14bSRao Shoaib * 9*9525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10*9525b14bSRao Shoaib * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11*9525b14bSRao Shoaib * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12*9525b14bSRao Shoaib * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13*9525b14bSRao Shoaib * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14*9525b14bSRao Shoaib * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15*9525b14bSRao Shoaib * PERFORMANCE OF THIS SOFTWARE. 167c478bd9Sstevel@tonic-gate */ 177c478bd9Sstevel@tonic-gate 187c478bd9Sstevel@tonic-gate /* 197c478bd9Sstevel@tonic-gate * Copyright (c) 1985, 1988, 1993 207c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 217c478bd9Sstevel@tonic-gate * 227c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 237c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 247c478bd9Sstevel@tonic-gate * are met: 257c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 267c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 277c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 287c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 297c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 307c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 317c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 327c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 337c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 347c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 357c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 367c478bd9Sstevel@tonic-gate * without specific prior written permission. 377c478bd9Sstevel@tonic-gate * 387c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 397c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 407c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 417c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 427c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 437c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 447c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 457c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 467c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 477c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 487c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ 527c478bd9Sstevel@tonic-gate /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 55*9525b14bSRao Shoaib static const char rcsid[] = "$Id: dns_ho.c,v 1.23 2008/11/14 02:36:51 marka Exp $"; 567c478bd9Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* Imports. */ 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #include "port_before.h" 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #include <sys/types.h> 637c478bd9Sstevel@tonic-gate #include <sys/param.h> 647c478bd9Sstevel@tonic-gate #include <sys/socket.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #include <netinet/in.h> 677c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 687c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #include <ctype.h> 717c478bd9Sstevel@tonic-gate #include <errno.h> 727c478bd9Sstevel@tonic-gate #include <stdlib.h> 737c478bd9Sstevel@tonic-gate #include <netdb.h> 747c478bd9Sstevel@tonic-gate #include <resolv.h> 757c478bd9Sstevel@tonic-gate #include <stdio.h> 767c478bd9Sstevel@tonic-gate #include <string.h> 777c478bd9Sstevel@tonic-gate #include <syslog.h> 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate #include <isc/memcluster.h> 807c478bd9Sstevel@tonic-gate #include <irs.h> 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate #include "port_after.h" 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #include "irs_p.h" 857c478bd9Sstevel@tonic-gate #include "dns_p.h" 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #ifdef SPRINTF_CHAR 887c478bd9Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x) 897c478bd9Sstevel@tonic-gate #else 907c478bd9Sstevel@tonic-gate # define SPRINTF(x) sprintf x 917c478bd9Sstevel@tonic-gate #endif 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* Definitions. */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #define MAXALIASES 35 967c478bd9Sstevel@tonic-gate #define MAXADDRS 35 977c478bd9Sstevel@tonic-gate 98*9525b14bSRao Shoaib #define MAXPACKET (65535) /*%< Maximum TCP message size */ 997c478bd9Sstevel@tonic-gate #define BOUNDS_CHECK(ptr, count) \ 1007c478bd9Sstevel@tonic-gate if ((ptr) + (count) > eom) { \ 1017c478bd9Sstevel@tonic-gate had_error++; \ 1027c478bd9Sstevel@tonic-gate continue; \ 1037c478bd9Sstevel@tonic-gate } else (void)0 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate typedef union { 1067c478bd9Sstevel@tonic-gate HEADER hdr; 1077c478bd9Sstevel@tonic-gate u_char buf[MAXPACKET]; 1087c478bd9Sstevel@tonic-gate } querybuf; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate struct dns_res_target { 1117c478bd9Sstevel@tonic-gate struct dns_res_target *next; 112*9525b14bSRao Shoaib querybuf qbuf; /*%< query buffer */ 113*9525b14bSRao Shoaib u_char *answer; /*%< buffer to put answer */ 114*9525b14bSRao Shoaib int anslen; /*%< size of answer buffer */ 115*9525b14bSRao Shoaib int qclass, qtype; /*%< class and type of query */ 116*9525b14bSRao Shoaib int action; /*%< condition whether query is really issued */ 117*9525b14bSRao Shoaib char qname[MAXDNAME +1]; /*%< domain name */ 1187c478bd9Sstevel@tonic-gate #if 0 119*9525b14bSRao Shoaib int n; /*%< result length */ 1207c478bd9Sstevel@tonic-gate #endif 1217c478bd9Sstevel@tonic-gate }; 1227c478bd9Sstevel@tonic-gate enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE}; 1237c478bd9Sstevel@tonic-gate enum {RESQRY_SUCCESS, RESQRY_FAIL}; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate struct pvt { 1267c478bd9Sstevel@tonic-gate struct hostent host; 1277c478bd9Sstevel@tonic-gate char * h_addr_ptrs[MAXADDRS + 1]; 1287c478bd9Sstevel@tonic-gate char * host_aliases[MAXALIASES]; 1297c478bd9Sstevel@tonic-gate char hostbuf[8*1024]; 130*9525b14bSRao Shoaib u_char host_addr[16]; /*%< IPv4 or IPv6 */ 1317c478bd9Sstevel@tonic-gate struct __res_state *res; 1327c478bd9Sstevel@tonic-gate void (*free_res)(void *); 1337c478bd9Sstevel@tonic-gate }; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate typedef union { 1367c478bd9Sstevel@tonic-gate int32_t al; 1377c478bd9Sstevel@tonic-gate char ac; 1387c478bd9Sstevel@tonic-gate } align; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; 1417c478bd9Sstevel@tonic-gate static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; 1427c478bd9Sstevel@tonic-gate /* Note: the IPv6 loopback address is in the "tunnel" space */ 143*9525b14bSRao Shoaib static const u_char v6local[] = { 0,0, 0,1 }; /*%< last 4 bytes of IPv6 addr */ 1447c478bd9Sstevel@tonic-gate /* Forwards. */ 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate static void ho_close(struct irs_ho *this); 1477c478bd9Sstevel@tonic-gate static struct hostent * ho_byname(struct irs_ho *this, const char *name); 1487c478bd9Sstevel@tonic-gate static struct hostent * ho_byname2(struct irs_ho *this, const char *name, 1497c478bd9Sstevel@tonic-gate int af); 1507c478bd9Sstevel@tonic-gate static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, 1517c478bd9Sstevel@tonic-gate int len, int af); 1527c478bd9Sstevel@tonic-gate static struct hostent * ho_next(struct irs_ho *this); 1537c478bd9Sstevel@tonic-gate static void ho_rewind(struct irs_ho *this); 1547c478bd9Sstevel@tonic-gate static void ho_minimize(struct irs_ho *this); 1557c478bd9Sstevel@tonic-gate static struct __res_state * ho_res_get(struct irs_ho *this); 1567c478bd9Sstevel@tonic-gate static void ho_res_set(struct irs_ho *this, 1577c478bd9Sstevel@tonic-gate struct __res_state *res, 1587c478bd9Sstevel@tonic-gate void (*free_res)(void *)); 1597c478bd9Sstevel@tonic-gate static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, 1607c478bd9Sstevel@tonic-gate const struct addrinfo *pai); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static void map_v4v6_hostent(struct hostent *hp, char **bp, 1637c478bd9Sstevel@tonic-gate char *ep); 1647c478bd9Sstevel@tonic-gate static void addrsort(res_state, char **, int); 1657c478bd9Sstevel@tonic-gate static struct hostent * gethostans(struct irs_ho *this, 1667c478bd9Sstevel@tonic-gate const u_char *ansbuf, int anslen, 1677c478bd9Sstevel@tonic-gate const char *qname, int qtype, 1687c478bd9Sstevel@tonic-gate int af, int size, 1697c478bd9Sstevel@tonic-gate struct addrinfo **ret_aip, 1707c478bd9Sstevel@tonic-gate const struct addrinfo *pai); 1717c478bd9Sstevel@tonic-gate static int add_hostent(struct pvt *pvt, char *bp, char **hap, 1727c478bd9Sstevel@tonic-gate struct addrinfo *ai); 1737c478bd9Sstevel@tonic-gate static int init(struct irs_ho *this); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* Exports. */ 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate struct irs_ho * 1787c478bd9Sstevel@tonic-gate irs_dns_ho(struct irs_acc *this) { 1797c478bd9Sstevel@tonic-gate struct irs_ho *ho; 1807c478bd9Sstevel@tonic-gate struct pvt *pvt; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate UNUSED(this); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate if (!(pvt = memget(sizeof *pvt))) { 1857c478bd9Sstevel@tonic-gate errno = ENOMEM; 1867c478bd9Sstevel@tonic-gate return (NULL); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate memset(pvt, 0, sizeof *pvt); 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate if (!(ho = memget(sizeof *ho))) { 1917c478bd9Sstevel@tonic-gate memput(pvt, sizeof *pvt); 1927c478bd9Sstevel@tonic-gate errno = ENOMEM; 1937c478bd9Sstevel@tonic-gate return (NULL); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate memset(ho, 0x5e, sizeof *ho); 1967c478bd9Sstevel@tonic-gate ho->private = pvt; 1977c478bd9Sstevel@tonic-gate ho->close = ho_close; 1987c478bd9Sstevel@tonic-gate ho->byname = ho_byname; 1997c478bd9Sstevel@tonic-gate ho->byname2 = ho_byname2; 2007c478bd9Sstevel@tonic-gate ho->byaddr = ho_byaddr; 2017c478bd9Sstevel@tonic-gate ho->next = ho_next; 2027c478bd9Sstevel@tonic-gate ho->rewind = ho_rewind; 2037c478bd9Sstevel@tonic-gate ho->minimize = ho_minimize; 2047c478bd9Sstevel@tonic-gate ho->res_get = ho_res_get; 2057c478bd9Sstevel@tonic-gate ho->res_set = ho_res_set; 2067c478bd9Sstevel@tonic-gate ho->addrinfo = ho_addrinfo; 2077c478bd9Sstevel@tonic-gate return (ho); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* Methods. */ 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate static void 2137c478bd9Sstevel@tonic-gate ho_close(struct irs_ho *this) { 2147c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate ho_minimize(this); 2177c478bd9Sstevel@tonic-gate if (pvt->res && pvt->free_res) 2187c478bd9Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 2197c478bd9Sstevel@tonic-gate memput(pvt, sizeof *pvt); 2207c478bd9Sstevel@tonic-gate memput(this, sizeof *this); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate static struct hostent * 2247c478bd9Sstevel@tonic-gate ho_byname(struct irs_ho *this, const char *name) { 2257c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2267c478bd9Sstevel@tonic-gate struct hostent *hp; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (init(this) == -1) 2297c478bd9Sstevel@tonic-gate return (NULL); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) { 2327c478bd9Sstevel@tonic-gate hp = ho_byname2(this, name, AF_INET6); 2337c478bd9Sstevel@tonic-gate if (hp) 2347c478bd9Sstevel@tonic-gate return (hp); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate return (ho_byname2(this, name, AF_INET)); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate static struct hostent * 2407c478bd9Sstevel@tonic-gate ho_byname2(struct irs_ho *this, const char *name, int af) 2417c478bd9Sstevel@tonic-gate { 2427c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2437c478bd9Sstevel@tonic-gate struct hostent *hp = NULL; 2447c478bd9Sstevel@tonic-gate int n, size; 2457c478bd9Sstevel@tonic-gate char tmp[NS_MAXDNAME]; 2467c478bd9Sstevel@tonic-gate const char *cp; 2477c478bd9Sstevel@tonic-gate struct addrinfo ai; 2487c478bd9Sstevel@tonic-gate struct dns_res_target *q, *p; 2497c478bd9Sstevel@tonic-gate int querystate = RESQRY_FAIL; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if (init(this) == -1) 2527c478bd9Sstevel@tonic-gate return (NULL); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate q = memget(sizeof(*q)); 2557c478bd9Sstevel@tonic-gate if (q == NULL) { 2567c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2577c478bd9Sstevel@tonic-gate errno = ENOMEM; 2587c478bd9Sstevel@tonic-gate goto cleanup; 2597c478bd9Sstevel@tonic-gate } 260*9525b14bSRao Shoaib memset(q, 0, sizeof(*q)); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate switch (af) { 2637c478bd9Sstevel@tonic-gate case AF_INET: 2647c478bd9Sstevel@tonic-gate size = INADDRSZ; 2657c478bd9Sstevel@tonic-gate q->qclass = C_IN; 2667c478bd9Sstevel@tonic-gate q->qtype = T_A; 2677c478bd9Sstevel@tonic-gate q->answer = q->qbuf.buf; 2687c478bd9Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 2697c478bd9Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 2707c478bd9Sstevel@tonic-gate break; 2717c478bd9Sstevel@tonic-gate case AF_INET6: 2727c478bd9Sstevel@tonic-gate size = IN6ADDRSZ; 2737c478bd9Sstevel@tonic-gate q->qclass = C_IN; 2747c478bd9Sstevel@tonic-gate q->qtype = T_AAAA; 2757c478bd9Sstevel@tonic-gate q->answer = q->qbuf.buf; 2767c478bd9Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 2777c478bd9Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 2787c478bd9Sstevel@tonic-gate break; 2797c478bd9Sstevel@tonic-gate default: 2807c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2817c478bd9Sstevel@tonic-gate errno = EAFNOSUPPORT; 2827c478bd9Sstevel@tonic-gate hp = NULL; 2837c478bd9Sstevel@tonic-gate goto cleanup; 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * if there aren't any dots, it could be a user-level alias. 2887c478bd9Sstevel@tonic-gate * this is also done in res_nquery() since we are not the only 2897c478bd9Sstevel@tonic-gate * function that looks up host names. 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, 2927c478bd9Sstevel@tonic-gate tmp, sizeof tmp))) 2937c478bd9Sstevel@tonic-gate name = cp; 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate for (p = q; p; p = p->next) { 2967c478bd9Sstevel@tonic-gate switch(p->action) { 2977c478bd9Sstevel@tonic-gate case RESTGT_DOALWAYS: 2987c478bd9Sstevel@tonic-gate break; 2997c478bd9Sstevel@tonic-gate case RESTGT_AFTERFAILURE: 3007c478bd9Sstevel@tonic-gate if (querystate == RESQRY_SUCCESS) 3017c478bd9Sstevel@tonic-gate continue; 3027c478bd9Sstevel@tonic-gate break; 3037c478bd9Sstevel@tonic-gate case RESTGT_IGNORE: 3047c478bd9Sstevel@tonic-gate continue; 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, 3087c478bd9Sstevel@tonic-gate p->answer, p->anslen)) < 0) { 3097c478bd9Sstevel@tonic-gate querystate = RESQRY_FAIL; 3107c478bd9Sstevel@tonic-gate continue; 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate memset(&ai, 0, sizeof(ai)); 3147c478bd9Sstevel@tonic-gate ai.ai_family = af; 3157c478bd9Sstevel@tonic-gate if ((hp = gethostans(this, p->answer, n, name, p->qtype, 3167c478bd9Sstevel@tonic-gate af, size, NULL, 3177c478bd9Sstevel@tonic-gate (const struct addrinfo *)&ai)) != NULL) 318*9525b14bSRao Shoaib goto cleanup; /*%< no more loop is necessary */ 3197c478bd9Sstevel@tonic-gate querystate = RESQRY_FAIL; 3207c478bd9Sstevel@tonic-gate continue; 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate cleanup: 3247c478bd9Sstevel@tonic-gate if (q != NULL) 3257c478bd9Sstevel@tonic-gate memput(q, sizeof(*q)); 3267c478bd9Sstevel@tonic-gate return(hp); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate static struct hostent * 3307c478bd9Sstevel@tonic-gate ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) 3317c478bd9Sstevel@tonic-gate { 3327c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 3337c478bd9Sstevel@tonic-gate const u_char *uaddr = addr; 3347c478bd9Sstevel@tonic-gate char *qp; 3357c478bd9Sstevel@tonic-gate struct hostent *hp = NULL; 3367c478bd9Sstevel@tonic-gate struct addrinfo ai; 3377c478bd9Sstevel@tonic-gate struct dns_res_target *q, *q2, *p; 3387c478bd9Sstevel@tonic-gate int n, size, i; 3397c478bd9Sstevel@tonic-gate int querystate = RESQRY_FAIL; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate if (init(this) == -1) 3427c478bd9Sstevel@tonic-gate return (NULL); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate q = memget(sizeof(*q)); 3457c478bd9Sstevel@tonic-gate q2 = memget(sizeof(*q2)); 3467c478bd9Sstevel@tonic-gate if (q == NULL || q2 == NULL) { 3477c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 3487c478bd9Sstevel@tonic-gate errno = ENOMEM; 3497c478bd9Sstevel@tonic-gate goto cleanup; 3507c478bd9Sstevel@tonic-gate } 351*9525b14bSRao Shoaib memset(q, 0, sizeof(*q)); 352*9525b14bSRao Shoaib memset(q2, 0, sizeof(*q2)); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate if (af == AF_INET6 && len == IN6ADDRSZ && 3557c478bd9Sstevel@tonic-gate (!memcmp(uaddr, mapped, sizeof mapped) || 3567c478bd9Sstevel@tonic-gate (!memcmp(uaddr, tunnelled, sizeof tunnelled) && 3577c478bd9Sstevel@tonic-gate memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) { 3587c478bd9Sstevel@tonic-gate /* Unmap. */ 3597c478bd9Sstevel@tonic-gate addr = (const char *)addr + sizeof mapped; 3607c478bd9Sstevel@tonic-gate uaddr += sizeof mapped; 3617c478bd9Sstevel@tonic-gate af = AF_INET; 3627c478bd9Sstevel@tonic-gate len = INADDRSZ; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate switch (af) { 3657c478bd9Sstevel@tonic-gate case AF_INET: 3667c478bd9Sstevel@tonic-gate size = INADDRSZ; 3677c478bd9Sstevel@tonic-gate q->qclass = C_IN; 3687c478bd9Sstevel@tonic-gate q->qtype = T_PTR; 3697c478bd9Sstevel@tonic-gate q->answer = q->qbuf.buf; 3707c478bd9Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 3717c478bd9Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 3727c478bd9Sstevel@tonic-gate break; 3737c478bd9Sstevel@tonic-gate case AF_INET6: 3747c478bd9Sstevel@tonic-gate size = IN6ADDRSZ; 3757c478bd9Sstevel@tonic-gate q->qclass = C_IN; 3767c478bd9Sstevel@tonic-gate q->qtype = T_PTR; 3777c478bd9Sstevel@tonic-gate q->answer = q->qbuf.buf; 3787c478bd9Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 3797c478bd9Sstevel@tonic-gate q->next = q2; 3807c478bd9Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 3817c478bd9Sstevel@tonic-gate q2->qclass = C_IN; 3827c478bd9Sstevel@tonic-gate q2->qtype = T_PTR; 3837c478bd9Sstevel@tonic-gate q2->answer = q2->qbuf.buf; 3847c478bd9Sstevel@tonic-gate q2->anslen = sizeof(q2->qbuf); 385*9525b14bSRao Shoaib if ((pvt->res->options & RES_NO_NIBBLE2) != 0U) 3867c478bd9Sstevel@tonic-gate q2->action = RESTGT_IGNORE; 3877c478bd9Sstevel@tonic-gate else 3887c478bd9Sstevel@tonic-gate q2->action = RESTGT_AFTERFAILURE; 3897c478bd9Sstevel@tonic-gate break; 3907c478bd9Sstevel@tonic-gate default: 3917c478bd9Sstevel@tonic-gate errno = EAFNOSUPPORT; 3927c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 3937c478bd9Sstevel@tonic-gate hp = NULL; 3947c478bd9Sstevel@tonic-gate goto cleanup; 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate if (size > len) { 3977c478bd9Sstevel@tonic-gate errno = EINVAL; 3987c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 3997c478bd9Sstevel@tonic-gate hp = NULL; 4007c478bd9Sstevel@tonic-gate goto cleanup; 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate switch (af) { 4037c478bd9Sstevel@tonic-gate case AF_INET: 4047c478bd9Sstevel@tonic-gate qp = q->qname; 4057c478bd9Sstevel@tonic-gate (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa", 4067c478bd9Sstevel@tonic-gate (uaddr[3] & 0xff), 4077c478bd9Sstevel@tonic-gate (uaddr[2] & 0xff), 4087c478bd9Sstevel@tonic-gate (uaddr[1] & 0xff), 4097c478bd9Sstevel@tonic-gate (uaddr[0] & 0xff)); 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate case AF_INET6: 4127c478bd9Sstevel@tonic-gate if (q->action != RESTGT_IGNORE) { 413*9525b14bSRao Shoaib const char *nibsuff = res_get_nibblesuffix(pvt->res); 4147c478bd9Sstevel@tonic-gate qp = q->qname; 4157c478bd9Sstevel@tonic-gate for (n = IN6ADDRSZ - 1; n >= 0; n--) { 4167c478bd9Sstevel@tonic-gate i = SPRINTF((qp, "%x.%x.", 4177c478bd9Sstevel@tonic-gate uaddr[n] & 0xf, 4187c478bd9Sstevel@tonic-gate (uaddr[n] >> 4) & 0xf)); 419*9525b14bSRao Shoaib if (i != 4) 4207c478bd9Sstevel@tonic-gate abort(); 4217c478bd9Sstevel@tonic-gate qp += i; 4227c478bd9Sstevel@tonic-gate } 423*9525b14bSRao Shoaib if (strlen(q->qname) + strlen(nibsuff) + 1 > 424*9525b14bSRao Shoaib sizeof q->qname) { 425*9525b14bSRao Shoaib errno = ENAMETOOLONG; 426*9525b14bSRao Shoaib RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 427*9525b14bSRao Shoaib hp = NULL; 428*9525b14bSRao Shoaib goto cleanup; 429*9525b14bSRao Shoaib } 430*9525b14bSRao Shoaib strcpy(qp, nibsuff); /* (checked) */ 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate if (q2->action != RESTGT_IGNORE) { 433*9525b14bSRao Shoaib const char *nibsuff2 = res_get_nibblesuffix2(pvt->res); 4347c478bd9Sstevel@tonic-gate qp = q2->qname; 4357c478bd9Sstevel@tonic-gate for (n = IN6ADDRSZ - 1; n >= 0; n--) { 4367c478bd9Sstevel@tonic-gate i = SPRINTF((qp, "%x.%x.", 4377c478bd9Sstevel@tonic-gate uaddr[n] & 0xf, 4387c478bd9Sstevel@tonic-gate (uaddr[n] >> 4) & 0xf)); 439*9525b14bSRao Shoaib if (i != 4) 4407c478bd9Sstevel@tonic-gate abort(); 4417c478bd9Sstevel@tonic-gate qp += i; 4427c478bd9Sstevel@tonic-gate } 443*9525b14bSRao Shoaib if (strlen(q2->qname) + strlen(nibsuff2) + 1 > 444*9525b14bSRao Shoaib sizeof q2->qname) { 445*9525b14bSRao Shoaib errno = ENAMETOOLONG; 446*9525b14bSRao Shoaib RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 447*9525b14bSRao Shoaib hp = NULL; 448*9525b14bSRao Shoaib goto cleanup; 449*9525b14bSRao Shoaib } 450*9525b14bSRao Shoaib strcpy(qp, nibsuff2); /* (checked) */ 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate break; 4537c478bd9Sstevel@tonic-gate default: 4547c478bd9Sstevel@tonic-gate abort(); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate for (p = q; p; p = p->next) { 4587c478bd9Sstevel@tonic-gate switch(p->action) { 4597c478bd9Sstevel@tonic-gate case RESTGT_DOALWAYS: 4607c478bd9Sstevel@tonic-gate break; 4617c478bd9Sstevel@tonic-gate case RESTGT_AFTERFAILURE: 4627c478bd9Sstevel@tonic-gate if (querystate == RESQRY_SUCCESS) 4637c478bd9Sstevel@tonic-gate continue; 4647c478bd9Sstevel@tonic-gate break; 4657c478bd9Sstevel@tonic-gate case RESTGT_IGNORE: 4667c478bd9Sstevel@tonic-gate continue; 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate if ((n = res_nquery(pvt->res, p->qname, p->qclass, p->qtype, 4707c478bd9Sstevel@tonic-gate p->answer, p->anslen)) < 0) { 4717c478bd9Sstevel@tonic-gate querystate = RESQRY_FAIL; 4727c478bd9Sstevel@tonic-gate continue; 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate memset(&ai, 0, sizeof(ai)); 4767c478bd9Sstevel@tonic-gate ai.ai_family = af; 4777c478bd9Sstevel@tonic-gate hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size, 4787c478bd9Sstevel@tonic-gate NULL, (const struct addrinfo *)&ai); 4797c478bd9Sstevel@tonic-gate if (!hp) { 4807c478bd9Sstevel@tonic-gate querystate = RESQRY_FAIL; 4817c478bd9Sstevel@tonic-gate continue; 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate memcpy(pvt->host_addr, addr, len); 4857c478bd9Sstevel@tonic-gate pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; 4867c478bd9Sstevel@tonic-gate pvt->h_addr_ptrs[1] = NULL; 4877c478bd9Sstevel@tonic-gate if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { 4887c478bd9Sstevel@tonic-gate map_v4v6_address((char*)pvt->host_addr, 4897c478bd9Sstevel@tonic-gate (char*)pvt->host_addr); 4907c478bd9Sstevel@tonic-gate pvt->host.h_addrtype = AF_INET6; 4917c478bd9Sstevel@tonic-gate pvt->host.h_length = IN6ADDRSZ; 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 495*9525b14bSRao Shoaib goto cleanup; /*%< no more loop is necessary. */ 4967c478bd9Sstevel@tonic-gate } 497*9525b14bSRao Shoaib hp = NULL; /*%< H_ERRNO was set by subroutines */ 4987c478bd9Sstevel@tonic-gate cleanup: 4997c478bd9Sstevel@tonic-gate if (q != NULL) 5007c478bd9Sstevel@tonic-gate memput(q, sizeof(*q)); 5017c478bd9Sstevel@tonic-gate if (q2 != NULL) 5027c478bd9Sstevel@tonic-gate memput(q2, sizeof(*q2)); 5037c478bd9Sstevel@tonic-gate return(hp); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate static struct hostent * 5077c478bd9Sstevel@tonic-gate ho_next(struct irs_ho *this) { 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate UNUSED(this); 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate return (NULL); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate static void 5157c478bd9Sstevel@tonic-gate ho_rewind(struct irs_ho *this) { 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate UNUSED(this); 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* NOOP */ 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate static void 5237c478bd9Sstevel@tonic-gate ho_minimize(struct irs_ho *this) { 5247c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate if (pvt->res) 5277c478bd9Sstevel@tonic-gate res_nclose(pvt->res); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate static struct __res_state * 5317c478bd9Sstevel@tonic-gate ho_res_get(struct irs_ho *this) { 5327c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate if (!pvt->res) { 5357c478bd9Sstevel@tonic-gate struct __res_state *res; 5367c478bd9Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 5377c478bd9Sstevel@tonic-gate if (!res) { 5387c478bd9Sstevel@tonic-gate errno = ENOMEM; 5397c478bd9Sstevel@tonic-gate return (NULL); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate memset(res, 0, sizeof *res); 5427c478bd9Sstevel@tonic-gate ho_res_set(this, res, free); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate return (pvt->res); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* XXX */ 5497c478bd9Sstevel@tonic-gate extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *, 5507c478bd9Sstevel@tonic-gate const char *)); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate static struct addrinfo * 5537c478bd9Sstevel@tonic-gate ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) 5547c478bd9Sstevel@tonic-gate { 5557c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5567c478bd9Sstevel@tonic-gate int n; 5577c478bd9Sstevel@tonic-gate char tmp[NS_MAXDNAME]; 5587c478bd9Sstevel@tonic-gate const char *cp; 5597c478bd9Sstevel@tonic-gate struct dns_res_target *q, *q2, *p; 5607c478bd9Sstevel@tonic-gate struct addrinfo sentinel, *cur; 5617c478bd9Sstevel@tonic-gate int querystate = RESQRY_FAIL; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if (init(this) == -1) 5647c478bd9Sstevel@tonic-gate return (NULL); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel)); 5677c478bd9Sstevel@tonic-gate cur = &sentinel; 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate q = memget(sizeof(*q)); 5707c478bd9Sstevel@tonic-gate q2 = memget(sizeof(*q2)); 5717c478bd9Sstevel@tonic-gate if (q == NULL || q2 == NULL) { 5727c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 5737c478bd9Sstevel@tonic-gate errno = ENOMEM; 5747c478bd9Sstevel@tonic-gate goto cleanup; 5757c478bd9Sstevel@tonic-gate } 576*9525b14bSRao Shoaib memset(q, 0, sizeof(*q2)); 577*9525b14bSRao Shoaib memset(q2, 0, sizeof(*q2)); 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate switch (pai->ai_family) { 5807c478bd9Sstevel@tonic-gate case AF_UNSPEC: 5817c478bd9Sstevel@tonic-gate /* prefer IPv6 */ 5827c478bd9Sstevel@tonic-gate q->qclass = C_IN; 5837c478bd9Sstevel@tonic-gate q->qtype = T_AAAA; 5847c478bd9Sstevel@tonic-gate q->answer = q->qbuf.buf; 5857c478bd9Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 5867c478bd9Sstevel@tonic-gate q->next = q2; 5877c478bd9Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 5887c478bd9Sstevel@tonic-gate q2->qclass = C_IN; 5897c478bd9Sstevel@tonic-gate q2->qtype = T_A; 5907c478bd9Sstevel@tonic-gate q2->answer = q2->qbuf.buf; 5917c478bd9Sstevel@tonic-gate q2->anslen = sizeof(q2->qbuf); 5927c478bd9Sstevel@tonic-gate q2->action = RESTGT_DOALWAYS; 5937c478bd9Sstevel@tonic-gate break; 5947c478bd9Sstevel@tonic-gate case AF_INET: 5957c478bd9Sstevel@tonic-gate q->qclass = C_IN; 5967c478bd9Sstevel@tonic-gate q->qtype = T_A; 5977c478bd9Sstevel@tonic-gate q->answer = q->qbuf.buf; 5987c478bd9Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 5997c478bd9Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 6007c478bd9Sstevel@tonic-gate break; 6017c478bd9Sstevel@tonic-gate case AF_INET6: 6027c478bd9Sstevel@tonic-gate q->qclass = C_IN; 6037c478bd9Sstevel@tonic-gate q->qtype = T_AAAA; 6047c478bd9Sstevel@tonic-gate q->answer = q->qbuf.buf; 6057c478bd9Sstevel@tonic-gate q->anslen = sizeof(q->qbuf); 6067c478bd9Sstevel@tonic-gate q->action = RESTGT_DOALWAYS; 6077c478bd9Sstevel@tonic-gate break; 6087c478bd9Sstevel@tonic-gate default: 609*9525b14bSRao Shoaib RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /*%< better error? */ 6107c478bd9Sstevel@tonic-gate goto cleanup; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * if there aren't any dots, it could be a user-level alias. 6157c478bd9Sstevel@tonic-gate * this is also done in res_nquery() since we are not the only 6167c478bd9Sstevel@tonic-gate * function that looks up host names. 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, 6197c478bd9Sstevel@tonic-gate tmp, sizeof tmp))) 6207c478bd9Sstevel@tonic-gate name = cp; 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate for (p = q; p; p = p->next) { 6237c478bd9Sstevel@tonic-gate struct addrinfo *ai; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate switch(p->action) { 6267c478bd9Sstevel@tonic-gate case RESTGT_DOALWAYS: 6277c478bd9Sstevel@tonic-gate break; 6287c478bd9Sstevel@tonic-gate case RESTGT_AFTERFAILURE: 6297c478bd9Sstevel@tonic-gate if (querystate == RESQRY_SUCCESS) 6307c478bd9Sstevel@tonic-gate continue; 6317c478bd9Sstevel@tonic-gate break; 6327c478bd9Sstevel@tonic-gate case RESTGT_IGNORE: 6337c478bd9Sstevel@tonic-gate continue; 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, 6377c478bd9Sstevel@tonic-gate p->answer, p->anslen)) < 0) { 6387c478bd9Sstevel@tonic-gate querystate = RESQRY_FAIL; 6397c478bd9Sstevel@tonic-gate continue; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate (void)gethostans(this, p->answer, n, name, p->qtype, 642*9525b14bSRao Shoaib pai->ai_family, /*%< XXX: meaningless */ 6437c478bd9Sstevel@tonic-gate 0, &ai, pai); 6447c478bd9Sstevel@tonic-gate if (ai) { 6457c478bd9Sstevel@tonic-gate querystate = RESQRY_SUCCESS; 6467c478bd9Sstevel@tonic-gate cur->ai_next = ai; 647*9525b14bSRao Shoaib while (cur->ai_next) 6487c478bd9Sstevel@tonic-gate cur = cur->ai_next; 649*9525b14bSRao Shoaib } else 6507c478bd9Sstevel@tonic-gate querystate = RESQRY_FAIL; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate cleanup: 6547c478bd9Sstevel@tonic-gate if (q != NULL) 6557c478bd9Sstevel@tonic-gate memput(q, sizeof(*q)); 6567c478bd9Sstevel@tonic-gate if (q2 != NULL) 6577c478bd9Sstevel@tonic-gate memput(q2, sizeof(*q2)); 6587c478bd9Sstevel@tonic-gate return(sentinel.ai_next); 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate static void 6627c478bd9Sstevel@tonic-gate ho_res_set(struct irs_ho *this, struct __res_state *res, 6637c478bd9Sstevel@tonic-gate void (*free_res)(void *)) { 6647c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (pvt->res && pvt->free_res) { 6677c478bd9Sstevel@tonic-gate res_nclose(pvt->res); 6687c478bd9Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate pvt->res = res; 6727c478bd9Sstevel@tonic-gate pvt->free_res = free_res; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* Private. */ 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate static struct hostent * 6787c478bd9Sstevel@tonic-gate gethostans(struct irs_ho *this, 6797c478bd9Sstevel@tonic-gate const u_char *ansbuf, int anslen, const char *qname, int qtype, 680*9525b14bSRao Shoaib int af, int size, /*!< meaningless for addrinfo cases */ 6817c478bd9Sstevel@tonic-gate struct addrinfo **ret_aip, const struct addrinfo *pai) 6827c478bd9Sstevel@tonic-gate { 6837c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 6847c478bd9Sstevel@tonic-gate int type, class, ancount, qdcount, n, haveanswer, had_error; 685*9525b14bSRao Shoaib int error = NETDB_SUCCESS; 6867c478bd9Sstevel@tonic-gate int (*name_ok)(const char *); 6877c478bd9Sstevel@tonic-gate const HEADER *hp; 6887c478bd9Sstevel@tonic-gate const u_char *eom; 6897c478bd9Sstevel@tonic-gate const u_char *eor; 6907c478bd9Sstevel@tonic-gate const u_char *cp; 6917c478bd9Sstevel@tonic-gate const char *tname; 6927c478bd9Sstevel@tonic-gate const char *hname; 6937c478bd9Sstevel@tonic-gate char *bp, *ep, **ap, **hap; 6947c478bd9Sstevel@tonic-gate char tbuf[MAXDNAME+1]; 6957c478bd9Sstevel@tonic-gate struct addrinfo sentinel, *cur, ai; 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate if (pai == NULL) abort(); 6987c478bd9Sstevel@tonic-gate if (ret_aip != NULL) 6997c478bd9Sstevel@tonic-gate *ret_aip = NULL; 7007c478bd9Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel)); 7017c478bd9Sstevel@tonic-gate cur = &sentinel; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate tname = qname; 7047c478bd9Sstevel@tonic-gate eom = ansbuf + anslen; 7057c478bd9Sstevel@tonic-gate switch (qtype) { 7067c478bd9Sstevel@tonic-gate case T_A: 7077c478bd9Sstevel@tonic-gate case T_AAAA: 708*9525b14bSRao Shoaib case T_ANY: /*%< use T_ANY only for T_A/T_AAAA lookup */ 7097c478bd9Sstevel@tonic-gate name_ok = res_hnok; 7107c478bd9Sstevel@tonic-gate break; 7117c478bd9Sstevel@tonic-gate case T_PTR: 7127c478bd9Sstevel@tonic-gate name_ok = res_dnok; 7137c478bd9Sstevel@tonic-gate break; 7147c478bd9Sstevel@tonic-gate default: 7157c478bd9Sstevel@tonic-gate abort(); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate pvt->host.h_addrtype = af; 7197c478bd9Sstevel@tonic-gate pvt->host.h_length = size; 7207c478bd9Sstevel@tonic-gate hname = pvt->host.h_name = NULL; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * Find first satisfactory answer. 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate if (ansbuf + HFIXEDSZ > eom) { 7267c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7277c478bd9Sstevel@tonic-gate return (NULL); 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate hp = (const HEADER *)ansbuf; 7307c478bd9Sstevel@tonic-gate ancount = ntohs(hp->ancount); 7317c478bd9Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 7327c478bd9Sstevel@tonic-gate bp = pvt->hostbuf; 7337c478bd9Sstevel@tonic-gate ep = pvt->hostbuf + sizeof(pvt->hostbuf); 7347c478bd9Sstevel@tonic-gate cp = ansbuf + HFIXEDSZ; 7357c478bd9Sstevel@tonic-gate if (qdcount != 1) { 7367c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7377c478bd9Sstevel@tonic-gate return (NULL); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate n = dn_expand(ansbuf, eom, cp, bp, ep - bp); 7407c478bd9Sstevel@tonic-gate if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { 7417c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7427c478bd9Sstevel@tonic-gate return (NULL); 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate cp += n + QFIXEDSZ; 7457c478bd9Sstevel@tonic-gate if (cp > eom) { 7467c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7477c478bd9Sstevel@tonic-gate return (NULL); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 7507c478bd9Sstevel@tonic-gate /* res_nsend() has already verified that the query name is the 7517c478bd9Sstevel@tonic-gate * same as the one we sent; this just gets the expanded name 7527c478bd9Sstevel@tonic-gate * (i.e., with the succeeding search-domain tacked on). 7537c478bd9Sstevel@tonic-gate */ 754*9525b14bSRao Shoaib n = strlen(bp) + 1; /*%< for the \\0 */ 7557c478bd9Sstevel@tonic-gate if (n > MAXHOSTNAMELEN) { 7567c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 7577c478bd9Sstevel@tonic-gate return (NULL); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate pvt->host.h_name = bp; 7607c478bd9Sstevel@tonic-gate hname = bp; 7617c478bd9Sstevel@tonic-gate bp += n; 7627c478bd9Sstevel@tonic-gate /* The qname can be abbreviated, but hname is now absolute. */ 7637c478bd9Sstevel@tonic-gate qname = pvt->host.h_name; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate ap = pvt->host_aliases; 7667c478bd9Sstevel@tonic-gate *ap = NULL; 7677c478bd9Sstevel@tonic-gate pvt->host.h_aliases = pvt->host_aliases; 7687c478bd9Sstevel@tonic-gate hap = pvt->h_addr_ptrs; 7697c478bd9Sstevel@tonic-gate *hap = NULL; 7707c478bd9Sstevel@tonic-gate pvt->host.h_addr_list = pvt->h_addr_ptrs; 7717c478bd9Sstevel@tonic-gate haveanswer = 0; 7727c478bd9Sstevel@tonic-gate had_error = 0; 7737c478bd9Sstevel@tonic-gate while (ancount-- > 0 && cp < eom && !had_error) { 7747c478bd9Sstevel@tonic-gate n = dn_expand(ansbuf, eom, cp, bp, ep - bp); 7757c478bd9Sstevel@tonic-gate if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { 7767c478bd9Sstevel@tonic-gate had_error++; 7777c478bd9Sstevel@tonic-gate continue; 7787c478bd9Sstevel@tonic-gate } 779*9525b14bSRao Shoaib cp += n; /*%< name */ 7807c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 7817c478bd9Sstevel@tonic-gate type = ns_get16(cp); 782*9525b14bSRao Shoaib cp += INT16SZ; /*%< type */ 7837c478bd9Sstevel@tonic-gate class = ns_get16(cp); 784*9525b14bSRao Shoaib cp += INT16SZ + INT32SZ; /*%< class, TTL */ 7857c478bd9Sstevel@tonic-gate n = ns_get16(cp); 786*9525b14bSRao Shoaib cp += INT16SZ; /*%< len */ 7877c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, n); 7887c478bd9Sstevel@tonic-gate if (class != C_IN) { 7897c478bd9Sstevel@tonic-gate cp += n; 7907c478bd9Sstevel@tonic-gate continue; 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate eor = cp + n; 7937c478bd9Sstevel@tonic-gate if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 7947c478bd9Sstevel@tonic-gate type == T_CNAME) { 7957c478bd9Sstevel@tonic-gate if (haveanswer) { 7967c478bd9Sstevel@tonic-gate int level = LOG_CRIT; 7977c478bd9Sstevel@tonic-gate #ifdef LOG_SECURITY 7987c478bd9Sstevel@tonic-gate level |= LOG_SECURITY; 7997c478bd9Sstevel@tonic-gate #endif 8007c478bd9Sstevel@tonic-gate syslog(level, 8017c478bd9Sstevel@tonic-gate "gethostans: possible attempt to exploit buffer overflow while looking up %s", 8027c478bd9Sstevel@tonic-gate *qname ? qname : "."); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); 8057c478bd9Sstevel@tonic-gate if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { 8067c478bd9Sstevel@tonic-gate had_error++; 8077c478bd9Sstevel@tonic-gate continue; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate cp += n; 8107c478bd9Sstevel@tonic-gate /* Store alias. */ 8117c478bd9Sstevel@tonic-gate if (ap >= &pvt->host_aliases[MAXALIASES-1]) 8127c478bd9Sstevel@tonic-gate continue; 8137c478bd9Sstevel@tonic-gate *ap++ = bp; 814*9525b14bSRao Shoaib n = strlen(bp) + 1; /*%< for the \\0 */ 8157c478bd9Sstevel@tonic-gate bp += n; 8167c478bd9Sstevel@tonic-gate /* Get canonical name. */ 817*9525b14bSRao Shoaib n = strlen(tbuf) + 1; /*%< for the \\0 */ 8187c478bd9Sstevel@tonic-gate if (n > (ep - bp) || n > MAXHOSTNAMELEN) { 8197c478bd9Sstevel@tonic-gate had_error++; 8207c478bd9Sstevel@tonic-gate continue; 8217c478bd9Sstevel@tonic-gate } 822*9525b14bSRao Shoaib strcpy(bp, tbuf); /* (checked) */ 8237c478bd9Sstevel@tonic-gate pvt->host.h_name = bp; 8247c478bd9Sstevel@tonic-gate hname = bp; 8257c478bd9Sstevel@tonic-gate bp += n; 8267c478bd9Sstevel@tonic-gate continue; 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate if (qtype == T_PTR && type == T_CNAME) { 8297c478bd9Sstevel@tonic-gate n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); 8307c478bd9Sstevel@tonic-gate if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { 8317c478bd9Sstevel@tonic-gate had_error++; 8327c478bd9Sstevel@tonic-gate continue; 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate cp += n; 8357c478bd9Sstevel@tonic-gate #ifdef RES_USE_DNAME 836*9525b14bSRao Shoaib if ((pvt->res->options & RES_USE_DNAME) != 0U) 8377c478bd9Sstevel@tonic-gate #endif 8387c478bd9Sstevel@tonic-gate { 8397c478bd9Sstevel@tonic-gate /* 8407c478bd9Sstevel@tonic-gate * We may be able to check this regardless 8417c478bd9Sstevel@tonic-gate * of the USE_DNAME bit, but we add the check 8427c478bd9Sstevel@tonic-gate * for now since the DNAME support is 8437c478bd9Sstevel@tonic-gate * experimental. 8447c478bd9Sstevel@tonic-gate */ 8457c478bd9Sstevel@tonic-gate if (ns_samename(tname, bp) != 1) 8467c478bd9Sstevel@tonic-gate continue; 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate /* Get canonical name. */ 849*9525b14bSRao Shoaib n = strlen(tbuf) + 1; /*%< for the \\0 */ 8507c478bd9Sstevel@tonic-gate if (n > (ep - bp)) { 8517c478bd9Sstevel@tonic-gate had_error++; 8527c478bd9Sstevel@tonic-gate continue; 8537c478bd9Sstevel@tonic-gate } 854*9525b14bSRao Shoaib strcpy(bp, tbuf); /* (checked) */ 8557c478bd9Sstevel@tonic-gate tname = bp; 8567c478bd9Sstevel@tonic-gate bp += n; 8577c478bd9Sstevel@tonic-gate continue; 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate if (qtype == T_ANY) { 8607c478bd9Sstevel@tonic-gate if (!(type == T_A || type == T_AAAA)) { 8617c478bd9Sstevel@tonic-gate cp += n; 8627c478bd9Sstevel@tonic-gate continue; 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate } else if (type != qtype) { 8657c478bd9Sstevel@tonic-gate cp += n; 8667c478bd9Sstevel@tonic-gate continue; 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate switch (type) { 8697c478bd9Sstevel@tonic-gate case T_PTR: 8707c478bd9Sstevel@tonic-gate if (ret_aip != NULL) { 8717c478bd9Sstevel@tonic-gate /* addrinfo never needs T_PTR */ 8727c478bd9Sstevel@tonic-gate cp += n; 8737c478bd9Sstevel@tonic-gate continue; 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate if (ns_samename(tname, bp) != 1) { 8767c478bd9Sstevel@tonic-gate cp += n; 8777c478bd9Sstevel@tonic-gate continue; 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate n = dn_expand(ansbuf, eor, cp, bp, ep - bp); 8807c478bd9Sstevel@tonic-gate if (n < 0 || !maybe_hnok(pvt->res, bp) || 8817c478bd9Sstevel@tonic-gate n >= MAXHOSTNAMELEN) { 8827c478bd9Sstevel@tonic-gate had_error++; 8837c478bd9Sstevel@tonic-gate break; 8847c478bd9Sstevel@tonic-gate } 8857c478bd9Sstevel@tonic-gate cp += n; 8867c478bd9Sstevel@tonic-gate if (!haveanswer) { 8877c478bd9Sstevel@tonic-gate pvt->host.h_name = bp; 8887c478bd9Sstevel@tonic-gate hname = bp; 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate else if (ap < &pvt->host_aliases[MAXALIASES-1]) 8917c478bd9Sstevel@tonic-gate *ap++ = bp; 8927c478bd9Sstevel@tonic-gate else 8937c478bd9Sstevel@tonic-gate n = -1; 8947c478bd9Sstevel@tonic-gate if (n != -1) { 895*9525b14bSRao Shoaib n = strlen(bp) + 1; /*%< for the \\0 */ 8967c478bd9Sstevel@tonic-gate bp += n; 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate break; 8997c478bd9Sstevel@tonic-gate case T_A: 9007c478bd9Sstevel@tonic-gate case T_AAAA: 9017c478bd9Sstevel@tonic-gate if (ns_samename(hname, bp) != 1) { 9027c478bd9Sstevel@tonic-gate cp += n; 9037c478bd9Sstevel@tonic-gate continue; 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate if (type == T_A && n != INADDRSZ) { 9067c478bd9Sstevel@tonic-gate cp += n; 9077c478bd9Sstevel@tonic-gate continue; 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate if (type == T_AAAA && n != IN6ADDRSZ) { 9107c478bd9Sstevel@tonic-gate cp += n; 9117c478bd9Sstevel@tonic-gate continue; 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate /* make addrinfo. don't overwrite constant PAI */ 9157c478bd9Sstevel@tonic-gate ai = *pai; 9167c478bd9Sstevel@tonic-gate ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET; 9177c478bd9Sstevel@tonic-gate cur->ai_next = addr2addrinfo( 9187c478bd9Sstevel@tonic-gate (const struct addrinfo *)&ai, 9197c478bd9Sstevel@tonic-gate (const char *)cp); 9207c478bd9Sstevel@tonic-gate if (cur->ai_next == NULL) 9217c478bd9Sstevel@tonic-gate had_error++; 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate if (!haveanswer) { 9247c478bd9Sstevel@tonic-gate int nn; 9257c478bd9Sstevel@tonic-gate 926*9525b14bSRao Shoaib nn = strlen(bp) + 1; /*%< for the \\0 */ 9277c478bd9Sstevel@tonic-gate if (nn >= MAXHOSTNAMELEN) { 9287c478bd9Sstevel@tonic-gate cp += n; 9297c478bd9Sstevel@tonic-gate had_error++; 9307c478bd9Sstevel@tonic-gate continue; 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate pvt->host.h_name = bp; 9337c478bd9Sstevel@tonic-gate hname = bp; 9347c478bd9Sstevel@tonic-gate bp += nn; 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate /* Ensure alignment. */ 9377c478bd9Sstevel@tonic-gate bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & 9387c478bd9Sstevel@tonic-gate ~(sizeof(align) - 1)); 9397c478bd9Sstevel@tonic-gate /* Avoid overflows. */ 940*9525b14bSRao Shoaib if (bp + n > &pvt->hostbuf[sizeof(pvt->hostbuf) - 1]) { 9417c478bd9Sstevel@tonic-gate had_error++; 9427c478bd9Sstevel@tonic-gate continue; 9437c478bd9Sstevel@tonic-gate } 944*9525b14bSRao Shoaib if (ret_aip) { /*%< need addrinfo. keep it. */ 945*9525b14bSRao Shoaib while (cur->ai_next) 9467c478bd9Sstevel@tonic-gate cur = cur->ai_next; 947*9525b14bSRao Shoaib } else if (cur->ai_next) { /*%< need hostent */ 9487c478bd9Sstevel@tonic-gate struct addrinfo *aip = cur->ai_next; 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate for (aip = cur->ai_next; aip; 9517c478bd9Sstevel@tonic-gate aip = aip->ai_next) { 9527c478bd9Sstevel@tonic-gate int m; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate m = add_hostent(pvt, bp, hap, aip); 9557c478bd9Sstevel@tonic-gate if (m < 0) { 9567c478bd9Sstevel@tonic-gate had_error++; 9577c478bd9Sstevel@tonic-gate break; 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate if (m == 0) 9607c478bd9Sstevel@tonic-gate continue; 961b07ce584SStacey Marshall if (hap < &pvt->h_addr_ptrs[MAXADDRS]) 9627c478bd9Sstevel@tonic-gate hap++; 9637c478bd9Sstevel@tonic-gate *hap = NULL; 9647c478bd9Sstevel@tonic-gate bp += m; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate freeaddrinfo(cur->ai_next); 9687c478bd9Sstevel@tonic-gate cur->ai_next = NULL; 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate cp += n; 9717c478bd9Sstevel@tonic-gate break; 9727c478bd9Sstevel@tonic-gate default: 9737c478bd9Sstevel@tonic-gate abort(); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate if (!had_error) 9767c478bd9Sstevel@tonic-gate haveanswer++; 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate if (haveanswer) { 9797c478bd9Sstevel@tonic-gate if (ret_aip == NULL) { 9807c478bd9Sstevel@tonic-gate *ap = NULL; 9817c478bd9Sstevel@tonic-gate *hap = NULL; 9827c478bd9Sstevel@tonic-gate 983b07ce584SStacey Marshall if (pvt->res->nsort && hap != pvt->h_addr_ptrs && 984b07ce584SStacey Marshall qtype == T_A) 9857c478bd9Sstevel@tonic-gate addrsort(pvt->res, pvt->h_addr_ptrs, 986b07ce584SStacey Marshall hap - pvt->h_addr_ptrs); 9877c478bd9Sstevel@tonic-gate if (pvt->host.h_name == NULL) { 988*9525b14bSRao Shoaib n = strlen(qname) + 1; /*%< for the \\0 */ 9897c478bd9Sstevel@tonic-gate if (n > (ep - bp) || n >= MAXHOSTNAMELEN) 9907c478bd9Sstevel@tonic-gate goto no_recovery; 991*9525b14bSRao Shoaib strcpy(bp, qname); /* (checked) */ 9927c478bd9Sstevel@tonic-gate pvt->host.h_name = bp; 9937c478bd9Sstevel@tonic-gate bp += n; 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) 9967c478bd9Sstevel@tonic-gate map_v4v6_hostent(&pvt->host, &bp, ep); 9977c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 9987c478bd9Sstevel@tonic-gate return (&pvt->host); 9997c478bd9Sstevel@tonic-gate } else { 10007c478bd9Sstevel@tonic-gate if ((pai->ai_flags & AI_CANONNAME) != 0) { 10017c478bd9Sstevel@tonic-gate if (pvt->host.h_name == NULL) { 10027c478bd9Sstevel@tonic-gate sentinel.ai_next->ai_canonname = 10037c478bd9Sstevel@tonic-gate strdup(qname); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate else { 10067c478bd9Sstevel@tonic-gate sentinel.ai_next->ai_canonname = 10077c478bd9Sstevel@tonic-gate strdup(pvt->host.h_name); 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate *ret_aip = sentinel.ai_next; 10117c478bd9Sstevel@tonic-gate return(NULL); 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate no_recovery: 10157c478bd9Sstevel@tonic-gate if (sentinel.ai_next) { 10167c478bd9Sstevel@tonic-gate /* this should be impossible, but check it for safety */ 10177c478bd9Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next); 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate if (error == NETDB_SUCCESS) 10207c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 10217c478bd9Sstevel@tonic-gate else 10227c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, error); 10237c478bd9Sstevel@tonic-gate return(NULL); 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate static int 10277c478bd9Sstevel@tonic-gate add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) 10287c478bd9Sstevel@tonic-gate { 10297c478bd9Sstevel@tonic-gate int addrlen; 10307c478bd9Sstevel@tonic-gate char *addrp; 10317c478bd9Sstevel@tonic-gate const char **tap; 10327c478bd9Sstevel@tonic-gate char *obp = bp; 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate switch(ai->ai_addr->sa_family) { 10357c478bd9Sstevel@tonic-gate case AF_INET6: 10367c478bd9Sstevel@tonic-gate addrlen = IN6ADDRSZ; 10377c478bd9Sstevel@tonic-gate addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; 10387c478bd9Sstevel@tonic-gate break; 10397c478bd9Sstevel@tonic-gate case AF_INET: 10407c478bd9Sstevel@tonic-gate addrlen = INADDRSZ; 10417c478bd9Sstevel@tonic-gate addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr; 10427c478bd9Sstevel@tonic-gate break; 10437c478bd9Sstevel@tonic-gate default: 1044*9525b14bSRao Shoaib return(-1); /*%< abort? */ 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate /* Ensure alignment. */ 10487c478bd9Sstevel@tonic-gate bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & 10497c478bd9Sstevel@tonic-gate ~(sizeof(align) - 1)); 10507c478bd9Sstevel@tonic-gate /* Avoid overflows. */ 1051*9525b14bSRao Shoaib if (bp + addrlen > &pvt->hostbuf[sizeof(pvt->hostbuf) - 1]) 10527c478bd9Sstevel@tonic-gate return(-1); 1053b07ce584SStacey Marshall if (hap >= &pvt->h_addr_ptrs[MAXADDRS]) 1054*9525b14bSRao Shoaib return(0); /*%< fail, but not treat it as an error. */ 10557c478bd9Sstevel@tonic-gate /* Suppress duplicates. */ 10567c478bd9Sstevel@tonic-gate for (tap = (const char **)pvt->h_addr_ptrs; 10577c478bd9Sstevel@tonic-gate *tap != NULL; 10587c478bd9Sstevel@tonic-gate tap++) 10597c478bd9Sstevel@tonic-gate if (memcmp(*tap, addrp, addrlen) == 0) 10607c478bd9Sstevel@tonic-gate break; 10617c478bd9Sstevel@tonic-gate if (*tap != NULL) 10627c478bd9Sstevel@tonic-gate return (0); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate memcpy(*hap = bp, addrp, addrlen); 10657c478bd9Sstevel@tonic-gate return((bp + addrlen) - obp); 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate static void 10697c478bd9Sstevel@tonic-gate map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) { 10707c478bd9Sstevel@tonic-gate char **ap; 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) 10737c478bd9Sstevel@tonic-gate return; 10747c478bd9Sstevel@tonic-gate hp->h_addrtype = AF_INET6; 10757c478bd9Sstevel@tonic-gate hp->h_length = IN6ADDRSZ; 10767c478bd9Sstevel@tonic-gate for (ap = hp->h_addr_list; *ap; ap++) { 10777c478bd9Sstevel@tonic-gate int i = (u_long)*bpp % sizeof(align); 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate if (i != 0) 10807c478bd9Sstevel@tonic-gate i = sizeof(align) - i; 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate if ((ep - *bpp) < (i + IN6ADDRSZ)) { 10837c478bd9Sstevel@tonic-gate /* Out of memory. Truncate address list here. */ 10847c478bd9Sstevel@tonic-gate *ap = NULL; 10857c478bd9Sstevel@tonic-gate return; 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate *bpp += i; 10887c478bd9Sstevel@tonic-gate map_v4v6_address(*ap, *bpp); 10897c478bd9Sstevel@tonic-gate *ap = *bpp; 10907c478bd9Sstevel@tonic-gate *bpp += IN6ADDRSZ; 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate static void 10957c478bd9Sstevel@tonic-gate addrsort(res_state statp, char **ap, int num) { 10967c478bd9Sstevel@tonic-gate int i, j, needsort = 0, aval[MAXADDRS]; 10977c478bd9Sstevel@tonic-gate char **p; 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate p = ap; 11007c478bd9Sstevel@tonic-gate for (i = 0; i < num; i++, p++) { 11017c478bd9Sstevel@tonic-gate for (j = 0 ; (unsigned)j < statp->nsort; j++) 11027c478bd9Sstevel@tonic-gate if (statp->sort_list[j].addr.s_addr == 11037c478bd9Sstevel@tonic-gate (((struct in_addr *)(*p))->s_addr & 11047c478bd9Sstevel@tonic-gate statp->sort_list[j].mask)) 11057c478bd9Sstevel@tonic-gate break; 11067c478bd9Sstevel@tonic-gate aval[i] = j; 11077c478bd9Sstevel@tonic-gate if (needsort == 0 && i > 0 && j < aval[i-1]) 11087c478bd9Sstevel@tonic-gate needsort = i; 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate if (!needsort) 11117c478bd9Sstevel@tonic-gate return; 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate while (needsort < num) { 11147c478bd9Sstevel@tonic-gate for (j = needsort - 1; j >= 0; j--) { 11157c478bd9Sstevel@tonic-gate if (aval[j] > aval[j+1]) { 11167c478bd9Sstevel@tonic-gate char *hp; 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate i = aval[j]; 11197c478bd9Sstevel@tonic-gate aval[j] = aval[j+1]; 11207c478bd9Sstevel@tonic-gate aval[j+1] = i; 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate hp = ap[j]; 11237c478bd9Sstevel@tonic-gate ap[j] = ap[j+1]; 11247c478bd9Sstevel@tonic-gate ap[j+1] = hp; 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate } else 11277c478bd9Sstevel@tonic-gate break; 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate needsort++; 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate static int 11347c478bd9Sstevel@tonic-gate init(struct irs_ho *this) { 11357c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate if (!pvt->res && !ho_res_get(this)) 11387c478bd9Sstevel@tonic-gate return (-1); 1139*9525b14bSRao Shoaib if (((pvt->res->options & RES_INIT) == 0U) && 11407c478bd9Sstevel@tonic-gate res_ninit(pvt->res) == -1) 11417c478bd9Sstevel@tonic-gate return (-1); 11427c478bd9Sstevel@tonic-gate return (0); 11437c478bd9Sstevel@tonic-gate } 1144